H.264网络传输中马赛克问题的解决

本技术文章版权属于刘超 [email protected] ,如有转载请注明出处。

本文讲解的H.264的马赛克问题 是以 T264为 基础的。 T264 是国内的开源项目,官方网站为 http://sourceforge.net/projects/t264 ,目前和 JM H.264 的官方源码)、 X264 http://developers.videolan.org/x264.html )一起被称为 H.264 三大 Codec T264 的程序做过汇编优化,速度还可以,但只能解 T264 本身的码流。

MPEG 帧的概念和 H.264 的补充

MPEG 定义

根据 MPEG 的定义,帧分为 I ,B ,P 帧。这些帧定义如下:

I 帧:就是关键帧, I 帧压缩采用基准帧模式,只提供帧内压缩,即把帧图像压缩到 I 帧时,仅仅考虑了帧内的图像。 I 帧压缩不能除去帧间冗余度。帧内压缩基于离散余弦变换( DCT ),类似于 JPEG H.261 图像中使用 DCT 的压缩标准。 I 帧压缩可以得到 6 1 的压缩比而不产生任何可觉察的模糊现象。

B 帧:为双向帧间编码。它从前面和后面的 I 帧或 P 帧中提取数据。 B 帧基于当前帧与前一帧和后一帧图像之间的差别进行压缩。 B 帧压缩可以达到 200 1 的压缩比,其文件尺寸一般为 I 帧压缩尺寸的 15% ,不到 P 帧压缩尺寸的一半。

P 帧:采用了前向预测,意思是 P 帧是根据前面的 P 帧或 I 帧预测得来的。 P 帧采用预测编码,利用相邻帧的一般统计信息进行预测。也就是说,它考虑运动特性,提供帧间编码。 P 帧预测当前帧与前面最近的 I 帧或 P 帧的差别。

H.264 补充

H.264 中也有 I B P 帧,不同的是, H.264 是以多幅图像为参考,因此可以获取更高的压缩比,以及更连贯的动作。但是这也造成 H.264 耗资源大,延时也略大于 MPEG-4

除了 I B P 帧外, H.264 提出了 SP SI 帧,这两种帧介于 I P 之间。 SP 的编码原理和 P 类似,仍是基于帧间预测的运动补偿预测编码,两者之间的差异在于 SP 帧能够参照不同参考帧重构出相同的图像帧。充分利用这一特性, SP 帧可以取代 I 帧,广泛应用于 Bitstream Switching, Splicing, Random Access, Fast Forward Fast Backward 以及 Error Recovery 等应用中。同时大大降低了码率的开销。 SI 则是基于帧内预测的编码技术,其重构图像的方法和 SP 完全相同。

SP 帧的编码效率尽管略低于 P ,却远远高于 I ,大大改善了 H.264 的网络亲和性,支持灵活的流媒体服务应用,具有很强的抗误码性能,适于在噪声干扰大、丢包率高的无线信道中传输。

T264 中帧的概念

T264 中主要包括了 IDR,I,P,B 四种。

IDR :类似于 H.264 标准的 I 帧,在马赛克问题中起着至关重要的作用。在 IDR 之后的图像不会再以 IDR 之前的图像为参考,间断性的插入 IDR ,可以把视频分成段。

I :类似于 H.264 标准的 SP 帧,进行了帧间的预测。 T264 I 的取名让我们走了不少弯路。我们一直把 I 作为关键帧来处理,但是发现在网络丢包的情况下只播放 I 帧,也会有马赛克现象出现。而且前面的包丢的越多, I 帧的马赛克现象越严重,这就表明 I 帧也和前面的帧作了帧内预测。对 IDR 帧的实验和研究才让我们走出误区, IDR 才是真正的标准中的 I 帧。

P B :这两个和标准中一致,和多幅图像做了帧间的预测。

T264 流的改造

目前 T264 支持的码流主要有如下几种:

0) IDR P P P …..P I P P P P … P I P P …

1) IDR B P B P…..B P B P I B P B P …

2) IDR B B P B B P…..B B P I B B P

在数据的刚开始总会有一个 IDR 帧出现,之后就不再有 IDR 。这样可以让数据量很小,但是解码端必须要收到第一个 IDR 帧,否则整个数据都将不能正确解码,这就导致我们实验时必须先启动解压端,然后再启动压缩端,以保证第一个 IDR 顺利到达。

后两种带有 B 的码流在目前的 T264 的源码中已经不再使用。 B 帧的加入虽然可以让数据量变小,但是也会造成 CPU 消耗过多,在丢包的情况下数据难以恢复的现象。我想 T264 只所以不采用后面两种码流,大概就是考虑这些问题。

目前 T264 采用的码流为第一种,对于本地文件压缩,这种码流非常适合,但是对于网络传输来说,这种码流有着重大的问题。因为网络传输时第一个 IDR 帧很可能不能被解压缩端所获取,这样就造成严重的误码和程序错误。对于这个问题,我的解决方案是定期投放 IDR 帧。由于过多的 IDR 会带来数据量变大,为此我们又要采取另外一种措施,就是尽可能放弃 I 帧,以此来减少由于 IDR 数量增加造成的数据量增大的问题。因此我们的码流如下所示:

IDR P P P …..P IDR P P P P … P IDR P P …

马赛克问题的探讨

在确定好我们的码流后,我将对马赛克问题做详细的分析。目前我们采用了每 10 帧一个 IDR 的方式,为了更好的说明问题作出了如下图表:

 

码流

IDR

P

P

P

P

P

P

P

P

P

IDR

P

P

P

P

P

帧号

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

 

上表中 1 11 号帧为 IDR 帧,其余位 P 帧。假设第 7 帧丢失,如下图所示:

码流

IDR

P

P

P

P

P

 

P

P

P

IDR

P

P

P

P

P

帧号

1

2

3

4

5

6

 

8

9

10

11

12

13

14

15

16

那么根据 P 帧的特性,第 8 帧就会参考前面的序列 1-6 来解码,由于第 7 帧和第 6 帧是有细微的区别的,这样第八帧率在解码的时候就会产生误码,也就会有轻微的马赛克现象。

当第 9 帧再参考第 8 帧解码时,由于 8 本身已经有了轻微的马赛克, 9 将会对马赛克放大。到了 10 马赛克更加严重。

如下表所示,如果丢失第 3 帧:

码流

IDR

P

 

P

P

P

P

P

P

P

IDR

P

P

P

P

P

帧号

1

2

 

4

5

6

7

8

9

10

11

12

13

14

15

16

4 5 6 7 8 9 10 将会依次对马赛克进行放大,这时的马赛克会比丢失第 7 帧更严重。

这也说明,在同一个 IDR P 的序列中丢失的包越往前,马赛克越严重。直到下一个 IDR 帧,马赛克将会结束。

马赛克问题的解决方案

分析了马赛克出现的原理之后,我们提出了马赛克问题的解决方案。仍然拿上面丢失第 7 帧的例子来看。

码流

IDR

P

P

P

P

P

 

P

P

P

IDR

P

P

P

P

P

帧号

1

2

3

4

5

6

 

8

9

10

11

12

13

14

15

16

我们可以考虑在丢失第 7 帧的情况下,同时也把该序列中在该帧后面的其他帧丢失,本例中,我们应该丢失 8 9 10 ,等待下一个 IDR 帧的到来。

如果丢失 IDR 帧,我们会把 IDR 相关的帧序列都丢失,以防止误码的产生。

这种方式可以有效地解决马赛克现象,源节点发出去 30fps 的视频,在网络上丢包之后到接收端可能看到的只是 20fps, 或者 10fps ,但是不会有马赛克问题产生。

我们这种解决方式也有缺陷的地方,比如第 7 帧的丢失,造成 8,9,10 帧也跟着丢失,那么在播放视频时, 1-6 帧都播放的很流畅,到 7-10 就会停住,也就是会出现忽快忽慢的现象。但是由于互联网丢包的随机性,这种现象在互联网上可能不太严重。另外这种方式对接收到的帧的利用率不是很高,如果第 3 帧丢失,那么第 4-10 帧即使收到也要人为的丢失。以后我们可以考虑利用相关的帧对丢失的帧进行预测,重新生成丢失的帧,并补齐。但是这样的实现的难度很大,目前还没有一个技术去实现这个。还有一个办法就是 8 9 10 帧做去方块滤波处理,同时对边缘进行模糊处理,让 8-10 模糊的播放出来,而不至于出现马赛克和忽快忽慢的现象。

总结

H.264 的加入让我们的带宽有了 1/3 的节省,目前 30fps 320*240 的视频占据带宽大概为 15kBytes/s ,比 MPEG-4 25kBytes/s 以上有了很大提高。同时马赛克问题也得到了合适的解决。

目前我对T264的代码做了点改动,主要是在消除马赛克方面,以及解压端先启动程序错误的问题。不方便在网上直接公开,需要的话,发邮件给我吧。[email protected] 或者 [email protected]

你可能感兴趣的:(音视频开发)