H.264文件结构学习笔记

简介

相关研究显示 H.264/AVC 与 MPEG-2 及 MPEG-4 相较之下,无论是压缩率或视讯质量皆有大幅的提升,而且H.264/AVC也首次将 视讯编码层(Video Coding Layer,VCL)与网络提取层(Network Abstraction Layer,NAL)的概念涵盖进来,以往视讯标准着重的是压缩效能部分,而H.264/AVC包含一个内建的NAL网络协议适应层,即由NAL来提供网络的状态,可以让VCL有更好的编译码弹性与纠错能力,使得H.264/AVC非常适用于多媒体串流(multimedia streaming)及行动电视(mobile TV)的相关应用

编码核心思想

在编码方面,我理解的他的理论依据是:参照一段时间内图像的统计结果表明,在相邻几幅图像画面中,一般有差别的像素只有10%以内的点,亮度差值变化不超过2%,而色度差值的变化只有1%以内。所以对于一段变化不大图像画面,我们可以先编码出一个完整的图像帧A,随后的B帧就不编码全部图像,只写入与A帧的差别,这样B帧的大小就只有完整帧的1/10或更小!B帧之后的C帧如果变化不大,我们可以继续以参考B的方式编码C帧,这样循环下去。这段图像我们称为一个序列(序列就是有相同特点的一段数据),当某个图像与之前的图像变化很大,无法参考前面的帧来生成,那我们就结束上一个序列,开始下一段序列,也就是对这个图像生成一个完整帧A1,随后的图像就参考A1生成,只写入与A1的差别内容。

在H264协议里定义了三种帧,完整编码的帧叫I帧,参考之前的I帧生成的只包含差异部分编码的帧叫P帧,还有一种参考前后的帧编码的帧叫B帧。

H264采用的核心算法是帧内压缩和帧间压缩,帧内压缩是生成I帧的算法,帧间压缩是生成B帧和P帧的算法。

关于序列的说明

在H264中图像以序列为单位进行组织,一个序列是一段图像编码后的数据流,以I帧开始,到下一个I帧结束。

一个序列的第一个图像叫做 IDR 图像(立即刷新图像),IDR 图像都是 I 帧图像,但不是所有I帧图像都是IDR图像。H.264 引入 IDR 图像是为了解码的同步,当解码器解码到 IDR 图像时,立即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列。这样,如果前一个序列出现重大错误,在这里可以获得重新同步的机会。IDR图像之后的图像永远不会使用IDR之前的图像的数据来解码。

一个序列就是一段内容差异不太大的图像编码后生成的一串数据流。当运动变化比较少时,一个序列可以很长,因为运动变化少就代表图像画面的内容变动很小,所以就可以编一个I帧,然后一直P帧、B帧了。当运动变化多时,可能一个序列就比较短了,比如就包含一个I帧和3、4个P帧。

IPB帧

I帧

1.它是一个全帧压缩编码帧。它将全帧图像信息进行JPEG压缩编码及传输;

2.解码时仅用I帧的数据就可重构完整图像;

3.I帧描述了图像背景和运动主体的详情;

4.I帧不需要参考其他画面而生成;

5.I帧是P帧和B帧的参考帧(其质量直接影响到同组中以后各帧的质量);

6.I帧是帧组GOP(既一个帧序列)的基础帧(第一帧),在一组中只有一个I帧;

7.I帧不需要考虑运动矢量;

8.I帧所占数据的信息量比较大

P帧

前向预测编码帧。P帧表示的是这一帧跟之前的一个关键帧(或P帧)的差别,解码时需要用之前缓存的画面叠加上本帧定义的差别,生成最终画面。(也就是差别帧,P帧没有完整画面数据,只有与前一帧的画面差别的数据)

P帧的预测与重构:P帧是以I帧为参考帧,在I帧中找出P帧“某点”的预测值和运动矢量,取预测差值和运动矢量一起传送。在接收端根据运动矢量从I帧中找出P帧“某点”的预测值并与差值相加以得到P帧“某点”样值,从而可得到完整的P帧。

1.P帧是I帧后面相隔1~2帧的编码帧;

2.P帧采用运动补偿的方法传送它与前面的I或P帧的差值及运动矢量(预测误差);

3.解码时必须将I帧中的预测值与预测误差求和后才能重构完整的P帧图像;

4.P帧属于前向预测的帧间编码。它只参考前面最靠近它的I帧或P帧;

5.P帧可以是其后面P帧的参考帧,也可以是其前后的B帧的参考帧;

