H.266/VVC代码学习笔记16:VTM6.0中的getTriangleMergeCandidates()函数

在之前的博客详细讲了一下目前VVC中的TPM技术的详细原理,其中涉及到了三角预测模式的单向Merge列表的构建,链接为:H.266/VVC相关技术学习笔记:帧间预测中的TPM技术(Triangle partition Mode) 本篇博客将这部分函数getTriangleMergeCandidates()的代码附上,本人加了基本的注释,如果有错误或者有疑问的地方可以私信我。

//这里是三角预测模式的Merge列表构建的地方,从普通的Merge列表中派生出来
void PU::getTriangleMergeCandidates( const PredictionUnit &pu, MergeCtx& triangleMrgCtx )
{
  MergeCtx tmpMergeCtx;

  const Slice &slice = *pu.cs->slice;
  const uint32_t maxNumMergeCand = slice.getMaxNumMergeCand();//最大的Merge候选数量

  triangleMrgCtx.numValidMergeCand = 0;


  //三角Merge列表的长度为6,首先对其中的候选都进行初始化
  for (int32_t i = 0; i < TRIANGLE_MAX_NUM_UNI_CANDS; i++)
  {
    triangleMrgCtx.GBiIdx[i] = GBI_DEFAULT;//双向预测权重
    triangleMrgCtx.interDirNeighbours[i] = 0;//相邻块候选的预测方向:单向或者双向,1表示前向,2表示后向,3表示双向
    triangleMrgCtx.mrgTypeNeighbours[i] = MRG_TYPE_DEFAULT_N;//Merge类型
    triangleMrgCtx.mvFieldNeighbours[(i << 1)].refIdx = NOT_VALID;//候选的前向参考索引
    triangleMrgCtx.mvFieldNeighbours[(i << 1) + 1].refIdx = NOT_VALID;//候选的后向参考索引
    triangleMrgCtx.mvFieldNeighbours[(i << 1)].mv = Mv();//候选的前向MV
    triangleMrgCtx.mvFieldNeighbours[(i << 1) + 1].mv = Mv();//候选的后向MV
#if JVET_O0057_ALTHPELIF
    triangleMrgCtx.useAltHpelIf[i] = false;
#endif
  }
  //首先构造普通的长度为6的Merge列表
  PU::getInterMergeCandidates(pu, tmpMergeCtx, 0);

  //对Merge列表中的每一个候选进行遍历,选出满足条件的候选添加进三角的单向预测列表中
  for (int32_t i = 0; i < maxNumMergeCand; i++)
  {
    int parity = i & 1;//奇偶性,判断每个候选的奇偶性,1为奇数,0为偶数
    if (tmpMergeCtx.interDirNeighbours[i] & (0x01 + parity))//这里优先选出普通Merge列表偶数候选的前向MV给当前三角单向Merge候选
                                                            //或者优先选出普通Merge列表奇数候选的后向MV给当前三角单向Merge候选
    {
      triangleMrgCtx.interDirNeighbours[triangleMrgCtx.numValidMergeCand] = 1 + parity;//赋予三角merge候选对应的预测方向
      triangleMrgCtx.mrgTypeNeighbours[triangleMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N;
      triangleMrgCtx.mvFieldNeighbours[(triangleMrgCtx.numValidMergeCand << 1) + !parity].mv = Mv(0, 0);
      triangleMrgCtx.mvFieldNeighbours[(triangleMrgCtx.numValidMergeCand << 1) + parity].mv = tmpMergeCtx.mvFieldNeighbours[(i << 1) + parity].mv;
      triangleMrgCtx.mvFieldNeighbours[(triangleMrgCtx.numValidMergeCand << 1) + !parity].refIdx = -1;
      triangleMrgCtx.mvFieldNeighbours[(triangleMrgCtx.numValidMergeCand << 1) + parity].refIdx = tmpMergeCtx.mvFieldNeighbours[(i << 1) + parity].refIdx;
      triangleMrgCtx.numValidMergeCand++;
      if (triangleMrgCtx.numValidMergeCand == TRIANGLE_MAX_NUM_UNI_CANDS)
      {
        return;
      }
      continue;
    }

    if (tmpMergeCtx.interDirNeighbours[i] & (0x02 - parity))//若普通Merge列表偶数候选只有后向MV,则将其后向MV给当前三角单向Merge候选
                                                            //若普通Merge列表奇数候选只有前向MV,则将其前向MV给当前三角单向Merge候选
    {
      triangleMrgCtx.interDirNeighbours[triangleMrgCtx.numValidMergeCand] = 2 - parity;
      triangleMrgCtx.mrgTypeNeighbours[triangleMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N;
      triangleMrgCtx.mvFieldNeighbours[(triangleMrgCtx.numValidMergeCand << 1) + !parity].mv = tmpMergeCtx.mvFieldNeighbours[(i << 1) + !parity].mv;
      triangleMrgCtx.mvFieldNeighbours[(triangleMrgCtx.numValidMergeCand << 1) + parity].mv = Mv(0, 0);
      triangleMrgCtx.mvFieldNeighbours[(triangleMrgCtx.numValidMergeCand << 1) + !parity].refIdx = tmpMergeCtx.mvFieldNeighbours[(i << 1) + !parity].refIdx;
      triangleMrgCtx.mvFieldNeighbours[(triangleMrgCtx.numValidMergeCand << 1) + parity].refIdx = -1;
      triangleMrgCtx.numValidMergeCand++;
      if (triangleMrgCtx.numValidMergeCand == TRIANGLE_MAX_NUM_UNI_CANDS)
      {
        return;
      }
    }
  }
}

你可能感兴趣的:(H.266/VVC代码学习笔记,视频编码,H.266/VVC)