【H.264/AVC视频编解码技术详解】二十六、帧间预测编码(4):宏块的帧间预测解码

《H.264/AVC视频编解码技术详解》视频教程已经在“CSDN学院”上线,视频中详述了H.264的背景、标准协议和实现,并通过一个实战工程的形式对H.264的标准进行解析和实现,欢迎观看!

“纸上得来终觉浅,绝知此事要躬行”,只有自己按照标准文档以代码的形式操作一遍,才能对视频压缩编码标准的思想和方法有足够深刻的理解和体会!

链接地址:H.264/AVC视频编解码技术详解

GitHub代码地址:点击这里


一、帧间预测宏块类型

在讨论帧内预测的章节中我们已经讨论过部分宏块类型的分类。我们知道,对于帧间编码的宏块,其划分方式可以分为两步,其一为宏块级划分,其二为子宏块级划分。下面分别讨论这两个步骤。

1.1 帧间预测宏块划分

我们知道,对于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值,其取值及含义为:

  • Pred_L0:只从List0中选择一个参考帧;
  • Pred_L1:只从List1中选择一个参考帧;
  • BiPred:双向预测,从List0和List1中各选择一个参考帧;
  • Direct:用于B_Direct_16x16和B_Skip模式;

1.2 子宏块的划分

当帧间编码宏块按照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中的位置。

三、Skip模式和Direct预测

首先需要区分的是下列的几种模式:

  • P_Skip: 即COPY模式,在该模式下无运动矢量残差,无像素预测残差。重建时以MVP作为实际运动矢量,以预测像素块作为重建;
  • B_Skip:同P_Skip类似的是该模式下同样无运动矢量残差,无像素预测残差。重建时,以Direct模式获取双向MV,以预测像素块作为重建;
  • B_Direct:B_Direct模式分为B_Direct_8x8和B_Direct_16x16,分别表示整个宏块和一个子块按照B_Direct模式编码。该模式下,无运动矢量残差,有像素预测残差。重建时,以Direct模式获取双向MV,以预测像素块加上预测残差像素块作为重建;

Direct预测模式

Direct预测模式定义在标准文档的8.4.1.2节。主要执行步骤如下:

  • 计算共置运动矢量(co-located motion vector)、参考帧索引等信息;
  • 如果direct_spatial_mv_pred_flag为1,表示采用空间Direct模式;
  • 如果direct_spatial_mv_pred_flag为0,表示采用时间Direct模式;

3.1 计算共置运动矢量和参考帧索引等信息

  1. 首先获取共置图像(colPic),对于帧编码的视频,colPic即参考帧列表List1的首帧RefPicList1[0]。

  2. 然后计算luma4x4BlkIdx的值;计算方法根据direct_8x8_inference_flag的取值不同:

    • 如果direct_8x8_inference_flag为0,luma4x4BlkIdx的计算方法为 (4 * mbPartIdx + subMbPartIdx);
    • 否则,luma4x4BlkIdx的计算方法为 (5 * mbPartIdx);
  3. luma4x4BlkIdx计算完成后,根据4×4子块逆扫描顺序将luma4x4BlkIdx转换为子块坐标(xCol, yCol);

  4. 根据表8-8的定义,计算共置宏块地址mbAddrCol、子块坐标yM和mv映射系数vertMvScale;从表中可知,对于帧编码视频,其mbAddrCol值等于当前宏块地址CurrMbAddr,子块坐标的yM等于步骤3中计算得到的yCol,mv映射系数vertMvScale为One_To_One。

  5. 设mbTypeCol和subMbTypeCol分别为共置宏块及其内部对应子块的类型,mbPartIdxCol和subMbPartIdxCol分别为共置宏块及其内部对应子块的内部划分索引值。根据子块坐标(xCol, yM)、mbTypeCol(如果共置宏块是8x8分割,则还有subMbTypeCol的数据),得到mbPartIdxCol和subMbPartIdxCol;

  6. 计算mvCol和refIdxCol。根据共置宏块的类型判断:

    1. 如果共置宏块是帧内编码宏块,则mvCol设为(0,0),refIdxCol设为-1;
    2. 如果共置宏块不是帧内编码宏块,则要判断共置宏块的predFlagL0Col和predFlagL1Col值;如果predFlagL0Col为1,则取共置宏块或其中的目标子块的MvL0作为mvCol,取RefIdxL0作为refIdxCol;
    3. 如果predFlagL0Col为0而predFlagL1Col为1,则取MvL1作为mvCol,取RefIdxL1作为refIdxCol;

3.2 空间Direct预测模式

空间Direct模式适用于B_Skip和B_Direct的运动矢量预测过程。该过程传入的数据包括mbPartIdx和subMbPartIdx,输出的数据结果有:

  • 两个方向的参考帧索引refIdxL0, refIdxL1;
  • 两个方向的运动矢量mvL0和mvL1;
  • 运动矢量计数subMvCnt;
  • 两个方向的预测方向标识位predFlagL0和predFlagL1;

首先计算两个方向的参考帧索引refIdxL0, refIdxL1。其主要步骤为:

  1. 获取当前8x8子块的分割类型currSubMbType;
  2. 计算当前子块的三个相邻块(左、上、右上)的三对参考帧索引(refIdxL0N和refIdxL1N);
  3. refIdxL0, refIdxL1分别为三个相邻块对应方向参考帧索引的最小正值,如果都不存在则都设为0,并将一个特定的标识位directZeroPredictionFlag设为1;

第二步为调用3.1中的方法计算mvCol和refIdxCol;

第三步为计算colZeroFlag。如果下列条件全部符合,则colZeroFlag为1,否则colZeroFlag为0:

  • RefPicList1[0]为用于短期参考;
  • refIdxCol值为0;
  • 以1/4像素为单位,mvCol的两个分量都在-1到1之间;

最后,计算预测mv的值。如果下列条件符合其中之一,预测mv的两个分量全部为0;否则,按照运动矢量预测的方式通过相邻像素块的运动信息预测mv的值:

  • 标识位directZeroPredictionFlag的值为1;
  • refIdxLx的值为负值;
  • refIdxLx的值为0,且colZeroFlag为1;

两个方向的预测方向标识位predFlagL0和predFlagL1分别代表两个方向的refIdx是否为非负值,subMvCnt的值表示两个标识位有几个为真。

3.3 时间Direct预测模式

与空间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的计算方式为:

  • mvL0 = mvCol;
  • mvL1 = 0;

否则,如果pic1和pic2的poc不相等,且refIdxL0代表的是一个短期参考帧,则mvL0和mvL1都是mvCol经过变换之后的缩放值,其缩放系数由当前帧、pic0和pic1的POC计算决定。计算方法如下图所示:

其时间与mv的关系可由下图表示:

  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值