6.由于P帧是参考帧,它可能造成解码错误的扩散;

7.由于是差值传送,P帧的压缩比较高。

B帧

双向预测内插编码帧。B帧是双向差别帧,也就是B帧记录的是本帧与前后帧的差别(具体比较复杂,有4种情况,但我这样说简单些),换言之,要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,但是解码时CPU会比较累。

B帧以前面的I或P帧和后面的P帧为参考帧,“找出”B帧“某点”的预测值和两个运动矢量,并取预测差值和运动矢量传送。接收端根据运动矢量在两个参考帧中“找出(算出)”预测值并与差值求和,得到B帧“某点”样值,从而可得到完整的B帧。

1.B帧是由前面的I或P帧和后面的P帧来进行预测的;

2.B帧传送的是它与前面的I或P帧和后面的P帧之间的预测误差及运动矢量;

3.B帧是双向预测编码帧;

4.B帧压缩比最高,因为它只反映了参考帧间运动主体的变化情况,预测比较准确;

5.B帧不是参考帧,不会造成解码错误的扩散。

注:I、B、P各帧是根据压缩算法的需要,是人为定义的,它们都是实实在在的物理帧。一般来说,I帧的压缩率是7(跟JPG差不多),P帧是20,B帧可以达到50。可见使用B帧能节省大量空间,节省出来的空间可以用来保存多一些I帧,这样在相同码率下,可以提供更好的画质。

压缩方法

h264的压缩方法:

1.分组:把几帧图像分为一组(GOP,也就是一个序列),为防止运动变化,帧数不宜取多。

2.定义帧:将每组内各帧图像定义为三种类型,即I帧、B帧和P帧;

3.预测帧:以I帧做为基础帧,以I帧预测P帧,再由I帧和P帧预测B帧;

4.数据传输:最后将I帧数据与预测的差值信息进行存储和传输。

帧内(Intraframe)压缩也称为空间压缩(Spatial compression)。当压缩一帧图像时,仅考虑本帧的数据而不考虑相邻帧之间的冗余信息,这实际上与静态图像压缩类似。帧内一般采用有损压缩算法,由于帧内压缩是编码一个完整的图像,所以可以独立的解码、显示。帧内压缩一般达不到很高的压缩,跟编码jpeg差不多。

帧间(Interframe)压缩的原理是:相邻几帧的数据有很大的相关性,或者说前后两帧信息变化很小的特点。也即连续的视频其相邻帧之间具有冗余信息,根据这一特性,压缩相邻帧之间的冗余量就可以进一步提高压缩量,减小压缩比。帧间压缩也称为时间压缩(Temporal compression),它通过比较时间轴上不同帧之间的数据进行压缩。帧间压缩一般是无损的。帧差值(Frame differencing)算法是一种典型的时间压缩法,它通过比较本帧与相邻帧之间的差异,仅记录本帧与其相邻帧的差值,这样可以大大减少数据量。

网络提取层(NAL)

以NAL封包为单位的方式来做为VCL编译码的运算单位,这样传输层拿到NAL封包之后不需要再进行切割,只需附加该传输协议的文件头信息(adding header only)就可以交由底层传送出去。

如图所示,可以将NAL当成是一个专作封装(packaging)的模块,用来将VCL压缩过的bitstream封装成适当大小的封包单位(NAL-unit),并在NAL-unit Header中的NAL-unit Type字段记载此封包的型式,每种型式分别对应到VCL中不同的编解碼工具。NAL另外一个重要的功能为当网络发生壅塞而导致封包错误或接收次序错乱(out-of-order)的状况时,传输层协议会在Reference Flag作设定的动作,接收端的VCL在收到这种NAL封包时,就知道要进行所谓的纠错运算(error concealment),在解压缩的同时也会尝试将错误修正回来

