H.264/AVC视频编解码技术详解二十六帧间预测编码:宏块的帧间预测解码
Posted 取次花丛懒回顾
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了H.264/AVC视频编解码技术详解二十六帧间预测编码:宏块的帧间预测解码相关的知识,希望对你有一定的参考价值。
《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 计算共置运动矢量和参考帧索引等信息
-
首先获取共置图像(colPic),对于帧编码的视频,colPic即参考帧列表List1的首帧RefPicList1[0]。
-
然后计算luma4x4BlkIdx的值;计算方法根据direct_8x8_inference_flag的取值不同:
- 如果direct_8x8_inference_flag为0,luma4x4BlkIdx的计算方法为 (4 * mbPartIdx + subMbPartIdx);
- 否则,luma4x4BlkIdx的计算方法为 (5 * mbPartIdx);
-
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。根据共置宏块的类型判断:
- 如果共置宏块是帧内编码宏块,则mvCol设为(0,0),refIdxCol设为-1;
- 如果共置宏块不是帧内编码宏块,则要判断共置宏块的predFlagL0Col和predFlagL1Col值;如果predFlagL0Col为1,则取共置宏块或其中的目标子块的MvL0作为mvCol,取RefIdxL0作为refIdxCol;
- 如果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。其主要步骤为:
- 获取当前8x8子块的分割类型currSubMbType;
- 计算当前子块的三个相邻块(左、上、右上)的三对参考帧索引(refIdxL0N和refIdxL1N);
- 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的关系可由下图表示:
以上是关于H.264/AVC视频编解码技术详解二十六帧间预测编码:宏块的帧间预测解码的主要内容,如果未能解决你的问题,请参考以下文章
H.264/AVC视频编解码技术详解二十三帧间预测编码:帧间预测编码的基本原理
H.264/AVC视频编解码技术详解二十三帧间预测编码:帧间预测编码的基本原理
H.264/AVC视频编解码技术详解二十五帧间预测编码:参考帧列表
H.264/AVC视频编解码技术详解二十五帧间预测编码:参考帧列表