Skip to content
Snippets Groups Projects
EncCu.cpp 150 KiB
Newer Older
  • Learn to ignore specific revisions
  • Xiaozhong Xu's avatar
    Xiaozhong Xu committed
            int yPred = pu.bv.getVer();
    
            if (!PU::isBlockVectorValid(pu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, 0, 0, xPred, yPred, lcuWidth)) // not valid bv derived
            {
              numValidBv--;
              continue;
            }
            PU::spanMotionInfo(pu, mergeCtx);
    
            distParam.cur.buf = piRefSrch + refStride * yPred + xPred;
    
            Distortion sad = distParam.distFunc(distParam);
            unsigned int bitsCand = mergeCand + 1;
            if (mergeCand == tempCS->slice->getMaxNumMergeCand() - 1)
            {
              bitsCand--;
            }
            double cost = (double)sad + (double)bitsCand * sqrtLambdaForFirstPass;
            static_vector<int, MRG_MAX_NUM_CANDS> * nullList = nullptr;
    
            updateCandList(mergeCand, cost, RdModeList, candCostList
              , *nullList, -1
             , numMrgSATDCand);
          }
    
          // Try to limit number of candidates using SATD-costs
          if (numValidBv)
          {
            numMrgSATDCand = numValidBv;
            for (unsigned int i = 1; i < numValidBv; i++)
            {
              if (candCostList[i] > MRG_FAST_RATIO*candCostList[0])
              {
                numMrgSATDCand = i;
                break;
              }
            }
          }
          else
          {
            tempCS->dist = 0;
            tempCS->fracBits = 0;
            tempCS->cost = MAX_DOUBLE;
    
    Nan Hu's avatar
    Nan Hu committed
            tempCS->costDbOffset = 0;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
            tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
            return;
          }
    
          tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
        }
      //}
    
    
      const unsigned int iteration = encTestMode.lossless ? 1 : 2;
    
    Nan Hu's avatar
    Nan Hu committed
      m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      // 2. Pass: check candidates using full RD test
      for (unsigned int numResidualPass = 0; numResidualPass < iteration; numResidualPass++)
      {
        for (unsigned int mrgHADIdx = 0; mrgHADIdx < numMrgSATDCand; mrgHADIdx++)
        {
          unsigned int mergeCand = RdModeList[mrgHADIdx];
          if (!(numResidualPass == 1 && candHasNoResidual[mergeCand] == 1))
          {
            if (!(bestIsSkip && (numResidualPass == 0)))
            {
    
    Tung Nguyen's avatar
    Tung Nguyen committed
              {
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
                // first get merge candidates
                CodingUnit &cu = tempCS->addCU(CS::getArea(*tempCS, tempCS->area, (const ChannelType)partitioner.chType), (const ChannelType)partitioner.chType);
    
                partitioner.setCUData(cu);
                cu.slice = tempCS->slice;
                cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap(tempCS->area.lumaPos());
                cu.skip = false;
    
    Yu Han's avatar
    Yu Han committed
                cu.predMode = MODE_IBC;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
                cu.transQuantBypass = encTestMode.lossless;
                cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
                cu.qp = encTestMode.qp;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
                PredictionUnit &pu = tempCS->addPU(cu, partitioner.chType);// tempCS->addPU(cu);
    
    Yu Han's avatar
    Yu Han committed
                pu.intraDir[0] = DC_IDX; // set intra pred for ibc block
                pu.intraDir[1] = PLANAR_IDX; // set intra pred for ibc block
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
                cu.mmvdSkip = false;
                pu.mmvdMergeFlag = false;
    
    #if JVET_N0324_REGULAR_MRG_FLAG
                pu.regularMergeFlag = false;
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
                cu.triangle = false;
                mergeCtx.setMergeInfo(pu, mergeCand);
                PU::spanMotionInfo(pu, mergeCtx);
    
    
    Yu Han's avatar
    Yu Han committed
                assert(mergeCtx.mrgTypeNeighbours[mergeCand] == MRG_TYPE_IBC); //  should be IBC candidate at this round
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
                const bool chroma = !(CS::isDualITree(*tempCS));
    
                //  MC
                m_pcInterSearch->motionCompensation(pu,REF_PIC_LIST_0, true, chroma);
                m_CABACEstimator->getCtx() = m_CurrCtx->start;
    
                m_pcInterSearch->encodeResAndCalcRdInterCU(*tempCS, partitioner, (numResidualPass != 0), true, chroma);
                xEncodeDontSplit(*tempCS, partitioner);
    
    
    #if ENABLE_QPA_SUB_CTU
                xCheckDQP (*tempCS, partitioner);
    #else
                // this if-check is redundant
    
                if (tempCS->pps->getUseDQP() && partitioner.currQgEnable())
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
                {
                  xCheckDQP(*tempCS, partitioner);
                }
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
    
                DTRACE_MODE_COST(*tempCS, m_pcRdCost->getLambda());
                xCheckBestMode(tempCS, bestCS, partitioner, encTestMode);
    
                tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
              }
    
                if (m_pcEncCfg->getUseFastDecisionForMerge() && !bestIsSkip)
                {
                  if (bestCS->getCU(partitioner.chType) == NULL)
                    bestIsSkip = 0;
                  else
                  bestIsSkip = bestCS->getCU(partitioner.chType)->rootCbf == 0;
                }
            }
          }
        }
      }
    
    Nan Hu's avatar
    Nan Hu committed
      if ( m_bestModeUpdated && bestCS->cost != MAX_DOUBLE )
    
    Nan Hu's avatar
    Nan Hu committed
      {
    
    Nan Hu's avatar
    Nan Hu committed
        xCalDebCost( *bestCS, partitioner );
    
    Nan Hu's avatar
    Nan Hu committed
      }
    
    Yu Han's avatar
    Yu Han committed
    void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode)
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    {
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_N0318_N0467_IBC_SIZE
      if (tempCS->area.lwidth() == 128 && tempCS->area.lheight() == 128) // disable 128x128 IBC mode
      {
        return;
      }
    #else
    
    Yu Han's avatar
    Yu Han committed
      if (tempCS->area.lwidth() > IBC_MAX_CAND_SIZE || tempCS->area.lheight() > IBC_MAX_CAND_SIZE) // currently only check 32x32 and below block for ibc merge/skip
      {
        return;
      }
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Yu Han's avatar
    Yu Han committed
    
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
    
    
    Nan Hu's avatar
    Nan Hu committed
        m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
    
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        CodingUnit &cu = tempCS->addCU(CS::getArea(*tempCS, tempCS->area, partitioner.chType), partitioner.chType);
    
        partitioner.setCUData(cu);
        cu.slice = tempCS->slice;
        cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap(tempCS->area.lumaPos());
        cu.skip = false;
    
    Yu Han's avatar
    Yu Han committed
        cu.predMode = MODE_IBC;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        cu.transQuantBypass = encTestMode.lossless;
        cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
        cu.qp = encTestMode.qp;
        cu.imv = 0;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
        CU::addPUs(cu);
    
    
    Nan Hu's avatar
    Nan Hu committed
        m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
    
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        PredictionUnit& pu = *cu.firstPU;
        cu.mmvdSkip = false;
        pu.mmvdMergeFlag = false;
    
    #if JVET_N0324_REGULAR_MRG_FLAG
        pu.regularMergeFlag = false;
    #endif
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_N0843_BVP_SIMPLIFICATION
        pu.shareParentPos  = tempCS->sharedBndPos;
        pu.shareParentSize = tempCS->sharedBndSize;
    #endif
    
    
    Yu Han's avatar
    Yu Han committed
        pu.intraDir[0] = DC_IDX; // set intra pred for ibc block
        pu.intraDir[1] = PLANAR_IDX; // set intra pred for ibc block
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
    
    Yu Han's avatar
    Yu Han committed
        pu.interDir = 1; // use list 0 for IBC mode
    
    Yu Han's avatar
    Yu Han committed
        pu.refIdx[REF_PIC_LIST_0] = MAX_NUM_REF; // last idx in the list
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
        if (partitioner.chType == CHANNEL_TYPE_LUMA)
        {
    
    Yu Han's avatar
    Yu Han committed
          bool bValid = m_pcInterSearch->predIBCSearch(cu, partitioner, m_ctuIbcSearchRangeX, m_ctuIbcSearchRangeY, m_ibcHashMap);
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
          if (bValid)
          {
            PU::spanMotionInfo(pu);
            const bool chroma = !(CS::isDualITree(*tempCS));
            //  MC
            m_pcInterSearch->motionCompensation(pu, REF_PIC_LIST_0, true, chroma);
    
    
    Tung Nguyen's avatar
    Tung Nguyen committed
            {
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
              m_pcInterSearch->encodeResAndCalcRdInterCU(*tempCS, partitioner, false, true, chroma);
    
              xEncodeDontSplit(*tempCS, partitioner);
    
    
    #if ENABLE_QPA_SUB_CTU
              xCheckDQP (*tempCS, partitioner);
    #else
              // this if-check is redundant
    
              if (tempCS->pps->getUseDQP() && partitioner.currQgEnable())
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
              {
                xCheckDQP(*tempCS, partitioner);
              }
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
    
    Nan Hu's avatar
    Nan Hu committed
              tempCS->useDbCost = m_pcEncCfg->getUseEncDbOpt();
              if ( m_bestModeUpdated )
    
    Nan Hu's avatar
    Nan Hu committed
              {
    
    Nan Hu's avatar
    Nan Hu committed
                xCalDebCost( *tempCS, partitioner );
    
    Nan Hu's avatar
    Nan Hu committed
              }
    
    Nan Hu's avatar
    Nan Hu committed
    
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
              DTRACE_MODE_COST(*tempCS, m_pcRdCost->getLambda());
              xCheckBestMode(tempCS, bestCS, partitioner, encTestMode);
    
            }
    
          } // bValid
          else
          {
            tempCS->dist = 0;
            tempCS->fracBits = 0;
            tempCS->cost = MAX_DOUBLE;
    
    Nan Hu's avatar
    Nan Hu committed
            tempCS->costDbOffset = 0;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          }
        }
    
    Yu Han's avatar
    Yu Han committed
     // chroma CU ibc comp
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        else
        {
          bool success = true;
          // chroma tree, reuse luma bv at minimal block level
          // enabled search only when each chroma sub-block has a BV from its luma sub-block
    
    Yu Han's avatar
    Yu Han committed
          assert(tempCS->getIbcLumaCoverage(pu.Cb()) == IBC_LUMA_COVERAGE_FULL);
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          // check if each BV for the chroma sub-block is valid
          //static const UInt unitArea = MIN_PU_SIZE * MIN_PU_SIZE;
          const CompArea lumaArea = CompArea(COMPONENT_Y, pu.chromaFormat, pu.Cb().lumaPos(), recalcSize(pu.chromaFormat, CHANNEL_TYPE_CHROMA, CHANNEL_TYPE_LUMA, pu.Cb().size()));
          PredictionUnit subPu;
          subPu.cs = pu.cs;
          subPu.cu = pu.cu;
          const ComponentID compID = COMPONENT_Cb; // use Cb to represent both Cb and CR, as their structures are the same
          int shiftHor = ::getComponentScaleX(compID, pu.chromaFormat);
          int shiftVer = ::getComponentScaleY(compID, pu.chromaFormat);
          //const ChromaFormat  chFmt = pu.chromaFormat;
    
          for (int y = lumaArea.y; y < lumaArea.y + lumaArea.height; y += MIN_PU_SIZE)
          {
            for (int x = lumaArea.x; x < lumaArea.x + lumaArea.width; x += MIN_PU_SIZE)
            {
              const MotionInfo &curMi = pu.cs->picture->cs->getMotionInfo(Position{ x, y });
    
              subPu.UnitArea::operator=(UnitArea(pu.chromaFormat, Area(x, y, MIN_PU_SIZE, MIN_PU_SIZE)));
              Position offsetRef = subPu.blocks[compID].pos().offset((curMi.bv.getHor() >> shiftHor), (curMi.bv.getVer() >> shiftVer));
              Position refEndPos(offsetRef.x + subPu.blocks[compID].size().width - 1, offsetRef.y + subPu.blocks[compID].size().height - 1 );
    
              if (!subPu.cs->isDecomp(refEndPos, toChannelType(compID)) || !subPu.cs->isDecomp(offsetRef, toChannelType(compID))) // ref block is not yet available for this chroma sub-block
              {
                success = false;
                break;
              }
            }
            if (!success)
              break;
          }
          ////////////////////////////////////////////////////////////////////////////
    
          if (success)
          {
    
    Yu Han's avatar
    Yu Han committed
            //pu.mergeType = MRG_TYPE_IBC;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
            m_pcInterSearch->motionCompensation(pu, REF_PIC_LIST_0, false, true); // luma=0, chroma=1
            m_pcInterSearch->encodeResAndCalcRdInterCU(*tempCS, partitioner, false, false, true);
    
            xEncodeDontSplit(*tempCS, partitioner);
    
            xCheckDQP(*tempCS, partitioner);
    
    Nan Hu's avatar
    Nan Hu committed
            tempCS->useDbCost = m_pcEncCfg->getUseEncDbOpt();
    
    Nan Hu's avatar
    Nan Hu committed
            if ( m_bestModeUpdated )
            {
              xCalDebCost( *tempCS, partitioner );
            }
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
            DTRACE_MODE_COST(*tempCS, m_pcRdCost->getLambda());
    
            xCheckBestMode(tempCS, bestCS, partitioner, encTestMode);
          }
          else
          {
            tempCS->dist = 0;
            tempCS->fracBits = 0;
            tempCS->cost = MAX_DOUBLE;
    
    Nan Hu's avatar
    Nan Hu committed
            tempCS->costDbOffset = 0;
    
    Yu Han's avatar
    Yu Han committed
      // check ibc mode in encoder RD
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      //////////////////////////////////////////////////////////////////////////////////////////////
    
    
    void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
    {
      tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
    
    
      m_pcInterSearch->setAffineModeSelected(false);
    
      if( tempCS->slice->getCheckLDC() )
      {
        m_bestGbiCost[0] = m_bestGbiCost[1] = std::numeric_limits<double>::max();
        m_bestGbiIdx[0] = m_bestGbiIdx[1] = -1;
      }
    
      m_pcInterSearch->resetBufferedUniMotions();
      int gbiLoopNum = (tempCS->slice->isInterB() ? GBI_NUM : 1);
    
      gbiLoopNum = (tempCS->sps->getUseGBi() ? gbiLoopNum : 1);
    
    
      if( tempCS->area.lwidth() * tempCS->area.lheight() < GBI_SIZE_CONSTRAINT )
      {
        gbiLoopNum = 1;
      }
    
      double curBestCost = bestCS->cost;
      double equGBiCost = MAX_DOUBLE;
    
    
    Nan Hu's avatar
    Nan Hu committed
      m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
    
    
      for( int gbiLoopIdx = 0; gbiLoopIdx < gbiLoopNum; gbiLoopIdx++ )
      {
        if( m_pcEncCfg->getUseGBiFast() )
        {
          auto blkCache = dynamic_cast< CacheBlkInfoCtrl* >(m_modeCtrl);
    
          if( blkCache )
          {
            bool isBestInter = blkCache->getInter(bestCS->area);
            uint8_t bestGBiIdx = blkCache->getGbiIdx(bestCS->area);
    
            if( isBestInter && g_GbiSearchOrder[gbiLoopIdx] != GBI_DEFAULT && g_GbiSearchOrder[gbiLoopIdx] != bestGBiIdx )
            {
              continue;
            }
          }
        }
        if( !tempCS->slice->getCheckLDC() )
        {
          if( gbiLoopIdx != 0 && gbiLoopIdx != 3 && gbiLoopIdx != 4 )
          {
            continue;
          }
        }
    
      CodingUnit &cu      = tempCS->addCU( tempCS->area, partitioner.chType );
    
      partitioner.setCUData( cu );
      cu.slice            = tempCS->slice;
      cu.tileIdx          = tempCS->picture->tileMap->getTileIdxMap( tempCS->area.lumaPos() );
      cu.skip             = false;
    
    //cu.affine
      cu.predMode         = MODE_INTER;
      cu.transQuantBypass = encTestMode.lossless;
      cu.chromaQpAdj      = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
      cu.qp               = encTestMode.qp;
      CU::addPUs( cu );
    
    
      cu.GBiIdx = g_GbiSearchOrder[gbiLoopIdx];
      uint8_t gbiIdx = cu.GBiIdx;
      bool  testGbi = (gbiIdx != GBI_DEFAULT);
    
      m_pcInterSearch->predInterSearch( cu, partitioner );
    
    
      gbiIdx = CU::getValidGbiIdx(cu);
      if( testGbi && gbiIdx == GBI_DEFAULT ) // Enabled GBi but the search results is uni.
      {
        tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
        continue;
      }
      CHECK(!(testGbi || (!testGbi && gbiIdx == GBI_DEFAULT)), " !( bTestGbi || (!bTestGbi && gbiIdx == GBI_DEFAULT ) )");
    
      bool isEqualUni = false;
      if( m_pcEncCfg->getUseGBiFast() )
      {
        if( cu.firstPU->interDir != 3 && testGbi == 0 )
        {
          isEqualUni = true;
        }
      }
    
    Tung Nguyen's avatar
    Tung Nguyen committed
      xEncodeInterResidual( tempCS, bestCS, partitioner, encTestMode, 0
                            , 0
                            , &equGBiCost
    
      if( g_GbiSearchOrder[gbiLoopIdx] == GBI_DEFAULT )
        m_pcInterSearch->setAffineModeSelected((bestCS->cus.front()->affine && !(bestCS->cus.front()->firstPU->mergeFlag)));
    
      tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
    
      double skipTH = MAX_DOUBLE;
      skipTH = (m_pcEncCfg->getUseGBiFast() ? 1.05 : MAX_DOUBLE);
      if( equGBiCost > curBestCost * skipTH )
      {
        break;
      }
    
      if( m_pcEncCfg->getUseGBiFast() )
      {
        if( isEqualUni == true && m_pcEncCfg->getIntraPeriod() == -1 )
        {
          break;
        }
      }
      if( g_GbiSearchOrder[gbiLoopIdx] == GBI_DEFAULT && xIsGBiSkip(cu) && m_pcEncCfg->getUseGBiFast() )
      {
        break;
      }
     }  // for( UChar gbiLoopIdx = 0; gbiLoopIdx < gbiLoopNum; gbiLoopIdx++ )
    
    Nan Hu's avatar
    Nan Hu committed
      if ( m_bestModeUpdated && bestCS->cost != MAX_DOUBLE )
      {
        xCalDebCost( *bestCS, partitioner );
      }
    
    }
    
    
    
    
    
    bool EncCu::xCheckRDCostInterIMV( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
    {
      int iIMV = int( ( encTestMode.opts & ETO_IMV ) >> ETO_IMV_SHIFT );
    
      m_pcInterSearch->setAffineModeSelected(false);
    
      // Only int-Pel, 4-Pel and fast 4-Pel allowed
      CHECK( iIMV != 1 && iIMV != 2 && iIMV != 3, "Unsupported IMV Mode" );
      // Fast 4-Pel Mode
    
    
    Nan Hu's avatar
    Nan Hu committed
      m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
    
    
      EncTestMode encTestModeBase = encTestMode;                                        // copy for clearing non-IMV options
      encTestModeBase.opts        = EncTestModeOpts( encTestModeBase.opts & ETO_IMV );  // clear non-IMV options (is that intended?)
    
      tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
    
    
      m_pcInterSearch->resetBufferedUniMotions();
      int gbiLoopNum = (tempCS->slice->isInterB() ? GBI_NUM : 1);
    
      gbiLoopNum = (tempCS->slice->getSPS()->getUseGBi() ? gbiLoopNum : 1);
    
    
      if( tempCS->area.lwidth() * tempCS->area.lheight() < GBI_SIZE_CONSTRAINT )
      {
        gbiLoopNum = 1;
      }
    
    
      double curBestCost = bestCS->cost;
      double equGBiCost = MAX_DOUBLE;
    
      for( int gbiLoopIdx = 0; gbiLoopIdx < gbiLoopNum; gbiLoopIdx++ )
      {
        if( m_pcEncCfg->getUseGBiFast() )
        {
          auto blkCache = dynamic_cast< CacheBlkInfoCtrl* >(m_modeCtrl);
    
          if( blkCache )
          {
            bool isBestInter = blkCache->getInter(bestCS->area);
            uint8_t bestGBiIdx = blkCache->getGbiIdx(bestCS->area);
    
            if( isBestInter && g_GbiSearchOrder[gbiLoopIdx] != GBI_DEFAULT && g_GbiSearchOrder[gbiLoopIdx] != bestGBiIdx )
            {
              continue;
            }
          }
        }
    
        if( !tempCS->slice->getCheckLDC() )
        {
          if( gbiLoopIdx != 0 && gbiLoopIdx != 3 && gbiLoopIdx != 4 )
          {
            continue;
          }
        }
    
        if( m_pcEncCfg->getUseGBiFast() && tempCS->slice->getCheckLDC() && g_GbiSearchOrder[gbiLoopIdx] != GBI_DEFAULT
          && (m_bestGbiIdx[0] >= 0 && g_GbiSearchOrder[gbiLoopIdx] != m_bestGbiIdx[0])
          && (m_bestGbiIdx[1] >= 0 && g_GbiSearchOrder[gbiLoopIdx] != m_bestGbiIdx[1]))
        {
          continue;
        }
    
    Adam Wieckowski's avatar
    Adam Wieckowski committed
      CodingUnit &cu = tempCS->addCU( tempCS->area, partitioner.chType );
    
    Adam Wieckowski's avatar
    Adam Wieckowski committed
      partitioner.setCUData( cu );
      cu.slice            = tempCS->slice;
      cu.tileIdx          = tempCS->picture->tileMap->getTileIdxMap( tempCS->area.lumaPos() );
      cu.skip             = false;
      cu.mmvdSkip = false;
    //cu.affine
      cu.predMode         = MODE_INTER;
      cu.transQuantBypass = encTestMode.lossless;
      cu.chromaQpAdj      = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
      cu.qp               = encTestMode.qp;
    
    Adam Wieckowski's avatar
    Adam Wieckowski committed
      CU::addPUs( cu );
    
      bool testGbi;
      uint8_t gbiIdx;
    
      bool affineAmvrEanbledFlag = cu.slice->getSPS()->getAffineAmvrEnabledFlag();
    
    Adam Wieckowski's avatar
    Adam Wieckowski committed
      cu.GBiIdx = g_GbiSearchOrder[gbiLoopIdx];
      gbiIdx = cu.GBiIdx;
      testGbi = (gbiIdx != GBI_DEFAULT);
    
    Adam Wieckowski's avatar
    Adam Wieckowski committed
      cu.firstPU->interDir = 10;
    
      m_pcInterSearch->predInterSearch( cu, partitioner );
    
      if ( cu.firstPU->interDir <= 3 )
      {
        gbiIdx = CU::getValidGbiIdx(cu);
    
    Adam Wieckowski's avatar
    Adam Wieckowski committed
        return false;
      }
    
    Valeri George's avatar
    Valeri George committed
      if( m_pcEncCfg->getMCTSEncConstraint() && ( ( cu.firstPU->refIdx[L0] < 0 && cu.firstPU->refIdx[L1] < 0 ) || ( !( MCTSHelper::checkMvBufferForMCTSConstraint( *cu.firstPU ) ) ) ) )
      {
        // Do not use this mode
        tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
        continue;
      }
    
      if( testGbi && gbiIdx == GBI_DEFAULT ) // Enabled GBi but the search results is uni.
      {
        tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
        continue;
      }
      CHECK(!(testGbi || (!testGbi && gbiIdx == GBI_DEFAULT)), " !( bTestGbi || (!bTestGbi && gbiIdx == GBI_DEFAULT ) )");
    
      bool isEqualUni = false;
      if( m_pcEncCfg->getUseGBiFast() )
      {
        if( cu.firstPU->interDir != 3 && testGbi == 0 )
        {
          isEqualUni = true;
        }
      }
    
      if ( !CU::hasSubCUNonZeroMVd( cu ) && !CU::hasSubCUNonZeroAffineMVd( cu ) )
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        if (m_modeCtrl->useModeResult(encTestModeBase, tempCS, partitioner))
        {
          std::swap(tempCS, bestCS);
          // store temp best CI for next CU coding
          m_CurrCtx->best = m_CABACEstimator->getCtx();
        }
    
        if ( affineAmvrEanbledFlag )
        {
          tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
          continue;
        }
        else
        {
          return false;
        }
    
    Tung Nguyen's avatar
    Tung Nguyen committed
      xEncodeInterResidual( tempCS, bestCS, partitioner, encTestModeBase, 0
                            , 0
                            , &equGBiCost
    
      tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
    
      double skipTH = MAX_DOUBLE;
      skipTH = (m_pcEncCfg->getUseGBiFast() ? 1.05 : MAX_DOUBLE);
      if( equGBiCost > curBestCost * skipTH )
      {
        break;
      }
    
      if( m_pcEncCfg->getUseGBiFast() )
      {
        if( isEqualUni == true && m_pcEncCfg->getIntraPeriod() == -1 )
        {
          break;
        }
      }
      if( g_GbiSearchOrder[gbiLoopIdx] == GBI_DEFAULT && xIsGBiSkip(cu) && m_pcEncCfg->getUseGBiFast() )
      {
        break;
      }
    
     } // for( UChar gbiLoopIdx = 0; gbiLoopIdx < gbiLoopNum; gbiLoopIdx++ )
    
    
    Nan Hu's avatar
    Nan Hu committed
      if ( m_bestModeUpdated && bestCS->cost != MAX_DOUBLE )
      {
        xCalDebCost( *bestCS, partitioner );
      }
    
    Nan Hu's avatar
    Nan Hu committed
    
    
      return tempCS->slice->getSPS()->getAffineAmvrEnabledFlag() ? validMode : true;
    
    Nan Hu's avatar
    Nan Hu committed
    void EncCu::xCalDebCost( CodingStructure &cs, Partitioner &partitioner, bool calDist )
    
    Nan Hu's avatar
    Nan Hu committed
    {
    
    Nan Hu's avatar
    Nan Hu committed
      if ( cs.cost == MAX_DOUBLE )
      {
    
    Nan Hu's avatar
    Nan Hu committed
        cs.costDbOffset = 0;
    
    Nan Hu's avatar
    Nan Hu committed
      }
    
    Nan Hu's avatar
    Nan Hu committed
    
    
    Nan Hu's avatar
    Nan Hu committed
      if ( cs.slice->getDeblockingFilterDisable() || ( !m_pcEncCfg->getUseEncDbOpt() && !calDist ) )
      {
    
    Nan Hu's avatar
    Nan Hu committed
        return;
    
    Nan Hu's avatar
    Nan Hu committed
      }
    
    Nan Hu's avatar
    Nan Hu committed
    
      m_pcLoopFilter->setEnc(true);
      const ChromaFormat format = cs.area.chromaFormat;
      CodingUnit*                cu = cs.getCU(partitioner.chType);
    
    Nan Hu's avatar
    Nan Hu committed
      const Position lumaPos = cu->Y().valid() ? cu->Y().pos() : recalcPosition( format, cu->chType, CHANNEL_TYPE_LUMA, cu->blocks[cu->chType].pos() );
      bool topEdgeAvai  = lumaPos.y > 0 && ( ( lumaPos.y % 8 ) == 0 );
      bool leftEdgeAvai = lumaPos.x > 0 && ( ( lumaPos.x % 8 ) == 0 );
    
    Nan Hu's avatar
    Nan Hu committed
      bool anyEdgeAvai = topEdgeAvai || leftEdgeAvai;
      cs.costDbOffset = 0;
    
    
    Nan Hu's avatar
    Nan Hu committed
      if ( calDist )
    
    Nan Hu's avatar
    Nan Hu committed
      {
    
    Nan Hu's avatar
    Nan Hu committed
        const UnitArea currCsArea = clipArea( CS::getArea( cs, cs.area, partitioner.chType ), *cs.picture );
        ComponentID compStr = ( CS::isDualITree( cs ) && !isLuma( partitioner.chType ) ) ? COMPONENT_Cb : COMPONENT_Y;
        ComponentID compEnd = ( CS::isDualITree( cs ) && isLuma( partitioner.chType ) ) ? COMPONENT_Y : COMPONENT_Cr;
    
    Nan Hu's avatar
    Nan Hu committed
        Distortion finalDistortion = 0;
    
    Nan Hu's avatar
    Nan Hu committed
        for ( int comp = compStr; comp <= compEnd; comp++ )
    
    Nan Hu's avatar
    Nan Hu committed
        {
    
    Nan Hu's avatar
    Nan Hu committed
          const ComponentID compID = ComponentID( comp );
          CPelBuf org = cs.getOrgBuf( compID );
          CPelBuf reco = cs.getRecoBuf( compID );
          finalDistortion += getDistortionDb( cs, org, reco, compID, currCsArea.block( compID ), false );
    
    Nan Hu's avatar
    Nan Hu committed
        }
        //updated distortion
        cs.dist = finalDistortion;
      }
    
    
    Nan Hu's avatar
    Nan Hu committed
      if ( anyEdgeAvai && m_pcEncCfg->getUseEncDbOpt() )
    
    Nan Hu's avatar
    Nan Hu committed
      {
    
    Nan Hu's avatar
    Nan Hu committed
        ComponentID compStr = ( CS::isDualITree( cs ) && !isLuma( partitioner.chType ) ) ? COMPONENT_Cb : COMPONENT_Y;
        ComponentID compEnd = ( CS::isDualITree( cs ) &&  isLuma( partitioner.chType ) ) ? COMPONENT_Y : COMPONENT_Cr;
    
    Nan Hu's avatar
    Nan Hu committed
    
    
    Nan Hu's avatar
    Nan Hu committed
        const UnitArea currCsArea = clipArea( CS::getArea( cs, cs.area, partitioner.chType ), *cs.picture );
    
    Nan Hu's avatar
    Nan Hu committed
    
        PelStorage&          picDbBuf = m_pcLoopFilter->getDbEncPicYuvBuffer();
    
        //deblock neighbour pixels
    
    Nan Hu's avatar
    Nan Hu committed
        const Size     lumaSize = cu->Y().valid() ? cu->Y().size() : recalcSize( format, cu->chType, CHANNEL_TYPE_LUMA, cu->blocks[cu->chType].size() );
    
    Nan Hu's avatar
    Nan Hu committed
    
        const int verOffset = lumaPos.y > 7 ? 8 : 4;
        const int horOffset = lumaPos.x > 7 ? 8 : 4;
    
    Nan Hu's avatar
    Nan Hu committed
        const UnitArea areaTop(  format, Area( lumaPos.x, lumaPos.y - verOffset, lumaSize.width, verOffset  ) );
        const UnitArea areaLeft( format, Area( lumaPos.x - horOffset, lumaPos.y, horOffset, lumaSize.height ) );
        for ( int compIdx = compStr; compIdx <= compEnd; compIdx++ )
    
    Nan Hu's avatar
    Nan Hu committed
        {
          ComponentID compId = (ComponentID)compIdx;
    
          //Copy current CU's reco to Deblock Pic Buffer
    
    Nan Hu's avatar
    Nan Hu committed
          const CompArea&  curCompArea = currCsArea.block( compId );
          picDbBuf.getBuf( curCompArea ).copyFrom( cs.getRecoBuf( curCompArea ) );
          if ( cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && isLuma( compId ) )
    
    Nan Hu's avatar
    Nan Hu committed
          {
    
    Nan Hu's avatar
    Nan Hu committed
            picDbBuf.getBuf( curCompArea ).rspSignal( m_pcReshape->getInvLUT() );
    
    Nan Hu's avatar
    Nan Hu committed
          }
    
          //left neighbour
    
    Nan Hu's avatar
    Nan Hu committed
          if ( leftEdgeAvai )
    
    Nan Hu's avatar
    Nan Hu committed
          {
            const CompArea&  compArea = areaLeft.block(compId);
    
    Nan Hu's avatar
    Nan Hu committed
            picDbBuf.getBuf( compArea ).copyFrom( cs.picture->getRecoBuf( compArea ) );
            if ( cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && isLuma( compId ) )
    
    Nan Hu's avatar
    Nan Hu committed
            {
    
    Nan Hu's avatar
    Nan Hu committed
              picDbBuf.getBuf( compArea ).rspSignal( m_pcReshape->getInvLUT() );
    
    Nan Hu's avatar
    Nan Hu committed
            }
          }
          //top neighbour
    
    Nan Hu's avatar
    Nan Hu committed
          if ( topEdgeAvai )
    
    Nan Hu's avatar
    Nan Hu committed
          {
    
    Nan Hu's avatar
    Nan Hu committed
            const CompArea&  compArea = areaTop.block( compId );
            picDbBuf.getBuf( compArea ).copyFrom( cs.picture->getRecoBuf( compArea ) );
            if ( cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && isLuma( compId ) )
    
    Nan Hu's avatar
    Nan Hu committed
            {
    
    Nan Hu's avatar
    Nan Hu committed
              picDbBuf.getBuf( compArea ).rspSignal( m_pcReshape->getInvLUT() );
    
    Nan Hu's avatar
    Nan Hu committed
            }
          }
        }
    
        //deblock
    
    Nan Hu's avatar
    Nan Hu committed
        if ( leftEdgeAvai )
    
    Nan Hu's avatar
    Nan Hu committed
        {
    
    Nan Hu's avatar
    Nan Hu committed
          m_pcLoopFilter->xDeblockCU( *cu, EDGE_VER );
    
    Nan Hu's avatar
    Nan Hu committed
        }
    
        if (topEdgeAvai)
        {
    
    Nan Hu's avatar
    Nan Hu committed
          m_pcLoopFilter->xDeblockCU( *cu, EDGE_HOR );
    
    Nan Hu's avatar
    Nan Hu committed
        }
    
        //update current CU SSE
        Distortion distCur = 0;
    
    Nan Hu's avatar
    Nan Hu committed
        for ( int compIdx = compStr; compIdx <= compEnd; compIdx++ )
    
    Nan Hu's avatar
    Nan Hu committed
        {
          ComponentID compId = (ComponentID)compIdx;
    
    Nan Hu's avatar
    Nan Hu committed
          CPelBuf reco = picDbBuf.getBuf( currCsArea.block( compId ) );
          CPelBuf org = cs.getOrgBuf( compId );
          distCur += getDistortionDb( cs, org, reco, compId, currCsArea.block( compId ), true );
    
    Nan Hu's avatar
    Nan Hu committed
        }
    
        //calculate difference between DB_before_SSE and DB_after_SSE for neighbouring CUs
        Distortion distBeforeDb = 0, distAfterDb = 0;
        for (int compIdx = compStr; compIdx <= compEnd; compIdx++)
        {
          ComponentID compId = (ComponentID)compIdx;
    
    Nan Hu's avatar
    Nan Hu committed
          if ( leftEdgeAvai )
    
    Nan Hu's avatar
    Nan Hu committed
          {
    
    Nan Hu's avatar
    Nan Hu committed
            const CompArea&  compArea = areaLeft.block( compId );
            CPelBuf org = cs.picture->getOrigBuf( compArea );
            CPelBuf reco = cs.picture->getRecoBuf( compArea );
            CPelBuf recoDb = picDbBuf.getBuf( compArea );
            distBeforeDb += getDistortionDb( cs, org, reco,   compId, compArea, false );
            distAfterDb  += getDistortionDb( cs, org, recoDb, compId, compArea, true  );
    
    Nan Hu's avatar
    Nan Hu committed
          }
    
    Nan Hu's avatar
    Nan Hu committed
          if ( topEdgeAvai )
    
    Nan Hu's avatar
    Nan Hu committed
          {
    
    Nan Hu's avatar
    Nan Hu committed
            const CompArea&  compArea = areaTop.block( compId );
            CPelBuf org = cs.picture->getOrigBuf( compArea );
            CPelBuf reco = cs.picture->getRecoBuf( compArea );
            CPelBuf recoDb = picDbBuf.getBuf( compArea );
            distBeforeDb += getDistortionDb( cs, org, reco,   compId, compArea, false );
            distAfterDb  += getDistortionDb( cs, org, recoDb, compId, compArea, true  );
    
    Nan Hu's avatar
    Nan Hu committed
          }
        }
    
        //updated cost
        int64_t distTmp = distCur - cs.dist + distAfterDb - distBeforeDb;
        int sign = distTmp < 0 ? -1 : 1;
        distTmp = distTmp < 0 ? -distTmp : distTmp;
    
    Nan Hu's avatar
    Nan Hu committed
        cs.costDbOffset = sign * m_pcRdCost->calcRdCost( 0, distTmp );
    
    Nan Hu's avatar
    Nan Hu committed
      }
    
    Nan Hu's avatar
    Nan Hu committed
    
    
    Nan Hu's avatar
    Nan Hu committed
      m_pcLoopFilter->setEnc( false );
    
    Nan Hu's avatar
    Nan Hu committed
    }
    
    
    Nan Hu's avatar
    Nan Hu committed
    Distortion EncCu::getDistortionDb( CodingStructure &cs, CPelBuf org, CPelBuf reco, ComponentID compID, const CompArea& compArea, bool afterDb )
    
    Nan Hu's avatar
    Nan Hu committed
    {
      Distortion dist = 0;
    #if WCG_EXT
    
    #if JVET_N0671_RDCOST_FIX
      m_pcRdCost->setChromaFormat(cs.sps->getChromaFormatIdc());
    #endif 
    
    Nan Hu's avatar
    Nan Hu committed
      CPelBuf orgLuma = cs.picture->getOrigBuf( cs.area.blocks[COMPONENT_Y] );
    
    Nan Hu's avatar
    Nan Hu committed
      if ( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || (
        m_pcEncCfg->getReshaper() && ( cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() ) ) )
    
    Nan Hu's avatar
    Nan Hu committed
      {
    
    Nan Hu's avatar
    Nan Hu committed
        if ( compID == COMPONENT_Y && !afterDb && !m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled())
    
    Nan Hu's avatar
    Nan Hu committed
        {
    
    Nan Hu's avatar
    Nan Hu committed
          CompArea    tmpArea( COMPONENT_Y, cs.area.chromaFormat, Position( 0, 0 ), compArea.size() );
          PelBuf tmpRecLuma = m_tmpStorageLCU->getBuf( tmpArea );
          tmpRecLuma.copyFrom( reco );
          tmpRecLuma.rspSignal( m_pcReshape->getInvLUT() );
          dist += m_pcRdCost->getDistPart( org, tmpRecLuma, cs.sps->getBitDepth( toChannelType( compID ) ), compID, DF_SSE_WTD, &orgLuma );
    
    Nan Hu's avatar
    Nan Hu committed
        }
        else
        {
    
    Nan Hu's avatar
    Nan Hu committed
          dist += m_pcRdCost->getDistPart( org, reco, cs.sps->getBitDepth( toChannelType( compID ) ), compID, DF_SSE_WTD, &orgLuma );
    
    Nan Hu's avatar
    Nan Hu committed
        }
      }
    
    Nan Hu's avatar
    Nan Hu committed
      else if ( m_pcEncCfg->getReshaper() && cs.slice->getReshapeInfo().getUseSliceReshaper() && cs.slice->isIntra() ) //intra slice
    
    Nan Hu's avatar
    Nan Hu committed
      {
    
    Nan Hu's avatar
    Nan Hu committed
        if ( compID == COMPONENT_Y && afterDb )
    
    Nan Hu's avatar
    Nan Hu committed
        {
    
    Nan Hu's avatar
    Nan Hu committed
          CompArea    tmpArea( COMPONENT_Y, cs.area.chromaFormat, Position( 0, 0 ), compArea.size() );
          PelBuf tmpRecLuma = m_tmpStorageLCU->getBuf( tmpArea );
          tmpRecLuma.copyFrom( reco );
          tmpRecLuma.rspSignal( m_pcReshape->getFwdLUT() );
          dist += m_pcRdCost->getDistPart( org, tmpRecLuma, cs.sps->getBitDepth( toChannelType( compID ) ), compID, DF_SSE );
    
    Nan Hu's avatar
    Nan Hu committed
        }
        else
        {
    
    Nan Hu's avatar
    Nan Hu committed
          dist += m_pcRdCost->getDistPart( org, reco, cs.sps->getBitDepth(toChannelType( compID ) ), compID, DF_SSE );
    
    Nan Hu's avatar
    Nan Hu committed
        }
      }
      else
    #endif
      {
    
    Nan Hu's avatar
    Nan Hu committed
        dist = m_pcRdCost->getDistPart( org, reco, cs.sps->getBitDepth( toChannelType( compID ) ), compID, DF_SSE );
    
    Nan Hu's avatar
    Nan Hu committed
      }
      return dist;
    }
    
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    void EncCu::xEncodeInterResidual(   CodingStructure *&tempCS
                                      , CodingStructure *&bestCS
                                      , Partitioner &partitioner
                                      , const EncTestMode& encTestMode
                                      , int residualPass
                                      , bool* bestHasNonResi
                                      , double* equGBiCost
    
    {
      if( residualPass == 1 && encTestMode.lossless )
      {
        return;
      }
    
      CodingUnit*            cu        = tempCS->getCU( partitioner.chType );
      double   bestCostInternal        = MAX_DOUBLE;
    
      double           bestCostBegin   = bestCS->cost;
      CodingUnit*      prevBestCU      = bestCS->getCU( partitioner.chType );
      uint8_t          prevBestSbt     = ( prevBestCU == nullptr ) ? 0 : prevBestCU->sbtInfo;
    
      bool              swapped        = false; // avoid unwanted data copy
      bool             reloadCU        = false;
    
    Xiang Li's avatar
    Xiang Li committed
      // Not allow very big |MVd| to avoid CABAC crash caused by too large MVd. Normally no impact on coding performance.
      const int maxMvd = 1 << 15;
      const PredictionUnit& pu = *cu->firstPU;
      if (!cu->affine)
      {
        if ((pu.refIdx[0] >= 0 && (pu.mvd[0].getAbsHor() >= maxMvd || pu.mvd[0].getAbsVer() >= maxMvd))
          || (pu.refIdx[1] >= 0 && (pu.mvd[1].getAbsHor() >= maxMvd || pu.mvd[1].getAbsVer() >= maxMvd)))
        {
          return;
        }
      }
    
      else
      {
        for (int refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
        {
          if (pu.refIdx[refList] >= 0)
          {
            for (int ctrlP = 1 + (cu->affineType == AFFINEMODEL_6PARAM); ctrlP >= 0; ctrlP--)
            {
              if (pu.mvdAffi[refList][ctrlP].getAbsHor() >= maxMvd || pu.mvdAffi[refList][ctrlP].getAbsVer() >= maxMvd)
              {
                return;
              }
            }
          }
        }
      }
    
    #if JVET_N0334_MVCLIPPING
      // avoid MV exceeding 18-bit dynamic range
      const int maxMv = 1 << 17;
      if (!cu->affine && !pu.mergeFlag)
      {
        if ( (pu.refIdx[0] >= 0 && (pu.mv[0].getAbsHor() >= maxMv || pu.mv[0].getAbsVer() >= maxMv))
          || (pu.refIdx[1] >= 0 && (pu.mv[1].getAbsHor() >= maxMv || pu.mv[1].getAbsVer() >= maxMv)))
        {
          return;
        }
      }
      if (cu->affine && !pu.mergeFlag)
      {
        for (int refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
        {
          if (pu.refIdx[refList] >= 0)
          {
            for (int ctrlP = 1 + (cu->affineType == AFFINEMODEL_6PARAM); ctrlP >= 0; ctrlP--)
            {
              if (pu.mvAffi[refList][ctrlP].getAbsHor() >= maxMv || pu.mvAffi[refList][ctrlP].getAbsVer() >= maxMv)
              {
                return;
              }
            }
          }
        }
      }
    #endif
    
      const bool mtsAllowed = tempCS->sps->getUseInterMTS() && CU::isInter( *cu ) && partitioner.currArea().lwidth() <= MTS_INTER_MAX_CU_SIZE && partitioner.currArea().lheight() <= MTS_INTER_MAX_CU_SIZE;
    
      uint8_t sbtAllowed = cu->checkAllowedSbt();
      uint8_t numRDOTried = 0;
      Distortion sbtOffDist = 0;
      bool    sbtOffRootCbf = 0;
      double  sbtOffCost      = MAX_DOUBLE;
      double  currBestCost = MAX_DOUBLE;
      bool    doPreAnalyzeResi = ( sbtAllowed || mtsAllowed ) && residualPass == 0;
    
      m_pcInterSearch->initTuAnalyzer();
      if( doPreAnalyzeResi )
      {
        m_pcInterSearch->calcMinDistSbt( *tempCS, *cu, sbtAllowed );
      }
    
      auto    slsSbt = dynamic_cast<SaveLoadEncInfoSbt*>( m_modeCtrl );
      int     slShift = 4 + std::min( (int)gp_sizeIdxInfo->idxFrom( cu->lwidth() ) + (int)gp_sizeIdxInfo->idxFrom( cu->lheight() ), 9 );
      Distortion curPuSse = m_pcInterSearch->getEstDistSbt( NUMBER_SBT_MODE );
      uint8_t currBestSbt = 0;
      uint8_t currBestTrs = MAX_UCHAR;
      uint8_t histBestSbt = MAX_UCHAR;
      uint8_t histBestTrs = MAX_UCHAR;
      m_pcInterSearch->setHistBestTrs( MAX_UCHAR, MAX_UCHAR );
      if( doPreAnalyzeResi )
      {
        if( m_pcInterSearch->getSkipSbtAll() && !mtsAllowed ) //emt is off
        {
          histBestSbt = 0; //try DCT2
          m_pcInterSearch->setHistBestTrs( histBestSbt, histBestTrs );
        }
        else
        {
          assert( curPuSse != std::numeric_limits<uint64_t>::max() );
          uint16_t compositeSbtTrs = slsSbt->findBestSbt( cu->cs->area, (uint32_t)( curPuSse >> slShift ) );
          histBestSbt = ( compositeSbtTrs >> 0 ) & 0xff;
          histBestTrs = ( compositeSbtTrs >> 8 ) & 0xff;
          if( m_pcInterSearch->getSkipSbtAll() && CU::isSbtMode( histBestSbt ) ) //special case, skip SBT when loading SBT
          {
            histBestSbt = 0; //try DCT2
          }
          m_pcInterSearch->setHistBestTrs( histBestSbt, histBestTrs );
        }
      }
    
        if( reloadCU )
        {
          if( bestCost == bestCS->cost ) //The first EMT pass didn't become the bestCS, so we clear the TUs generated
          {
            tempCS->clearTUs();
          }
          else if( false == swapped )
          {
            tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
            tempCS->copyStructure( *bestCS, partitioner.chType );
            tempCS->getPredBuf().copyFrom( bestCS->getPredBuf() );
            bestCost = bestCS->cost;
            cu       = tempCS->getCU( partitioner.chType );
            swapped = true;
          }
          else
          {
            tempCS->clearTUs();
            bestCost = bestCS->cost;
            cu       = tempCS->getCU( partitioner.chType );
          }
    
          //we need to restart the distortion for the new tempCS, the bit count and the cost
          tempCS->dist     = 0;
          tempCS->fracBits = 0;
          tempCS->cost     = MAX_DOUBLE;
    
    Nan Hu's avatar
    Nan Hu committed
          tempCS->costDbOffset = 0;
    
        if( skipResidual || histBestSbt == MAX_UCHAR || !CU::isSbtMode( histBestSbt ) )
        {
    
        m_pcInterSearch->encodeResAndCalcRdInterCU( *tempCS, partitioner, skipResidual );
    
        numRDOTried += mtsAllowed ? 2 : 1;
    
        xEncodeDontSplit( *tempCS, partitioner );
    
        xCheckDQP( *tempCS, partitioner );
    
    
        if( NULL != bestHasNonResi && (bestCostInternal > tempCS->cost) )
        {
          bestCostInternal = tempCS->cost;
    
          if (!(tempCS->getPU(partitioner.chType)->mhIntraFlag))
    
          if (tempCS->getPU(partitioner.chType)->mhIntraFlag)
    
    Nan Hu's avatar
    Nan Hu committed
            tempCS->costDbOffset = 0;
    
        currBestCost = tempCS->cost;
        sbtOffCost = tempCS->cost;
        sbtOffDist = tempCS->dist;
        sbtOffRootCbf = cu->rootCbf;
        currBestSbt = CU::getSbtInfo( cu->firstTU->mtsIdx > 1 ? SBT_OFF_MTS : SBT_OFF_DCT, 0 );
        currBestTrs = cu->firstTU->mtsIdx;
    
        if( cu->lwidth() <= MAX_TB_SIZEY && cu->lheight() <= MAX_TB_SIZEY )
    
        {
          CHECK( tempCS->tus.size() != 1, "tu must be only one" );
        }
    
    #if WCG_EXT
        DTRACE_MODE_COST( *tempCS, m_pcRdCost->getLambda( true ) );
    #else
        DTRACE_MODE_COST( *tempCS, m_pcRdCost->getLambda() );
    #endif
        xCheckBestMode( tempCS, bestCS, partitioner, encTestMode );