一个完整的H.264/AVC bitstream是由多个NAL-units所组成的,所以此bitstream也称之为NAL unit stream,一个NAL unit stream内可以包含多个压缩视讯序列(coded video sequence),一个单独的压缩视讯序列代表一部视讯影片,而压缩视讯序列又是由多个access units所组成,当接收端收到一个access unit后,可以完整地译码成单张的画面,而每个压缩视讯序列的第一个access unit必须为Instantaneous Decoding Refresh (IDR) access unit,IDRaccess unit的内容全是采用intra-prediction编码,所以自己本身即可完全译码,不用参考其他access unit的数据。access unit亦是由多个NAL-units所组成,标准中总共规范12种的NAL-unit型式,这些可以进一步分类成VCL NAL-unit及non-VCL NAL-unit,所谓的VCL NAL-unit纯粹是压缩影像的内容,而所谓的non-VCL NAL-unit则有两种:Parameter Sets与Supplemental Enhancement Information (SEI),SEI可以存放影片简介、版权宣告、用户自行定义的数据…等;Parameter Sets主要是描述整个压缩视讯序列的参数,例如:长宽比例、影像显现的时间点(timestamp)、相关译码所需的参数…等,这些信息非常重要,万一在传送的过程中发生错误,会导致整段影片无法译码,以往像MPEG-2/-4都把这些信息放在一般的packet header,所以很容易随着packet loss而消失,现在H.264/AVC将这些信息独立出来成为特殊的parameter set,可以采用所谓的out-of-band的方式来传送,以便将out-of-band channel用最高层级的信道编码(channel coding)保护机制,来保证传输的正确性。

总结:

第一层是多个序列帧(多个GOP)。

第二层是每个序列帧中具体的IPB帧。

第三层是每一帧具体的数据(NALU)。

NALU

NAL单元格式:

NAL头 + RBSP

RBSP:封装于网络抽象单元的数据称之为原始字节序列载荷RBSP,它是NAL的基本传输单元。其中,RBSP又分为视频编码数据和控制数据。其基本结构是:在原始编码数据的后面填加了结尾比特。一个bit“1”若干比特“0”,以便字节对齐。

RBSP的类型:

RBSP 类型之一 PS: 包括序列参数集 SPS 和 图像参数集 PPS

SPS:包含的是针对一连续编码视频序列的参数,如标识符 seq_parameter_set_id、帧数及 POC 的约束、参考帧数目、解码图像尺寸和帧场编码模式选择标识等等。

PPS:对应的是一个序列中某一幅图像或者某几幅图像,其参数如标识符 pic_parameter_set_id、可选的 seq_parameter_set_id、熵编码模式选择标识、片组数目、初始量化参数和去方块滤波系数调整标识等等。

NALU类型

标识NAL单元中的RBSP数据类型,其中,nal_unit_type为1, 2, 3, 4, 5及12的NAL单元称为VCL的NAL单元,其他类型的NAL单元为非VCL的NAL单元。

0:未规定

1:非IDR图像中不采用数据划分的片段

2:非IDR图像中A类数据划分片段

3:非IDR图像中B类数据划分片段

4:非IDR图像中C类数据划分片段

5:IDR图像的片段

6:补充增强信息 (SEI)

7:序列参数集

8:图像参数集

9:分割符

10:序列结束符

11:流结束符

12:填充数据

13 – 23:保留

24 – 31:未规定

视讯编码层(VCL)

视频压缩的原理是利用影像在时间与空间上存有相似性,这些相似的数据经过压缩算法处理之后,可以将人眼无法感知的部分抽离出来,这些称为视觉冗余(visual redundancy)的部分在去除之后,就可以达到视频压缩的目的。如图1所示,H.264/AVC的视讯编码机制是以图块(block-based)为基础单元,也就是说先将整张影像分割成许多矩形的小区域,称之为巨图块(macroblock,MB),再将这些巨图块进行编码,先使用画面内预测(intra-prediction)与画面间预测(inter-prediction)技术,以去除影像之间的相似性来得到所谓的差余影像(residual),再将差余影像施以空间转换(transform)与量化(quantize)来去除视觉冗余,最后视讯编码层会输出编码过的比特流(bitstream),之后再包装成网络提取层的单元封包(NAL-unit),经由网络传送到远程或储存在储存媒体中。

H.264/AVC影像格式阶层架构

H.264/AVC的阶层架构由小到大依序是sub-block、block、macroblock、slice、slicegroup、frame/field-picture、sequence。对一个采用4:2:0取样的MB而言,它是由16x16点的Luma与相对应的2个8x8点Chroma来组成,而在H.264/AVC的规范中,MB可再分割成多个16x8、8x16、8x8、8x4、4x8、4x4格式的sub-blocks。所谓的slice是许多MB的集合,而一张影像是由许多slice所组成(图3),slice为H.264/AVC格式中的最小可译码单位(self-decodable unit),也就是说一个slice单靠本身的压缩数据就能译码,而不必依靠其他slice,这样的好处是当传送到远程时,每接收完一笔slice的压缩数据就能马上译码,不用等待整张的数据接收完后才能开始,而且万一传送的过程中发生数据遗失或错误,也只是影响该笔slice,不会对其他slice有所影响,但跟MPEG-2的slice不同处在于它允许slice的范围可以超过一行MB,也就是说H.264/AVC允许整张影像只由单一个slice组成。

