H264如何实现预测

1 前言

文献[H264基本原理]通俗易懂地讲解了编码基本原理,编码过程主要包括图片分区(宏块)、预测、转换(频域变换)、量化、熵编码以及打包成比特流,其中,帧内预测编码是本文将展开的关注点,如果你对预测这一概念仍缺乏感性的认识,建议先阅读[参考文献 H264基本原理]。

2 预测

由于同一帧内邻近像素的相关性,我们可以采用帧内预测的方式压缩视频帧数据,而由于邻近帧在时间上的重复特征,我们可以采用帧间预测的方式进行编码数据压缩。预测的意思是,我们不直接对像素本身进行编码,而是通过已编码的像素数据来“推导”当前像素,作为预测值,当然,预测值与实际取样值之间是存在差异的,该差值称作残差。预测值加上残差,就可以得到实际值。预测是最简单实用的视频压缩编码方式。

我们把关注点放在帧内预测上,当编码当前块时,我们可以根据当前块的上方与左方已编码块的邻近像素点,构建当前块的预测块,使得预测块与当前块最为“匹配”。预测块加上两者的残差,就可以构建出当前块,这样,在编码中就只需要编码预测块与当前块的残差即可,而不需要对当前块的每个像素点进行编码,节省码流。

实现这个预测有几点需要考虑,1,预测的输入与输出是什么,2,块的大小如何决定,3,有哪些可用的预测方式构建预测块,4,图像包括亮度宏块与色度宏块,两者的预测是否需要有所区别,5,不同大小的宏块,是否可用的预测方式都是一样的。我们接下来一个一个地讨论。

  • 在H264中,帧内预测的输入是预测块的上方与左方的邻近像素点,以[图1 帧内预测像素示意]为例,A,B,…,M为作为预测输入的邻近像素点,a,b,c,…p为所预测像素点,即输出。这是关于第1点的讨论。

在这里插入图片描述

图1 帧内预测像素示意图
  • 对于亮度块而言,有16x16的宏块,4x4的子块,对于色度块而言,只有8x8的宏块。由于采样的关系,色度块的大小为亮度块的1/2,但没有2x2这么细颗粒度的色度子块。也就是说,宏块可以分为16x16亮度块,4x4亮度块与8x8色度块。这是关于第2点的讨论。对于帧间预测,宏块分割类型更多,与帧内预测是不一样的,这一点需要分清楚。

下图中,展示了一帧图像的宏块分割情况,宏块包括I宏块(帧内预测宏块)、P宏块(帧间预测宏块)与B宏块(帧间预测宏块),图中圈出来的宏块由16个4x4子块构成。

在这里插入图片描述

  • 预测模式根据宏块分割不同而不同,对于16x16的宏块,有4种预测模式,对于4x4的子块,有9种预测模式,而对于8x8的色度块,类似于帧内16x16预测的4种预测模式。这回答了第3、4、5点的问题。

4x4亮度预测模式

4x4亮度预测模式如[图2 4x4亮度预测模式示意]所示。各个模式的描述参考[表1 4x4亮度预测模式描述]。

在这里插入图片描述

图2 4x4亮度预测模式示意

表1 4x4亮度预测模式描述

在这里插入图片描述

16x16亮度预测模式

16x16亮度预测模式如[图3 16x16亮度预测模式示意]所示。各个模式的描述参考[表2 16x16亮度预测模式描述]。

在这里插入图片描述

图3 16x16亮度预测模式示意

表2 16x6亮度预测模式描述

在这里插入图片描述

8x8色度预测模式

每个帧内编码宏块的 8×8 色度成分由已编码左上方色度像素预测而得,两种色度成分常用同一种预测模式。4 种预测模式类似于帧内 16×16 预测的 4 种预测模式,只是模式编号不同。其中 DC(模式 0)、水平(模式 1)、垂直(模式 2)、平面(模式 3)。

另外地,我们再进一步考虑预测模式的编码,每个4x4块帧内预测模式需要编码到码流中,解码器根据码流中每个宏块的预测模式进行预测解码,但实际上,如果每个4x4块块帧内预测模式都进行编码,则需要大量比特,为了更进一步节省比特,我们可以对预测模式本身进行预测。例如,A、B、E 分别为左边、上边和当前块,如果 A 和 B 预测模式为模式 1,E 的最佳预测模式很可能也为模式 1。如果块A和块B分别用模式3和模式1预测 。当前块E的最可能的预测模式则为1。

