在讨论帧内预测的章节中我们已经讨论过部分宏块类型的分类。我们知道,对于帧间编码的宏块,其划分方式可以分为两步,其一为宏块级划分,其二为子宏块级划分。下面分别讨论这两个步骤。
我们知道,对于P宏块,其宏块级划分有4种方式:16×16、16×8、8×16和8×8。此外还存在两种模式即P_8x8ref0和P_Skip模式。其定义如下表所示:
其中,P_8x8ref0表示虽然宏块是按照8×8划分,但码流中不传输ref_idx等信息。对于每一个子块,其ref_idx信息默认为0。
从上表中可知,对于P帧的宏块划分,其NumMbPart的取值范围为1、2或4,其MbPartPredMode的取值为Pred_L0或不存在。
对于B宏块,其宏块划分方式有B_Direct_16x16、B_X0_X1_MxN、B_8x8和B_Skip模式。其定义方式如下:
从上表中可知,除了B_8x8需要进一步进行子块划分因此没有MbPartPredMode之外,其他模式均定义了一个或两个的MbPartPredMode值,其取值及含义为:
当帧间编码宏块按照8×8划分时,每一个8×8子块可能会进一步进行划分,其划分方法如下表所示:
对P宏块:
对B宏块:
从上述的表格中我们可以看出,对宏块和子宏块的划分,其每一个划分的参数含义都是类似的。比较明显的一个区别是:再对B宏块的8×8子块进行进一步分割后,每一个8×8子块内的分块都只有一个SubMbPredMode,因为其中的所有分块都共享一个参考帧索引。
同宏块划分类似,每一个子块划分的SubMbPredMode可能的取值也包括Pred_L0、Pred_L1、BiPred、Direct等。
一个宏块中包含帧间编码信息的结构可能有sub_mb_pred和mb_pred两种,如下表所示:
其中,sub_mb_pred主要用于P_8x8、P_8x8ref0和B_8x8三种,其定义为:
在sub_mb_pred结构中,首先保存的是4个8×8子块的划分模式sub_mb_type,然后依次保存了参考帧索引值ref_idx_l0、ref_idx_l1和运动矢量残差mvd_l0、mvd_l1。
mb_pred主要用于非8×8模式的帧间编码宏块分割以及帧内编码的宏块,其定义为:
其内部结构同sub_mb_pred类似,也包含了参考帧索引值ref_idx_l0、ref_idx_l1和运动矢量残差mvd_l0、mvd_l1。
在获取到了宏块划分中的参考帧索引后,可以直接从对应的参考帧列表中获取参考帧,即ref_idx_l0表示在参考帧列表List0的位置,ref_idx_l1表示在参考帧列表List1中的位置。
首先需要区分的是下列的几种模式:
Direct预测模式定义在标准文档的8.4.1.2节。主要执行步骤如下:
首先获取共置图像(colPic),对于帧编码的视频,colPic即参考帧列表List1的首帧RefPicList1[0]。
然后计算luma4x4BlkIdx的值;计算方法根据direct_8x8_inference_flag的取值不同:
luma4x4BlkIdx计算完成后,根据4×4子块逆扫描顺序将luma4x4BlkIdx转换为子块坐标(xCol, yCol);
根据表8-8的定义,计算共置宏块地址mbAddrCol、子块坐标yM和mv映射系数vertMvScale;从表中可知,对于帧编码视频,其mbAddrCol值等于当前宏块地址CurrMbAddr,子块坐标的yM等于步骤3中计算得到的yCol,mv映射系数vertMvScale为One_To_One。
设mbTypeCol和subMbTypeCol分别为共置宏块及其内部对应子块的类型,mbPartIdxCol和subMbPartIdxCol分别为共置宏块及其内部对应子块的内部划分索引值。根据子块坐标(xCol, yM)、mbTypeCol(如果共置宏块是8x8分割,则还有subMbTypeCol的数据),得到mbPartIdxCol和subMbPartIdxCol;
计算mvCol和refIdxCol。根据共置宏块的类型判断:
空间Direct模式适用于B_Skip和B_Direct的运动矢量预测过程。该过程传入的数据包括mbPartIdx和subMbPartIdx,输出的数据结果有:
首先计算两个方向的参考帧索引refIdxL0, refIdxL1。其主要步骤为:
第二步为调用3.1中的方法计算mvCol和refIdxCol;
第三步为计算colZeroFlag。如果下列条件全部符合,则colZeroFlag为1,否则colZeroFlag为0:
最后,计算预测mv的值。如果下列条件符合其中之一,预测mv的两个分量全部为0;否则,按照运动矢量预测的方式通过相邻像素块的运动信息预测mv的值:
两个方向的预测方向标识位predFlagL0和predFlagL1分别代表两个方向的refIdx是否为非负值,subMvCnt的值表示两个标识位有几个为真。
与空间Direct模式类似,时间Direct模式同样适用于B_Skip和B_Direct的运动矢量预测过程。其输入输出的数据也与之一致。
首先调用3.1中的方法计算mvCol和refIdxCol;
在获取到了refIdxCol后,按照标准的说明,调用MapColToList0()获取到新的refIdxL0。实际上对于帧编码视频,MapColToList0()的作用就是从List0中找到第一个包含refIdxCol的参考帧,并将其索引值返回给refIdxL0。此外,refIdxL1的值被设为0。
下一步操作是计算currPicOrField和两个参考帧pic0以及pic1。对于帧编码视频,pic0设为RefPicList0[refIdxL0],pic1设为RefPicList1[0];currPicOrField为当前的图像对象。
最后计算两个预测mv的值。如果refIdxL0代表的是一个长期参考帧,或者pic1和pic2的poc相等,则两个预测mv的计算方式为:
否则,如果pic1和pic2的poc不相等,且refIdxL0代表的是一个短期参考帧,则mvL0和mvL1都是mvCol经过变换之后的缩放值,其缩放系数由当前帧、pic0和pic1的POC计算决定。计算方法如下图所示:
其时间与mv的关系可由下图表示: