VTM3.0代码阅读:getInterMergeCandidates函数

xCheckRDCostMerge2Nx2N函数中调用getInterMergeCandidates获取merge候选,存储于mrgCtx。
MergeCtx类用来表示merge候选列表,其中存储merge候选列表中的各种信息:

class MergeCtx
{
	//...
public:
  MvField       mvFieldNeighbours [ MRG_MAX_NUM_CANDS << 1 ]; // double length for mv of both lists	双向mv,所以列表长为7*2,存储merge候选的mv和refIdx
  #if JVET_L0646_GBI
  uint8_t       GBiIdx            [ MRG_MAX_NUM_CANDS      ];
#endif
  unsigned char interDirNeighbours[ MRG_MAX_NUM_CANDS      ];	//merge候选的帧间方向
  MergeType     mrgTypeNeighbours [ MRG_MAX_NUM_CANDS      ];	//merge候选的merge模式
  int           numValidMergeCand;								//merge候选数目
  bool          hasMergedCandList;								//是否存在merge候选列表

  Void setMergeInfo( PredictionUnit& pu, int candIdx );
};

merge列表构成流程:
merge列表初始化;
获取空域的merge候选信息,顺序依次为pu的左、上、右上、左下,如果不足4个,再加入左上;
获取时域的merge候选信息,位置为当前pu的右下位置和中心位置;
添加HMVP;
添加组合平均mvp;
用0补全merge候选列表。

getInterMergeCandidates函数和L1002文档描述构建merge列表的方法是一样的
相比于VTM1.0,其中添加了HMVP和成对平均mvp
过程当中也穿插了GBI、CPR和MMVD的一些东西
注意一下对CPR_Merge候选的处理

void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
#if JVET_L0054_MMVD
                                 int mmvdList,
#endif
                                 const int& mrgCandIdx )
{
  const CodingStructure &cs  = *pu.cs;
  const Slice &slice         = *pu.cs->slice;
  const uint32_t maxNumMergeCand = slice.getMaxNumMergeCand();		//最大merge候选数目为7
  const bool canFastExit     = pu.cs->pps->getLog2ParallelMergeLevelMinus2() == 0;

  for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui)	//merge候选列表的初始化
  {
#if !JVET_L0090_PAIR_AVG
    isCandInter[ui] = false;
#endif
#if JVET_L0646_GBI
    mrgCtx.GBiIdx[ui] = GBI_DEFAULT;
#endif
    mrgCtx.interDirNeighbours[ui] = 0;
    mrgCtx.mrgTypeNeighbours [ui] = MRG_TYPE_DEFAULT_N;
    mrgCtx.mvFieldNeighbours[(ui << 1)    ].refIdx = NOT_VALID;
    mrgCtx.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID;
  }

  mrgCtx.numValidMergeCand = maxNumMergeCand;		//numValidMergeCand=7
  // compute the location of the current PU

  int cnt = 0;


#if JVET_L0293_CPR && JVET_L0054_MMVD
  int mrgCandIdxCPR = mrgCandIdx;
#endif
#if JVET_L0293_CPR && !JVET_L0369_SUBBLOCK_MERGE
  int cntCPR = 0;
#endif

  const Position posLT = pu.Y().topLeft();
  const Position posRT = pu.Y().topRight();
  const Position posLB = pu.Y().bottomLeft();		//当前pu的左上、右上、左下坐标

  MotionInfo miAbove, miLeft, miAboveLeft, miAboveRight, miBelowLeft;

  //left
  const PredictionUnit* puLeft = cs.getPURestricted( posLB.offset( -1, 0 ), pu, pu.chType );	//获取当前pu左侧的pu

  const bool isAvailableA1 = puLeft && isDiffMER( pu, *puLeft ) && pu.cu != puLeft->cu && CU::isInter( *puLeft->cu );	//获取的左侧pu的运动信息是否可用

  if( isAvailableA1 )		//如果左侧pu的运动信息可用,则加入merge候选列表中
  {
    miLeft = puLeft->getMotionInfo( posLB.offset(-1, 0) );		//左侧pu的运动信息

#if !JVET_L0090_PAIR_AVG
    isCandInter[cnt] = true;
#endif

    // get Inter Dir
    mrgCtx.interDirNeighbours[cnt] = miLeft.interDir;		//运动信息加入merge候选列表
#if JVET_L0646_GBI
    mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puLeft->cu->GBiIdx : GBI_DEFAULT;
#endif
    // get Mv from Left
#if JVET_L0293_CPR
    if (puLeft->cu->cpr)
    {
      mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_CPR;		//如果相邻pu为CPR模式,那么加入merge列表时记录一下
#if !JVET_L0369_SUBBLOCK_MERGE
      cntCPR++;

#endif
#if JVET_L0293_CPR && JVET_L0054_MMVD
      if (mmvdList != 0 && mrgCandIdx != -1)
        mrgCandIdxCPR++;
#endif
    }
#endif
    mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miLeft.mv[0], miLeft.refIdx[0]);	//运动信息加入merge候选列表

    if (slice.isInterB())
    {
      mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miLeft.mv[1], miLeft.refIdx[1]);
    }