在这里插入图片描述

图4 预测模式本身的预测示意

3 编码

3.1 宏块层句法编码

在H264码流中,句法元素被组织成序列、图像、片、宏块、子宏块5个层次,关于宏块层的句法参考[表3 宏块层语义],宏块层主要指明了当前宏块的类型mb_type,子宏块的语义sub_mb_pred,宏块预测的语义mb_pred,残差编码方案coded_block_pattern,以及宏块层中的量化参数偏移值mb_qp_delta。mb_type包含丰富的信息,在不同的片组中,该变量具有不同的取值范围,含义也不一样,片组包括I片、P片与B片。接下来,我们不直接解释每个元素的含义,而是讨论该宏块层句法设计的思路,以此理解主要的句法元素。
注意,子宏块并非指宏块的一部分,当帧间预测时,一个宏块被分割成4个8x8子块,每个8x8子块称作子宏块,子宏块包括P宏块与B宏块。

表3 宏块层语义
在这里插入图片描述

表4 宏块预测语义
在这里插入图片描述

3.2 最简单的Intra_16x16宏块编码

上一节我们讨论了预测的实现要点,这一节我们尝试一下自己编码宏块,先从最简单的16x16宏块开始,且只考虑I片中的。

H264规定,不同片中允许出现的宏块类型也不同,I片中只允许出现 I宏块,P片中既可以有P宏块也可以有I宏块,B片、SI片与SP片也类似如此。

设想我们正在编码一个16x16的宏块,关于该宏块的信息都要编码到码流中,这些信息包括:该宏块采用4种预测模式中的哪一种,有没有残差数据,亮度块需不需要传递残差数据,色度块需不需要传递残差数据,残差数据包括直流分量与交流分量,是否都传递还是传递其中哪一种分量。

在后续变换的步骤中,色度块与帧内16x16亮度块的频域变换的输入数据是残差,输出是直流分量与交流分量,也就是DC系数与AC系数,传递残差即传递DC/AC系数,除了色度块与帧内16x16亮度块,其他宏块残差的频域变换输出只有DC系数。

我们来设想一种编码方案,用2个比特表示亮度预测模式,2个比特表示色度预测模式,2个比特表示亮度块传递的分量,2个比特表示色度块传递的分量,一共8个比特。

如果16x16宏块里包括16个4x4子块,而子块的亮度预测模式有9种,可以用4个比特表示,那么我们可能要用16x4个比特来表示这个16x16宏块的所有子块亮度预测模式,子块的色度预测模式有4种,可以用2个比特表示,那么我们可能要用16x2个比特来表示这个16x16宏块的所有子块色度预测模式,16x2个比特表示亮度块传递的分量,16x2个比特表示色度块传递的分量,一共16x4+16x2+16x2+16x2=160个比特

160个比特好像有点多,我们来看看哪里可以作一下优化,毕竟上面的计算依靠于直接简单的设想。

3.3 优化预测模式编码

首先考虑一下预测模式的传递,16x16宏块可能是Intra_16x16类型,也可能是Intra_4x4类型,后者会导致大量比特的占用,我们要把这两种类型分开表述与编码,对于Intra_4x4类型,将预测模式信息单独编码,也就是在mb_pred句法中表述,单独编码可能减少不了多少比特,因此,我们采用一种技术来节省子块预测模式的编码比特:不直接对子块预测模式进行编码,而是进行预测。正如章节2所述,Intra_4x4宏块的预测模式与该子块的上方与左方宏块具有强相关性,采用某种映射关系,根据上方与左方宏块的预测模式来推导当前块的预测模式,这样,我们甚至连1个比特都不用就可以表述当前Intra_4x4宏块的预测模式了,想想我们可以节省16x4=64个比特,这实在是太棒了!不过转念一想,并不是每个Intra_4x4宏块的预测模式都可以被预测的,如果是这样,那我们就单独为这个不能被预测的Intra_4x4宏块指定预测模式。这一策略下,只要大部分Intra_4x4宏块的预测模式能够被预测,那我们可以节省好多个比特来表述与编码Intra_4x4宏块的预测模式。

