Skip to content
Snippets Groups Projects
UnitTools.cpp 185 KiB
Newer Older
  • Learn to ignore specific revisions
  •   uint32_t uiCutoff    = std::min( uiArrayAddr, 3u );
    
      if (slice.isInterB())
      {
        static const uint32_t NUM_PRIORITY_LIST = 12;
        static const uint32_t uiPriorityList0[NUM_PRIORITY_LIST] = { 0 , 1, 0, 2, 1, 2, 0, 3, 1, 3, 2, 3 };
        static const uint32_t uiPriorityList1[NUM_PRIORITY_LIST] = { 1 , 0, 2, 0, 2, 1, 3, 0, 3, 1, 3, 2 };
    
        for (int idx = 0; idx < uiCutoff * (uiCutoff - 1) && uiArrayAddr != maxNumMergeCand; idx++)
        {
          CHECK( idx >= NUM_PRIORITY_LIST, "Invalid priority list number" );
          int i = uiPriorityList0[idx];
          int j = uiPriorityList1[idx];
          if (isCandInter[i] && isCandInter[j] && (mrgCtx.interDirNeighbours[i] & 0x1) && (mrgCtx.interDirNeighbours[j] & 0x2))
          {
            isCandInter[uiArrayAddr] = true;
            mrgCtx.interDirNeighbours[uiArrayAddr] = 3;
    
            mrgCtx.GBiIdx[uiArrayAddr] = ((mrgCtx.interDirNeighbours[uiArrayAddr] == 3)) ? CU::deriveGbiIdx(mrgCtx.GBiIdx[i], mrgCtx.GBiIdx[j]) : GBI_DEFAULT;
    
    
            // get Mv from cand[i] and cand[j]
            mrgCtx.mvFieldNeighbours[ uiArrayAddr << 1     ].setMvField(mrgCtx.mvFieldNeighbours[ i << 1     ].mv, mrgCtx.mvFieldNeighbours[ i << 1     ].refIdx);
            mrgCtx.mvFieldNeighbours[(uiArrayAddr << 1) + 1].setMvField(mrgCtx.mvFieldNeighbours[(j << 1) + 1].mv, mrgCtx.mvFieldNeighbours[(j << 1) + 1].refIdx);
    
            int iRefPOCL0 = slice.getRefPOC(REF_PIC_LIST_0, mrgCtx.mvFieldNeighbours[(uiArrayAddr << 1)    ].refIdx);
            int iRefPOCL1 = slice.getRefPOC(REF_PIC_LIST_1, mrgCtx.mvFieldNeighbours[(uiArrayAddr << 1) + 1].refIdx);
    
            if( iRefPOCL0 == iRefPOCL1 && mrgCtx.mvFieldNeighbours[( uiArrayAddr << 1 )].mv == mrgCtx.mvFieldNeighbours[( uiArrayAddr << 1 ) + 1].mv )
            {
              isCandInter[uiArrayAddr] = false;
            }
            else
            {
              uiArrayAddr++;
            }
          }
        }
      }
    
      // early termination
      if (uiArrayAddr == maxNumMergeCand)
      {
        return;
      }
    
    
      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)
      {
    
        mrgCtx.interDirNeighbours [uiArrayAddr     ] = 1;
    
        mrgCtx.GBiIdx             [uiArrayAddr     ] = GBI_DEFAULT;
    
        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);
        }
    
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        if ( mrgCtx.interDirNeighbours[uiArrayAddr] == 1 && pu.cs->slice->getRefPic(REF_PIC_LIST_0, mrgCtx.mvFieldNeighbours[uiArrayAddr << 1].refIdx)->getPOC() == pu.cs->slice->getPOC())
        {
    
    Yu Han's avatar
    Yu Han committed
          mrgCtx.mrgTypeNeighbours[uiArrayAddr] = MRG_TYPE_IBC;
    
        uiArrayAddr++;
    
        if (refcnt == iNumRefIdx - 1)
        {
          r = 0;
        }
        else
        {
          ++r;
          ++refcnt;
        }
      }
      mrgCtx.numValidMergeCand = uiArrayAddr;
    }
    
    #if JVET_M0147_DMVR
    bool PU::checkDMVRCondition(const PredictionUnit& pu)
    {
    
      if (pu.cs->sps->getUseDMVR())
    
      {
        return pu.mergeFlag
          && pu.mergeType == MRG_TYPE_DEFAULT_N
          && !pu.cu->affine
          && !pu.mmvdMergeFlag
          && !pu.cu->mmvdSkip
          && PU::isBiPredFromDifferentDirEqDistPoc(pu)
          && (pu.lheight() >= 8)
          && ((pu.lheight() * pu.lwidth()) >= 64)
          ;
      }
      else
      {
        return false;
      }
    }
    #endif
    
    Yu Han's avatar
    Yu Han committed
    // for ibc pu validation
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    bool PU::isBlockVectorValid(PredictionUnit& pu, int xPos, int yPos, int width, int height, int picWidth, int picHeight, int xStartInCU, int yStartInCU, int xBv, int yBv, int ctuSize)
    {
      const int ctuSizeLog2 = g_aucLog2[ctuSize];
    
      int refRightX = xPos + xBv + width - 1;
      int refBottomY = yPos + yBv + height - 1;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      int refLeftX = xPos + xBv;
      int refTopY = yPos + yBv;
    
      if ((xPos + xBv) < 0)
      {
        return false;
      }
      if (refRightX >= picWidth)
      {
        return false;
      }
    
      if ((yPos + yBv) < 0)
      {
        return false;
      }
      if (refBottomY >= picHeight)
      {
        return false;
      }
      if ((xBv + width) > 0 && (yBv + height) > 0)
      {
        return false;
      }
    
      // cannot be in the above CTU row
      if (refTopY >> ctuSizeLog2 < yPos >> ctuSizeLog2)
        return false;
    
      // cannot be in the below CTU row
      if (refBottomY >> ctuSizeLog2 > yPos >> ctuSizeLog2)
      {
        return false;
      }
    
      // in the same CTU line
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0407_IBC_RANGE
    
      if ((refRightX >> ctuSizeLog2 <= xPos >> ctuSizeLog2) && (refLeftX >> ctuSizeLog2 >= (xPos >> ctuSizeLog2) - 1))
    #else
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      if ((refRightX >> ctuSizeLog2 <= xPos >> ctuSizeLog2) && (refLeftX >> ctuSizeLog2 >= (xPos >> ctuSizeLog2)))
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      {
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0407_IBC_RANGE
    
        // in the same CTU, or left CTU
        // if part of ref block is in the left CTU, some area can be referred from the not-yet updated local CTU buffer
        if ((refLeftX >> ctuSizeLog2) == ((xPos >> ctuSizeLog2) - 1))
        {
          // ref block's collocated block in current CTU
          const Position refPosCol = pu.Y().topLeft().offset(xBv + ctuSize, yBv);
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          int offset64x = (refPosCol.x >> (ctuSizeLog2 - 1)) << (ctuSizeLog2 - 1);
          int offset64y = (refPosCol.y >> (ctuSizeLog2 - 1)) << (ctuSizeLog2 - 1);
          const Position refPosCol64x64 = {offset64x, offset64y};
    
          if (pu.cs->isDecomp(refPosCol64x64, toChannelType(COMPONENT_Y)))
            return false;
        }
    #endif
    
    Yu Han's avatar
    Yu Han committed
    #if !JVET_M0407_IBC_RANGE
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        // in the same CTU, check if the reference block is already coded
        const Position refPosLT = pu.Y().topLeft().offset(xBv, yBv);
        const Position refPosBR = pu.Y().bottomRight().offset(xBv, yBv);
        const ChannelType      chType = toChannelType(COMPONENT_Y);
        {
          if (!pu.cs->isDecomp(refPosBR, chType))
            return false;
          if (!pu.cs->isDecomp(refPosLT, chType))
            return false;
        }
        return true;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      }
      else
        return false;
    
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0407_IBC_RANGE
    
      // in the same CTU, or valid area from left CTU. Check if the reference block is already coded
      const Position refPosLT = pu.Y().topLeft().offset(xBv, yBv);
      const Position refPosBR = pu.Y().bottomRight().offset(xBv, yBv);
      const ChannelType      chType = toChannelType(COMPONENT_Y);
      if (!pu.cs->isDecomp(refPosBR, chType))
        return false;
      if (!pu.cs->isDecomp(refPosLT, chType))
        return false;
      return true;
    #endif
    
    
    Yu Han's avatar
    Yu Han committed
    }// for ibc pu validation
    
    
    static int xGetDistScaleFactor(const int &iCurrPOC, const int &iCurrRefPOC, const int &iColPOC, const int &iColRefPOC)
    {
      int iDiffPocD = iColPOC - iColRefPOC;
      int iDiffPocB = iCurrPOC - iCurrRefPOC;
    
      if (iDiffPocD == iDiffPocB)
      {
        return 4096;
      }
      else
      {
        int iTDB = Clip3(-128, 127, iDiffPocB);
        int iTDD = Clip3(-128, 127, iDiffPocD);
        int iX = (0x4000 + abs(iTDD / 2)) / iTDD;
        int iScale = Clip3(-4096, 4095, (iTDB * iX + 32) >> 6);
        return iScale;
      }
    }
    
    
    #if JVET_M0512_MOTION_BUFFER_COMPRESSION
    int convertMvFixedToFloat(int32_t val)
    {
      int sign  = val >> 31;
      int scale = floorLog2((val ^ sign) | MV_MANTISSA_UPPER_LIMIT) - (MV_MANTISSA_BITCOUNT - 1);
    
      int exponent;
      int mantissa;
      if (scale >= 0)
      {
        int round = (1 << scale) >> 1;
        int n     = (val + round) >> scale;
        exponent  = scale + ((n ^ sign) >> (MV_MANTISSA_BITCOUNT - 1));
        mantissa  = (n & MV_MANTISSA_UPPER_LIMIT) | (sign << (MV_MANTISSA_BITCOUNT - 1));
      }
      else
      {
        exponent = 0;
        mantissa = val;
      }
    
      return exponent | (mantissa << MV_EXPONENT_BITCOUNT);
    }
    
    int convertMvFloatToFixed(int val)
    {
      int exponent = val & MV_EXPONENT_MASK;
      int mantissa = val >> MV_EXPONENT_BITCOUNT;
      return exponent == 0 ? mantissa : (mantissa ^ MV_MANTISSA_LIMIT) << (exponent - 1);
    }
    
    int roundMvComp(int x)
    {
      return convertMvFloatToFixed(convertMvFixedToFloat(x));
    }
    #endif
    
    
    int PU::getDistScaleFactor(const int &currPOC, const int &currRefPOC, const int &colPOC, const int &colRefPOC)
    {
      return xGetDistScaleFactor(currPOC, currRefPOC, colPOC, colRefPOC);
    }
    
    void PU::getInterMMVDMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const int& mrgCandIdx)
    {
      int refIdxList0, refIdxList1;
      int k;
      int currBaseNum = 0;
      const uint16_t maxNumMergeCand = mrgCtx.numValidMergeCand;
    
      for (k = 0; k < maxNumMergeCand; k++)
      {
        if (mrgCtx.mrgTypeNeighbours[k] == MRG_TYPE_DEFAULT_N)
        {
          refIdxList0 = mrgCtx.mvFieldNeighbours[(k << 1)].refIdx;
          refIdxList1 = mrgCtx.mvFieldNeighbours[(k << 1) + 1].refIdx;
    
          if ((refIdxList0 >= 0) && (refIdxList1 >= 0))
          {
            mrgCtx.mmvdBaseMv[currBaseNum][0] = mrgCtx.mvFieldNeighbours[(k << 1)];
            mrgCtx.mmvdBaseMv[currBaseNum][1] = mrgCtx.mvFieldNeighbours[(k << 1) + 1];
          }
          else if (refIdxList0 >= 0)
          {
            mrgCtx.mmvdBaseMv[currBaseNum][0] = mrgCtx.mvFieldNeighbours[(k << 1)];
            mrgCtx.mmvdBaseMv[currBaseNum][1] = MvField(Mv(0, 0), -1);
          }
          else if (refIdxList1 >= 0)
          {
            mrgCtx.mmvdBaseMv[currBaseNum][0] = MvField(Mv(0, 0), -1);
            mrgCtx.mmvdBaseMv[currBaseNum][1] = mrgCtx.mvFieldNeighbours[(k << 1) + 1];
          }
    
          currBaseNum++;
    
          if (currBaseNum == MMVD_BASE_MV_NUM)
            break;
        }
      }
    
      if (currBaseNum < MMVD_BASE_MV_NUM)
      {
        for (k = currBaseNum; k < MMVD_BASE_MV_NUM; k++)
        {
    
    #if JVET_M0068_M0171_MMVD_CLEANUP
          mrgCtx.mmvdBaseMv[k][0] = MvField(Mv(0, 0), 0);
          const Slice &slice = *pu.cs->slice;
          mrgCtx.mmvdBaseMv[k][1] = MvField(Mv(0, 0), (slice.isInterB() ? 0 : -1));
    #else
    
          mrgCtx.mmvdBaseMv[k][0] = MvField(Mv(0, 0), 0);
          mrgCtx.mmvdBaseMv[k][0] = MvField(Mv(0, 0), 0);
    
          mrgCtx.GBiIdx[k] = GBI_DEFAULT;
          mrgCtx.interDirNeighbours[k] = (mrgCtx.mmvdBaseMv[k][0].refIdx >= 0) + (mrgCtx.mmvdBaseMv[k][1].refIdx >= 0) * 2;
    
    bool PU::getColocatedMVP(const PredictionUnit &pu, const RefPicList &eRefPicList, const Position &_pos, Mv& rcMv, const int &refIdx )
    {
      // don't perform MV compression when generally disabled or subPuMvp is used
    
      const unsigned scale = 4 * std::max<int>(1, 4 * AMVP_DECIMATION_FACTOR / 4);
    
      const unsigned mask  = ~( scale - 1 );
    
      const Position pos = Position{ PosType( _pos.x & mask ), PosType( _pos.y & mask ) };
    
      const Slice &slice = *pu.cs->slice;
    
      // use coldir.
      const Picture* const pColPic = slice.getRefPic(RefPicList(slice.isInterB() ? 1 - slice.getColFromL0Flag() : 0), slice.getColRefIdx());
    
      if( !pColPic )
      {
        return false;
      }
    
      RefPicList eColRefPicList = slice.getCheckLDC() ? eRefPicList : RefPicList(slice.getColFromL0Flag());
    
      const MotionInfo& mi = pColPic->cs->getMotionInfo( pos );
    
      if( !mi.isInter )
      {
        return false;
      }
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
      if (mi.isIBCmot)
      {
        return false;
      }
    #endif
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
      if (CU::isIBC(*pu.cu))
    #else
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      if (eRefPicList == REF_PIC_LIST_0 && pu.cs->slice->getRefPic(eRefPicList, refIdx)->getPOC() == pu.cs->slice->getPOC())
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      {
        return false;
      }
    
      int iColRefIdx = mi.refIdx[eColRefPicList];
    
      if (iColRefIdx < 0)
      {
        eColRefPicList = RefPicList(1 - eColRefPicList);
        iColRefIdx = mi.refIdx[eColRefPicList];
    
        if (iColRefIdx < 0)
        {
          return false;
        }
      }
    
      const Slice *pColSlice = nullptr;
    
      for( const auto s : pColPic->slices )
      {
        if( s->getIndependentSliceIdx() == mi.sliceIdx )
        {
          pColSlice = s;
          break;
        }
      }
    
      CHECK( pColSlice == nullptr, "Slice segment not found" );
    
      const Slice &colSlice = *pColSlice;
    
      const bool bIsCurrRefLongTerm = slice.getRefPic(eRefPicList, refIdx)->longTerm;
      const bool bIsColRefLongTerm  = colSlice.getIsUsedAsLongTerm(eColRefPicList, iColRefIdx);
    
      if (bIsCurrRefLongTerm != bIsColRefLongTerm)
      {
        return false;
      }
    
    
      // Scale the vector.
      Mv cColMv = mi.mv[eColRefPicList];
    
    #if JVET_M0512_MOTION_BUFFER_COMPRESSION
      cColMv.setHor(roundMvComp(cColMv.getHor()));
      cColMv.setVer(roundMvComp(cColMv.getVer()));
    #endif
    
    
      if (bIsCurrRefLongTerm /*|| bIsColRefLongTerm*/)
      {
        rcMv = cColMv;
      }
      else
      {
        const int currPOC    = slice.getPOC();
        const int colPOC     = colSlice.getPOC();
        const int colRefPOC  = colSlice.getRefPOC(eColRefPicList, iColRefIdx);
        const int currRefPOC = slice.getRefPic(eRefPicList, refIdx)->getPOC();
        const int distscale  = xGetDistScaleFactor(currPOC, currRefPOC, colPOC, colRefPOC);
    
        if (distscale == 4096)
        {
          rcMv = cColMv;
        }
        else
        {
          rcMv = cColMv.scaleMv(distscale);
        }
      }
    
      return true;
    }
    
    bool PU::isDiffMER(const PredictionUnit &pu1, const PredictionUnit &pu2)
    {
      const unsigned xN = pu1.lumaPos().x;
      const unsigned yN = pu1.lumaPos().y;
      const unsigned xP = pu2.lumaPos().x;
      const unsigned yP = pu2.lumaPos().y;
    
      unsigned plevel = pu1.cs->pps->getLog2ParallelMergeLevelMinus2() + 2;
    
      if ((xN >> plevel) != (xP >> plevel))
      {
        return true;
      }
    
      if ((yN >> plevel) != (yP >> plevel))
      {
        return true;
      }
    
      return false;
    }
    
    Yu Han's avatar
    Yu Han committed
    void PU::getIbcMVPsEncOnly(PredictionUnit &pu, Mv* MvPred, int& nbPred)
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    {
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      //-- Get Spatial MV
      Position posLT = pu.Y().topLeft();
      Position posRT = pu.Y().topRight();
      Position posLB = pu.Y().bottomLeft();
    
      unsigned int left = 0, above = 0;
    
      //left
      const PredictionUnit *neibLeftPU = NULL;
      neibLeftPU = pu.cs->getPURestricted(posLB.offset(-1, 0), pu, pu.cs->chType);
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
      left = (neibLeftPU) ? CU::isIBC(*neibLeftPU->cu) : 0;
    #else
    
    Yu Han's avatar
    Yu Han committed
      left = (neibLeftPU) ? neibLeftPU->cu->ibc : 0;
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
      if (left)
      {
        MvPred[nbPred++] = neibLeftPU->bv;
        if (getDerivedBV(pu, MvPred[nbPred - 1], MvPred[nbPred]))
          nbPred++;
      }
    
      //above
      const PredictionUnit *neibAbovePU = NULL;
      neibAbovePU = pu.cs->getPURestricted(posRT.offset(0, -1), pu, pu.cs->chType);
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
      above = (neibAbovePU) ? CU::isIBC(*neibAbovePU->cu) : 0;
    #else
    
    Yu Han's avatar
    Yu Han committed
      above = (neibAbovePU) ? neibAbovePU->cu->ibc : 0;
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
      if (above)
      {
        MvPred[nbPred++] = neibAbovePU->bv;
        if (getDerivedBV(pu, MvPred[nbPred - 1], MvPred[nbPred]))
          nbPred++;
      }
    
      // Below Left predictor search
      const PredictionUnit *neibBelowLeftPU = NULL;
      neibBelowLeftPU = pu.cs->getPURestricted(posLB.offset(-1, 1), pu, pu.cs->chType);
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
      unsigned int belowLeft = (neibBelowLeftPU) ? CU::isIBC(*neibBelowLeftPU->cu) : 0;
    #else
    
    Yu Han's avatar
    Yu Han committed
      unsigned int belowLeft = (neibBelowLeftPU) ? neibBelowLeftPU->cu->ibc : 0;
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
      if (belowLeft)
      {
        MvPred[nbPred++] = neibBelowLeftPU->bv;
        if (getDerivedBV(pu, MvPred[nbPred - 1], MvPred[nbPred]))
          nbPred++;
      }
    
    
      // Above Right predictor search
      const PredictionUnit *neibAboveRightPU = NULL;
      neibAboveRightPU = pu.cs->getPURestricted(posRT.offset(1, -1), pu, pu.cs->chType);
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
      unsigned int aboveRight = (neibAboveRightPU) ? CU::isIBC(*neibAboveRightPU->cu) : 0;
    #else
    
    Yu Han's avatar
    Yu Han committed
      unsigned int aboveRight = (neibAboveRightPU) ? neibAboveRightPU->cu->ibc : 0;
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
      if (aboveRight)
      {
        MvPred[nbPred++] = neibAboveRightPU->bv;
        if (getDerivedBV(pu, MvPred[nbPred - 1], MvPred[nbPred]))
          nbPred++;
      }
    
    
      // Above Left predictor search
      const PredictionUnit *neibAboveLeftPU = NULL;
      neibAboveLeftPU = pu.cs->getPURestricted(posLT.offset(-1, -1), pu, pu.cs->chType);
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
      unsigned int aboveLeft = (neibAboveLeftPU) ? CU::isIBC(*neibAboveLeftPU->cu) : 0;
    #else
    
    Yu Han's avatar
    Yu Han committed
      unsigned int aboveLeft = (neibAboveLeftPU) ? neibAboveLeftPU->cu->ibc : 0;
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
      if (aboveLeft)
      {
        MvPred[nbPred++] = neibAboveLeftPU->bv;
        if (getDerivedBV(pu, MvPred[nbPred - 1], MvPred[nbPred]))
          nbPred++;
      }
    }
    
    bool PU::getDerivedBV(PredictionUnit &pu, const Mv& currentMv, Mv& derivedMv)
    {
      int   cuPelX = pu.lumaPos().x;
      int   cuPelY = pu.lumaPos().y;
      int rX = cuPelX + currentMv.getHor();
      int rY = cuPelY + currentMv.getVer();
      int offsetX = currentMv.getHor();
      int offsetY = currentMv.getVer();
    
    
      if (rX < 0 || rY < 0 || rX >= pu.cs->slice->getSPS()->getPicWidthInLumaSamples() || rY >= pu.cs->slice->getSPS()->getPicHeightInLumaSamples())
      {
        return false;
      }
    
      const PredictionUnit *neibRefPU = NULL;
      neibRefPU = pu.cs->getPURestricted(pu.lumaPos().offset(offsetX, offsetY), pu, pu.cs->chType);
    
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
      bool isIBC = (neibRefPU) ? CU::isIBC(*neibRefPU->cu) : 0;
    #else
    
    Yu Han's avatar
    Yu Han committed
      bool isIBC = (neibRefPU) ? neibRefPU->cu->ibc : 0;
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Yu Han's avatar
    Yu Han committed
      if (isIBC)
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      {
        derivedMv = neibRefPU->bv;
        derivedMv += currentMv;
      }
    
    Yu Han's avatar
    Yu Han committed
      return isIBC;
    
    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
     * Constructs a list of candidates for IBC AMVP (See specification, section "Derivation process for motion vector predictor candidates")
     */
    
    Yu Han's avatar
    Yu Han committed
    void PU::fillIBCMvpCand(PredictionUnit &pu, AMVPInfo &amvpInfo)
    
    Yu Han's avatar
    Yu Han committed
    {
      CodingStructure &cs = *pu.cs;
    
      AMVPInfo *pInfo = &amvpInfo;
    
      pInfo->numCand = 0;
    
      //-- Get Spatial MV
      Position posLT = pu.Y().topLeft();
      Position posRT = pu.Y().topRight();
      Position posLB = pu.Y().bottomLeft();
    
      bool isScaledFlagLX = false; /// variable name from specification; true when the PUs below left or left are available (availableA0 || availableA1).
      {
        const PredictionUnit* tmpPU = cs.getPURestricted(posLB.offset(-1, 1), pu, pu.chType); // getPUBelowLeft(idx, partIdxLB);
        isScaledFlagLX = tmpPU != NULL && CU::isIBC(*tmpPU->cu);
        if (!isScaledFlagLX)
        {
          tmpPU = cs.getPURestricted(posLB.offset(-1, 0), pu, pu.chType);
          isScaledFlagLX = tmpPU != NULL && CU::isIBC(*tmpPU->cu);
        }
      }
    
      // Left predictor search
      if (isScaledFlagLX)
      {
    
    Yu Han's avatar
    Yu Han committed
        bool isAdded = addIBCMVPCand(pu, posLB, MD_BELOW_LEFT, *pInfo);
    
    Yu Han's avatar
    Yu Han committed
        if (!isAdded)
    
    Yu Han's avatar
    Yu Han committed
          isAdded = addIBCMVPCand(pu, posLB, MD_LEFT, *pInfo);
    
    Yu Han's avatar
    Yu Han committed
        }
      }
    
      // Above predictor search
      {
    
    Yu Han's avatar
    Yu Han committed
        bool isAdded = addIBCMVPCand(pu, posRT, MD_ABOVE_RIGHT, *pInfo);
    
    Yu Han's avatar
    Yu Han committed
        if (!isAdded)
    
    Yu Han's avatar
    Yu Han committed
          isAdded = addIBCMVPCand(pu, posRT, MD_ABOVE, *pInfo);
    
    Yu Han's avatar
    Yu Han committed
          if (!isAdded)
    
    Yu Han's avatar
    Yu Han committed
            addIBCMVPCand(pu, posLT, MD_ABOVE_LEFT, *pInfo);
    
    Yu Han's avatar
    Yu Han committed
          }
        }
      }
    
      if (pu.cu->imv != 0)
      {
        for (int i = 0; i < pInfo->numCand; i++)
        {
          pInfo->mvCand[i].roundToAmvrSignalPrecision(MV_PRECISION_INTERNAL, pu.cu->imv);
        }
      }
    
      if (pInfo->numCand == 2)
      {
        if (pInfo->mvCand[0] == pInfo->mvCand[1])
        {
          pInfo->numCand = 1;
        }
      }
    
      if (pInfo->numCand < AMVP_MAX_NUM_CANDS)
      {
    
    Yu Han's avatar
    Yu Han committed
        addAMVPHMVPCand(pu, REF_PIC_LIST_0, REF_PIC_LIST_1, cs.slice->getPOC(), *pInfo, pu.cu->imv);
    
    Yu Han's avatar
    Yu Han committed
      }
    
      if (pInfo->numCand > AMVP_MAX_NUM_CANDS)
      {
        pInfo->numCand = AMVP_MAX_NUM_CANDS;
      }
    
      while (pInfo->numCand < AMVP_MAX_NUM_CANDS)
      {
        pInfo->mvCand[pInfo->numCand] = Mv(0, 0);
        pInfo->numCand++;
      }
    
    Yu Han's avatar
    Yu Han committed
    
      for (Mv &mv : pInfo->mvCand)
    
    Yu Han's avatar
    Yu Han committed
        mv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
        mv.roundToAmvrSignalPrecision(MV_PRECISION_QUARTER, pu.cu->imv);
    
    /** Constructs a list of candidates for AMVP (See specification, section "Derivation process for motion vector predictor candidates")
    * \param uiPartIdx
    * \param uiPartAddr
    * \param eRefPicList
    * \param iRefIdx
    * \param pInfo
    */
    void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const int &refIdx, AMVPInfo &amvpInfo)
    {
      CodingStructure &cs = *pu.cs;
    
      AMVPInfo *pInfo = &amvpInfo;
    
      pInfo->numCand = 0;
    
      if (refIdx < 0)
      {
        return;
      }
    
      //-- Get Spatial MV
      Position posLT = pu.Y().topLeft();
      Position posRT = pu.Y().topRight();
      Position posLB = pu.Y().bottomLeft();
    
      bool isScaledFlagLX = false; /// variable name from specification; true when the PUs below left or left are available (availableA0 || availableA1).
    
      {
        const PredictionUnit* tmpPU = cs.getPURestricted( posLB.offset( -1, 1 ), pu, pu.chType ); // getPUBelowLeft(idx, partIdxLB);
        isScaledFlagLX = tmpPU != NULL && CU::isInter( *tmpPU->cu );
    
        if( !isScaledFlagLX )
        {
          tmpPU = cs.getPURestricted( posLB.offset( -1, 0 ), pu, pu.chType );
          isScaledFlagLX = tmpPU != NULL && CU::isInter( *tmpPU->cu );
        }
      }
    
      // Left predictor search
      if( isScaledFlagLX )
      {
        bool bAdded = addMVPCandUnscaled( pu, eRefPicList, refIdx, posLB, MD_BELOW_LEFT, *pInfo );
    
        if( !bAdded )
        {
          bAdded = addMVPCandUnscaled( pu, eRefPicList, refIdx, posLB, MD_LEFT, *pInfo );
    
          if( !bAdded )
          {
            bAdded = addMVPCandWithScaling( pu, eRefPicList, refIdx, posLB, MD_BELOW_LEFT, *pInfo );
    
            if( !bAdded )
            {
              addMVPCandWithScaling( pu, eRefPicList, refIdx, posLB, MD_LEFT, *pInfo );
            }
          }
        }
      }
    
      // Above predictor search
      {
        bool bAdded = addMVPCandUnscaled( pu, eRefPicList, refIdx, posRT, MD_ABOVE_RIGHT, *pInfo );
    
        if( !bAdded )
        {
          bAdded = addMVPCandUnscaled( pu, eRefPicList, refIdx, posRT, MD_ABOVE, *pInfo );
    
          if( !bAdded )
          {
            addMVPCandUnscaled( pu, eRefPicList, refIdx, posLT, MD_ABOVE_LEFT, *pInfo );
          }
        }
      }
    
      if( !isScaledFlagLX )
      {
        bool bAdded = addMVPCandWithScaling( pu, eRefPicList, refIdx, posRT, MD_ABOVE_RIGHT, *pInfo );
    
        if( !bAdded )
        {
          bAdded = addMVPCandWithScaling( pu, eRefPicList, refIdx, posRT, MD_ABOVE, *pInfo );
    
          if( !bAdded )
          {
            addMVPCandWithScaling( pu, eRefPicList, refIdx, posLT, MD_ABOVE_LEFT, *pInfo );
          }
        }
      }
    
    
    #if JVET_M0281_AMVP_ROUNDING || JVET_M0117_AMVP_LIST_GEN
    
      for( int i = 0; i < pInfo->numCand; i++ )
      {
        pInfo->mvCand[i].roundToAmvrSignalPrecision(MV_PRECISION_INTERNAL, pu.cu->imv);
      }
    #else
    
      if( pu.cu->imv != 0)
      {
        for( int i = 0; i < pInfo->numCand; i++ )
        {
    
          pInfo->mvCand[i].roundToAmvrSignalPrecision(MV_PRECISION_INTERNAL, pu.cu->imv);
    
    
      if( pInfo->numCand == 2 )
      {
        if( pInfo->mvCand[0] == pInfo->mvCand[1] )
        {
          pInfo->numCand = 1;
        }
      }
    
    
    #if JVET_M0281_AMVP_ROUNDING || JVET_M0117_AMVP_LIST_GEN
    
      if( cs.slice->getEnableTMVPFlag() && pInfo->numCand < AMVP_MAX_NUM_CANDS )
    #else
    
      {
        // Get Temporal Motion Predictor
        const int refIdx_Col = refIdx;
    
        Position posRB = pu.Y().bottomRight().offset(-3, -3);
    
        const PreCalcValues& pcv = *cs.pcv;
    
        Position posC0;
        bool C0Avail = false;
        Position posC1 = pu.Y().center();
    
    #if JVET_M0170_MRG_SHARELIST
        bool C1Avail =  ( posC1.x  < pcv.lumaWidth ) && ( posC1.y < pcv.lumaHeight ) ;
    #endif
    
    
        Mv cColMv;
    
        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
          {
            // in the reference the CTU address is not set - thus probably resulting in no using this C0 possibility
            posC0 = posRB.offset(4, 4);
          }
          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
          {
            // same as for last column but not last row
            posC0 = posRB.offset(4, 4);
          }
        }
    
    
    #if JVET_M0170_MRG_SHARELIST
        if ((C0Avail && getColocatedMVP(pu, eRefPicList, posC0, cColMv, refIdx_Col)) || (C1Avail && getColocatedMVP(pu, eRefPicList, posC1, cColMv, refIdx_Col)))
    #else
    
        if ((C0Avail && getColocatedMVP(pu, eRefPicList, posC0, cColMv, refIdx_Col)) || getColocatedMVP(pu, eRefPicList, posC1, cColMv, refIdx_Col))
    
    #if JVET_M0281_AMVP_ROUNDING || JVET_M0117_AMVP_LIST_GEN
    
          cColMv.roundToAmvrSignalPrecision(MV_PRECISION_INTERNAL, pu.cu->imv);
    #else
    
            cColMv.roundToAmvrSignalPrecision(MV_PRECISION_INTERNAL, pu.cu->imv);
    
    #if JVET_M0117_AMVP_LIST_GEN
          pInfo->mvCand[pInfo->numCand++] = cColMv;
    #else
    
          int i = 0;
          for (i = 0; i < pInfo->numCand; i++)
          {
            if (cColMv == pInfo->mvCand[i])
            {
              break;
            }
          }
          if (i == pInfo->numCand)
          {
            pInfo->mvCand[pInfo->numCand++] = cColMv;
          }
    
      if (pInfo->numCand < AMVP_MAX_NUM_CANDS)
      {
        const int        currRefPOC = cs.slice->getRefPic(eRefPicList, refIdx)->getPOC();
        const RefPicList eRefPicList2nd = (eRefPicList == REF_PIC_LIST_0) ? REF_PIC_LIST_1 : REF_PIC_LIST_0;
        addAMVPHMVPCand(pu, eRefPicList, eRefPicList2nd, currRefPOC, *pInfo, pu.cu->imv);
      }
    
      if (pInfo->numCand > AMVP_MAX_NUM_CANDS)
      {
        pInfo->numCand = AMVP_MAX_NUM_CANDS;
      }
    
      while (pInfo->numCand < AMVP_MAX_NUM_CANDS)
      {
        pInfo->mvCand[pInfo->numCand] = Mv( 0, 0 );
        pInfo->numCand++;
      }
    
      for (Mv &mv : pInfo->mvCand)
    
        mv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
    
    #if !JVET_M0281_AMVP_ROUNDING && !JVET_M0117_AMVP_LIST_GEN
    
        mv.roundToAmvrSignalPrecision(MV_PRECISION_QUARTER, pu.cu->imv);
    
    bool PU::addAffineMVPCandUnscaled( const PredictionUnit &pu, const RefPicList &refPicList, const int &refIdx, const Position &pos, const MvpDir &dir, AffineAMVPInfo &affiAMVPInfo )
    
    {
      CodingStructure &cs = *pu.cs;
      const PredictionUnit *neibPU = NULL;
      Position neibPos;
    
      {
      case MD_LEFT:
        neibPos = pos.offset( -1, 0 );
        break;
      case MD_ABOVE:
        neibPos = pos.offset( 0, -1 );
        break;
      case MD_ABOVE_RIGHT:
        neibPos = pos.offset( 1, -1 );
        break;
      case MD_BELOW_LEFT:
        neibPos = pos.offset( -1, 1 );
        break;
      case MD_ABOVE_LEFT:
        neibPos = pos.offset( -1, -1 );
        break;
      default:
        break;
      }
    
      neibPU = cs.getPURestricted( neibPos, pu, pu.chType );
    
      if ( neibPU == NULL || !CU::isInter( *neibPU->cu ) || !neibPU->cu->affine
        || neibPU->mergeType != MRG_TYPE_DEFAULT_N
        )
      {
        return false;
      }
    
      Mv outputAffineMv[3];
      const MotionInfo& neibMi = neibPU->getMotionInfo( neibPos );
    
    
      const int        currRefPOC = cs.slice->getRefPic( refPicList, refIdx )->getPOC();
      const RefPicList refPicList2nd = (refPicList == REF_PIC_LIST_0) ? REF_PIC_LIST_1 : REF_PIC_LIST_0;
    
    
      for ( int predictorSource = 0; predictorSource < 2; predictorSource++ ) // examine the indicated reference picture list, then if not available, examine the other list.
      {
    
        const RefPicList eRefPicListIndex = (predictorSource == 0) ? refPicList : refPicList2nd;
    
        const int        neibRefIdx = neibMi.refIdx[eRefPicListIndex];
    
        if ( ((neibPU->interDir & (eRefPicListIndex + 1)) == 0) || pu.cu->slice->getRefPOC( eRefPicListIndex, neibRefIdx ) != currRefPOC )
        {
          continue;
        }
    
        xInheritedAffineMv( pu, neibPU, eRefPicListIndex, outputAffineMv );
    
    #if JVET_M0246_AFFINE_AMVR
        if ( pu.cu->imv == 0 )
        {
    #endif
          outputAffineMv[0].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
          outputAffineMv[1].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
    #if JVET_M0246_AFFINE_AMVR
        }
        else if ( pu.cu->imv == 2 )
        {
          outputAffineMv[0].roundToPrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT );
          outputAffineMv[1].roundToPrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT );
        }
    #endif
    
        affiAMVPInfo.mvCandLT[affiAMVPInfo.numCand] = outputAffineMv[0];
        affiAMVPInfo.mvCandRT[affiAMVPInfo.numCand] = outputAffineMv[1];
        if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
        {
    
    #if JVET_M0246_AFFINE_AMVR
          if ( pu.cu->imv == 0 )
          {
    #endif
            outputAffineMv[2].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
    #if JVET_M0246_AFFINE_AMVR
          }
          else if ( pu.cu->imv == 2 )
          {
            outputAffineMv[2].roundToPrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT );
          }
    #endif
    
          affiAMVPInfo.mvCandLB[affiAMVPInfo.numCand] = outputAffineMv[2];
        }
        affiAMVPInfo.numCand++;
        return true;
      }
    
      return false;
    }
    
    
    void PU::xInheritedAffineMv( const PredictionUnit &pu, const PredictionUnit* puNeighbour, RefPicList eRefPicList, Mv rcMv[3] )
    {
      int posNeiX = puNeighbour->Y().pos().x;
      int posNeiY = puNeighbour->Y().pos().y;
      int posCurX = pu.Y().pos().x;
      int posCurY = pu.Y().pos().y;
    
      int neiW = puNeighbour->Y().width;
      int curW = pu.Y().width;
      int neiH = puNeighbour->Y().height;
      int curH = pu.Y().height;