#if JVET_L0293_CPR && JVET_L0054_MMVD
    if (mrgCandIdxCPR == cnt && canFastExit)
#else
    if( mrgCandIdx == cnt && canFastExit )
#endif
    {
      return;
    }

    cnt++;
  }

  // early termination
  if (cnt == maxNumMergeCand)	//若merge候选列表已满,return
  {
    return;
  }


  // above					//上侧的pu运动信息,处理方法与上面相同
  const PredictionUnit *puAbove = cs.getPURestricted( posRT.offset( 0, -1 ), pu, pu.chType );

  bool isAvailableB1 = puAbove && isDiffMER( pu, *puAbove ) && pu.cu != puAbove->cu && CU::isInter( *puAbove->cu );

  if( isAvailableB1 )
  {
    miAbove = puAbove->getMotionInfo( posRT.offset( 0, -1 ) );

    if( !isAvailableA1 || ( miAbove != miLeft ) )
    {
#if !JVET_L0090_PAIR_AVG
      isCandInter[cnt] = true;
#endif

      // get Inter Dir
      mrgCtx.interDirNeighbours[cnt] = miAbove.interDir;
      // get Mv from Above
#if JVET_L0646_GBI
      mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAbove->cu->GBiIdx : GBI_DEFAULT;
#endif
#if JVET_L0293_CPR
      if (puAbove->cu->cpr)
      {
        mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_CPR;
#if !JVET_L0369_SUBBLOCK_MERGE
        cntCPR++;

#endif
#if JVET_L0293_CPR && JVET_L0054_MMVD
        if (mmvdList != 0 && mrgCandIdx != -1)
          mrgCandIdxCPR++;
#endif
      }
#endif
	    mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miAbove.mv[0], miAbove.refIdx[0] );

      if( slice.isInterB() )
      {
        mrgCtx.mvFieldNeighbours[( cnt << 1 ) + 1].setMvField( miAbove.mv[1], miAbove.refIdx[1] );
      }
#if JVET_L0293_CPR && JVET_L0054_MMVD
      if (mrgCandIdxCPR == cnt && canFastExit)
#else
      if( mrgCandIdx == cnt && canFastExit )
#endif
      {
        return;
      }

      cnt++;
    }
  }

  // early termination
  if( cnt == maxNumMergeCand )
  {
    return;
  }

  // above right				//右上侧pu运动信息,处理方法与上面相同
  const PredictionUnit *puAboveRight = cs.getPURestricted( posRT.offset( 1, -1 ), pu, pu.chType );

  bool isAvailableB0 = puAboveRight && isDiffMER( pu, *puAboveRight ) && CU::isInter( *puAboveRight->cu );

  if( isAvailableB0 )
  {
    miAboveRight = puAboveRight->getMotionInfo( posRT.offset( 1, -1 ) );

#if HM_JEM_MERGE_CANDS
    if( ( !isAvailableB1 || ( miAbove != miAboveRight ) ) && ( !isAvailableA1 || ( miLeft != miAboveRight ) ) )
#else
    if( !isAvailableB1 || ( miAbove != miAboveRight ) )
#endif
    {
#if !JVET_L0090_PAIR_AVG
      isCandInter[cnt] = true;
#endif

      // get Inter Dir
      mrgCtx.interDirNeighbours[cnt] = miAboveRight.interDir;
      // get Mv from Above-right
#if JVET_L0646_GBI
      mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAboveRight->cu->GBiIdx : GBI_DEFAULT;
#endif
#if JVET_L0293_CPR
      if (puAboveRight->cu->cpr)
      {
        mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_CPR;
#if !JVET_L0369_SUBBLOCK_MERGE
        cntCPR++;

#endif
#if JVET_L0293_CPR && JVET_L0054_MMVD
        if (mmvdList != 0 && mrgCandIdx != -1)
          mrgCandIdxCPR++;
#endif
      }
#endif
	    mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miAboveRight.mv[0], miAboveRight.refIdx[0] );

      if( slice.isInterB() )
      {
        mrgCtx.mvFieldNeighbours[( cnt << 1 ) + 1].setMvField( miAboveRight.mv[1], miAboveRight.refIdx[1] );
      }

#if JVET_L0293_CPR && JVET_L0054_MMVD
      if (mrgCandIdxCPR == cnt && canFastExit)
#else
      if( mrgCandIdx == cnt && canFastExit )
#endif
      {
        return;
      }

      cnt++;
    }
  }
  // early termination
  if( cnt == maxNumMergeCand )
  {
    return;
  }

  //left bottom					//左下侧pu运动信息,处理方法与上面相同
  const PredictionUnit *puLeftBottom = cs.getPURestricted( posLB.offset( -1, 1 ), pu, pu.chType );

  bool isAvailableA0 = puLeftBottom && isDiffMER( pu, *puLeftBottom ) && CU::isInter( *puLeftBottom->cu );

  if( isAvailableA0 )
  {
    miBelowLeft = puLeftBottom->getMotionInfo( posLB.offset( -1, 1 ) );

#if HM_JEM_MERGE_CANDS
    if( ( !isAvailableA1 || ( miBelowLeft != miLeft ) ) && ( !isAvailableB1 || ( miBelowLeft != miAbove ) ) && ( !isAvailableB0 || ( miBelowLeft != miAboveRight ) ) )
#else
    if( !isAvailableA1 || ( miBelowLeft != miLeft ) )
#endif
    {
#if !JVET_L0090_PAIR_AVG
      isCandInter[cnt] = true;
#endif

      // get Inter Dir
      mrgCtx.interDirNeighbours[cnt] = miBelowLeft.interDir;
#if JVET_L0646_GBI
      mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puLeftBottom->cu->GBiIdx : GBI_DEFAULT;
#endif
      // get Mv from Bottom-Left
#if JVET_L0293_CPR
      if (puLeftBottom->cu->cpr)
      {
        mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_CPR;
#if !JVET_L0369_SUBBLOCK_MERGE
        cntCPR++;

#endif
#if JVET_L0293_CPR && JVET_L0054_MMVD
        if (mmvdList != 0 && mrgCandIdx != -1)
          mrgCandIdxCPR++;
#endif
      }
#endif
      mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miBelowLeft.mv[0], miBelowLeft.refIdx[0] );

      if( slice.isInterB() )
      {
        mrgCtx.mvFieldNeighbours[( cnt << 1 ) + 1].setMvField( miBelowLeft.mv[1], miBelowLeft.refIdx[1] );
      }

#if JVET_L0293_CPR && JVET_L0054_MMVD
      if (mrgCandIdxCPR == cnt && canFastExit)
#else
      if( mrgCandIdx == cnt && canFastExit )
#endif
      {
        return;
      }

      cnt++;
    }
  }
  // early termination
  if( cnt == maxNumMergeCand )
  {
    return;
  }

  // above left