因此,我们可以看到[表4 宏块预测语义]中有prev_intra4x4_pred_mode_flag[luma4x4BlkIdx]、rem_intra4x4_pred_mode[luma4x4BlkIdx]以及intra_chroma_pred_mode字段,句法元素prev_intra4x4_pred_mode_flag用来指明帧内预测中亮度分量的预测模式的预测值是否是实际预测模式,如果是,就不需要另外传预测模式,如果不是,就由rem_intra4x4_pred_mode指定实际预测模式。实际上,由于色度预测模式只有4种,只需要2个比特表述,因此色度预测模式不进行预测,intra_chroma_pred_mode在帧内预测时直接指定色度的预测模式。

3.4 优化非Intra_16x16宏块残差编码

其次,我们再考虑一下非Intra_16x16的宏块残差数据分量的传递,对于Intra_16x16的宏块,可能存在直流分量(DC系数)与交流分量(AC系数),而对于非Intra_16x16的宏块,可能存在交流分量(AC系数)。我们可以采用4个比特表示16x16宏块中4个子块的残差传递情况,每个比特表示1个子块,0表示对应子块残差全部不被传送,1表示对应子块残差系数被传送。因此,有了coded_block_pattern这个字段。coded_block_pattern即CBP,指亮度和色度分量的各小块的残差的编码方案,所谓编码方案有以下几种:

  • 所有残差,包括DC、AC都编码;
  • 只对DC系数编码;
  • 所有残差,包括DC、AC都不编码

这个句法元素同时隐含了一个宏块中亮度、色度分量的CBP,两个色度分量的CBP是相同的。亮度与色度分量的CBP如何从coded_block_pattern中计算而来?对于非Intra_16x16的宏块类型:

CodedBlockPatternLuma = coded_block_pattern % 16

CodecBlockPatternChroma = coded_block_pattern /16

  • CodedBlockPatternLuma:是一个16位的变量,其中只有最低四位有定义。由于非Intra_16x16的宏块不单独编码DC系数,所以这个变量只指明两种编码方案:残差全部编码或全部不编码。变量的最低位比特从最低位开始,每一位对应一个子块,该位等于1时表明对应子块残差系数被传送;该位等于0时表明对应子块残差全部不被传送,解码器把这些残差系数赋为0。

  • CodedBlockPatternChroma:当值为0、1、2时有定义,见[表5 CodedBlockPatternChroma的定义]。

从上面可以看出,亮度与色度分量并非直接用两个变量编码分别表述,而是通过一个变量的取余操作、取商操作得到。

表5 CodedBlockPatternChroma 的定义
在这里插入图片描述

3.5 优化Intra_16x16宏块残差编码

接下来,我们考虑一下Intra_16x16宏块的亮度与色度残差编码方案如何传递。可以用4个比特表述亮度CBP,2个比特表述色度CBP(Intra_16x16宏块色度分量没有交流分量),一共6个比特。Intra_16x16宏块本身有4种预测模式,可能用2个比特表述。加起来一共8个比特。只能用8个比特了吗?已经是最小量的比特表述了吗?我们再缕一下,一个Intra_16x16宏块有4种预测模式,每种预测模式下亮度CBP有3种可能性,色度CBP有2种可能性,也就是每种预测模式下残差编码方案有6种可能性,总的来说,一个Intra_16x16宏块可能分类为4x6类,这24类包括了所有的预测模式与残差编码方案的可能组合。那么,为何不能用5个比特来表示Intra_16x16宏块的这些信息,比8个比特还少了3个比特!当然可以,这就是mb_type的意义所在。

在H264中,mb_type指明当前宏块的类型,作为在宏块层的第一个语法元素,它描述跟整个宏块有关的基本的类型信息,在I片中的mb_type,具体语义见[表6 I片中的mb_type]。

表6 I片中的mb_type
在这里插入图片描述

