【ECM技术】Non-adjacent special candidates技术

该技术修正了merge候选列表建立的过程。merge候选列表添加的顺序为:

  1. 空域候选,图中的1-4
  2. TMVP
  3. 不相邻的空域候选,图中的6-20(新增)
  4. HMVP
  5. 成对平均MVP
  6. 零候选
    【ECM技术】Non-adjacent special candidates技术_第1张图片

其中不相邻的空域候选的推导如下:
往外扩展四圈,每圈水平方向步长增加CUwidth,垂直方向步长增加CUheight。在每圈上找出五个坐标,由offsetX和offsetY共同定位,分别为0~4,如图所示。第一圈取0,1,4,剩余两圈均取五个。
【ECM技术】Non-adjacent special candidates技术_第2张图片
轮数为index,每轮水平偏移量为iHor=width*(index+1),垂直偏移量为iVer=height*(index+1)。每个点的偏移量由offsetX和offsetY表示。此处偏移量均指的是距离当前CU左上角的偏移。各点的偏移量如下:
【ECM技术】Non-adjacent special candidates技术_第3张图片

代码:
在ECM2中该技术由宏NON_ADJACENT_MRG_CAND所控制,主要内容在函数getInterMergeCandidates中添加了TMVP之后,成对平均MVP之前,如下

#if NON_ADJACENT_MRG_CAND
  MotionInfo miNeighbor;
  int offsetX = 0;//LJY:各个点相对于当前CU的左上角的偏移量
  int offsetY = 0;
  const int iNACANDIDATE_NUM[4] = { 3, 5, 5, 5 };//LJY:共有四轮扩展,每轮取的点数
  const int idxMap[4][5] = { { 0, 1, 4 },{ 0, 1, 2, 3, 4 },{ 0, 1, 2, 3, 4 },{ 0, 1, 2, 3, 4 } };//LJY:每轮取到的点

  for (int iDistanceIndex = 0; iDistanceIndex < NADISTANCE_LEVEL && cnt < maxNumMergeCand - 1; iDistanceIndex++)
  {
    const int iNADistanceHor = pu.Y().width  * (iDistanceIndex + 1);//LJY:每轮距离当前CU左上角的距离
    const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1);

    for (int NASPIdx = 0; NASPIdx < iNACANDIDATE_NUM[iDistanceIndex] && cnt < maxNumMergeCand - 1; NASPIdx++)
    {
      switch (idxMap[iDistanceIndex][NASPIdx])
      {
        //LJY:根据距离及宽高计算得到五个点的偏移量
      case 0:offsetX = -iNADistanceHor - 1; offsetY = pu.Y().height + iNADistanceVer - 1; break;
      case 1:offsetX = pu.Y().width + iNADistanceHor - 1; offsetY = -iNADistanceVer - 1; break;
      case 2:offsetX = pu.Y().width >> 1;   offsetY = -iNADistanceVer - 1;    break;
      case 3:offsetX = -iNADistanceHor - 1; offsetY = pu.Y().height >> 1; break;
      case 4:offsetX = -iNADistanceHor - 1; offsetY = -iNADistanceVer - 1;    break;
      default: printf("error!"); exit(0); break;
      }

      const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType);//LJY:获取到对应点所在的CU

      bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER( pu.lumaPos(), posLT.offset( offsetX, offsetY ) , plevel) && CU::isInter(*puNonAdjacent->cu);

      if (isAvailableNonAdjacent)
      {
        //LJY:获取对应点所在CU的运动信息
        miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY));


        // get Inter Dir
        mrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir;
        // get Mv from Above-Left
        mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]);
        mrgCtx.useAltHpelIf[cnt] = miNeighbor.useAltHpelIf;
        // get Mv from Above-right
        mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->BcwIdx : BCW_DEFAULT;
#if INTER_LIC
        mrgCtx.LICFlags[cnt] = miNeighbor.usesLIC;
#endif
        if (slice.isInterB())
        {
          mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]);
#if MULTI_HYP_PRED
          mrgCtx.addHypNeighbours[cnt] = puNonAdjacent->addHypData;
#endif
        }

#if NON_ADJACENT_MRG_CAND || TM_MRG
        if (!mrgCtx.xCheckSimilarMotion(cnt
#if TM_MRG
                               , mvdSimilarityThresh
#endif
        ))
#endif
        {
          if (mrgCandIdx == cnt)
          {
            return;
          }
          cnt++;
        }
      }

    }
  }
#endif

你可能感兴趣的:(ECM,视频编码,视频处理,算法)