#if JVET_L0369_SUBBLOCK_MERGE
  if ( cnt < 4 )				//如果4个位置没有获得满4个运动信息,那么merge候选列表加入左上侧pu的运动信息
#else
  if( cnt < ( enableSubPuMvp ? 6 : 4 ) )
#endif
  {
    const PredictionUnit *puAboveLeft = cs.getPURestricted( posLT.offset( -1, -1 ), pu, pu.chType );

    bool isAvailableB2 = puAboveLeft && isDiffMER( pu, *puAboveLeft ) && CU::isInter( *puAboveLeft->cu );

    if( isAvailableB2 )
    {
      miAboveLeft = puAboveLeft->getMotionInfo( posLT.offset( -1, -1 ) );

#if HM_JEM_MERGE_CANDS
      if( ( !isAvailableA1 || ( miLeft != miAboveLeft ) ) && ( !isAvailableB1 || ( miAbove != miAboveLeft ) ) && ( !isAvailableA0 || ( miBelowLeft != miAboveLeft ) ) && ( !isAvailableB0 || ( miAboveRight != miAboveLeft ) ) )
#else
      if( ( !isAvailableA1 || ( miLeft != miAboveLeft ) ) && ( !isAvailableB1 || ( miAbove != miAboveLeft ) ) )
#endif
      {
#if !JVET_L0090_PAIR_AVG
        isCandInter[cnt] = true;
#endif

        // get Inter Dir
        mrgCtx.interDirNeighbours[cnt] = miAboveLeft.interDir;
#if JVET_L0646_GBI
        mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAboveLeft->cu->GBiIdx : GBI_DEFAULT;
#endif
        // get Mv from Above-Left
#if JVET_L0293_CPR
        if (puAboveLeft->cu->cpr)
        {
          mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_CPR;
#if !JVET_L0369_SUBBLOCK_MERGE
          cntCPR++;

#endif
#if JVET_L0293_CPR && JVET_L0054_MMVD
          if (mmvdList != 0 && mrgCandIdx != -1)
            mrgCandIdxCPR++;
#endif
        }
#endif
        mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miAboveLeft.mv[0], miAboveLeft.refIdx[0] );

        if( slice.isInterB() )
        {
          mrgCtx.mvFieldNeighbours[( cnt << 1 ) + 1].setMvField( miAboveLeft.mv[1], miAboveLeft.refIdx[1] );
        }

#if JVET_L0293_CPR && JVET_L0054_MMVD
        if (mrgCandIdxCPR == cnt && canFastExit)
#else
        if( mrgCandIdx == cnt && canFastExit )
#endif
        {
          return;
        }

        cnt++;
      }
    }
  }
  // early termination
  if (cnt == maxNumMergeCand)
  {
    return;
  }

  if (slice.getEnableTMVPFlag())			//merge候选列表加入时域候选TMVP
  {
    //>> MTK colocated-RightBottom
    // offset the pos to be sure to "point" to the same position the uiAbsPartIdx would've pointed to
    Position posRB = pu.Y().bottomRight().offset(-3, -3);

    const PreCalcValues& pcv = *cs.pcv;

    Position posC0;
    Position posC1 = pu.Y().center();
    bool C0Avail = false;

    if (((posRB.x + pcv.minCUWidth) < pcv.lumaWidth) && ((posRB.y + pcv.minCUHeight) < pcv.lumaHeight))
    {
      {
        Position posInCtu( posRB.x & pcv.maxCUWidthMask, posRB.y & pcv.maxCUHeightMask );

        if( ( posInCtu.x + 4 < pcv.maxCUWidth ) &&           // is not at the last column of CTU
            ( posInCtu.y + 4 < pcv.maxCUHeight ) )           // is not at the last row    of CTU
        {
          posC0 = posRB.offset( 4, 4 );
          C0Avail = true;
        }
        else if( posInCtu.x + 4 < pcv.maxCUWidth )           // is not at the last column of CTU But is last row of CTU
        {
          posC0 = posRB.offset( 4, 4 );
          // in the reference the CTU address is not set - thus probably resulting in no using this C0 possibility
        }
        else if( posInCtu.y + 4 < pcv.maxCUHeight )          // is not at the last row of CTU But is last column of CTU
        {
          posC0 = posRB.offset( 4, 4 );
          C0Avail = true;
        }
        else //is the right bottom corner of CTU
        {
          posC0 = posRB.offset( 4, 4 );
          // same as for last column but not last row
        }
      }
    }

    Mv        cColMv;
    int       iRefIdx     = 0;
    int       dir         = 0;
    unsigned  uiArrayAddr = cnt;		//getColocatedMVP获取posC0和posC1位置的时域MV,存入cColMv,L0前向mv
    bool      bExistMV    = ( C0Avail && getColocatedMVP(pu, REF_PIC_LIST_0, posC0, cColMv, iRefIdx ) )
                                      || getColocatedMVP(pu, REF_PIC_LIST_0, posC1, cColMv, iRefIdx );

    if (bExistMV)
    {
      dir     |= 1;
      mrgCtx.mvFieldNeighbours[2 * uiArrayAddr].setMvField(cColMv, iRefIdx);
    }

    if (slice.isInterB())
    {
      bExistMV = ( C0Avail && getColocatedMVP(pu, REF_PIC_LIST_1, posC0, cColMv, iRefIdx ) )	//B帧的反向mv
                           || getColocatedMVP(pu, REF_PIC_LIST_1, posC1, cColMv, iRefIdx );
      if (bExistMV)
      {
        dir     |= 2;
        mrgCtx.mvFieldNeighbours[2 * uiArrayAddr + 1].setMvField(cColMv, iRefIdx);
      }
    }

    if( dir != 0 )			//dir不为0,即获得到了TMVP
    {
      bool addTMvp = true;

      if( addTMvp )			//TMVP运动信息加入到merge列表中
      {
        mrgCtx.interDirNeighbours[uiArrayAddr] = dir;
#if !JVET_L0090_PAIR_AVG
        isCandInter              [uiArrayAddr] = true;
#endif
#if JVET_L0646_GBI
        mrgCtx.GBiIdx[uiArrayAddr] = GBI_DEFAULT;
#endif
#if JVET_L0293_CPR && JVET_L0054_MMVD
        if (mrgCandIdxCPR == cnt && canFastExit)
#else
        if( mrgCandIdx == cnt && canFastExit )
#endif
        {
          return;
        }

        cnt++;
      }
    }
  }

  // early termination
  if (cnt == maxNumMergeCand)
  {
    return;
  }

