基于子块的TMVP (SbTMVP)
VTM中提出的基于子块的TMVP(subblock-based temporal motion vector prediction ,SbTMVP)和HEVC中的TMVP类似。TMVP计算方法可以参考扩展的merge模式中1.2节时域候选列表构建。
SbTMVP和TMVP主要有以下两点不同:
-
TMVP在CU级预测运动而SbTMVP在sub-CU级预测运动。
-
TMVP直接使用同位图像的同位块计算时域MV,而SbTMVP在计算同位块前先进行一个运动偏移,这个运动偏移来自当前CU的空域相邻块的MV。
SbTMVP计算当前CU的子CU的MV分为两步:
1、如下图所示,检查当前CU的空域相邻块A1,如果A1的参考图像正好是当前图像的同位图像则用A1的MV作为运动偏移,否则运动偏移设为(0,0)。
2、使用第1步得到的运动偏移(将当前块的坐标加上运动偏移)从同位图像获得子CU的运动信息(MV和参考图像索引)。如下图所示,图中假设使用A1的MV作为运动偏移,然后对每个子CU获取其在同位图像中对应块的运动信息,然后按照TMVP的处理方法将获得的MV进行缩放得到子CU的MV。
在VTM5中,基于子块的merge list内既包含SbTMVP候选项也包含affine merge候选项。在序列参数集(sequence parameter set ,SPS)中有标志位表明是否使用SbTMVP模式,如果允许使用SbTMVP模式那么在基于子块的merge list中SbTMVP候选项在affine merge候选项前面。该list中候选项数量在SPS中指定,VTM5规定最多候选数量为5。
在SbTMVP中子CU的大小固定为8x8,且和affine merge模式一样只有当CU宽高都大于等于8时才使用SbTMVP模式。
Adaptive motion vector resolution (AMVR)
在HEVC中当slice header中use_integer_mv_flag=0时,MVD(CU的MV和MVP的差值)按照1/4亮度像素精度传输。VVC提出了CU级的AMVR,AMVR允许CU的MVD使用不同精度编码。
其中可选精度如下:
-
Normal AMVP模式:1/4亮度像素精度,整亮度像素精度,4倍亮度像素精度。
-
Affine AMVP模式:1/4亮度像素精度,整亮度像素精度,1/16亮度像素精度。.
在CU级,只有当MVD至少有一个非零分量时才需要传输其精度。如果所有MVD分量(水平分量和垂直分量)都是0,则MVD默认使用1/4亮度像素精度。
当一个CU至少有一个非零MVD分量时,有一个标志位表示该CU的MVD是否使用1/4亮度像素精度,如果该标志位为0则表示使用1/4亮度像素精度不需要再传其他标志位。否则,对于Normal AMVP模式的CU需要第二个标志位表示是否使用整亮度像素精度或4倍亮度像素精度。对于Affine AMVP模式的CU需要第二个标志位表示是否使用整亮度像素精度或1/16亮度像素精度。为了确保重建的MV有同样的精度MVP会四舍五入到和MVD同样的精度。MVP朝0进行四舍五入(也就是负MVP朝正无穷方向,正MVP朝负无穷方向)。
在VTM5中两种模式的像素精度定义如下:
const MvPrecision Mv::m_amvrPrecision[3] = { MV_PRECISION_QUARTER, MV_PRECISION_INT, MV_PRECISION_4PEL }; // for cu.imv=0, 1 and 2
const MvPrecision Mv::m_amvrPrecAffine[3] = { MV_PRECISION_QUARTER, MV_PRECISION_SIXTEENTH, MV_PRECISION_INT }; // for cu.imv=0, 1 and 2
精度转换代码如下:
void changePrecision(const MvPrecision& src, const MvPrecision& dst){const int shift = (int)dst - (int)src;if (shift >= 0){*this <<= shift;}else{const int rightShift = -shift;const int nOffset = 1 << (rightShift - 1);
#if JVET_N0335_N0085_MV_ROUNDINGhor = hor >= 0 ? (hor + nOffset - 1) >> rightShift : (hor + nOffset) >> rightShift;ver = ver >= 0 ? (ver + nOffset - 1) >> rightShift : (ver + nOffset) >> rightShift;
#elsehor = hor >= 0 ? (hor + nOffset) >> rightShift : -((-hor + nOffset) >> rightShift);ver = ver >= 0 ? (ver + nOffset) >> rightShift : -((-ver + nOffset) >> rightShift);
#endif}}
void roundToPrecision(const MvPrecision& src, const MvPrecision& dst){changePrecision(src, dst);changePrecision(dst, src);}
参考
JVET-N1002
JVET-M0246
JVET-M0165
感兴趣的请关注微信公众号Video Coding