Skip to content
Snippets Groups Projects
UnitTools.cpp 167 KiB
Newer Older
  • Learn to ignore specific revisions
  • 
      if (iColRefIdx < 0 && (slice.getCheckLDC() || bAllowMirrorMV))
      {
        eColRefPicList = RefPicList(1 - eColRefPicList);
        iColRefIdx = mi.refIdx[eColRefPicList];
    
        if (iColRefIdx < 0)
        {
          return false;
        }
      }
    
      if (iColRefIdx >= 0 && slice.getNumRefIdx(eCurrRefPicList) > 0)
      {
        iColPOC = pColSlice->getPOC();
        iColRefPOC = pColSlice->getRefPOC(eColRefPicList, iColRefIdx);
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        if (iColPOC == iColRefPOC)
          return false;
    
        ///////////////////////////////////////////////////////////////
        // Set the target reference index to 0, may be changed later //
        ///////////////////////////////////////////////////////////////
        iCurrRefPOC = slice.getRefPic(eCurrRefPicList, 0)->getPOC();
        // Scale the vector.
        cColMv = mi.mv[eColRefPicList];
    
    #if JVET_M0512_MOTION_BUFFER_COMPRESSION
        cColMv.setHor(roundMvComp(cColMv.getHor()));
        cColMv.setVer(roundMvComp(cColMv.getVer()));
    #endif
    
        //pcMvFieldSP[2*iPartition + eCurrRefPicList].getMv();
        // Assume always short-term for now
        iScale = xGetDistScaleFactor(iCurrPOC, iCurrRefPOC, iColPOC, iColRefPOC);
    
        if (iScale != 4096)
        {
    
          cColMv = cColMv.scaleMv(iScale);
        }
    
        return true;
      }
      return false;
    }
    
    
    void clipColPos(int& posX, int& posY, const PredictionUnit& pu)
    {
      Position puPos = pu.lumaPos();
    
      int log2CtuSize = g_aucLog2[pu.cs->sps->getCTUSize()];
    
      int ctuX = ((puPos.x >> log2CtuSize) << log2CtuSize);
      int ctuY = ((puPos.y >> log2CtuSize) << log2CtuSize);
    
      int horMax = std::min((int)pu.cs->sps->getPicWidthInLumaSamples() - 1, ctuX + (int)pu.cs->sps->getCTUSize() + 3);
      int horMin = std::max((int)0, ctuX);
      int verMax = std::min((int)pu.cs->sps->getPicHeightInLumaSamples() - 1, ctuY + (int)pu.cs->sps->getCTUSize() - 1);
      int verMin = std::max((int)0, ctuY);
    
    
      posX = std::min(horMax, std::max(horMin, posX));
      posY = std::min(verMax, std::max(verMin, posY));
    }
    
    bool PU::getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx& mrgCtx, bool& LICFlag, const int count
    
    Yu Han's avatar
    Yu Han committed
    #if !JVET_M0409_ATMVP_FIX && JVET_M0483_IBC==0
    
    Yu Han's avatar
    Yu Han committed
      , const int countIBC
    
    Yu Han's avatar
    Yu Han committed
    #if !JVET_M0409_ATMVP_FIX && JVET_M0483_IBC==0
    
    Yu Han's avatar
    Yu Han committed
      if (count == countIBC && pu.cs->slice->getSPS()->getSpsNext().getIBCMode())
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        return false;
    
      const Slice   &slice = *pu.cs->slice;
      const unsigned scale = 4 * std::max<int>(1, 4 * AMVP_DECIMATION_FACTOR / 4);
      const unsigned mask = ~(scale - 1);
    
      const Picture *pColPic = slice.getRefPic(RefPicList(slice.isInterB() ? 1 - slice.getColFromL0Flag() : 0), slice.getColRefIdx());
      Mv cTMv;
      RefPicList fetchRefPicList = RefPicList(slice.isInterB() ? 1 - slice.getColFromL0Flag() : 0);
    
      bool terminate = false;
      for (unsigned currRefListId = 0; currRefListId < (slice.getSliceType() == B_SLICE ? 2 : 1) && !terminate; currRefListId++)
      {
    
        if ( count )
        {
          RefPicList currRefPicList = RefPicList(slice.getCheckLDC() ? (slice.getColFromL0Flag() ? currRefListId : 1 - currRefListId) : currRefListId);
            
          if ((mrgCtx.interDirNeighbours[0] & (1 << currRefPicList)) && slice.getRefPic(currRefPicList, mrgCtx.mvFieldNeighbours[0 * 2 + currRefPicList].refIdx) == pColPic)
          {
            cTMv = mrgCtx.mvFieldNeighbours[0 * 2 + currRefPicList].mv;
            terminate = true;
            fetchRefPicList = currRefPicList;
            break;
          }
        }
    
      }
    
      ///////////////////////////////////////////////////////////////////////
      ////////          GET Initial Temporal Vector                  ////////
      ///////////////////////////////////////////////////////////////////////
    
      int mvPrec = MV_FRACTIONAL_BITS_INTERNAL;
    
    
      Mv cTempVector = cTMv;
      bool  tempLICFlag = false;
    
      // compute the location of the current PU
      Position puPos = pu.lumaPos();
      Size puSize = pu.lumaSize();
    
      int numPartLine = std::max(puSize.width >> ATMVP_SUB_BLOCK_SIZE, 1u);
      int numPartCol = std::max(puSize.height >> ATMVP_SUB_BLOCK_SIZE, 1u);
      int puHeight = numPartCol == 1 ? puSize.height : 1 << ATMVP_SUB_BLOCK_SIZE;
      int puWidth = numPartLine == 1 ? puSize.width : 1 << ATMVP_SUB_BLOCK_SIZE;
    
    
      Mv cColMv;
      // use coldir.
      bool     bBSlice = slice.isInterB();
    
      Position centerPos;
    
      bool found = false;
      cTempVector = cTMv;
    
      int tempX = cTempVector.getHor() >> mvPrec;
      int tempY = cTempVector.getVer() >> mvPrec;
    
      centerPos.x = puPos.x + (puSize.width >> 1) + tempX;
      centerPos.y = puPos.y + (puSize.height >> 1) + tempY;
    
      clipColPos(centerPos.x, centerPos.y, pu);
    
    
      centerPos = Position{ PosType(centerPos.x & mask), PosType(centerPos.y & mask) };
    
      // derivation of center motion parameters from the collocated CU
      const MotionInfo &mi = pColPic->cs->getMotionInfo(centerPos);
    
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
      if (mi.isInter && mi.isIBCmot == false)
    #else
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
      {
        for (unsigned currRefListId = 0; currRefListId < (bBSlice ? 2 : 1); currRefListId++)
        {
          RefPicList  currRefPicList = RefPicList(currRefListId);
    
          if (deriveScaledMotionTemporal(slice, centerPos, pColPic, currRefPicList, cColMv, fetchRefPicList))
          {
            // set as default, for further motion vector field spanning
            mrgCtx.mvFieldNeighbours[(count << 1) + currRefListId].setMvField(cColMv, 0);
            mrgCtx.interDirNeighbours[count] |= (1 << currRefListId);
            LICFlag = tempLICFlag;
    
            mrgCtx.GBiIdx[count] = GBI_DEFAULT;
    
            found = true;
          }
          else
          {
            mrgCtx.mvFieldNeighbours[(count << 1) + currRefListId].setMvField(Mv(), NOT_VALID);
            mrgCtx.interDirNeighbours[count] &= ~(1 << currRefListId);
          }
        }
      }
    
      if (!found)
      {
        return false;
      }
    
      int xOff = (puWidth >> 1) + tempX;
      int yOff = (puHeight >> 1) + tempY;
    
    
      MotionBuf& mb = mrgCtx.subPuMvpMiBuf;
    
      const bool isBiPred = isBipredRestriction(pu);
    
      for (int y = puPos.y; y < puPos.y + puSize.height; y += puHeight)
      {
        for (int x = puPos.x; x < puPos.x + puSize.width; x += puWidth)
        {
          Position colPos{ x + xOff, y + yOff };
    
    
          clipColPos(colPos.x, colPos.y, pu);
    
    
          colPos = Position{ PosType(colPos.x & mask), PosType(colPos.y & mask) };
    
          const MotionInfo &colMi = pColPic->cs->getMotionInfo(colPos);
    
          MotionInfo mi;
    
          mi.isInter = true;
          mi.sliceIdx = slice.getIndependentSliceIdx();
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
          mi.isIBCmot = false;
          if (colMi.isInter && colMi.isIBCmot == false)
    #else
    
    Yu Han's avatar
    Yu Han committed
          if (colMi.isInter && !((colMi.interDir == 1 || colMi.interDir == 3) && (pColPic->cs->slice->getRefPOC(REF_PIC_LIST_0, colMi.refIdx[0]) == pColPic->cs->slice->getPOC()) && pu.cs->sps->getSpsNext().getIBCMode()))
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
          {
            for (unsigned currRefListId = 0; currRefListId < (bBSlice ? 2 : 1); currRefListId++)
            {
              RefPicList currRefPicList = RefPicList(currRefListId);
              if (deriveScaledMotionTemporal(slice, colPos, pColPic, currRefPicList, cColMv, fetchRefPicList))
              {
                mi.refIdx[currRefListId] = 0;
                mi.mv[currRefListId] = cColMv;
              }
            }
            }
          else
          {
            // intra coded, in this case, no motion vector is available for list 0 or list 1, so use default
            mi.mv[0] = mrgCtx.mvFieldNeighbours[(count << 1) + 0].mv;
            mi.mv[1] = mrgCtx.mvFieldNeighbours[(count << 1) + 1].mv;
            mi.refIdx[0] = mrgCtx.mvFieldNeighbours[(count << 1) + 0].refIdx;
            mi.refIdx[1] = mrgCtx.mvFieldNeighbours[(count << 1) + 1].refIdx;
          }
    
          mi.interDir = (mi.refIdx[0] != -1 ? 1 : 0) + (mi.refIdx[1] != -1 ? 2 : 0);
    
          if (isBiPred && mi.interDir == 3)
          {
            mi.interDir = 1;
            mi.mv[1] = Mv();
            mi.refIdx[1] = NOT_VALID;
          }
    
          mb.subBuf(g_miScaling.scale(Position{ x, y } -pu.lumaPos()), g_miScaling.scale(Size(puWidth, puHeight))).fill(mi);
          }
        }
    
      return true;
      }
    
    void PU::spanMotionInfo( PredictionUnit &pu, const MergeCtx &mrgCtx )
    {
      MotionBuf mb = pu.getMotionBuf();
    
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      if( !pu.mergeFlag || pu.mergeType == MRG_TYPE_DEFAULT_N 
    
    Yu Han's avatar
    Yu Han committed
        || pu.mergeType == MRG_TYPE_IBC
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        )
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
        mi.isInter = !CU::isIntra(*pu.cu);
        mi.isIBCmot = CU::isIBC(*pu.cu);
    #else
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
        mi.sliceIdx = pu.cu->slice->getIndependentSliceIdx();
    
        if( mi.isInter )
        {
          mi.interDir = pu.interDir;
    
          for( int i = 0; i < NUM_REF_PIC_LIST_01; i++ )
          {
            mi.mv[i]     = pu.mv[i];
            mi.refIdx[i] = pu.refIdx[i];
          }
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
          if (mi.isIBCmot)
    #else
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          if (pu.interDir == 1 && pu.cu->slice->getRefPOC(REF_PIC_LIST_0, pu.refIdx[0]) == pu.cu->slice->getPOC())
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          {
            mi.bv = pu.bv;
          }
    
        }
    
        if( pu.cu->affine )
        {
          for( int y = 0; y < mb.height; y++ )
          {
            for( int x = 0; x < mb.width; x++ )
            {
              MotionInfo &dest = mb.at( x, y );
              dest.isInter  = mi.isInter;
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
              dest.isIBCmot = false;
    #endif
    
              dest.interDir = mi.interDir;
              dest.sliceIdx = mi.sliceIdx;
              for( int i = 0; i < NUM_REF_PIC_LIST_01; i++ )
              {
                if( mi.refIdx[i] == -1 )
                {
                  dest.mv[i] = Mv();
                }
                dest.refIdx[i] = mi.refIdx[i];
              }
            }
          }
        }
        else
        {
          mb.fill( mi );
        }
      }
      else if (pu.mergeType == MRG_TYPE_SUBPU_ATMVP)
      {
        CHECK(mrgCtx.subPuMvpMiBuf.area() == 0 || !mrgCtx.subPuMvpMiBuf.buf, "Buffer not initialized");
        mb.copyFrom(mrgCtx.subPuMvpMiBuf);
      }
      else
      {
    
        if( isBipredRestriction( pu ) )
        {
          for( int y = 0; y < mb.height; y++ )
          {
            for( int x = 0; x < mb.width; x++ )
            {
              MotionInfo &mi = mb.at( x, y );
              if( mi.interDir == 3 )
              {
                mi.interDir  = 1;
                mi.mv    [1] = Mv();
                mi.refIdx[1] = NOT_VALID;
              }
            }
          }
        }
      }
    }
    
    void PU::applyImv( PredictionUnit& pu, MergeCtx &mrgCtx, InterPrediction *interPred )
    {
      if( !pu.mergeFlag )
      {
        if( pu.interDir != 2 /* PRED_L1 */ )
        {
    
          pu.mvd[0].changePrecisionAmvr( pu.cu->imv, MV_PRECISION_QUARTER);
    
          unsigned mvp_idx = pu.mvpIdx[0];
          AMVPInfo amvpInfo;
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
          if (CU::isIBC(*pu.cu))
    
    Yu Han's avatar
    Yu Han committed
          {
            PU::fillIBCMvpCand(pu, amvpInfo);
          }
    
    Yu Han's avatar
    Yu Han committed
          else
    #endif
    
          PU::fillMvpCand(pu, REF_PIC_LIST_0, pu.refIdx[0], amvpInfo);
          pu.mvpNum[0] = amvpInfo.numCand;
          pu.mvpIdx[0] = mvp_idx;
          pu.mv    [0] = amvpInfo.mvCand[mvp_idx] + pu.mvd[0];
    
          pu.mv[0].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          if (pu.interDir == 1 && pu.cs->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[REF_PIC_LIST_0])->getPOC() == pu.cs->slice->getPOC())
          {
    
    Yu Han's avatar
    Yu Han committed
            pu.cu->ibc = true;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          }
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
        }
    
        if (pu.interDir != 1 /* PRED_L0 */)
        {
          if( !( pu.cu->cs->slice->getMvdL1ZeroFlag() && pu.interDir == 3 ) && pu.cu->imv )/* PRED_BI */
          {
    
            pu.mvd[1].changePrecisionAmvr(pu.cu->imv, MV_PRECISION_QUARTER);
    
          }
          unsigned mvp_idx = pu.mvpIdx[1];
          AMVPInfo amvpInfo;
          PU::fillMvpCand(pu, REF_PIC_LIST_1, pu.refIdx[1], amvpInfo);
          pu.mvpNum[1] = amvpInfo.numCand;
          pu.mvpIdx[1] = mvp_idx;
          pu.mv    [1] = amvpInfo.mvCand[mvp_idx] + pu.mvd[1];
    
          pu.mv[1].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
    
        }
      }
      else
      {
        // this function is never called for merge
        THROW("unexpected");
    
        PU::getInterMergeCandidates ( pu, mrgCtx 
          , 0
        );
    
    #if !JVET_M0068_M0171_MMVD_CLEANUP
    
    
        mrgCtx.setMergeInfo( pu, pu.mergeIdx );
      }
    
      PU::spanMotionInfo( pu, mrgCtx );
    }
    
    bool PU::isBiPredFromDifferentDir( const PredictionUnit& pu )
    {
      if ( pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0 )
      {
        const int iPOC0 = pu.cu->slice->getRefPOC( REF_PIC_LIST_0, pu.refIdx[0] );
        const int iPOC1 = pu.cu->slice->getRefPOC( REF_PIC_LIST_1, pu.refIdx[1] );
        const int iPOC  = pu.cu->slice->getPOC();
        if ( (iPOC - iPOC0)*(iPOC - iPOC1) < 0 )
        {
          return true;
        }
      }
    
      return false;
    }
    
    void PU::restrictBiPredMergeCands( const PredictionUnit &pu, MergeCtx& mergeCtx )
    {
      if( PU::isBipredRestriction( pu ) )
      {
        for( uint32_t mergeCand = 0; mergeCand < mergeCtx.numValidMergeCand; ++mergeCand )
        {
          if( mergeCtx.interDirNeighbours[ mergeCand ] == 3 )
          {
            mergeCtx.interDirNeighbours[ mergeCand ] = 1;
            mergeCtx.mvFieldNeighbours[( mergeCand << 1 ) + 1].setMvField( Mv( 0, 0 ), -1 );
    
            mergeCtx.GBiIdx[mergeCand] = GBI_DEFAULT;
    
    #if JVET_M0068_M0171_MMVD_CLEANUP
    void PU::restrictBiPredMergeCandsOne(PredictionUnit &pu)
    {
      if (PU::isBipredRestriction(pu))
      {
        if (pu.interDir == 3)
        {
          pu.interDir = 1;
          pu.refIdx[1] = -1;
          pu.mv[1] = Mv(0, 0);
          pu.cu->GBiIdx = GBI_DEFAULT;
        }
      }
    }
    #endif
    
    
    rlliao's avatar
    rlliao committed
    void PU::getTriangleMergeCandidates( const PredictionUnit &pu, MergeCtx& triangleMrgCtx )
    
    {
      const CodingStructure &cs  = *pu.cs;
      const Slice &slice         = *pu.cs->slice;
      const int32_t maxNumMergeCand = TRIANGLE_MAX_NUM_UNI_CANDS;
    
    rlliao's avatar
    rlliao committed
      triangleMrgCtx.numValidMergeCand = 0;
    
    
      for( int32_t i = 0; i < maxNumMergeCand; i++ )
      {
    
    rlliao's avatar
    rlliao committed
        triangleMrgCtx.interDirNeighbours[i] = 0;
        triangleMrgCtx.mrgTypeNeighbours [i] = MRG_TYPE_DEFAULT_N;
        triangleMrgCtx.mvFieldNeighbours[(i << 1)    ].refIdx = NOT_VALID;
        triangleMrgCtx.mvFieldNeighbours[(i << 1) + 1].refIdx = NOT_VALID;
        triangleMrgCtx.mvFieldNeighbours[(i << 1)    ].mv = Mv();
        triangleMrgCtx.mvFieldNeighbours[(i << 1) + 1].mv = Mv();
    
    rlliao's avatar
    rlliao committed
      MotionInfo candidate[TRIANGLE_MAX_NUM_CANDS_MEM];
      int32_t candCount = 0;
    
    
      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 );
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      const bool isAvailableA1 = puLeft && isDiffMER( pu, *puLeft ) && pu.cu != puLeft->cu && CU::isInter( *puLeft->cu )
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Yu Han's avatar
    Yu Han committed
        && !puLeft->cu->ibc
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        ;
    
      if( isAvailableA1 )
      {
        miLeft = puLeft->getMotionInfo( posLB.offset(-1, 0) );
    
    rlliao's avatar
    rlliao committed
        candidate[candCount].isInter   = true;
        candidate[candCount].interDir  = miLeft.interDir;
        candidate[candCount].mv[0]     = miLeft.mv[0];
        candidate[candCount].mv[1]     = miLeft.mv[1];
        candidate[candCount].refIdx[0] = miLeft.refIdx[0];
        candidate[candCount].refIdx[1] = miLeft.refIdx[1];
        candCount++;
    
      }
    
      // above
      const PredictionUnit *puAbove = cs.getPURestricted( posRT.offset( 0, -1 ), pu, pu.chType );
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      bool isAvailableB1 = puAbove && isDiffMER( pu, *puAbove ) && pu.cu != puAbove->cu && CU::isInter( *puAbove->cu )
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Yu Han's avatar
    Yu Han committed
        && !puAbove->cu->ibc
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        ;
    
      if( isAvailableB1 )
      {
        miAbove = puAbove->getMotionInfo( posRT.offset( 0, -1 ) );
        
        if( !isAvailableA1 || ( miAbove != miLeft ) )
        {
    
    rlliao's avatar
    rlliao committed
          candidate[candCount].isInter   = true;
          candidate[candCount].interDir  = miAbove.interDir;
          candidate[candCount].mv[0]     = miAbove.mv[0];
          candidate[candCount].mv[1]     = miAbove.mv[1];
          candidate[candCount].refIdx[0] = miAbove.refIdx[0];
          candidate[candCount].refIdx[1] = miAbove.refIdx[1];
          candCount++;
    
        }
      }
      
      // above right
      const PredictionUnit *puAboveRight = cs.getPURestricted( posRT.offset( 1, -1 ), pu, pu.chType );
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      bool isAvailableB0 = puAboveRight && isDiffMER( pu, *puAboveRight ) && CU::isInter( *puAboveRight->cu )
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Yu Han's avatar
    Yu Han committed
        && !puAboveRight->cu->ibc
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        ;
    
    
      if( isAvailableB0 )
      {
        miAboveRight = puAboveRight->getMotionInfo( posRT.offset( 1, -1 ) );
    
        if( ( !isAvailableB1 || ( miAbove != miAboveRight ) ) && ( !isAvailableA1 || ( miLeft != miAboveRight ) ) )
        {
    
    rlliao's avatar
    rlliao committed
          candidate[candCount].isInter   = true;
          candidate[candCount].interDir  = miAboveRight.interDir;
          candidate[candCount].mv[0]     = miAboveRight.mv[0];
          candidate[candCount].mv[1]     = miAboveRight.mv[1];
          candidate[candCount].refIdx[0] = miAboveRight.refIdx[0];
          candidate[candCount].refIdx[1] = miAboveRight.refIdx[1];
          candCount++;
    
        }
      }  
    
      //left bottom
      const PredictionUnit *puLeftBottom = cs.getPURestricted( posLB.offset( -1, 1 ), pu, pu.chType );
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      bool isAvailableA0 = puLeftBottom && isDiffMER( pu, *puLeftBottom ) && CU::isInter( *puLeftBottom->cu )
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Yu Han's avatar
    Yu Han committed
        && !puLeftBottom->cu->ibc
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        ;
    
      if( isAvailableA0 )
      {
        miBelowLeft = puLeftBottom->getMotionInfo( posLB.offset( -1, 1 ) );
        
        if( ( !isAvailableA1 || ( miBelowLeft != miLeft ) ) && ( !isAvailableB1 || ( miBelowLeft != miAbove ) ) && ( !isAvailableB0 || ( miBelowLeft != miAboveRight ) ) )
        {
    
    rlliao's avatar
    rlliao committed
          candidate[candCount].isInter   = true;
          candidate[candCount].interDir  = miBelowLeft.interDir;
          candidate[candCount].mv[0]     = miBelowLeft.mv[0];
          candidate[candCount].mv[1]     = miBelowLeft.mv[1];
          candidate[candCount].refIdx[0] = miBelowLeft.refIdx[0];
          candidate[candCount].refIdx[1] = miBelowLeft.refIdx[1];
          candCount++;
    
        }
      }
    
      // above left
      const PredictionUnit *puAboveLeft = cs.getPURestricted( posLT.offset( -1, -1 ), pu, pu.chType );
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      bool isAvailableB2 = puAboveLeft && isDiffMER( pu, *puAboveLeft ) && CU::isInter( *puAboveLeft->cu )
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Yu Han's avatar
    Yu Han committed
        && !puAboveLeft->cu->ibc
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        ;
    
    
      if( isAvailableB2 )
      {
        miAboveLeft = puAboveLeft->getMotionInfo( posLT.offset( -1, -1 ) );
    
        if( ( !isAvailableA1 || ( miLeft != miAboveLeft ) ) && ( !isAvailableB1 || ( miAbove != miAboveLeft ) ) && ( !isAvailableA0 || ( miBelowLeft != miAboveLeft ) ) && ( !isAvailableB0 || ( miAboveRight != miAboveLeft ) ) )
        {
    
    rlliao's avatar
    rlliao committed
          candidate[candCount].isInter   = true;
          candidate[candCount].interDir  = miAboveLeft.interDir;
          candidate[candCount].mv[0]     = miAboveLeft.mv[0];
          candidate[candCount].mv[1]     = miAboveLeft.mv[1];
          candidate[candCount].refIdx[0] = miAboveLeft.refIdx[0];
          candidate[candCount].refIdx[1] = miAboveLeft.refIdx[1];
          candCount++;
    
        }
      }
      
      if( slice.getEnableTMVPFlag() )
      {
        Position posRB = pu.Y().bottomRight().offset(-3, -3);
    
        const PreCalcValues& pcv = *cs.pcv;
    
        Position posC0;
        Position posC1 = pu.Y().center();
    
    rlliao's avatar
    rlliao committed
        bool isAvailableC0 = false;
    
    #if JVET_M0170_MRG_SHARELIST
        bool isAvailableC1 = (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 );
    
    rlliao's avatar
    rlliao committed
            isAvailableC0 = 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 );
    
    rlliao's avatar
    rlliao committed
            isAvailableC0 = true;
    
          }
          else //is the right bottom corner of CTU
          {
            posC0 = posRB.offset( 4, 4 );
            // same as for last column but not last row
          }
        }
    
        // C0
        Mv        cColMv;
    
    rlliao's avatar
    rlliao committed
        int32_t   refIdx     = 0;
        bool      existMV    = ( isAvailableC0 && getColocatedMVP( pu, REF_PIC_LIST_0, posC0, cColMv, refIdx ) );
        MotionInfo temporalMv;
        temporalMv.interDir  = 0;
        if( existMV )
    
    rlliao's avatar
    rlliao committed
          temporalMv.isInter   = true;
          temporalMv.interDir |= 1;
          temporalMv.mv[0]     = cColMv;
          temporalMv.refIdx[0] = refIdx;
    
    rlliao's avatar
    rlliao committed
        existMV = ( isAvailableC0 && getColocatedMVP( pu, REF_PIC_LIST_1, posC0, cColMv, refIdx ) );
        if( existMV )
    
    rlliao's avatar
    rlliao committed
          temporalMv.interDir |= 2;
          temporalMv.mv[1]     = cColMv;
          temporalMv.refIdx[1] = refIdx;
    
    rlliao's avatar
    rlliao committed
        if( temporalMv.interDir != 0 )
    
    rlliao's avatar
    rlliao committed
          candidate[candCount].isInter   = true;
          candidate[candCount].interDir  = temporalMv.interDir;
          candidate[candCount].mv[0]     = temporalMv.mv[0];
          candidate[candCount].mv[1]     = temporalMv.mv[1];
          candidate[candCount].refIdx[0] = temporalMv.refIdx[0];
          candidate[candCount].refIdx[1] = temporalMv.refIdx[1];
          candCount++;
    
    rlliao's avatar
    rlliao committed
        temporalMv.interDir = 0;
    
    #if JVET_M0170_MRG_SHARELIST
        existMV    = isAvailableC1 && getColocatedMVP(pu, REF_PIC_LIST_0, posC1, cColMv, refIdx );
    #else
    
    rlliao's avatar
    rlliao committed
        existMV    = getColocatedMVP(pu, REF_PIC_LIST_0, posC1, cColMv, refIdx );
    
    rlliao's avatar
    rlliao committed
        if( existMV )
    
    rlliao's avatar
    rlliao committed
          temporalMv.isInter   = true;
          temporalMv.interDir |= 1;
          temporalMv.mv[0]     = cColMv;
          temporalMv.refIdx[0] = refIdx;
    
    #if JVET_M0170_MRG_SHARELIST
        existMV    = isAvailableC1 && getColocatedMVP(pu, REF_PIC_LIST_1, posC1, cColMv, refIdx );
    #else
    
    rlliao's avatar
    rlliao committed
        existMV    = getColocatedMVP(pu, REF_PIC_LIST_1, posC1, cColMv, refIdx );
    
    rlliao's avatar
    rlliao committed
        if( existMV )
    
    rlliao's avatar
    rlliao committed
          temporalMv.interDir |= 2;
          temporalMv.mv[1]     = cColMv;
          temporalMv.refIdx[1] = refIdx;
    
    rlliao's avatar
    rlliao committed
        if( temporalMv.interDir != 0 )
    
    rlliao's avatar
    rlliao committed
          candidate[candCount].isInter   = true;
          candidate[candCount].interDir  = temporalMv.interDir;
          candidate[candCount].mv[0]     = temporalMv.mv[0];
          candidate[candCount].mv[1]     = temporalMv.mv[1];
          candidate[candCount].refIdx[0] = temporalMv.refIdx[0];
          candidate[candCount].refIdx[1] = temporalMv.refIdx[1];
          candCount++;
    
    rlliao's avatar
    rlliao committed
      }
      // put uni-prediction candidate to the triangle candidate list
      for( int32_t i = 0; i < candCount; i++ )
    
    rlliao's avatar
    rlliao committed
        if( candidate[i].interDir != 3 )
        {
          triangleMrgCtx.interDirNeighbours[triangleMrgCtx.numValidMergeCand] = candidate[i].interDir;
          triangleMrgCtx.mrgTypeNeighbours [triangleMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N;
          triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1)    ].mv = candidate[i].mv[0];
          triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) + 1].mv = candidate[i].mv[1];
          triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1)    ].refIdx = candidate[i].refIdx[0];
          triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) + 1].refIdx = candidate[i].refIdx[1];
          triangleMrgCtx.numValidMergeCand += isUniqueTriangleCandidates(pu, triangleMrgCtx);
          if( triangleMrgCtx.numValidMergeCand == TRIANGLE_MAX_NUM_UNI_CANDS )
    
    rlliao's avatar
    rlliao committed
      // put L0 mv of bi-prediction candidate to the triangle candidate list
      for( int32_t i = 0; i < candCount; i++ )
    
    rlliao's avatar
    rlliao committed
        if( candidate[i].interDir == 3 )
    
    rlliao's avatar
    rlliao committed
          triangleMrgCtx.interDirNeighbours[triangleMrgCtx.numValidMergeCand] = 1;
          triangleMrgCtx.mrgTypeNeighbours [triangleMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N;
          triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1)    ].mv = candidate[i].mv[0];
          triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) + 1].mv = Mv(0, 0);
          triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1)    ].refIdx = candidate[i].refIdx[0];
          triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) + 1].refIdx = -1;
          triangleMrgCtx.numValidMergeCand += isUniqueTriangleCandidates(pu, triangleMrgCtx);
          if( triangleMrgCtx.numValidMergeCand == TRIANGLE_MAX_NUM_UNI_CANDS )
    
    rlliao's avatar
    rlliao committed
      // put L1 mv of bi-prediction candidate to the triangle candidate list
      for( int32_t i = 0; i < candCount; i++ )
    
    rlliao's avatar
    rlliao committed
        if( candidate[i].interDir == 3 )
    
    rlliao's avatar
    rlliao committed
          triangleMrgCtx.interDirNeighbours[triangleMrgCtx.numValidMergeCand] = 2;
          triangleMrgCtx.mrgTypeNeighbours [triangleMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N;
          triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1)    ].mv = Mv(0, 0);
          triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) + 1].mv = candidate[i].mv[1];
          triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1)    ].refIdx = -1;
          triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) + 1].refIdx = candidate[i].refIdx[1];
          triangleMrgCtx.numValidMergeCand += isUniqueTriangleCandidates(pu, triangleMrgCtx);
          if( triangleMrgCtx.numValidMergeCand == TRIANGLE_MAX_NUM_UNI_CANDS )
    
    rlliao's avatar
    rlliao committed
      // put average of L0 and L1 mvs of bi-prediction candidate to the triangle candidate list
      for( int32_t i = 0; i < candCount; i++ )
    
    rlliao's avatar
    rlliao committed
        if( candidate[i].interDir == 3 )
    
    rlliao's avatar
    rlliao committed
          int32_t curPicPoc   = slice.getPOC();
          int32_t refPicPocL0 = slice.getRefPOC(REF_PIC_LIST_0, candidate[i].refIdx[0]);
          int32_t refPicPocL1 = slice.getRefPOC(REF_PIC_LIST_1, candidate[i].refIdx[1]);
          Mv aveMv = candidate[i].mv[1];
    
          int32_t distscale = xGetDistScaleFactor( curPicPoc, refPicPocL0, curPicPoc, refPicPocL1 );
          if( distscale != 4096 )
          {
            aveMv = aveMv.scaleMv( distscale ); // scaling to L0
          }
    
    #if JVET_M0265_MV_ROUNDING_CLEANUP
          aveMv = aveMv + candidate[i].mv[0];
          roundAffineMv(aveMv.hor, aveMv.ver, 1);
    #else
    
    rlliao's avatar
    rlliao committed
          aveMv.setHor( ( aveMv.getHor() + candidate[i].mv[0].getHor() + 1 ) >> 1 );
          aveMv.setVer( ( aveMv.getVer() + candidate[i].mv[0].getVer() + 1 ) >> 1 );
    
    rlliao's avatar
    rlliao committed
          triangleMrgCtx.interDirNeighbours[triangleMrgCtx.numValidMergeCand] = 1;
          triangleMrgCtx.mrgTypeNeighbours [triangleMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N;
          triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1)    ].mv = aveMv;
          triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) + 1].mv = Mv(0, 0);
          triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1)    ].refIdx = candidate[i].refIdx[0];
          triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) + 1].refIdx = -1;
          triangleMrgCtx.numValidMergeCand += isUniqueTriangleCandidates(pu, triangleMrgCtx);
          if( triangleMrgCtx.numValidMergeCand == TRIANGLE_MAX_NUM_UNI_CANDS )
    
    rlliao's avatar
    rlliao committed
      int32_t numRefIdx = std::min( slice.getNumRefIdx(REF_PIC_LIST_0), slice.getNumRefIdx(REF_PIC_LIST_1) );
      int32_t cnt = 0;
      while( triangleMrgCtx.numValidMergeCand < TRIANGLE_MAX_NUM_UNI_CANDS )
    
    rlliao's avatar
    rlliao committed
        if( cnt < numRefIdx )
    
    rlliao's avatar
    rlliao committed
          triangleMrgCtx.interDirNeighbours[triangleMrgCtx.numValidMergeCand] = 1;
          triangleMrgCtx.mvFieldNeighbours[triangleMrgCtx.numValidMergeCand << 1].setMvField(Mv(0, 0), cnt);
          triangleMrgCtx.numValidMergeCand++;
    
    rlliao's avatar
    rlliao committed
          if( triangleMrgCtx.numValidMergeCand == TRIANGLE_MAX_NUM_UNI_CANDS )
    
    rlliao's avatar
    rlliao committed
          triangleMrgCtx.interDirNeighbours[triangleMrgCtx.numValidMergeCand] = 2;
          triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) + 1 ].setMvField(Mv(0, 0), cnt);
          triangleMrgCtx.numValidMergeCand++;
    
    rlliao's avatar
    rlliao committed
          cnt = (cnt + 1) % numRefIdx;
    
    rlliao's avatar
    rlliao committed
    bool PU::isUniqueTriangleCandidates( const PredictionUnit &pu, MergeCtx& triangleMrgCtx )
    
    rlliao's avatar
    rlliao committed
      int newCand = triangleMrgCtx.numValidMergeCand;
    
      for( int32_t i = 0; i < newCand; i++ )
      {
    
    rlliao's avatar
    rlliao committed
        int32_t predFlagCur  = triangleMrgCtx.interDirNeighbours[i] == 1 ? 0 : 1;
        int32_t predFlagNew  = triangleMrgCtx.interDirNeighbours[newCand] == 1 ? 0 : 1;
        int32_t refPicPocCur = pu.cs->slice->getRefPOC( (RefPicList)predFlagCur, triangleMrgCtx.mvFieldNeighbours[(i << 1) + predFlagCur].refIdx );
        int32_t refPicPocNew = pu.cs->slice->getRefPOC( (RefPicList)predFlagNew, triangleMrgCtx.mvFieldNeighbours[(newCand << 1) + predFlagNew].refIdx);
        if( refPicPocCur == refPicPocNew && triangleMrgCtx.mvFieldNeighbours[(i << 1) + predFlagCur].mv == triangleMrgCtx.mvFieldNeighbours[(newCand << 1) + predFlagNew].mv )
    
    #if !JVET_M0328_KEEP_ONE_WEIGHT_GROUP
    
    rlliao's avatar
    rlliao committed
    bool PU::getTriangleWeights( const PredictionUnit& pu, MergeCtx &triangleMrgCtx, const uint8_t candIdx0, const uint8_t candIdx1 )
    
    rlliao's avatar
    rlliao committed
      RefPicList refPicListCand0 = triangleMrgCtx.interDirNeighbours[candIdx0] == 1 ? REF_PIC_LIST_0 : REF_PIC_LIST_1;
      RefPicList refPicListCand1 = triangleMrgCtx.interDirNeighbours[candIdx1] == 1 ? REF_PIC_LIST_0 : REF_PIC_LIST_1;
      int32_t refPicPoc0 = pu.cs->slice->getRefPOC( refPicListCand0, triangleMrgCtx.mvFieldNeighbours[ (candIdx0 << 1) + refPicListCand0 ].refIdx );
      int32_t refPicPoc1 = pu.cs->slice->getRefPOC( refPicListCand1, triangleMrgCtx.mvFieldNeighbours[ (candIdx1 << 1) + refPicListCand1 ].refIdx );
    
    rlliao's avatar
    rlliao committed
      if( refPicPoc0 != refPicPoc1 )
    
      {
        // different reference picture
        return true;
      }
      
      // same reference picture, but mv difference is larger than 16 pel
      int32_t threshold = 16 << 4;
    
    rlliao's avatar
    rlliao committed
      Mv diffMv = triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + refPicListCand0].mv - triangleMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + refPicListCand1].mv;
    
    rlliao's avatar
    rlliao committed
      if( diffMv.getAbsHor() > threshold || diffMv.getAbsVer() > threshold  )
    
    #if JVET_M0883_TRIANGLE_SIGNALING
    void PU::spanTriangleMotionInfo( PredictionUnit &pu, MergeCtx &triangleMrgCtx, const bool splitDir, const uint8_t candIdx0, const uint8_t candIdx1 )
    #else
    
    rlliao's avatar
    rlliao committed
    void PU::spanTriangleMotionInfo( PredictionUnit &pu, MergeCtx &triangleMrgCtx, const uint8_t mergeIdx, const bool splitDir, const uint8_t candIdx0, const uint8_t candIdx1 )
    
    #if JVET_M0883_TRIANGLE_SIGNALING
      pu.triangleSplitDir = splitDir;
      pu.triangleMergeIdx0 = candIdx0;
      pu.triangleMergeIdx1 = candIdx1;
    #else
    
    rlliao's avatar
    rlliao committed
      pu.mergeIdx  = mergeIdx;
    
      MotionBuf mb = pu.getMotionBuf();
    
    
    rlliao's avatar
    rlliao committed
      MotionInfo biMv;
      biMv.isInter  = true;
    
    rlliao's avatar
    rlliao committed
      if( triangleMrgCtx.interDirNeighbours[candIdx0] == 1 && triangleMrgCtx.interDirNeighbours[candIdx1] == 2 )
    
    rlliao's avatar
    rlliao committed
        biMv.interDir  = 3;
        biMv.mv[0]     = triangleMrgCtx.mvFieldNeighbours[ candIdx0 << 1     ].mv;
        biMv.mv[1]     = triangleMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv;
        biMv.refIdx[0] = triangleMrgCtx.mvFieldNeighbours[ candIdx0 << 1     ].refIdx;
        biMv.refIdx[1] = triangleMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].refIdx;
    
    rlliao's avatar
    rlliao committed
      else if( triangleMrgCtx.interDirNeighbours[candIdx0] == 2 && triangleMrgCtx.interDirNeighbours[candIdx1] == 1 )
    
    rlliao's avatar
    rlliao committed
        biMv.interDir  = 3;
        biMv.mv[0]     = triangleMrgCtx.mvFieldNeighbours[ candIdx1 << 1     ].mv;
        biMv.mv[1]     = triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mv;
        biMv.refIdx[0] = triangleMrgCtx.mvFieldNeighbours[ candIdx1 << 1     ].refIdx;
        biMv.refIdx[1] = triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].refIdx;
    
    rlliao's avatar
    rlliao committed
      else if( triangleMrgCtx.interDirNeighbours[candIdx0] == 1 && triangleMrgCtx.interDirNeighbours[candIdx1] == 1 )
    
    rlliao's avatar
    rlliao committed
        int32_t refIdx = mappingRefPic( pu, pu.cs->slice->getRefPOC( REF_PIC_LIST_0, triangleMrgCtx.mvFieldNeighbours[candIdx1 << 1].refIdx ), REF_PIC_LIST_1 );
    
    rlliao's avatar
    rlliao committed
          biMv.interDir  = 3;
          biMv.mv[0]     = triangleMrgCtx.mvFieldNeighbours[candIdx0 << 1].mv;
          biMv.mv[1]     = triangleMrgCtx.mvFieldNeighbours[candIdx1 << 1].mv;
          biMv.refIdx[0] = triangleMrgCtx.mvFieldNeighbours[candIdx0 << 1].refIdx;
          biMv.refIdx[1] = refIdx;
    
    rlliao's avatar
    rlliao committed
          refIdx = mappingRefPic( pu, pu.cs->slice->getRefPOC( REF_PIC_LIST_0, triangleMrgCtx.mvFieldNeighbours[candIdx0 << 1].refIdx), REF_PIC_LIST_1 );
          biMv.interDir  = ( refIdx != -1 ) ? 3 : 1;
          biMv.mv[0]     = ( refIdx != -1 ) ? triangleMrgCtx.mvFieldNeighbours[candIdx1 << 1].mv : triangleMrgCtx.mvFieldNeighbours[candIdx0 << 1].mv;
          biMv.mv[1]     = ( refIdx != -1 ) ? triangleMrgCtx.mvFieldNeighbours[candIdx0 << 1].mv : Mv(0, 0);
          biMv.refIdx[0] = ( refIdx != -1 ) ? triangleMrgCtx.mvFieldNeighbours[candIdx1 << 1].refIdx : triangleMrgCtx.mvFieldNeighbours[candIdx0 << 1].refIdx;
          biMv.refIdx[1] = ( refIdx != -1 ) ? refIdx : -1;
    
    rlliao's avatar
    rlliao committed
      else if( triangleMrgCtx.interDirNeighbours[candIdx0] == 2 && triangleMrgCtx.interDirNeighbours[candIdx1] == 2 )
    
    rlliao's avatar
    rlliao committed
        int32_t refIdx = mappingRefPic( pu, pu.cs->slice->getRefPOC( REF_PIC_LIST_1, triangleMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].refIdx ), REF_PIC_LIST_0 );
    
    rlliao's avatar
    rlliao committed
          biMv.interDir  = 3;
          biMv.mv[0]     = triangleMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv;
          biMv.mv[1]     = triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mv;
          biMv.refIdx[0] = refIdx;
          biMv.refIdx[1] = triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].refIdx;
    
    rlliao's avatar
    rlliao committed
          refIdx = mappingRefPic( pu, pu.cs->slice->getRefPOC( REF_PIC_LIST_1, triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].refIdx ), REF_PIC_LIST_0 );
          biMv.interDir  = ( refIdx != -1 ) ? 3 : 2;
          biMv.mv[0]     = ( refIdx != -1 ) ? triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mv : Mv(0, 0);
          biMv.mv[1]     = ( refIdx != -1 ) ? triangleMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv : triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mv;
          biMv.refIdx[0] = ( refIdx != -1 ) ? refIdx : -1; 
          biMv.refIdx[1] = ( refIdx != -1 ) ? triangleMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].refIdx : triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].refIdx;
    
    rlliao's avatar
    rlliao committed
      int32_t idxW  = (int32_t)(g_aucLog2[pu.lwidth() ] - MIN_CU_LOG2);
      int32_t idxH  = (int32_t)(g_aucLog2[pu.lheight()] - MIN_CU_LOG2);
    
      for( int32_t y = 0; y < mb.height; y++ )
      {
        for( int32_t x = 0; x < mb.width; x++ )
        {
    
    rlliao's avatar
    rlliao committed
          if( g_triangleMvStorage[splitDir][idxH][idxW][y][x] == 2 )
    
          {
            mb.at( x, y ).isInter   = true;
    
    rlliao's avatar
    rlliao committed
            mb.at( x, y ).interDir  = biMv.interDir;
            mb.at( x, y ).refIdx[0] = biMv.refIdx[0];
            mb.at( x, y ).refIdx[1] = biMv.refIdx[1];
            mb.at( x, y ).mv    [0] = biMv.mv    [0];
            mb.at( x, y ).mv    [1] = biMv.mv    [1];
    
    rlliao's avatar
    rlliao committed
          else if( g_triangleMvStorage[splitDir][idxH][idxW][y][x] == 0 )
    
          {
            mb.at( x, y ).isInter   = true;
    
    rlliao's avatar
    rlliao committed
            mb.at( x, y ).interDir  = triangleMrgCtx.interDirNeighbours[candIdx0];
            mb.at( x, y ).refIdx[0] = triangleMrgCtx.mvFieldNeighbours[ candIdx0 << 1     ].refIdx;
            mb.at( x, y ).refIdx[1] = triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].refIdx;
            mb.at( x, y ).mv    [0] = triangleMrgCtx.mvFieldNeighbours[ candIdx0 << 1     ].mv;
            mb.at( x, y ).mv    [1] = triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mv;
    
    rlliao's avatar
    rlliao committed
            mb.at( x, y ).interDir  = triangleMrgCtx.interDirNeighbours[candIdx1];
            mb.at( x, y ).refIdx[0] = triangleMrgCtx.mvFieldNeighbours[ candIdx1 << 1     ].refIdx;
            mb.at( x, y ).refIdx[1] = triangleMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].refIdx;
            mb.at( x, y ).mv    [0] = triangleMrgCtx.mvFieldNeighbours[ candIdx1 << 1     ].mv;
            mb.at( x, y ).mv    [1] = triangleMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv;
    
          }
        }
      }
    }
    
    int32_t PU::mappingRefPic( const PredictionUnit &pu, int32_t refPicPoc, bool targetRefPicList )
    {
      int32_t numRefIdx = pu.cs->slice->getNumRefIdx( (RefPicList)targetRefPicList );
    
      for( int32_t i = 0; i < numRefIdx; i++ )
      {
        if( pu.cs->slice->getRefPOC( (RefPicList)targetRefPicList, i ) == refPicPoc )
        {
          return i;
        }
      }
      return -1;
    }
    
    
    void CU::resetMVDandMV2Int( CodingUnit& cu, InterPrediction *interPred )
    {
      for( auto &pu : CU::traversePUs( cu ) )
      {
        MergeCtx mrgCtx;
    
        if( !pu.mergeFlag )
        {
          if( pu.interDir != 2 /* PRED_L1 */ )
          {
            Mv mv        = pu.mv[0];
            Mv mvPred;
            AMVPInfo amvpInfo;
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
            if (CU::isIBC(*pu.cu))
    
    Yu Han's avatar
    Yu Han committed
              PU::fillIBCMvpCand(pu, amvpInfo);
    
    Yu Han's avatar
    Yu Han committed
            else
    #endif
    
            PU::fillMvpCand(pu, REF_PIC_LIST_0, pu.refIdx[0], amvpInfo);
            pu.mvpNum[0] = amvpInfo.numCand;
    
            mvPred       = amvpInfo.mvCand[pu.mvpIdx[0]];
    
            mv.roundToAmvrSignalPrecision(MV_PRECISION_QUARTER, cu.imv);
    
            pu.mv[0]     = mv;
            Mv mvDiff    = mv - mvPred;
            pu.mvd[0]    = mvDiff;
          }
          if( pu.interDir != 1 /* PRED_L0 */ )
          {
            Mv mv        = pu.mv[1];
            Mv mvPred;
            AMVPInfo amvpInfo;