[表6 I片中的mb_type]中 ,Intra_4x4 表示使用帧内 4x4 预测,Intra_16x16 表示使用帧内 16x16 预测。当使用帧内 16x16时,类型名称由了如下的结构组成:

I_16x16_x_y_z

其中,x 对应于表中“帧内 16x16 的预测模式”字段的值,y 对应于表中“色度 CBP”字段的值,z 对应于表中“亮度 CBP”的值。举个例子,值为24的mb_type类型名称为I_16x16_3_2_1,表示该帧内16x16的预测模式字段的值为3,即Intra_16x16_Plane模式,色度CBP字段的值为2,表示色度块所有残差系统都被传递,亮度CBP字段的值为1,表示亮度块只有DC系数被传递,AC系统赋值为0。色度CBP条目可以参考[表5 CodedBlockPatternChroma 的定义]。

使用帧内16x16 时,整个宏块是一个统一的整体,宏块中各子宏块、4x4 小块的预测模式信息都是相同的, 所以可以把这些信息放入mb_type ,以减少码流。其它宏块类型的这些信息必须在各子块中另外用句法元素指明,即,有两种特殊情况,I_4x4表示使用帧内4x4预测,预测模式与CBP的信息另外用句法元素指明,参考之前的章节3.4。I_PCM表示该宏块直接传递像素值信息,不进行预测,所有像素值在pcm_type中表示。

对于P片与B片中的mb_type,与I片的mb_type不太一样,但都是一个字段包含多个信息,以此减少码流。我们直接上[参考文献 新一代视频压缩编码标准]的表述。

P 片中的 mb_type ,具体语义见[表7 P 片中的 mb_type ]。

表7 P 片中的 mb_type
在这里插入图片描述
在[表 P 片中的 mb_type ]中,Pred_L0 表示用 L0,即前向预测。如果当前宏块的 mb_type 等于 0 到 4,mb_type 的含义见 [表 P 片中的 mb_type ];当 mb_type 等于 5 到 30 时, mb_type 的含义见[表 I 片中的 mb_type ], 用 mb_type-5 所得到的值来进行查找。预测模式(mb_type,n)预测模式是 mb_type 的函数,n 是宏块的第 n 个分区。

B片中的 mb_type,具体语义见[表8 B片中的 mb_type ]。

如果当前宏块是属于 B 片且 mb_type 等于 0 到 22, mb_type 的含义见 [表8 B片中的 mb_type ];当 mb_type 等于23 到 48 时,mb_type 的含义见[表6 I片中的 mb_type ], 用 mb_type-23 所得到的值来进行查找。

表8 B片中的 mb_type
在这里插入图片描述

[表8 B片中的 mb_type]中,Pred_L0 表示使用 L0,即前向预测,Pred_L1 表示使用 L1,即后向预测,Bipred 表示双向预测,Direct 表示直接预测模式。预测模式(mb_type,n)预测模式是 mb_type 的函数,n 是宏块的第n个分区。

以上,我们讨论了几个重要的句法元素,包括mb_type,pcm_byte,coded_block_pattern,prev_intra4x4_pred_mode_flag,rem_intra4x4_pred_mode以及intra_chroma_pred_mode,探讨了其设计的思路,体会其精心设计的句法,目的都是为了减少冗余信息,提高编码效率。

4 总结

预测这一概念往往是编解码入门的一个槛,甚至可以说,理解了预测,就理解了视频压缩编码的基本原理。针对预测编码,我们先提出预测的概念,类似于通过“推导”逼近真实像素,引出残差的概念,相当于预测值与实际值的差,知道了通过传递残差数据就可以还原实际的像素数据,接下来,我们讨论了实现预测的几个要点,并通过设想自行编码宏块,来设计句法元素,以此引出标准中的宏块层句法元素及其含义,理解了这样的句法设计的思路。在本文中,只讨论了帧内预测,并未关注帧间预测,后者会更为复杂。

参考文献

[1] 《H264基本原理》https://www.jianshu.com/p/97b4dc8c7f00
[2] 《从零开始理解视频编解码技术》https://zhuanlan.zhihu.com/p/93398878 转载自https://github.com/leandromoreira/digital_video_introduction
[3] 《新一代视频压缩编码标准》,毕厚杰

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值