#if JVET_L0266_HMVP						//HMVP   同一行ctu已编码cu的mvp
  int maxNumMergeCandMin1 = maxNumMergeCand - 1;
  if (cnt != maxNumMergeCandMin1)		//HMVP最多补到MAX-1
  {
#if JVET_L0369_SUBBLOCK_MERGE
    bool isAvailableSubPu = false;
    unsigned subPuMvpPos = 0;
#endif
#if JVET_L0090_PAIR_AVG
    bool bFound = addMergeHMVPCand(slice, mrgCtx, canFastExit
#if JVET_L0293_CPR && JVET_L0054_MMVD
      , (mmvdList != 0 && mrgCandIdx != -1) ? (const int) mrgCandIdxCPR : mrgCandIdx
#else
      , mrgCandIdx
#endif
      , maxNumMergeCandMin1, cnt, cnt, isAvailableSubPu, subPuMvpPos
#if JVET_L0293_CPR && JVET_L0054_MMVD
      , mmvdList
#endif
    );
#else
    bool bFound = addMergeHMVPCand(slice, mrgCtx, isCandInter, canFastExit
#if JVET_L0293_CPR
      , (mmvdList != 0 && mrgCandIdx != -1) ? (const int)mrgCandIdxCPR : mrgCandIdx
#else
      , mrgCandIdx
#endif
      , maxNumMergeCandMin1, cnt, cnt, isAvailableSubPu, subPuMvpPos
#if JVET_L0293_CPR && JVET_L0054_MMVD
      , mmvdList
#endif
    );
#endif
    if (bFound)
    {
      return;
    }
  }