Slice的编码模式(IPB帧)

H.264/AVC的slice依照编码的类型可以分成下列种类:(1)I-slice: slice的全部MB都采用intra-prediction的方式来编码;(2) P-slice: slice中的MB使用intra-prediction和inter-prediction的方式来编码,但每一个inter-prediction block最多只能使用一个移动向量;(3) B-slice:与P-slice类似,但每一个inter-prediction block可以使用二个移动向量。比较特别的是B-slice的‘B’是指Bi-predictive,与MPEG-2/-4 B-frame的Bi-directional概念有很大的不同,MPEG-2/-4 B-frame被限定只能由前一张和后一张的I(或P)-frame来做inter- prediction,但是H.264/AVC B-slice除了可由前一张和后一张影像的I(或P、B)-slice外,也能从前二张不同影像的I(或P、B)-slice来做inter- prediction,

而H.264/AVC另外增加两种特殊slice类型:

(1) SP-slice:即所谓的Switching P slice,为P-slice的一种特殊类型,用来串接两个不同bitrate的bitstream;

(2) SI-slice: 即所谓的Switching I slice,为I-slice的一种特殊类型,除了用来串接两个不同content的bitstream外,也可用来执行随机存取(random access)来达到网络VCR的功能。

这两种特殊的slice主要是考虑当进行Video-On-Demand streaming的应用时,对同一个视讯内容的影片来说,server会预先存放不同bitrate的压缩影片,而当带宽改变时,server就会送出适合当时带宽比特率的影片,传统的做法是需要等到适当的时间点来传送新的I-slice (容量较P-slice大上许多),但因为带宽变小导致需要较多的时间来传送I-slice,如此会让client端的影像有所延迟,为了让相同content但不同bitrate的bitstream可以较平顺地串接,使用SP-slice会很容易来达成(图4),不仅可以直接送出新的bitstream,也因为传送的P-slice的容量较小,所以不会有时间延迟的情形出现

SP-slice

SI-slice

画面内预测技术(Intra-frame Prediction)-帧内压缩

以往的压缩标准在进行intra-prediction时,多半只是将转换系数做差值编码,而H.264/AVC在空间领域(spatial domain)来进行像点之间的预测,而不是用转换过的系数,它提供两种intra-prediction的型式:intra_4x4及intra_16x16,所谓的intra_4x4是以Luma 4x4 sub-block为单位,找出它的参考对象(predictor)后,再将其与参考对象相减后所产生的差余影像(residual)送入转换算法,而寻找参考对象的模式共有9种预测的方向(上图),以mode 0 (vertical)为例,{a,e,i,m}、{b,f,j,n}、{c,g,k,o}、{d,h,l,p}的参考对象分别为A、B、C、D;Luma intra_16x16与Chroma的模式跟Luma intra_4x4类似

画面间预测技术(Inter-frame Prediction)-帧间压缩

至于横跨每张画面之间的预测技术,H.264/AVC提供了更丰富的编码模式,计有下述几种区块分割(partition)的方法:16x16、16x8、8x16、8x8、8x4、4x8、4x4,多样的分割方式可以让移动向量的预测更准确,如上图所示,画面中有些移动的区域并不是正方形,使用长方形或较小的4x4分割来做预测的区域,可以大幅降低差余影像的数值来增加了压缩比,但也因此P-slice中的MB最多可有16个移动向量(motion vector),而B-slice中的MB最多可拥有32个移动向量,虽然这些会增加移动向量档头(header)的容量,但整体来说对压缩比仍有正面的益处。

以往的压缩标准所使用的动态估测(motion estimation),只有使用前一张图像来作为预测的对象,H.264/AVC提供了多重参考图像(multiple reference frames)的概念,使得移动向量不再只限于前后相邻的影像,而是可以跨过多张影像,如上图所示,在时间点t的图块,可以使用t-1到t-2图像中的图块来作为预测的对象,当影片有周期重复性的内容时,例如:背景影像周期性的出现或被遮盖、对象有来回跳动的行为、形状忽大忽小,或是摄影机在拍摄时,因为有多处的取景点,并且摄影画面在取景点之间来回移动,这种情形在球类比赛转播时常出现,这些状况都能得到较好的动态预测结果,因而提高了压缩的效能。