MMVD是在getInterMergeCandidates函数中进行的,同时和普通merge模式以及CIIP模式竞争。
MMVD选择merge列表的前两个MergeMode作为baseMV,然后分别以这两个baseMV为中心,上下左右四个方向,每个方向分别都有8步偏移的MVD。
baseMV加上方向偏移的MVD,就得到了MMVD模式的MVP,然后在这248=64 个MVP中选最优作为MMVD模式的MVP。
class MergeCtx //MergeCtx存放merge列表的信息
{
//MMVD的baseMV同样存储在其中
public:
//.....
#if JVET_L0054_MMVD
MvField mmvdBaseMv[MMVD_BASE_MV_NUM][2]; //存放MMVD的两个baseMV,双向
void setMmvdMergeCandiInfo(PredictionUnit& pu, int candIdx); //由candIdx获得偏移mvd,继而获得MVP等运动信息赋给pu
#endif
void setMergeInfo( PredictionUnit& pu, int candIdx );
};
//merge列表构建完成之后,获取merge列表的前两个mergeMode为MMVD的baseMV
void PU::getInterMMVDMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const int& mrgCandIdx)
{
int refIdxList0, refIdxList1;
int k;
int currBaseNum = 0; //目前已获得的baseMV个数
const uint16_t maxNumMergeCand = mrgCtx.numValidMergeCand;
for (k = 0; k < maxNumMergeCand; k++)
{
if (mrgCtx.mrgTypeNeighbours[k] == MRG_TYPE_DEFAULT_N)
{
refIdxList0 = mrgCtx.mvFieldNeighbours[(k << 1)].refIdx;
refIdxList1 = mrgCtx.mvFieldNeighbours[(k << 1) + 1].refIdx;
if ((refIdxList0 >= 0) && (refIdxList1 >= 0)) //双向
{
mrgCtx.mmvdBaseMv[currBaseNum][0] = mrgCtx.mvFieldNeighbours[(k << 1)];
mrgCtx.mmvdBaseMv[currBaseNum][1] = mrgCtx.mvFieldNeighbours[(k << 1) + 1];
}
else if (refIdxList0 >= 0) //前向
{
mrgCtx.mmvdBaseMv[currBaseNum][0] = mrgCtx.mvFieldNeighbours[(k << 1)];
mrgCtx.mmvdBaseMv[currBaseNum][1] = MvField(Mv(0, 0), -1);
}
else if (refIdxList1 >= 0) //后向
{
mrgCtx.mmvdBaseMv[currBaseNum][0] = MvField(Mv(0, 0), -1);
mrgCtx.mmvdBaseMv[currBaseNum][1] = mrgCtx.mvFieldNeighbours[(k << 1) + 1];
}
currBaseNum++;
if (currBaseNum == MMVD_BASE_MV_NUM) //满两个baseMV跳出
break;
}
}
if (currBaseNum < MMVD_BASE_MV_NUM) //如果merge列表候选不足两个,MMVD的baseMV补0
{
for (k = currBaseNum; k