#endif

#if JVET_L0090_PAIR_AVG				//平均MVP
  // pairwise-average candidates	//PAIR_AVG的处理过程和L1002文档中所写一样
  {
    const int cutoff = std::min( cnt, 4 );
    const int end = cutoff * (cutoff - 1) / 2;
    constexpr int PRIORITY_LIST0[] = { 0, 0, 1, 0, 1, 2 };		//预定义的平均MVP对
    constexpr int PRIORITY_LIST1[] = { 1, 2, 2, 3, 3, 3 };

    for( int idx = 0; idx < end && cnt != maxNumMergeCand; idx++ )
    {
      const int i = PRIORITY_LIST0[idx];
      const int j = PRIORITY_LIST1[idx];

      mrgCtx.mvFieldNeighbours[cnt * 2].setMvField( Mv( 0, 0 ), NOT_VALID );
      mrgCtx.mvFieldNeighbours[cnt * 2 + 1].setMvField( Mv( 0, 0 ), NOT_VALID );
      // calculate average MV for L0 and L1 seperately
      unsigned char interDir = 0;
#if JVET_L0293_CPR

      // skip when one is BV and one is MV
      if (mrgCtx.mrgTypeNeighbours[i] != mrgCtx.mrgTypeNeighbours[j] && pu.cs->sps->getSpsNext().getCPRMode())
      {
        continue;
      }
#endif
      for( int refListId = 0; refListId < (slice.isInterB() ? 2 : 1); refListId++ )
      {
        const short refIdxI = mrgCtx.mvFieldNeighbours[i * 2 + refListId].refIdx;
        const short refIdxJ = mrgCtx.mvFieldNeighbours[j * 2 + refListId].refIdx;

        // both MVs are invalid, skip
        if( (refIdxI == NOT_VALID) && (refIdxJ == NOT_VALID) )
        {
          continue;
        }

        interDir += 1 << refListId;
        // both MVs are valid, average these two MVs
        if( (refIdxI != NOT_VALID) && (refIdxJ != NOT_VALID) )		//均可用时取平均加入merge列表
        {
          const Mv& MvI = mrgCtx.mvFieldNeighbours[i * 2 + refListId].mv;
          const Mv& MvJ = mrgCtx.mvFieldNeighbours[j * 2 + refListId].mv;

          // average two MVs
          Mv avgMv = MvI;
#if !REMOVE_MV_ADAPT_PREC
          if( pu.cs->sps->getSpsNext().getUseHighPrecMv() )
          {
            avgMv.setHighPrec();
          }
#endif
          avgMv += MvJ;
          avgMv.setHor( avgMv.getHor() / 2 );
          avgMv.setVer( avgMv.getVer() / 2 );
#if JVET_L0293_CPR

          if (mrgCtx.mrgTypeNeighbours[i] == MRG_TYPE_CPR && mrgCtx.mrgTypeNeighbours[j] == MRG_TYPE_CPR && pu.cs->sps->getSpsNext().getCPRMode())
          {
             mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_CPR;
             avgMv.setHor((avgMv.getHor() / 16) << 4);
             avgMv.setVer((avgMv.getVer() / 16) << 4);
          }
#endif

          mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField( avgMv, refIdxI );
        }
        // only one MV is valid, take the only one MV
        else if( refIdxI != NOT_VALID )
        {
          Mv singleMv = mrgCtx.mvFieldNeighbours[i * 2 + refListId].mv;
#if !REMOVE_MV_ADAPT_PREC
          if( pu.cs->sps->getSpsNext().getUseHighPrecMv() )
          {
            singleMv.setHighPrec();
          }
#endif
          mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField( singleMv, refIdxI );
        }
        else if( refIdxJ != NOT_VALID )
        {
          Mv singleMv = mrgCtx.mvFieldNeighbours[j * 2 + refListId].mv;
#if !REMOVE_MV_ADAPT_PREC
          if( pu.cs->sps->getSpsNext().getUseHighPrecMv() )
          {
            singleMv.setHighPrec();
          }
#endif
          mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField( singleMv, refIdxJ );
        }
      }

      mrgCtx.interDirNeighbours[cnt] = interDir;
      if( interDir > 0 )
      {
        cnt++;
      }
    }

    // early termination
    if( cnt == maxNumMergeCand )
    {
      return;
    }
  }
