Skip to content
Snippets Groups Projects
UnitTools.cpp 186 KiB
Newer Older
  • Learn to ignore specific revisions
  • Li's avatar
    Li committed
            int offset0 = (ui * 2) + mergeCandList.interDirNeighbours[ui] - 1;
            int offset1 = (mergeCandIndex * 2) + mergeCandList.interDirNeighbours[ui] - 1;
    
            if (mergeCandList.mvFieldNeighbours[offset0].refIdx == mergeCandList.mvFieldNeighbours[offset1].refIdx &&
    
                mergeCandList.mvFieldNeighbours[offset0].mv == mergeCandList.mvFieldNeighbours[offset1].mv
    
    #if JVET_L0090_PAIR_AVG
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
    bool PU::addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool canFastExit, const int& mrgCandIdx, const uint32_t maxNumMergeCandMin1, int &cnt, const int prevCnt, bool isAvailableSubPu, unsigned subPuMvpPos
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      , int mmvdList
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
      , bool ibcFlag
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    #if JVET_M0170_MRG_SHARELIST
      , bool isShared
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    )
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
    bool PU::addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool isCandInter[MRG_MAX_NUM_CANDS], bool canFastExit, const int& mrgCandIdx, const uint32_t maxNumMergeCandMin1, int &cnt, const int prevCnt, bool isAvailableSubPu, unsigned subPuMvpPos
      , int mmvdList
    )
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Yu Han's avatar
    Yu Han committed
      int mrgCandIdxIBC = mrgCandIdx;
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
      MotionInfo miNeighbor;
      bool hasPruned[MRG_MAX_NUM_CANDS];
    
    Li's avatar
    Li committed
      memset(hasPruned, 0, MRG_MAX_NUM_CANDS * sizeof(bool));
    
      if (isAvailableSubPu)
      {
        hasPruned[subPuMvpPos] = true;
      }
    
    #if JVET_M0170_MRG_SHARELIST
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
      int num_avai_candInLUT = ibcFlag ? (isShared ? slice.getAvailableLUTBkupIBCMrgNum() : slice.getAvailableLUTIBCMrgNum()) : (isShared ? slice.getAvailableLUTBkupMrgNum() : slice.getAvailableLUTMrgNum());
    
    Yu Han's avatar
    Yu Han committed
      int offset = ibcFlag ? MAX_NUM_HMVP_CANDS : 0;
    
    Yu Han's avatar
    Yu Han committed
    #else
    
      int num_avai_candInLUT = (isShared ? slice.getAvailableLUTBkupMrgNum() : slice.getAvailableLUTMrgNum());
    
    Yu Han's avatar
    Yu Han committed
    #endif
    #else
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
      int num_avai_candInLUT = ibcFlag ? slice.getAvailableLUTIBCMrgNum() : slice.getAvailableLUTMrgNum();
      int offset = ibcFlag ? MAX_NUM_HMVP_CANDS : 0;
    
      int num_avai_candInLUT = slice.getAvailableLUTMrgNum();
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
      for (int mrgIdx = 1; mrgIdx <= num_avai_candInLUT; mrgIdx++)
      {
    
    #if JVET_M0170_MRG_SHARELIST
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
        miNeighbor = ibcFlag ? (isShared ? slice.getMotionInfoFromLUTBkup(num_avai_candInLUT - mrgIdx + offset) : slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx + offset))
          : (isShared ? slice.getMotionInfoFromLUTBkup(num_avai_candInLUT - mrgIdx) : slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx));
    
    Yu Han's avatar
    Yu Han committed
    #else
    
        miNeighbor = isShared ? slice.getMotionInfoFromLUTBkup(num_avai_candInLUT - mrgIdx) : slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx);
    
    Yu Han's avatar
    Yu Han committed
    #endif
    #else
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
        miNeighbor = slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx + offset);
    
        miNeighbor = slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx);
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
        mrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir;
        mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]);
        if (slice.isInterB())
        {
          mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]);
        }
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0126_HMVP_MRG_PRUNING
        if (mrgIdx > 2 || !xCheckSimilarMotion(cnt, prevCnt, mrgCtx, hasPruned))
    #else
    
        if (!xCheckSimilarMotion(cnt, prevCnt, mrgCtx, hasPruned))
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
        {
    #if !JVET_L0090_PAIR_AVG
          isCandInter[cnt] = true;
    #endif
    
    #if JVET_M0264_HMVP_WITH_GBIIDX
          mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? miNeighbor.GBiIdx : GBI_DEFAULT;
    #endif
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          if (miNeighbor.interDir == 1 && slice.getRefPic(REF_PIC_LIST_0, miNeighbor.refIdx[0])->getPOC() == slice.getPOC())
          {
    
    Yu Han's avatar
    Yu Han committed
            mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
            if(mmvdList != 0 && mrgCandIdx != -1)
    
    Yu Han's avatar
    Yu Han committed
              mrgCandIdxIBC++;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          }
    
    Yu Han's avatar
    Yu Han committed
          if (mrgCandIdxIBC == cnt && canFastExit)
    
    Yu Han's avatar
    Yu Han committed
    #else
          if (mrgCandIdx == cnt && canFastExit)
    #endif
    
          {
            return true;
          }
          cnt ++;
          if (cnt  == maxNumMergeCandMin1)
          {
            break;
          }
        }
      }
      return false;
    }
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
    void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const int& mrgCandIdx)
    {
      const CodingStructure &cs = *pu.cs;
      const Slice &slice = *pu.cs->slice;
      const uint32_t maxNumMergeCand = slice.getMaxNumMergeCand();
      const bool canFastExit = pu.cs->pps->getLog2ParallelMergeLevelMinus2() == 0;
    
      for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui)
      {
        mrgCtx.GBiIdx[ui] = GBI_DEFAULT;
        mrgCtx.interDirNeighbours[ui] = 0;
        mrgCtx.mrgTypeNeighbours[ui] = MRG_TYPE_IBC;
    
    Yu Han's avatar
    Yu Han committed
        mrgCtx.mvFieldNeighbours[ui * 2].refIdx = NOT_VALID;
        mrgCtx.mvFieldNeighbours[ui * 2 + 1].refIdx = NOT_VALID;
    
    Yu Han's avatar
    Yu Han committed
      }
    
      mrgCtx.numValidMergeCand = maxNumMergeCand;
      // compute the location of the current PU
    
      int cnt = 0;
    
    
    #if JVET_M0170_MRG_SHARELIST
      const Position posLT = pu.shareParentPos;
      const Position posRT = pu.shareParentPos.offset(pu.shareParentSize.width - 1, 0);
      const Position posLB = pu.shareParentPos.offset(0, pu.shareParentSize.height - 1);
    #else
    
    Yu Han's avatar
    Yu Han committed
      const Position posLT = pu.Y().topLeft();
      const Position posRT = pu.Y().topRight();
      const Position posLB = pu.Y().bottomLeft();
    
    Yu Han's avatar
    Yu Han committed
    
      MotionInfo miAbove, miLeft, miAboveLeft, miAboveRight, miBelowLeft;
    
      //left
      const PredictionUnit* puLeft = cs.getPURestricted(posLB.offset(-1, 0), pu, pu.chType);
      const bool isAvailableA1 = puLeft && isDiffMER(pu, *puLeft) && pu.cu != puLeft->cu && CU::isIBC(*puLeft->cu);
      if (isAvailableA1)
      {
        miLeft = puLeft->getMotionInfo(posLB.offset(-1, 0));
    
        // get Inter Dir
        mrgCtx.interDirNeighbours[cnt] = miLeft.interDir;
        // get Mv from Left
        mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miLeft.mv[0], miLeft.refIdx[0]);
        if (mrgCandIdx == cnt && canFastExit)
        {
          return;
        }
        cnt++;
      }
    
      // early termination
      if (cnt == maxNumMergeCand)
      {
        return;
      }
    
    
      // above
      const PredictionUnit *puAbove = cs.getPURestricted(posRT.offset(0, -1), pu, pu.chType);
      bool isAvailableB1 = puAbove && isDiffMER(pu, *puAbove) && pu.cu != puAbove->cu && CU::isIBC(*puAbove->cu);
      if (isAvailableB1)
      {
        miAbove = puAbove->getMotionInfo(posRT.offset(0, -1));
    
        if (!isAvailableA1 || (miAbove != miLeft))
        {
          // get Inter Dir
          mrgCtx.interDirNeighbours[cnt] = miAbove.interDir;
          // get Mv from Above
          mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAbove.mv[0], miAbove.refIdx[0]);
          if (mrgCandIdx == cnt && canFastExit)
          {
            return;
          }
    
          cnt++;
        }
      }
    
      // early termination
      if (cnt == maxNumMergeCand)
      {
        return;
      }
    
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0126_HMVP_MRG_PRUNING
      int spatialCandPos = cnt;
    #endif
    
    
    Yu Han's avatar
    Yu Han committed
      // above right
      const PredictionUnit *puAboveRight = cs.getPURestricted(posRT.offset(1, -1), pu, pu.chType);
      bool isAvailableB0 = puAboveRight && isDiffMER(pu, *puAboveRight) && CU::isIBC(*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
        {
          // get Inter Dir
          mrgCtx.interDirNeighbours[cnt] = miAboveRight.interDir;
          // get Mv from Above-right
          mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAboveRight.mv[0], miAboveRight.refIdx[0]);
    
          if (mrgCandIdx == cnt && canFastExit)
          {
            return;
          }
    
          cnt++;
        }
      }
      // early termination
      if (cnt == maxNumMergeCand)
      {
        return;
      }
    
      //left bottom
      const PredictionUnit *puLeftBottom = cs.getPURestricted(posLB.offset(-1, 1), pu, pu.chType);
      bool isAvailableA0 = puLeftBottom && isDiffMER(pu, *puLeftBottom) && CU::isIBC(*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
        {
          // get Inter Dir
          mrgCtx.interDirNeighbours[cnt] = miBelowLeft.interDir;
          mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miBelowLeft.mv[0], miBelowLeft.refIdx[0]);
          if (mrgCandIdx == cnt && canFastExit)
          {
            return;
          }
    
          cnt++;
        }
      }
      // early termination
      if (cnt == maxNumMergeCand)
      {
        return;
      }
    
      // above left
      if (cnt < 4)
      {
        const PredictionUnit *puAboveLeft = cs.getPURestricted(posLT.offset(-1, -1), pu, pu.chType);
        bool isAvailableB2 = puAboveLeft && isDiffMER(pu, *puAboveLeft) && CU::isIBC(*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
          {
            // get Inter Dir
            mrgCtx.interDirNeighbours[cnt] = miAboveLeft.interDir;
            mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAboveLeft.mv[0], miAboveLeft.refIdx[0]);
            if (mrgCandIdx == cnt && canFastExit)
            {
              return;
            }
    
            cnt++;
          }
        }
      }
      // early termination
      if (cnt == maxNumMergeCand)
      {
        return;
      }
    
      int maxNumMergeCandMin1 = maxNumMergeCand - 1;
      if (cnt != maxNumMergeCandMin1)
      {
        bool isAvailableSubPu = false;
        unsigned subPuMvpPos = 0;
    
    
    #if JVET_M0170_MRG_SHARELIST
        bool  isShared = ((pu.Y().lumaSize().width != pu.shareParentSize.width) || (pu.Y().lumaSize().height != pu.shareParentSize.height));
    #endif
    
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_L0090_PAIR_AVG
        bool bFound = addMergeHMVPCand(slice, mrgCtx, canFastExit
          , mrgCandIdx
    
    Yu Han's avatar
    Yu Han committed
          , maxNumMergeCandMin1, cnt
    #if JVET_M0126_HMVP_MRG_PRUNING
          , spatialCandPos
    #else
          , cnt
    #endif
          , isAvailableSubPu, subPuMvpPos
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
          , true
    #endif
    #if JVET_M0170_MRG_SHARELIST
    
    Yu Han's avatar
    Yu Han committed
    #endif
        );
    #else
        bool bFound = addMergeHMVPCand(slice, mrgCtx, isCandInter, canFastExit
          , mrgCandIdx
          , maxNumMergeCandMin1, cnt, cnt, isAvailableSubPu, subPuMvpPos
        );
    #endif
        if (bFound)
        {
          return;
        }
      }
    
    #if JVET_L0090_PAIR_AVG
      // pairwise-average candidates
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0193_PAIR_AVG_REDUCTION==0
    
    Yu Han's avatar
    Yu Han committed
        const int cutoff = std::min(cnt, 4);
        const int end = cutoff * (cutoff - 1) / 2;
        constexpr int PRIORITY_LIST0[] = { 0, 0, 1, 0, 1, 2 };
        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];
    
    Yu Han's avatar
    Yu Han committed
    #else
        if (cnt>1 && cnt <maxNumMergeCand)
        {
    #endif
           mrgCtx.mvFieldNeighbours[cnt * 2    ].setMvField(Mv(0, 0), NOT_VALID);
           mrgCtx.mvFieldNeighbours[cnt * 2 + 1].setMvField(Mv(0, 0), NOT_VALID);
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0193_PAIR_AVG_REDUCTION
           const Mv& MvI = mrgCtx.mvFieldNeighbours[0 * 2].mv;
           const Mv& MvJ = mrgCtx.mvFieldNeighbours[1 * 2].mv;
    #else
           const Mv& MvI = mrgCtx.mvFieldNeighbours[i * 2 ].mv;
           const Mv& MvJ = mrgCtx.mvFieldNeighbours[j * 2 ].mv;
    #endif
           // average two MVs
           Mv avgMv = MvI;
    
    Yu Han's avatar
    Yu Han committed
           avgMv += MvJ;
           mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC;
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0265_MV_ROUNDING_CLEANUP
    
    Yu Han's avatar
    Yu Han committed
           roundAffineMv(avgMv.hor, avgMv.ver, 1);
    
    Yu Han's avatar
    Yu Han committed
           avgMv.roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT);
    
    Yu Han's avatar
    Yu Han committed
    #else
    
    Yu Han's avatar
    Yu Han committed
           avgMv.setHor(avgMv.getHor() / 2);
           avgMv.setVer(avgMv.getVer() / 2);
    
    Yu Han's avatar
    Yu Han committed
           avgMv.setHor((avgMv.getHor() / 16) << 4);
           avgMv.setVer((avgMv.getVer() / 16) << 4);
    
    Yu Han's avatar
    Yu Han committed
          mrgCtx.mvFieldNeighbours[cnt * 2 ].setMvField(avgMv, MAX_NUM_REF);
          mrgCtx.interDirNeighbours[cnt] = 1;
          cnt++;
    
    Yu Han's avatar
    Yu Han committed
        }
    
        // early termination
        if (cnt == maxNumMergeCand)
        {
          return;
        }
    #endif
    
      mrgCtx.numValidMergeCand = cnt;
    
    }
    #endif
    
    
    void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
    
                                     int mmvdList,
                                     const int& mrgCandIdx )
    
    {
      const CodingStructure &cs  = *pu.cs;
      const Slice &slice         = *pu.cs->slice;
      const uint32_t maxNumMergeCand = slice.getMaxNumMergeCand();
      const bool canFastExit     = pu.cs->pps->getLog2ParallelMergeLevelMinus2() == 0;
    
    
    #if !JVET_L0090_PAIR_AVG
      // this variable is unused if remove HEVC combined candidates
    
    Yu-Chi Su's avatar
    Yu-Chi Su committed
    #endif
    
        mrgCtx.GBiIdx[ui] = GBI_DEFAULT;
    
        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;
      // compute the location of the current PU
    
      int cnt = 0;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Yu Han's avatar
    Yu Han committed
      int mrgCandIdxIBC = mrgCandIdx;
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
    
    #if JVET_M0170_MRG_SHARELIST
      const Position posLT = pu.shareParentPos;
      const Position posRT = pu.shareParentPos.offset(pu.shareParentSize.width - 1, 0);
      const Position posLB = pu.shareParentPos.offset(0, pu.shareParentSize.height - 1);
    #else
    
      const Position posLT = pu.Y().topLeft();
      const Position posRT = pu.Y().topRight();
      const Position posLB = pu.Y().bottomLeft();
    
      MotionInfo miAbove, miLeft, miAboveLeft, miAboveRight, miBelowLeft;
    
      //left
      const PredictionUnit* puLeft = cs.getPURestricted( posLB.offset( -1, 0 ), pu, pu.chType );
    
      const bool isAvailableA1 = puLeft && isDiffMER( pu, *puLeft ) && pu.cu != puLeft->cu && CU::isInter( *puLeft->cu );
    
      if( isAvailableA1 )
      {
        miLeft = puLeft->getMotionInfo( posLB.offset(-1, 0) );
    
    
    
        // get Inter Dir
        mrgCtx.interDirNeighbours[cnt] = miLeft.interDir;
    
        mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puLeft->cu->GBiIdx : GBI_DEFAULT;
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Yu Han's avatar
    Yu Han committed
        if (puLeft->cu->ibc)
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        {
    
    Yu Han's avatar
    Yu Han committed
          mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          if (mmvdList != 0 && mrgCandIdx != -1)
    
    Yu Han's avatar
    Yu Han committed
            mrgCandIdxIBC++;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        }
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
        mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miLeft.mv[0], miLeft.refIdx[0]);
    
        if (slice.isInterB())
        {
          mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miLeft.mv[1], miLeft.refIdx[1]);
        }
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Yu Han's avatar
    Yu Han committed
        if (mrgCandIdxIBC == cnt && canFastExit)
    
    Yu Han's avatar
    Yu Han committed
    #else
        if (mrgCandIdx == cnt && canFastExit)
    #endif
    
        {
          return;
        }
    
        cnt++;
      }
    
      // early termination
      if (cnt == maxNumMergeCand)
      {
        return;
      }
    
    
      // above
      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 ) )
        {
    
    
          // get Inter Dir
          mrgCtx.interDirNeighbours[cnt] = miAbove.interDir;
    
          mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAbove->cu->GBiIdx : GBI_DEFAULT;
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Yu Han's avatar
    Yu Han committed
          if (puAbove->cu->ibc)
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          {
    
    Yu Han's avatar
    Yu Han committed
            mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
            if (mmvdList != 0 && mrgCandIdx != -1)
    
    Yu Han's avatar
    Yu Han committed
              mrgCandIdxIBC++;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          }
    
    Yu Han's avatar
    Yu Han committed
    #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] );
          }
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Yu Han's avatar
    Yu Han committed
          if (mrgCandIdxIBC == cnt && canFastExit)
    
    Yu Han's avatar
    Yu Han committed
    #else
          if (mrgCandIdx == cnt && canFastExit)
    #endif
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0126_HMVP_MRG_PRUNING
      int spatialCandPos = cnt;
    #endif
    
    
      // above right
      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
        {
    
    
          // get Inter Dir
          mrgCtx.interDirNeighbours[cnt] = miAboveRight.interDir;
    
          mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAboveRight->cu->GBiIdx : GBI_DEFAULT;
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Yu Han's avatar
    Yu Han committed
          if (puAboveRight->cu->ibc)
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          {
    
    Yu Han's avatar
    Yu Han committed
            mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
            if (mmvdList != 0 && mrgCandIdx != -1)
    
    Yu Han's avatar
    Yu Han committed
              mrgCandIdxIBC++;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          }
    
    Yu Han's avatar
    Yu Han committed
    #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] );
          }
    
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Yu Han's avatar
    Yu Han committed
          if (mrgCandIdxIBC == cnt && canFastExit)
    
    Yu Han's avatar
    Yu Han committed
    #else
          if (mrgCandIdx == cnt && canFastExit)
    #endif
    
          {
            return;
          }
    
          cnt++;
        }
      }
      // early termination
      if( cnt == maxNumMergeCand )
      {
        return;
      }
    
      //left bottom
      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
        {
    
    
          // get Inter Dir
          mrgCtx.interDirNeighbours[cnt] = miBelowLeft.interDir;
    
          mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puLeftBottom->cu->GBiIdx : GBI_DEFAULT;
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Yu Han's avatar
    Yu Han committed
          if (puLeftBottom->cu->ibc)
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          {
    
    Yu Han's avatar
    Yu Han committed
            mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
            if (mmvdList != 0 && mrgCandIdx != -1)
    
    Yu Han's avatar
    Yu Han committed
              mrgCandIdxIBC++;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          }
    
    Yu Han's avatar
    Yu Han committed
    #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] );
          }
    
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Yu Han's avatar
    Yu Han committed
          if (mrgCandIdxIBC == cnt && canFastExit)
    
    Yu Han's avatar
    Yu Han committed
    #else
          if (mrgCandIdx == cnt && canFastExit)
    #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
          {
    
    
            // get Inter Dir
            mrgCtx.interDirNeighbours[cnt] = miAboveLeft.interDir;
    
            mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAboveLeft->cu->GBiIdx : GBI_DEFAULT;
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Yu Han's avatar
    Yu Han committed
            if (puAboveLeft->cu->ibc)
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
            {
    
    Yu Han's avatar
    Yu Han committed
              mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
              if (mmvdList != 0 && mrgCandIdx != -1)
    
    Yu Han's avatar
    Yu Han committed
                mrgCandIdxIBC++;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
            }
    
    Yu Han's avatar
    Yu Han committed
    #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] );
            }
    
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Yu Han's avatar
    Yu Han committed
            if (mrgCandIdxIBC == cnt && canFastExit)
    
    Yu Han's avatar
    Yu Han committed
    #else
            if (mrgCandIdx == cnt && canFastExit)
    #endif
    
            {
              return;
            }
    
            cnt++;
          }
        }
      }
      // early termination
      if (cnt == maxNumMergeCand)
      {
        return;
      }
    
      if (slice.getEnableTMVPFlag())
      {
        //>> MTK colocated-RightBottom
        // offset the pos to be sure to "point" to the same position the uiAbsPartIdx would've pointed to
    
    #if JVET_M0170_MRG_SHARELIST
        Position posRB = pu.shareParentPos.offset(pu.shareParentSize.width-3, pu.shareParentSize.height - 3);
    #else
    
        Position posRB = pu.Y().bottomRight().offset(-3, -3);
    
    #if JVET_M0170_MRG_SHARELIST
        Position posC1 = pu.shareParentPos.offset((pu.shareParentSize.width/2), (pu.shareParentSize.height/2));
    #else
    
    #if JVET_M0170_MRG_SHARELIST
        bool C1Avail = (posC1.x < pcv.lumaWidth) && (posC1.y  < pcv.lumaHeight);
    #endif
    
    
        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;
        bool      bExistMV    = ( C0Avail && getColocatedMVP(pu, REF_PIC_LIST_0, posC0, cColMv, iRefIdx ) )
    
    #if JVET_M0170_MRG_SHARELIST
                                          || ( C1Avail && getColocatedMVP(pu, REF_PIC_LIST_0, posC1, cColMv, iRefIdx ));
    #else
    
                                          || 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 ) )
    
    #if JVET_M0170_MRG_SHARELIST
                               || (C1Avail &&  getColocatedMVP(pu, REF_PIC_LIST_1, posC1, cColMv, iRefIdx ) );
    #else
    
                               || getColocatedMVP(pu, REF_PIC_LIST_1, posC1, cColMv, iRefIdx );
    
          if (bExistMV)
          {
            dir     |= 2;
            mrgCtx.mvFieldNeighbours[2 * uiArrayAddr + 1].setMvField(cColMv, iRefIdx);
          }
        }
    
        if( dir != 0 )
        {
    
          for( int i = 0; i < iSpanCand; i++ )
          {
            if( mrgCtx.interDirNeighbours[  i           ] == dir &&
                mrgCtx.mvFieldNeighbours [  i << 1      ] == mrgCtx.mvFieldNeighbours[  uiArrayAddr << 1      ] &&
                mrgCtx.mvFieldNeighbours [( i << 1 ) + 1] == mrgCtx.mvFieldNeighbours[( uiArrayAddr << 1 ) + 1] )
            {
              addTMvp = false;
            }
          }
    #endif
          if( addTMvp )
          {
            mrgCtx.interDirNeighbours[uiArrayAddr] = dir;
    
            mrgCtx.GBiIdx[uiArrayAddr] = GBI_DEFAULT;
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Yu Han's avatar
    Yu Han committed
            if (mrgCandIdxIBC == cnt && canFastExit)
    
    Yu Han's avatar
    Yu Han committed
    #else
            if (mrgCandIdx == cnt && canFastExit)
    #endif
    
      int maxNumMergeCandMin1 = maxNumMergeCand - 1;
      if (cnt != maxNumMergeCandMin1)
      {
    
        bool isAvailableSubPu = false;
        unsigned subPuMvpPos = 0;
    
    #if JVET_L0090_PAIR_AVG
    
    #if JVET_M0170_MRG_SHARELIST
        bool  isShared = ((pu.Y().lumaSize().width != pu.shareParentSize.width) || (pu.Y().lumaSize().height != pu.shareParentSize.height));
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        bool bFound = addMergeHMVPCand(slice, mrgCtx, canFastExit
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Yu Han's avatar
    Yu Han committed
          , (mmvdList != 0 && mrgCandIdx != -1) ? (const int) mrgCandIdxIBC : mrgCandIdx
    
    Yu Han's avatar
    Yu Han committed
    #else
          , mrgCandIdx
    #endif
    
    Yu Han's avatar
    Yu Han committed
          , maxNumMergeCandMin1, cnt
    #if JVET_M0126_HMVP_MRG_PRUNING
          , spatialCandPos
    #else
          , cnt
    #endif
          , isAvailableSubPu, subPuMvpPos
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          , mmvdList
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
          , CU::isIBC(*pu.cu)
    #endif
    
    #if JVET_M0170_MRG_SHARELIST
          , isShared
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        );
    #else
        bool bFound = addMergeHMVPCand(slice, mrgCtx, isCandInter, canFastExit
    
    Yu Han's avatar
    Yu Han committed
          , (mmvdList != 0 && mrgCandIdx != -1) ? (const int)mrgCandIdxIBC : mrgCandIdx
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          , maxNumMergeCandMin1, cnt, cnt, isAvailableSubPu, subPuMvpPos
          , mmvdList
        );
    
    #if JVET_L0090_PAIR_AVG
      // pairwise-average candidates
      {
    
        const int cutoff = std::min( cnt, 4 );
        const int end = cutoff * (cutoff - 1) / 2;
        constexpr int PRIORITY_LIST0[] = { 0, 0, 1, 0, 1, 2 };
        constexpr int PRIORITY_LIST1[] = { 1, 2, 2, 3, 3, 3 };
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
        if (cnt > 1 && cnt < maxNumMergeCand)
    #else
    
        // skip when only 1 candidate is added so far or one is BV and one is MV
    
        if( cnt > 1 && cnt < maxNumMergeCand && !(mrgCtx.mrgTypeNeighbours[0] != mrgCtx.mrgTypeNeighbours[1] && pu.cs->sps->getIBCMode()))
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
        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;
    
    Yu Han's avatar
    Yu Han committed
    #if !JVET_M0193_PAIR_AVG_REDUCTION && JVET_M0483_IBC==0
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          // skip when one is BV and one is MV
    
          if (mrgCtx.mrgTypeNeighbours[i] != mrgCtx.mrgTypeNeighbours[j] && pu.cs->sps->getIBCMode())
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          {
            continue;
          }
    
          for( int refListId = 0; refListId < (slice.isInterB() ? 2 : 1); refListId++ )
          {
    
    #if JVET_M0193_PAIR_AVG_REDUCTION
            const short refIdxI = mrgCtx.mvFieldNeighbours[0 * 2 + refListId].refIdx;
            const short refIdxJ = mrgCtx.mvFieldNeighbours[1 * 2 + refListId].refIdx;
    #else
    
            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) )
            {
    
    #if JVET_M0193_PAIR_AVG_REDUCTION
              const Mv& MvI = mrgCtx.mvFieldNeighbours[0 * 2 + refListId].mv;
              const Mv& MvJ = mrgCtx.mvFieldNeighbours[1 * 2 + refListId].mv;
    #else
    
              const Mv& MvI = mrgCtx.mvFieldNeighbours[i * 2 + refListId].mv;
              const Mv& MvJ = mrgCtx.mvFieldNeighbours[j * 2 + refListId].mv;
    
    #if JVET_M0265_MV_ROUNDING_CLEANUP
              roundAffineMv(avgMv.hor, avgMv.ver, 1);
    #else
    
              avgMv.setHor( avgMv.getHor() / 2 );
              avgMv.setVer( avgMv.getVer() / 2 );
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
              if (mrgCtx.mrgTypeNeighbours[0] == MRG_TYPE_IBC && mrgCtx.mrgTypeNeighbours[1] == MRG_TYPE_IBC && pu.cs->sps->getIBCMode())
    
              if (mrgCtx.mrgTypeNeighbours[i] == MRG_TYPE_IBC && mrgCtx.mrgTypeNeighbours[j] == MRG_TYPE_IBC && pu.cs->sps->getIBCMode())
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
              {
    
    Yu Han's avatar
    Yu Han committed
                 mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
                 avgMv.setHor((avgMv.getHor() / 16) << 4);
                 avgMv.setVer((avgMv.getVer() / 16) << 4);
              }
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
              mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField( avgMv, refIdxI );
            }
            // only one MV is valid, take the only one MV
            else if( refIdxI != NOT_VALID )
            {
    
    #if JVET_M0193_PAIR_AVG_REDUCTION
              Mv singleMv = mrgCtx.mvFieldNeighbours[0 * 2 + refListId].mv;
    #else
    
              Mv singleMv = mrgCtx.mvFieldNeighbours[i * 2 + refListId].mv;
    
              mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField( singleMv, refIdxI );
            }
            else if( refIdxJ != NOT_VALID )
            {