Skip to content
Snippets Groups Projects
UnitTools.cpp 128 KiB
Newer Older
  • Learn to ignore specific revisions
  • {
      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;
    
    
      if ( count )
      {
        if ( (mrgCtx.interDirNeighbours[0] & (1 << REF_PIC_LIST_0)) && slice.getRefPic( REF_PIC_LIST_0, mrgCtx.mvFieldNeighbours[REF_PIC_LIST_0].refIdx ) == pColPic )
        {
          cTMv = mrgCtx.mvFieldNeighbours[REF_PIC_LIST_0].mv;
        }
        else if ( slice.isInterB() && (mrgCtx.interDirNeighbours[0] & (1 << REF_PIC_LIST_1)) && slice.getRefPic( REF_PIC_LIST_1, mrgCtx.mvFieldNeighbours[REF_PIC_LIST_1].refIdx ) == pColPic )
        {
          cTMv = mrgCtx.mvFieldNeighbours[REF_PIC_LIST_1].mv;
        }
      }
    
    
      ///////////////////////////////////////////////////////////////////////
      ////////          GET Initial Temporal Vector                  ////////
      ///////////////////////////////////////////////////////////////////////
    
      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;
    
      int refIdx = 0;
    
      // use coldir.
      bool     bBSlice = slice.isInterB();
    
      Position centerPos;
    
      bool found = false;
      cTempVector = cTMv;
    
    
      cTempVector.changePrecision(MV_PRECISION_SIXTEENTH, MV_PRECISION_INT);
      int tempX = cTempVector.getHor();
      int tempY = cTempVector.getVer();
    
    
      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 (mi.isInter && mi.isIBCmot == false)
    
        mrgCtx.interDirNeighbours[count] = 0;
    
    
        for (unsigned currRefListId = 0; currRefListId < (bBSlice ? 2 : 1); currRefListId++)
        {
          RefPicList  currRefPicList = RefPicList(currRefListId);
    
    
          if (getColocatedMVP(pu, currRefPicList, centerPos, cColMv, refIdx, true))
    
          {
            // 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.BcwIdx[count] = BCW_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;
    
    
          found = false;
    
          mi.isInter = true;
          mi.sliceIdx = slice.getIndependentSliceIdx();
    
    Yu Han's avatar
    Yu Han committed
          mi.isIBCmot = false;
          if (colMi.isInter && colMi.isIBCmot == false)
    
          {
            for (unsigned currRefListId = 0; currRefListId < (bBSlice ? 2 : 1); currRefListId++)
            {
              RefPicList currRefPicList = RefPicList(currRefListId);
    
              if (getColocatedMVP(pu, currRefPicList, colPos, cColMv, refIdx, true))
    
              {
                mi.refIdx[currRefListId] = 0;
                mi.mv[currRefListId] = cColMv;
    
                found = true;
    
          if (!found)
          {
            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);
          }
        }
    
    
    void PU::spanMotionInfo( PredictionUnit &pu, const MergeCtx &mrgCtx )
    {
      MotionBuf mb = pu.getMotionBuf();
    
    
      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
        mi.isInter = !CU::isIntra(*pu.cu);
        mi.isIBCmot = CU::isIBC(*pu.cu);
    
        mi.sliceIdx = pu.cu->slice->getIndependentSliceIdx();
    
        if( mi.isInter )
        {
          mi.interDir = pu.interDir;
    
    ahenkel's avatar
    ahenkel committed
          mi.useAltHpelIf = pu.cu->imv == IMV_HPEL;
    
    
          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 (mi.isIBCmot)
    
    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
              dest.isIBCmot = false;
    
              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 */ )
        {
    
    Xiang Li's avatar
    Xiang Li committed
          pu.mvd[0].changeTransPrecAmvr2Internal(pu.cu->imv);
    
          unsigned mvp_idx = pu.mvpIdx[0];
          AMVPInfo amvpInfo;
    
    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
    
          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].mvCliptoStorageBitDepth();
    
    Brian Heng's avatar
    Brian Heng committed
          if( !( pu.cu->cs->picHeader->getMvdL1ZeroFlag() && pu.interDir == 3 ) && pu.cu->imv )/* PRED_BI */
    
    Xiang Li's avatar
    Xiang Li committed
            pu.mvd[1].changeTransPrecAmvr2Internal(pu.cu->imv);
    
          }
          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].mvCliptoStorageBitDepth();
    
        }
      }
      else
      {
        // this function is never called for merge
        THROW("unexpected");
    
        PU::getInterMergeCandidates ( pu, mrgCtx
    
    
        mrgCtx.setMergeInfo( pu, pu.mergeIdx );
      }
    
      PU::spanMotionInfo( pu, mrgCtx );
    }
    
    
    bool PU::isBiPredFromDifferentDirEqDistPoc(const PredictionUnit& pu)
    {
      if (pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0)
      {
    
        if (pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0])->longTerm
          || pu.cu->slice->getRefPic(REF_PIC_LIST_1, pu.refIdx[1])->longTerm)
        {
          return false;
        }
    
        const int poc0 = pu.cu->slice->getRefPOC(REF_PIC_LIST_0, pu.refIdx[0]);
        const int poc1 = pu.cu->slice->getRefPOC(REF_PIC_LIST_1, pu.refIdx[1]);
        const int poc = pu.cu->slice->getPOC();
        if ((poc - poc0)*(poc - poc1) < 0)
    
          if (abs(poc - poc0) == abs(poc - poc1))
    
    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->BcwIdx = BCW_DEFAULT;
    
    rlliao's avatar
    rlliao committed
    void PU::getTriangleMergeCandidates( const PredictionUnit &pu, MergeCtx& triangleMrgCtx )
    
      MergeCtx tmpMergeCtx;
    
    
      const uint32_t maxNumMergeCand = pu.cs->sps->getMaxNumMergeCand();
    
    
      triangleMrgCtx.numValidMergeCand = 0;
    
      for (int32_t i = 0; i < TRIANGLE_MAX_NUM_UNI_CANDS; i++)
      {
    
        triangleMrgCtx.BcwIdx[i] = BCW_DEFAULT;
    
        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();
    
        triangleMrgCtx.useAltHpelIf[i] = false;
    
      }
    
      PU::getInterMergeCandidates(pu, tmpMergeCtx, 0);
    
      for (int32_t i = 0; i < maxNumMergeCand; i++)
      {
        int parity = i & 1;
        if (tmpMergeCtx.interDirNeighbours[i] & (0x01 + parity))
        {
          triangleMrgCtx.interDirNeighbours[triangleMrgCtx.numValidMergeCand] = 1 + parity;
          triangleMrgCtx.mrgTypeNeighbours[triangleMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N;
          triangleMrgCtx.mvFieldNeighbours[(triangleMrgCtx.numValidMergeCand << 1) + !parity].mv = Mv(0, 0);
          triangleMrgCtx.mvFieldNeighbours[(triangleMrgCtx.numValidMergeCand << 1) + parity].mv = tmpMergeCtx.mvFieldNeighbours[(i << 1) + parity].mv;
          triangleMrgCtx.mvFieldNeighbours[(triangleMrgCtx.numValidMergeCand << 1) + !parity].refIdx = -1;
          triangleMrgCtx.mvFieldNeighbours[(triangleMrgCtx.numValidMergeCand << 1) + parity].refIdx = tmpMergeCtx.mvFieldNeighbours[(i << 1) + parity].refIdx;
          triangleMrgCtx.numValidMergeCand++;
          if (triangleMrgCtx.numValidMergeCand == TRIANGLE_MAX_NUM_UNI_CANDS)
          {
            return;
          }
          continue;
        }
    
        if (tmpMergeCtx.interDirNeighbours[i] & (0x02 - parity))
        {
          triangleMrgCtx.interDirNeighbours[triangleMrgCtx.numValidMergeCand] = 2 - parity;
          triangleMrgCtx.mrgTypeNeighbours[triangleMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N;
          triangleMrgCtx.mvFieldNeighbours[(triangleMrgCtx.numValidMergeCand << 1) + !parity].mv = tmpMergeCtx.mvFieldNeighbours[(i << 1) + !parity].mv;
          triangleMrgCtx.mvFieldNeighbours[(triangleMrgCtx.numValidMergeCand << 1) + parity].mv = Mv(0, 0);
          triangleMrgCtx.mvFieldNeighbours[(triangleMrgCtx.numValidMergeCand << 1) + !parity].refIdx = tmpMergeCtx.mvFieldNeighbours[(i << 1) + !parity].refIdx;
          triangleMrgCtx.mvFieldNeighbours[(triangleMrgCtx.numValidMergeCand << 1) + parity].refIdx = -1;
          triangleMrgCtx.numValidMergeCand++;
          if (triangleMrgCtx.numValidMergeCand == TRIANGLE_MAX_NUM_UNI_CANDS)
          {
            return;
          }
        }
      }
    
    void PU::spanTriangleMotionInfo( PredictionUnit &pu, MergeCtx &triangleMrgCtx, const bool splitDir, const uint8_t candIdx0, const uint8_t candIdx1 )
    
      pu.triangleSplitDir = splitDir;
      pu.triangleMergeIdx0 = candIdx0;
      pu.triangleMergeIdx1 = candIdx1;
    
      MotionBuf mb = pu.getMotionBuf();
    
    
    rlliao's avatar
    rlliao committed
      MotionInfo biMv;
      biMv.isInter  = true;
    
      biMv.sliceIdx = pu.cs->slice->getIndependentSliceIdx();
    
    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 )
    
        biMv.interDir = 1;
        biMv.mv[0] = triangleMrgCtx.mvFieldNeighbours[candIdx1 << 1].mv;
        biMv.mv[1] = Mv(0, 0);
        biMv.refIdx[0] = triangleMrgCtx.mvFieldNeighbours[candIdx1 << 1].refIdx;
        biMv.refIdx[1] = -1;
    
    rlliao's avatar
    rlliao committed
      else if( triangleMrgCtx.interDirNeighbours[candIdx0] == 2 && triangleMrgCtx.interDirNeighbours[candIdx1] == 2 )
    
        biMv.interDir = 2;
        biMv.mv[0] = Mv(0, 0);
        biMv.mv[1] = triangleMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv;
        biMv.refIdx[0] = -1;
        biMv.refIdx[1] = triangleMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].refIdx;
    
      int32_t idxW  = (int32_t)(floorLog2(pu.lwidth() ) - MIN_CU_LOG2);
      int32_t idxH  = (int32_t)(floorLog2(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];
    
            mb.at( x, y ).sliceIdx  = biMv.sliceIdx;
    
    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;
    
            mb.at( x, y ).sliceIdx  = biMv.sliceIdx;
    
    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;
    
            mb.at( x, y ).sliceIdx  = biMv.sliceIdx;
    
          }
        }
      }
    }
    
    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;
    }
    
    #else
    void PU::getGeoMergeCandidates( const PredictionUnit &pu, MergeCtx& geoMrgCtx )
    {
      MergeCtx tmpMergeCtx;
    
    
    Ling Li's avatar
    Ling Li committed
    
    
    Ling Li's avatar
    Ling Li committed
      const uint32_t maxNumMergeCand = pu.cs->sps->getMaxNumMergeCand();
    
      geoMrgCtx.numValidMergeCand = 0;
    
      for (int32_t i = 0; i < GEO_MAX_NUM_UNI_CANDS; i++)
      {
        geoMrgCtx.BcwIdx[i] = BCW_DEFAULT;
        geoMrgCtx.interDirNeighbours[i] = 0;
        geoMrgCtx.mrgTypeNeighbours[i] = MRG_TYPE_DEFAULT_N;
        geoMrgCtx.mvFieldNeighbours[(i << 1)].refIdx = NOT_VALID;
        geoMrgCtx.mvFieldNeighbours[(i << 1) + 1].refIdx = NOT_VALID;
        geoMrgCtx.mvFieldNeighbours[(i << 1)].mv = Mv();
        geoMrgCtx.mvFieldNeighbours[(i << 1) + 1].mv = Mv();
        geoMrgCtx.useAltHpelIf[i] = false;
      }
    
      PU::getInterMergeCandidates(pu, tmpMergeCtx, 0);
    
      for (int32_t i = 0; i < maxNumMergeCand; i++)
      {
        int parity = i & 1;
        if( tmpMergeCtx.interDirNeighbours[i] & (0x01 + parity) )
        {
          geoMrgCtx.interDirNeighbours[geoMrgCtx.numValidMergeCand] = 1 + parity;
          geoMrgCtx.mrgTypeNeighbours[geoMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N;
          geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + !parity].mv = Mv(0, 0);
          geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + parity].mv = tmpMergeCtx.mvFieldNeighbours[(i << 1) + parity].mv;
          geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + !parity].refIdx = -1;
          geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + parity].refIdx = tmpMergeCtx.mvFieldNeighbours[(i << 1) + parity].refIdx;
          geoMrgCtx.numValidMergeCand++;
          if (geoMrgCtx.numValidMergeCand == GEO_MAX_NUM_UNI_CANDS)
          {
            return;
          }
          continue;
        }
    
        if (tmpMergeCtx.interDirNeighbours[i] & (0x02 - parity))
        {
          geoMrgCtx.interDirNeighbours[geoMrgCtx.numValidMergeCand] = 2 - parity;
          geoMrgCtx.mrgTypeNeighbours[geoMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N;
          geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + !parity].mv = tmpMergeCtx.mvFieldNeighbours[(i << 1) + !parity].mv;
          geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + parity].mv = Mv(0, 0);
          geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + !parity].refIdx = tmpMergeCtx.mvFieldNeighbours[(i << 1) + !parity].refIdx;
          geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + parity].refIdx = -1;
          geoMrgCtx.numValidMergeCand++;
          if (geoMrgCtx.numValidMergeCand == GEO_MAX_NUM_UNI_CANDS)
          {
            return;
          }
        }
      }
    }
    
    void PU::spanGeoMotionInfo( PredictionUnit &pu, MergeCtx &geoMrgCtx, const uint8_t splitDir, const uint8_t candIdx0, const uint8_t candIdx1)
    {
      pu.geoSplitDir  = splitDir;
      pu.geoMergeIdx0 = candIdx0;
      pu.geoMergeIdx1 = candIdx1;
      MotionBuf mb = pu.getMotionBuf();
    
      MotionInfo biMv;
      biMv.isInter  = true;
      biMv.sliceIdx = pu.cs->slice->getIndependentSliceIdx();
    
      if( geoMrgCtx.interDirNeighbours[candIdx0] == 1 && geoMrgCtx.interDirNeighbours[candIdx1] == 2 )
      {
        biMv.interDir  = 3;
        biMv.mv[0]     = geoMrgCtx.mvFieldNeighbours[ candIdx0 << 1     ].mv;
        biMv.mv[1]     = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv;
        biMv.refIdx[0] = geoMrgCtx.mvFieldNeighbours[ candIdx0 << 1     ].refIdx;
        biMv.refIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].refIdx;
      }
      else if( geoMrgCtx.interDirNeighbours[candIdx0] == 2 && geoMrgCtx.interDirNeighbours[candIdx1] == 1 )
      {
        biMv.interDir  = 3;
        biMv.mv[0]     = geoMrgCtx.mvFieldNeighbours[ candIdx1 << 1     ].mv;
        biMv.mv[1]     = geoMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mv;
        biMv.refIdx[0] = geoMrgCtx.mvFieldNeighbours[ candIdx1 << 1     ].refIdx;
        biMv.refIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].refIdx;
      }
      else if( geoMrgCtx.interDirNeighbours[candIdx0] == 1 && geoMrgCtx.interDirNeighbours[candIdx1] == 1 )
      {
        biMv.interDir = 1;
        biMv.mv[0] = geoMrgCtx.mvFieldNeighbours[candIdx1 << 1].mv;
        biMv.mv[1] = Mv(0, 0);
        biMv.refIdx[0] = geoMrgCtx.mvFieldNeighbours[candIdx1 << 1].refIdx;
        biMv.refIdx[1] = -1;
      }
      else if( geoMrgCtx.interDirNeighbours[candIdx0] == 2 && geoMrgCtx.interDirNeighbours[candIdx1] == 2 )
      {
        biMv.interDir = 2;
        biMv.mv[0] = Mv(0, 0);
        biMv.mv[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv;
        biMv.refIdx[0] = -1;
        biMv.refIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].refIdx;
      }
    
      int16_t angle = g_GeoParams[splitDir][0];
      int tpmMask = 0;
      int lookUpY = 0, motionIdx = 0;
      bool isFlip = angle >= 13 && angle <= 27;
    
      int distanceIdx = g_GeoParams[splitDir][1];
      int distanceX = angle;
      int distanceY = (distanceX + (GEO_NUM_ANGLES >> 2)) % GEO_NUM_ANGLES;
      int offsetX = (-(int)pu.lwidth()) >> 1;
      int offsetY = (-(int)pu.lheight()) >> 1;
      if (distanceIdx > 0)
      {
        if (angle % 16 == 8 || (angle % 16 != 0 && pu.lheight() >= pu.lwidth()))
    
          offsetY += angle < 16 ? ((distanceIdx * pu.lheight()) >> 3) : -(int)((distanceIdx * pu.lheight()) >> 3);
    
          offsetX += angle < 16 ? ((distanceIdx * pu.lwidth()) >> 3) : -(int)((distanceIdx * pu.lwidth()) >> 3);
    
      for (int y = 0; y < mb.height; y++)
      {
    
        lookUpY = (((4 * y + offsetY) << 1) + 5) * g_Dis[distanceY];
        for (int x = 0; x < mb.width; x++)
        {
          motionIdx = (((4 * x + offsetX) << 1) + 5) * g_Dis[distanceX] + lookUpY;
          tpmMask = abs(motionIdx) < 32 ? 2 : (motionIdx <= 0 ? (1 - isFlip) : isFlip);
          if (tpmMask == 2)
          {
            mb.at(x, y).isInter = true;
            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];
            mb.at(x, y).sliceIdx = biMv.sliceIdx;
          }
          else if (tpmMask == 0)
          {
            mb.at(x, y).isInter = true;
            mb.at(x, y).interDir = geoMrgCtx.interDirNeighbours[candIdx0];
            mb.at(x, y).refIdx[0] = geoMrgCtx.mvFieldNeighbours[candIdx0 << 1].refIdx;
            mb.at(x, y).refIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].refIdx;
            mb.at(x, y).mv[0] = geoMrgCtx.mvFieldNeighbours[candIdx0 << 1].mv;
            mb.at(x, y).mv[1] = geoMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mv;
            mb.at(x, y).sliceIdx = biMv.sliceIdx;
          }
          else
          {
            mb.at(x, y).isInter = true;
            mb.at(x, y).interDir = geoMrgCtx.interDirNeighbours[candIdx1];
            mb.at(x, y).refIdx[0] = geoMrgCtx.mvFieldNeighbours[candIdx1 << 1].refIdx;
            mb.at(x, y).refIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].refIdx;
            mb.at(x, y).mv[0] = geoMrgCtx.mvFieldNeighbours[candIdx1 << 1].mv;
            mb.at(x, y).mv[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv;
            mb.at(x, y).sliceIdx = biMv.sliceIdx;
          }
        }
    
    bool CU::hasSubCUNonZeroMVd( const CodingUnit& cu )
    {
      bool bNonZeroMvd = false;
    
      for( const auto &pu : CU::traversePUs( cu ) )
      {
        if( ( !pu.mergeFlag ) && ( !cu.skip ) )
        {
          if( pu.interDir != 2 /* PRED_L1 */ )
          {
            bNonZeroMvd |= pu.mvd[REF_PIC_LIST_0].getHor() != 0;
            bNonZeroMvd |= pu.mvd[REF_PIC_LIST_0].getVer() != 0;
          }
          if( pu.interDir != 1 /* PRED_L0 */ )
          {
    
    Brian Heng's avatar
    Brian Heng committed
            if( !pu.cu->cs->picHeader->getMvdL1ZeroFlag() || pu.interDir != 3 /* PRED_BI */ )
    
            {
              bNonZeroMvd |= pu.mvd[REF_PIC_LIST_1].getHor() != 0;
              bNonZeroMvd |= pu.mvd[REF_PIC_LIST_1].getVer() != 0;
            }
          }
        }
      }
    
      return bNonZeroMvd;
    }
    
    
    bool CU::hasSubCUNonZeroAffineMVd( const CodingUnit& cu )
    {
      bool nonZeroAffineMvd = false;
    
      if ( !cu.affine || cu.firstPU->mergeFlag )
      {
        return false;
      }
    
      for ( const auto &pu : CU::traversePUs( cu ) )
      {
        if ( ( !pu.mergeFlag ) && ( !cu.skip ) )
        {
          if ( pu.interDir != 2 /* PRED_L1 */ )
          {
            for ( int i = 0; i < ( cu.affineType == AFFINEMODEL_6PARAM ? 3 : 2 ); i++ )
            {
              nonZeroAffineMvd |= pu.mvdAffi[REF_PIC_LIST_0][i].getHor() != 0;
              nonZeroAffineMvd |= pu.mvdAffi[REF_PIC_LIST_0][i].getVer() != 0;
            }
          }
    
          if ( pu.interDir != 1 /* PRED_L0 */ )
          {
    
    Brian Heng's avatar
    Brian Heng committed
            if ( !pu.cu->cs->picHeader->getMvdL1ZeroFlag() || pu.interDir != 3 /* PRED_BI */ )
    
            {
              for ( int i = 0; i < ( cu.affineType == AFFINEMODEL_6PARAM ? 3 : 2 ); i++ )
              {
                nonZeroAffineMvd |= pu.mvdAffi[REF_PIC_LIST_1][i].getHor() != 0;
                nonZeroAffineMvd |= pu.mvdAffi[REF_PIC_LIST_1][i].getVer() != 0;
              }
            }
          }
        }
      }
    
      return nonZeroAffineMvd;
    }
    
    
    uint8_t CU::getSbtInfo( uint8_t idx, uint8_t pos )
    {
      return ( pos << 4 ) + ( idx << 0 );
    }
    
    uint8_t CU::getSbtIdx( const uint8_t sbtInfo )
    {
      return ( sbtInfo >> 0 ) & 0xf;
    }
    
    uint8_t CU::getSbtPos( const uint8_t sbtInfo )
    {
      return ( sbtInfo >> 4 ) & 0x3;
    }
    
    uint8_t CU::getSbtMode( uint8_t sbtIdx, uint8_t sbtPos )
    {
      uint8_t sbtMode = 0;
      switch( sbtIdx )
      {
      case SBT_VER_HALF: sbtMode = sbtPos + SBT_VER_H0;  break;
      case SBT_HOR_HALF: sbtMode = sbtPos + SBT_HOR_H0;  break;
      case SBT_VER_QUAD: sbtMode = sbtPos + SBT_VER_Q0;  break;
      case SBT_HOR_QUAD: sbtMode = sbtPos + SBT_HOR_Q0;  break;
      default:           assert( 0 );
      }
    
      assert( sbtMode < NUMBER_SBT_MODE );
      return sbtMode;
    }
    
    uint8_t CU::getSbtIdxFromSbtMode( uint8_t sbtMode )
    {
      if( sbtMode <= SBT_VER_H1 )
        return SBT_VER_HALF;
      else if( sbtMode <= SBT_HOR_H1 )
        return SBT_HOR_HALF;
      else if( sbtMode <= SBT_VER_Q1 )
        return SBT_VER_QUAD;
      else if( sbtMode <= SBT_HOR_Q1 )
        return SBT_HOR_QUAD;
      else
      {
        assert( 0 );
        return 0;
      }
    }
    
    uint8_t CU::getSbtPosFromSbtMode( uint8_t sbtMode )
    {
      if( sbtMode <= SBT_VER_H1 )
        return sbtMode - SBT_VER_H0;
      else if( sbtMode <= SBT_HOR_H1 )
        return sbtMode - SBT_HOR_H0;
      else if( sbtMode <= SBT_VER_Q1 )
        return sbtMode - SBT_VER_Q0;
      else if( sbtMode <= SBT_HOR_Q1 )
        return sbtMode - SBT_HOR_Q0;
      else
      {
        assert( 0 );
        return 0;
      }
    }
    
    uint8_t CU::targetSbtAllowed( uint8_t sbtIdx, uint8_t sbtAllowed )
    {
      uint8_t val = 0;
      switch( sbtIdx )
      {
      case SBT_VER_HALF: val = ( ( sbtAllowed >> SBT_VER_HALF ) & 0x1 ); break;
      case SBT_HOR_HALF: val = ( ( sbtAllowed >> SBT_HOR_HALF ) & 0x1 ); break;
      case SBT_VER_QUAD: val = ( ( sbtAllowed >> SBT_VER_QUAD ) & 0x1 ); break;
      case SBT_HOR_QUAD: val = ( ( sbtAllowed >> SBT_HOR_QUAD ) & 0x1 ); break;
      default:           CHECK( 1, "unknown SBT type" );
      }
      return val;
    }
    
    uint8_t CU::numSbtModeRdo( uint8_t sbtAllowed )
    {
      uint8_t num = 0;
      uint8_t sum = 0;
      num = targetSbtAllowed( SBT_VER_HALF, sbtAllowed ) + targetSbtAllowed( SBT_HOR_HALF, sbtAllowed );
      sum += std::min( SBT_NUM_RDO, ( num << 1 ) );
      num = targetSbtAllowed( SBT_VER_QUAD, sbtAllowed ) + targetSbtAllowed( SBT_HOR_QUAD, sbtAllowed );
      sum += std::min( SBT_NUM_RDO, ( num << 1 ) );
      return sum;
    }
    
    bool CU::isSbtMode( const uint8_t sbtInfo )
    {
      uint8_t sbtIdx = getSbtIdx( sbtInfo );
      return sbtIdx >= SBT_VER_HALF && sbtIdx <= SBT_HOR_QUAD;
    }
    
    bool CU::isSameSbtSize( const uint8_t sbtInfo1, const uint8_t sbtInfo2 )
    {
      uint8_t sbtIdx1 = getSbtIdxFromSbtMode( sbtInfo1 );
      uint8_t sbtIdx2 = getSbtIdxFromSbtMode( sbtInfo2 );
      if( sbtIdx1 == SBT_HOR_HALF || sbtIdx1 == SBT_VER_HALF )
        return sbtIdx2 == SBT_HOR_HALF || sbtIdx2 == SBT_VER_HALF;
      else if( sbtIdx1 == SBT_HOR_QUAD || sbtIdx1 == SBT_VER_QUAD )
        return sbtIdx2 == SBT_HOR_QUAD || sbtIdx2 == SBT_VER_QUAD;
      else
        return false;
    }
    
    
    bool CU::isPredRegDiffFromTB(const CodingUnit &cu, const ComponentID compID)
    {
      return (compID == COMPONENT_Y)
        && (cu.ispMode == VER_INTRA_SUBPARTITIONS &&
          CU::isMinWidthPredEnabledForBlkSize(cu.blocks[compID].width, cu.blocks[compID].height)
          );
    }
    
    bool CU::isMinWidthPredEnabledForBlkSize(const int w, const int h)
    {
      return ((w == 8 && h > 4) || w == 4);
    }
    
    bool CU::isFirstTBInPredReg(const CodingUnit& cu, const ComponentID compID, const CompArea &area)
    {
      return (compID == COMPONENT_Y) && cu.ispMode && ((area.topLeft().x - cu.Y().topLeft().x) % PRED_REG_MIN_WIDTH == 0);
    }
    
    void CU::adjustPredArea(CompArea &area)
    {
      area.width = std::max<int>(PRED_REG_MIN_WIDTH, area.width);
    }
    
    
    bool CU::isBcwIdxCoded( const CodingUnit &cu )
    
      if( cu.cs->sps->getUseBcw() == false )
    
        CHECK(cu.BcwIdx != BCW_DEFAULT, "Error: cu.BcwIdx != BCW_DEFAULT");
    
    Yu Han's avatar
    Yu Han committed
      if (cu.predMode == MODE_IBC)
      {
        return false;
      }
    
    
      if( cu.predMode == MODE_INTRA || cu.cs->slice->isInterP() )
      {
        return false;
      }
    
      if( cu.lwidth() * cu.lheight() < BCW_SIZE_CONSTRAINT )
    
      if( !cu.firstPU->mergeFlag )
    
        if( cu.firstPU->interDir == 3 )
        {
    
          WPScalingParam *wp0;
          WPScalingParam *wp1;
          int refIdx0 = cu.firstPU->refIdx[REF_PIC_LIST_0];
          int refIdx1 = cu.firstPU->refIdx[REF_PIC_LIST_1];
    
          cu.cs->slice->getWpScaling(REF_PIC_LIST_0, refIdx0, wp0);
          cu.cs->slice->getWpScaling(REF_PIC_LIST_1, refIdx1, wp1);
          if ((wp0[COMPONENT_Y].bPresentFlag || wp0[COMPONENT_Cb].bPresentFlag || wp0[COMPONENT_Cr].bPresentFlag
            || wp1[COMPONENT_Y].bPresentFlag || wp1[COMPONENT_Cb].bPresentFlag || wp1[COMPONENT_Cr].bPresentFlag))
          {
            return false;
          }
    
    uint8_t CU::getValidBcwIdx( const CodingUnit &cu )
    
    {
      if( cu.firstPU->interDir == 3 && !cu.firstPU->mergeFlag )
      {
    
      }
      else if( cu.firstPU->interDir == 3 && cu.firstPU->mergeFlag && cu.firstPU->mergeType == MRG_TYPE_DEFAULT_N )
      {
        // This is intended to do nothing here.
      }
      else if( cu.firstPU->mergeFlag && cu.firstPU->mergeType == MRG_TYPE_SUBPU_ATMVP )
      {
    
        CHECK(cu.BcwIdx != BCW_DEFAULT, " cu.BcwIdx != BCW_DEFAULT ");
    
        CHECK(cu.BcwIdx != BCW_DEFAULT, " cu.BcwIdx != BCW_DEFAULT ");
    
    void CU::setBcwIdx( CodingUnit &cu, uint8_t uh )
    
    {
      int8_t uhCnt = 0;
    
      if( cu.firstPU->interDir == 3 && !cu.firstPU->mergeFlag )
      {
    
        ++uhCnt;
      }
      else if( cu.firstPU->interDir == 3 && cu.firstPU->mergeFlag && cu.firstPU->mergeType == MRG_TYPE_DEFAULT_N )
      {
        // This is intended to do nothing here.
      }
      else if( cu.firstPU->mergeFlag && cu.firstPU->mergeType == MRG_TYPE_SUBPU_ATMVP )
      {
    
        cu.BcwIdx = BCW_DEFAULT;
    
        cu.BcwIdx = BCW_DEFAULT;
    
      }
    
      CHECK(uhCnt <= 0, " uhCnt <= 0 ");
    }
    
    
    uint8_t CU::deriveBcwIdx( uint8_t bcwLO, uint8_t bcwL1 )
    
      const int8_t w0 = getBcwWeight(bcwLO, REF_PIC_LIST_0);
      const int8_t w1 = getBcwWeight(bcwL1, REF_PIC_LIST_1);
      const int8_t th = g_BcwWeightBase >> 1;
    
      const int8_t off = 1;
    
      if( w0 == w1 || (w0 < (th - off) && w1 < (th - off)) || (w0 >(th + off) && w1 >(th + off)) )
      {
    
          return ( w0 >= th ? bcwLO : bcwL1 );
    
          return ( w1 >= th ? bcwL1 : bcwLO );
    
    bool CU::bdpcmAllowed( const CodingUnit& cu, const ComponentID compID )
    {
    
      SizeType transformSkipMaxSize = 1 << cu.cs->sps->getLog2MaxTransformSkipBlockSize();
    
      bool bdpcmAllowed = cu.cs->sps->getBDPCMEnabledFlag();
    
           bdpcmAllowed &= CU::isIntra( cu );
    
           if (isLuma(compID))
               bdpcmAllowed &= (cu.lwidth() <= transformSkipMaxSize && cu.lheight() <= transformSkipMaxSize);
           else
    
    hm.jang's avatar
    hm.jang committed
               bdpcmAllowed &= (cu.chromaSize().width <= transformSkipMaxSize && cu.chromaSize().height <= transformSkipMaxSize) && !cu.colorTransform;
    
      return bdpcmAllowed;
    }
    
    
    bool CU::isMTSAllowed(const CodingUnit &cu, const ComponentID compID)
    {
    
      SizeType tsMaxSize = 1 << cu.cs->sps->getLog2MaxTransformSkipBlockSize();
    
      const int maxSize  = CU::isIntra( cu ) ? MTS_INTRA_MAX_CU_SIZE : MTS_INTER_MAX_CU_SIZE;
      const int cuWidth  = cu.blocks[0].lumaSize().width;
      const int cuHeight = cu.blocks[0].lumaSize().height;
      bool mtsAllowed    = cu.chType == CHANNEL_TYPE_LUMA && compID == COMPONENT_Y;
    
      mtsAllowed &= CU::isIntra( cu ) ? cu.cs->sps->getUseIntraMTS() : cu.cs->sps->getUseInterMTS() && CU::isInter( cu );
      mtsAllowed &= cuWidth <= maxSize && cuHeight <= maxSize;
      mtsAllowed &= !cu.ispMode;
      mtsAllowed &= !cu.sbtInfo;
      mtsAllowed &= !(cu.bdpcmMode && cuWidth <= tsMaxSize && cuHeight <= tsMaxSize);
      return mtsAllowed;
    }
    
    
    // TU tools
    
    bool TU::isNonTransformedResidualRotated(const TransformUnit &tu, const ComponentID &compID)
    {
      return tu.cs->sps->getSpsRangeExtension().getTransformSkipRotationEnabledFlag() && tu.blocks[compID].width == 4 && tu.cu->predMode == MODE_INTRA;
    }
    
    bool TU::getCbf( const TransformUnit &tu, const ComponentID &compID )
    {
      return getCbfAtDepth( tu, compID, tu.depth );
    }