#endif

  uint32_t uiArrayAddr = cnt;

  int iNumRefIdx = slice.isInterB() ? std::min(slice.getNumRefIdx(REF_PIC_LIST_0), slice.getNumRefIdx(REF_PIC_LIST_1)) : slice.getNumRefIdx(REF_PIC_LIST_0);

  int r = 0;
  int refcnt = 0;
  while (uiArrayAddr < maxNumMergeCand)				//补0
  {
#if !JVET_L0090_PAIR_AVG
    isCandInter               [uiArrayAddr     ] = true;
#endif
    mrgCtx.interDirNeighbours [uiArrayAddr     ] = 1;
#if JVET_L0646_GBI
    mrgCtx.GBiIdx             [uiArrayAddr     ] = GBI_DEFAULT;
#endif
    mrgCtx.mvFieldNeighbours  [uiArrayAddr << 1].setMvField(Mv(0, 0), r);

    if (slice.isInterB())
    {
      mrgCtx.interDirNeighbours [ uiArrayAddr          ] = 3;
      mrgCtx.mvFieldNeighbours  [(uiArrayAddr << 1) + 1].setMvField(Mv(0, 0), r);
    }

#if JVET_L0293_CPR
    if ( mrgCtx.interDirNeighbours[uiArrayAddr] == 1 && pu.cs->slice->getRefPic(REF_PIC_LIST_0, mrgCtx.mvFieldNeighbours[uiArrayAddr << 1].refIdx)->getPOC() == pu.cs->slice->getPOC())
    {
      mrgCtx.mrgTypeNeighbours[uiArrayAddr] = MRG_TYPE_CPR;
    }
#endif

    uiArrayAddr++;

    if (refcnt == iNumRefIdx - 1)
    {
      r = 0;
    }
    else
    {
      ++r;
      ++refcnt;
    }
  }
  mrgCtx.numValidMergeCand = uiArrayAddr;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值