Skip to content
Snippets Groups Projects
EncCu.cpp 178 KiB
Newer Older
  • Learn to ignore specific revisions
  • #if !JVET_M0253_HASH_ME
    
        const uint8_t iteration = encTestMode.lossless ? 1 : 2;
    
    rlliao's avatar
    rlliao committed
        for( uint8_t noResidualPass = 0; noResidualPass < iteration; noResidualPass++ )
    
    #else
        uint8_t iteration;
        uint8_t iterationBegin = m_modeCtrl->getIsHashPerfectMatch() ? 1 : 0;
        if (encTestMode.lossless)
        {
          iteration = 1;
          iterationBegin = 0;
        }
        else
        {
          iteration = 2;
        }
        for (uint8_t noResidualPass = iterationBegin; noResidualPass < iteration; ++noResidualPass)
    #endif
    
    rlliao's avatar
    rlliao committed
          for( uint8_t mrgHADIdx = 0; mrgHADIdx < triangleNumMrgSATDCand; mrgHADIdx++ )
    
    rlliao's avatar
    rlliao committed
            uint8_t mergeCand = triangleRdModeList[mrgHADIdx];
    
    rlliao's avatar
    rlliao committed
            if ( ( (noResidualPass != 0) && trianglecandHasNoResidual[mergeCand] )
              || ( (noResidualPass == 0) && bestIsSkip ) )
    
    #if JVET_M0883_TRIANGLE_SIGNALING
            bool    splitDir = m_triangleModeTest[mergeCand].m_splitDir;
            uint8_t candIdx0 = m_triangleModeTest[mergeCand].m_candIdx0;
            uint8_t candIdx1 = m_triangleModeTest[mergeCand].m_candIdx1;
    #else
    
    rlliao's avatar
    rlliao committed
            bool    splitDir = g_triangleCombination[mergeCand][0];
            uint8_t candIdx0 = g_triangleCombination[mergeCand][1];
            uint8_t candIdx1 = g_triangleCombination[mergeCand][2];
    
    
            CodingUnit &cu = tempCS->addCU(tempCS->area, partitioner.chType);
    
            partitioner.setCUData(cu);
            cu.slice = tempCS->slice;
    
    Karsten Suehring's avatar
    Karsten Suehring committed
    #if HEVC_TILES_WPP
            cu.tileIdx          = tempCS->picture->tileMap->getTileIdxMap( tempCS->area.lumaPos() );
    #endif
    
            cu.skip = false;
            cu.predMode = MODE_INTER;
            cu.transQuantBypass = encTestMode.lossless;
            cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
            cu.qp = encTestMode.qp;
            cu.triangle = true;
            cu.mmvdSkip = false;
            cu.GBiIdx   = GBI_DEFAULT;
            PredictionUnit &pu = tempCS->addPU(cu, partitioner.chType);
    
    
    #if JVET_M0883_TRIANGLE_SIGNALING
            pu.triangleSplitDir = splitDir;
            pu.triangleMergeIdx0 = candIdx0;
            pu.triangleMergeIdx1 = candIdx1;
    #else
    
    rlliao's avatar
    rlliao committed
            pu.mergeIdx = mergeCand;
    
    #if JVET_M0883_TRIANGLE_SIGNALING
            PU::spanTriangleMotionInfo(pu, triangleMrgCtx, splitDir, candIdx0, candIdx1 );
    #else
    
    rlliao's avatar
    rlliao committed
            PU::spanTriangleMotionInfo(pu, triangleMrgCtx, mergeCand, splitDir, candIdx0, candIdx1 );
    
    Valeri George's avatar
    Valeri George committed
    #if JVET_M0445_MCTS
            if( m_pcEncCfg->getMCTSEncConstraint() && ( !( MCTSHelper::checkMvBufferForMCTSConstraint( *cu.firstPU ) ) ) )
            {
              // Do not use this mode
              tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
              return;
            }
    #endif
    
    rlliao's avatar
    rlliao committed
            if( tempBufSet )
    
    rlliao's avatar
    rlliao committed
              tempCS->getPredBuf().copyFrom( triangleWeightedBuffer[mergeCand] );
    
    rlliao's avatar
    rlliao committed
              triangleBuffer[candIdx0] = m_acMergeBuffer[candIdx0].getBuf( localUnitArea );
              triangleBuffer[candIdx1] = m_acMergeBuffer[candIdx1].getBuf( localUnitArea );
    
              PelUnitBuf predBuf         = tempCS->getPredBuf();
    
    #if JVET_M0328_KEEP_ONE_WEIGHT_GROUP
              m_pcInterSearch->weightedTriangleBlk( pu, splitDir, MAX_NUM_CHANNEL_TYPE, predBuf, triangleBuffer[candIdx0], triangleBuffer[candIdx1] );
    #else
    
    rlliao's avatar
    rlliao committed
              m_pcInterSearch->weightedTriangleBlk( pu, PU::getTriangleWeights(pu, triangleMrgCtx, candIdx0, candIdx1), splitDir, MAX_NUM_CHANNEL_TYPE, predBuf, triangleBuffer[candIdx0], triangleBuffer[candIdx1] );
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    #if JVET_M0464_UNI_MTS
            xEncodeInterResidual( tempCS, bestCS, partitioner, encTestMode, noResidualPass, NULL, ( noResidualPass == 0 ? &trianglecandHasNoResidual[mergeCand] : NULL ) );
    #else
    
    rlliao's avatar
    rlliao committed
            xEncodeInterResidual( tempCS, bestCS, partitioner, encTestMode, noResidualPass, NULL, true, ( (noResidualPass == 0 ) ? &trianglecandHasNoResidual[mergeCand] : NULL ) );
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    #endif
    
    
            if (m_pcEncCfg->getUseFastDecisionForMerge() && !bestIsSkip)
            {
              bestIsSkip = bestCS->getCU(partitioner.chType)->rootCbf == 0;
            }
            tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
    
    rlliao's avatar
    rlliao committed
          }// end loop mrgHADIdx
    
    Nan Hu's avatar
    Nan Hu committed
    #if JVET_M0428_ENC_DB_OPT
      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
      }
    
    Nan Hu's avatar
    Nan Hu committed
    #endif
    
    void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
    {
      if( m_modeCtrl->getFastDeltaQp() )
      {
        return;
      }
    
      if ( bestCS->area.lumaSize().width < 8 || bestCS->area.lumaSize().height < 8 )
      {
        return;
      }
    
    Nan Hu's avatar
    Nan Hu committed
    #if JVET_M0428_ENC_DB_OPT
      m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
    #endif
    
      const Slice &slice = *tempCS->slice;
    
      CHECK( slice.getSliceType() == I_SLICE, "Affine Merge modes not available for I-slices" );
    
      tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
    
      AffineMergeCtx affineMergeCtx;
      const SPS &sps = *tempCS->sps;
    
      MergeCtx mrgCtx;
    
      if ( sps.getSBTMVPEnabledFlag() )
    
      {
        Size bufSize = g_miScaling.scale( tempCS->area.lumaSize() );
        mrgCtx.subPuMvpMiBuf = MotionBuf( m_SubPuMiBuf, bufSize );
        affineMergeCtx.mrgCtx = &mrgCtx;
      }
    
      {
        // first get merge candidates
        CodingUnit cu( tempCS->area );
        cu.cs = tempCS;
        cu.predMode = MODE_INTER;
        cu.slice = tempCS->slice;
    #if HEVC_TILES_WPP
        cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap( tempCS->area.lumaPos() );
    #endif
    
    Huanbang Chen's avatar
    Huanbang Chen committed
        cu.mmvdSkip = false;
    
    
        PredictionUnit pu( tempCS->area );
        pu.cu = &cu;
        pu.cs = tempCS;
    
        PU::getAffineMergeCand( pu, affineMergeCtx );
    
        if ( affineMergeCtx.numValidMergeCand <= 0 )
        {
          return;
        }
      }
    
      bool candHasNoResidual[AFFINE_MRG_MAX_NUM_CANDS];
      for ( uint32_t ui = 0; ui < affineMergeCtx.numValidMergeCand; ui++ )
      {
        candHasNoResidual[ui] = false;
      }
    
      bool                                        bestIsSkip = false;
      uint32_t                                    uiNumMrgSATDCand = affineMergeCtx.numValidMergeCand;
      PelUnitBuf                                  acMergeBuffer[AFFINE_MRG_MAX_NUM_CANDS];
      static_vector<uint32_t, AFFINE_MRG_MAX_NUM_CANDS>  RdModeList;
      bool                                        mrgTempBufSet = false;
    
      for ( uint32_t i = 0; i < AFFINE_MRG_MAX_NUM_CANDS; i++ )
      {
        RdModeList.push_back( i );
      }
    
      if ( m_pcEncCfg->getUseFastMerge() )
      {
        uiNumMrgSATDCand = std::min( NUM_AFF_MRG_SATD_CAND, affineMergeCtx.numValidMergeCand );
        bestIsSkip = false;
    
        if ( auto blkCache = dynamic_cast<CacheBlkInfoCtrl*>(m_modeCtrl) )
        {
          bestIsSkip = blkCache->isSkip( tempCS->area );
        }
    
        static_vector<double, AFFINE_MRG_MAX_NUM_CANDS> candCostList;
    
        // 1. Pass: get SATD-cost for selected candidates and reduce their count
        if ( !bestIsSkip )
        {
          RdModeList.clear();
          mrgTempBufSet = true;
          const double sqrtLambdaForFirstPass = m_pcRdCost->getMotionLambda( encTestMode.lossless );
    
          CodingUnit &cu = tempCS->addCU( tempCS->area, partitioner.chType );
    
          partitioner.setCUData( cu );
          cu.slice = tempCS->slice;
    #if HEVC_TILES_WPP
          cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap( tempCS->area.lumaPos() );
    #endif
          cu.skip = false;
          cu.affine = true;
          cu.predMode = MODE_INTER;
          cu.transQuantBypass = encTestMode.lossless;
          cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
          cu.qp = encTestMode.qp;
    
          PredictionUnit &pu = tempCS->addPU( cu, partitioner.chType );
    
          DistParam distParam;
          const bool bUseHadamard = !encTestMode.lossless;
          m_pcRdCost->setDistParam( distParam, tempCS->getOrgBuf().Y(), m_acMergeBuffer[0].Y(), sps.getBitDepth( CHANNEL_TYPE_LUMA ), COMPONENT_Y, bUseHadamard );
    
          const UnitArea localUnitArea( tempCS->area.chromaFormat, Area( 0, 0, tempCS->area.Y().width, tempCS->area.Y().height ) );
    
          for ( uint32_t uiMergeCand = 0; uiMergeCand < affineMergeCtx.numValidMergeCand; uiMergeCand++ )
          {
            acMergeBuffer[uiMergeCand] = m_acMergeBuffer[uiMergeCand].getBuf( localUnitArea );
    
            // set merge information
            pu.interDir = affineMergeCtx.interDirNeighbours[uiMergeCand];
            pu.mergeFlag = true;
            pu.mergeIdx = uiMergeCand;
            cu.affineType = affineMergeCtx.affineType[uiMergeCand];
            cu.GBiIdx = affineMergeCtx.GBiIdx[uiMergeCand];
    
            pu.mergeType = affineMergeCtx.mergeType[uiMergeCand];
            if ( pu.mergeType == MRG_TYPE_SUBPU_ATMVP )
            {
              pu.refIdx[0] = affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][0].refIdx;
              pu.refIdx[1] = affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][0].refIdx;
              PU::spanMotionInfo( pu, mrgCtx );
            }
            else
            {
              PU::setAllAffineMvField( pu, affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0], REF_PIC_LIST_0 );
              PU::setAllAffineMvField( pu, affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1], REF_PIC_LIST_1 );
    
              PU::spanMotionInfo( pu );
            }
    
            distParam.cur = acMergeBuffer[uiMergeCand].Y();
    
            m_pcInterSearch->motionCompensation( pu, acMergeBuffer[uiMergeCand] );
    
            Distortion uiSad = distParam.distFunc( distParam );
            uint32_t   uiBitsCand = uiMergeCand + 1;
            if ( uiMergeCand == tempCS->slice->getMaxNumAffineMergeCand() - 1 )
            {
              uiBitsCand--;
            }
            double cost = (double)uiSad + (double)uiBitsCand * sqrtLambdaForFirstPass;
    
            static_vector<int, AFFINE_MRG_MAX_NUM_CANDS> emptyList;
    
            updateCandList( uiMergeCand, cost, RdModeList, candCostList
    
              , emptyList, -1
    
              , uiNumMrgSATDCand );
    
    
            CHECK( std::min( uiMergeCand + 1, uiNumMrgSATDCand ) != RdModeList.size(), "" );
          }
    
          // Try to limit number of candidates using SATD-costs
          for ( uint32_t i = 1; i < uiNumMrgSATDCand; i++ )
          {
            if ( candCostList[i] > MRG_FAST_RATIO * candCostList[0] )
            {
              uiNumMrgSATDCand = i;
              break;
            }
          }
    
          tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
        }
        else
        {
          uiNumMrgSATDCand = affineMergeCtx.numValidMergeCand;
        }
      }
    
    
    #if !JVET_M0253_HASH_ME
    
      const uint32_t iteration = encTestMode.lossless ? 1 : 2;
    
      // 2. Pass: check candidates using full RD test
      for ( uint32_t uiNoResidualPass = 0; uiNoResidualPass < iteration; uiNoResidualPass++ )
    
    #else
      uint32_t iteration;
      uint32_t iterationBegin = m_modeCtrl->getIsHashPerfectMatch() ? 1 : 0;
      if (encTestMode.lossless)
      {
        iteration = 1;
        iterationBegin = 0;
      }
      else
      {
        iteration = 2;
      }
      for (uint32_t uiNoResidualPass = iterationBegin; uiNoResidualPass < iteration; ++uiNoResidualPass)
    #endif
    
      {
        for ( uint32_t uiMrgHADIdx = 0; uiMrgHADIdx < uiNumMrgSATDCand; uiMrgHADIdx++ )
        {
          uint32_t uiMergeCand = RdModeList[uiMrgHADIdx];
    
          if ( ((uiNoResidualPass != 0) && candHasNoResidual[uiMergeCand])
            || ((uiNoResidualPass == 0) && bestIsSkip) )
          {
            continue;
          }
    
          // first get merge candidates
          CodingUnit &cu = tempCS->addCU( tempCS->area, partitioner.chType );
    
          partitioner.setCUData( cu );
          cu.slice = tempCS->slice;
    #if HEVC_TILES_WPP
          cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap( tempCS->area.lumaPos() );
    #endif
          cu.skip = false;
          cu.affine = true;
          cu.predMode = MODE_INTER;
          cu.transQuantBypass = encTestMode.lossless;
          cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
          cu.qp = encTestMode.qp;
          PredictionUnit &pu = tempCS->addPU( cu, partitioner.chType );
    
          // set merge information
          pu.mergeFlag = true;
          pu.mergeIdx = uiMergeCand;
          pu.interDir = affineMergeCtx.interDirNeighbours[uiMergeCand];
          cu.affineType = affineMergeCtx.affineType[uiMergeCand];
          cu.GBiIdx = affineMergeCtx.GBiIdx[uiMergeCand];
    
          pu.mergeType = affineMergeCtx.mergeType[uiMergeCand];
          if ( pu.mergeType == MRG_TYPE_SUBPU_ATMVP )
          {
            pu.refIdx[0] = affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][0].refIdx;
            pu.refIdx[1] = affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][0].refIdx;
            PU::spanMotionInfo( pu, mrgCtx );
          }
          else
          {
            PU::setAllAffineMvField( pu, affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0], REF_PIC_LIST_0 );
            PU::setAllAffineMvField( pu, affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1], REF_PIC_LIST_1 );
    
            PU::spanMotionInfo( pu );
          }
    
    
    Valeri George's avatar
    Valeri George committed
    #if JVET_M0445_MCTS
          if( m_pcEncCfg->getMCTSEncConstraint() && ( !( MCTSHelper::checkMvBufferForMCTSConstraint( *cu.firstPU ) ) ) )
          {
            // Do not use this mode
            tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
            return;
          }
    #endif
    
          if ( mrgTempBufSet )
          {
            tempCS->getPredBuf().copyFrom( acMergeBuffer[uiMergeCand] );
          }
          else
          {
            m_pcInterSearch->motionCompensation( pu );
          }
    
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    #if JVET_M0464_UNI_MTS
          xEncodeInterResidual( tempCS, bestCS, partitioner, encTestMode, uiNoResidualPass, NULL, ( uiNoResidualPass == 0 ? &candHasNoResidual[uiMergeCand] : NULL ) );
    #else
    
          xEncodeInterResidual( tempCS, bestCS, partitioner, encTestMode, uiNoResidualPass, NULL, true, ((uiNoResidualPass == 0) ? &candHasNoResidual[uiMergeCand] : NULL) );
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    #endif
    
    
          if ( m_pcEncCfg->getUseFastDecisionForMerge() && !bestIsSkip )
          {
            bestIsSkip = bestCS->getCU( partitioner.chType )->rootCbf == 0;
          }
          tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
        }// end loop uiMrgHADIdx
    
        if ( uiNoResidualPass == 0 && m_pcEncCfg->getUseEarlySkipDetection() )
        {
          const CodingUnit     &bestCU = *bestCS->getCU( partitioner.chType );
          const PredictionUnit &bestPU = *bestCS->getPU( partitioner.chType );
    
          if ( bestCU.rootCbf == 0 )
          {
            if ( bestPU.mergeFlag )
            {
              m_modeCtrl->setEarlySkipDetected();
            }
            else if ( m_pcEncCfg->getMotionEstimationSearchMethod() != MESEARCH_SELECTIVE )
            {
              int absolute_MV = 0;
    
              for ( uint32_t uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ )
              {
                if ( slice.getNumRefIdx( RefPicList( uiRefListIdx ) ) > 0 )
                {
                  absolute_MV += bestPU.mvd[uiRefListIdx].getAbsHor() + bestPU.mvd[uiRefListIdx].getAbsVer();
                }
              }
    
              if ( absolute_MV == 0 )
              {
                m_modeCtrl->setEarlySkipDetected();
              }
            }
          }
        }
      }
    
    Nan Hu's avatar
    Nan Hu committed
    #if JVET_M0428_ENC_DB_OPT
    
    Nan Hu's avatar
    Nan Hu committed
      if ( m_bestModeUpdated && bestCS->cost != MAX_DOUBLE )
      {
        xCalDebCost( *bestCS, partitioner );
      }
    
    Nan Hu's avatar
    Nan Hu committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    //////////////////////////////////////////////////////////////////////////////////////////////
    
    Yu Han's avatar
    Yu Han committed
    // ibc merge/skip mode check
    void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode)
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    {
    
    Yu Han's avatar
    Yu Han committed
      assert(tempCS->chType != CHANNEL_TYPE_CHROMA); // chroma IBC is derived
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
    
    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
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      {
        return;
      }
      const SPS &sps = *tempCS->sps;
    
      tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
      MergeCtx mergeCtx;
    
    
    
      if (sps.getSBTMVPEnabledFlag())
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      {
        Size bufSize = g_miScaling.scale(tempCS->area.lumaSize());
        mergeCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize);
      }
    
      {
        // first get merge candidates
        CodingUnit cu(tempCS->area);
        cu.cs = tempCS;
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
        cu.predMode = MODE_IBC;
    #else
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        cu.predMode = MODE_INTER;
    
    Yu Han's avatar
    Yu Han committed
        cu.ibc = true;
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        cu.slice = tempCS->slice;
    #if HEVC_TILES_WPP
        cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap(tempCS->area.lumaPos());
    #endif
        PredictionUnit pu(tempCS->area);
        pu.cu = &cu;
        pu.cs = tempCS;
        cu.mmvdSkip = false;
        pu.mmvdMergeFlag = false;
        cu.triangle = false;
    
    #if JVET_M0170_MRG_SHARELIST
        pu.shareParentPos = tempCS->sharedBndPos;
        pu.shareParentSize = tempCS->sharedBndSize;
    #endif
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
        PU::getIBCMergeCandidates(pu, mergeCtx);
    #else
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        PU::getInterMergeCandidates(pu, mergeCtx
          , 0
        );
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      }
    
      int candHasNoResidual[MRG_MAX_NUM_CANDS];
      for (unsigned int ui = 0; ui < mergeCtx.numValidMergeCand; ui++)
      {
        candHasNoResidual[ui] = 0;
      }
    
      bool                                        bestIsSkip = false;
      unsigned                                    numMrgSATDCand = mergeCtx.numValidMergeCand;
      static_vector<unsigned, MRG_MAX_NUM_CANDS>  RdModeList(MRG_MAX_NUM_CANDS);
      for (unsigned i = 0; i < MRG_MAX_NUM_CANDS; i++)
      {
        RdModeList[i] = i;
      }
    
      //{
        static_vector<double, MRG_MAX_NUM_CANDS>  candCostList(MRG_MAX_NUM_CANDS, MAX_DOUBLE);
        // 1. Pass: get SATD-cost for selected candidates and reduce their count
        {
          const double sqrtLambdaForFirstPass = m_pcRdCost->getMotionLambda(encTestMode.lossless);
    
          CodingUnit &cu = tempCS->addCU(CS::getArea(*tempCS, tempCS->area, (const ChannelType)partitioner.chType), (const ChannelType)partitioner.chType);
    
          partitioner.setCUData(cu);
          cu.slice = tempCS->slice;
    #if HEVC_TILES_WPP
          cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap(tempCS->area.lumaPos());
    #endif
          cu.skip = false;
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
          cu.predMode = MODE_IBC;
    #else
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          cu.predMode = MODE_INTER;
    
    Yu Han's avatar
    Yu Han committed
          cu.ibc = true;
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          cu.transQuantBypass = encTestMode.lossless;
          cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
          cu.qp = encTestMode.qp;
          cu.mmvdSkip = false;
          cu.triangle = false;
          DistParam distParam;
          const bool bUseHadamard = !encTestMode.lossless;
          PredictionUnit &pu = tempCS->addPU(cu, partitioner.chType); //tempCS->addPU(cu);
          pu.mmvdMergeFlag = false;
          Picture* refPic = pu.cu->slice->getPic();
          const CPelBuf refBuf = refPic->getRecoBuf(pu.blocks[COMPONENT_Y]);
          const Pel*        piRefSrch = refBuf.buf;
    
    Taoran Lu's avatar
    Taoran Lu committed
    #if JVET_M0427_INLOOP_RESHAPER
          if (tempCS->slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
          {
            const CompArea &area = cu.blocks[COMPONENT_Y];
            CompArea    tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
            PelBuf tmpLuma = m_tmpStorageLCU->getBuf(tmpArea);
            tmpLuma.copyFrom(tempCS->getOrgBuf().Y());
            tmpLuma.rspSignal(m_pcReshape->getFwdLUT());
            m_pcRdCost->setDistParam(distParam, tmpLuma, refBuf, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, bUseHadamard);
          }
          else
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          m_pcRdCost->setDistParam(distParam, tempCS->getOrgBuf().Y(), refBuf, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, bUseHadamard);
          int refStride = refBuf.stride;
          const UnitArea localUnitArea(tempCS->area.chromaFormat, Area(0, 0, tempCS->area.Y().width, tempCS->area.Y().height));
          int numValidBv = mergeCtx.numValidMergeCand;
          for (unsigned int mergeCand = 0; mergeCand < mergeCtx.numValidMergeCand; mergeCand++)
          {
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
            if (mergeCtx.interDirNeighbours[mergeCand] != 1)
            {
              numValidBv--;
              continue;
            }
            if (tempCS->slice->getRefPic(REF_PIC_LIST_0, mergeCtx.mvFieldNeighbours[mergeCand << 1].refIdx)->getPOC() != tempCS->slice->getPOC())
            {
              numValidBv--;
              continue;
            }
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
            mergeCtx.setMergeInfo(pu, mergeCand); // set bv info in merge mode
            const int cuPelX = pu.Y().x;
            const int cuPelY = pu.Y().y;
            int roiWidth = pu.lwidth();
            int roiHeight = pu.lheight();
            const int picWidth = pu.cs->slice->getSPS()->getPicWidthInLumaSamples();
            const int picHeight = pu.cs->slice->getSPS()->getPicHeightInLumaSamples();
            const unsigned int  lcuWidth = pu.cs->slice->getSPS()->getMaxCUWidth();
            int xPred = pu.bv.getHor();
            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
    #if JVET_M0428_ENC_DB_OPT
            tempCS->costDbOffset = 0;
    #endif
    
    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
    #if JVET_M0428_ENC_DB_OPT
      m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
    #endif
    
    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];
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          if (mergeCtx.interDirNeighbours[mergeCand] != 1)
          {
            continue;
          }
          if (tempCS->slice->getRefPic(REF_PIC_LIST_0, mergeCtx.mvFieldNeighbours[mergeCand << 1].refIdx)->getPOC() != tempCS->slice->getPOC())
          {
            continue;
          }
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          if (!(numResidualPass == 1 && candHasNoResidual[mergeCand] == 1))
          {
            if (!(bestIsSkip && (numResidualPass == 0)))
            {
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    #if JVET_M0464_UNI_MTS
              {
    #else
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
              unsigned char considerEmtSecondPass = 0;
              bool skipSecondEmtPass = true;
              bool hasResidual[2] = { false, false };
              double emtCost[2] = { MAX_DOUBLE, MAX_DOUBLE };
    
              // CU-level optimization
              for (unsigned char emtCuFlag = 0; emtCuFlag <= considerEmtSecondPass; emtCuFlag++)
              {
                if (m_pcEncCfg->getFastInterEMT() && emtCuFlag && skipSecondEmtPass)
                {
                  continue;
                }
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    #endif
    
    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;
    #if HEVC_TILES_WPP
                cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap(tempCS->area.lumaPos());
    #endif
                cu.skip = false;
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
                cu.predMode = MODE_IBC;
    #else
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
                cu.predMode = MODE_INTER;
    
    Yu Han's avatar
    Yu Han committed
                cu.ibc = true;
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
                cu.transQuantBypass = encTestMode.lossless;
                cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
                cu.qp = encTestMode.qp;
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    #if !JVET_M0464_UNI_MTS
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
                cu.emtFlag = false;
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    #endif
    
    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;
                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
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
                if (tempCS->pps->getUseDQP() && (partitioner.currDepth) <= tempCS->pps->getMaxCuDQPDepth())
                {
                  xCheckDQP(*tempCS, partitioner);
                }
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    #if !JVET_M0464_UNI_MTS
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
                hasResidual[emtCuFlag] = cu.rootCbf;
                emtCost[emtCuFlag] = tempCS->cost;
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    #endif
    
    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);
              }
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    #if !JVET_M0464_UNI_MTS
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
              if (numResidualPass == 0 && (emtCost[0] <= emtCost[1] ? !hasResidual[0] : !hasResidual[1]))
    
                {
                  // If no residual when allowing for one, then set mark to not try case where residual is forced to 0
                  candHasNoResidual[mergeCand] = 1;
                }
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
                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 JVET_M0428_ENC_DB_OPT
      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
      }
    
    Nan Hu's avatar
    Nan Hu committed
    #endif
    
    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 (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;
      }
    
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
    
    
    Nan Hu's avatar
    Nan Hu committed
    #if JVET_M0428_ENC_DB_OPT
        m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
    #endif
    
    
    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;
    #if HEVC_TILES_WPP
        cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap(tempCS->area.lumaPos());
    #endif
        cu.skip = false;
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
        cu.predMode = MODE_IBC;
    #else
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        cu.predMode = MODE_INTER;
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        cu.transQuantBypass = encTestMode.lossless;
        cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
        cu.qp = encTestMode.qp;
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC==0
    
    Yu Han's avatar
    Yu Han committed
        cu.ibc = true;
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        cu.imv = 0;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
        CU::addPUs(cu);
    
    
    Nan Hu's avatar
    Nan Hu committed
    #if JVET_M0428_ENC_DB_OPT
        m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
    #endif
    
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        PredictionUnit& pu = *cu.firstPU;
        cu.mmvdSkip = false;
        pu.mmvdMergeFlag = false;
    
    
    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
    
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
        pu.refIdx[REF_PIC_LIST_0] = MAX_NUM_REF; // last idx in the list
    
    Yu Han's avatar
    Yu Han committed
    #else
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        pu.refIdx[REF_PIC_LIST_0] = pu.cs->slice->getNumRefIdx(REF_PIC_LIST_0) - 1; // last idx in the list
    
    Yu Han's avatar
    Yu Han committed
    #endif
    
    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
    #if JVET_M0464_UNI_MTS
            {
    #else
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
            double    bestCost = bestCS->cost;
            unsigned char    considerEmtSecondPass = 0;
            bool      skipSecondEmtPass = true;
            double    emtFirstPassCost = MAX_DOUBLE;
    
            // CU-level optimization
    
            for (unsigned char emtCuFlag = 0; emtCuFlag <= considerEmtSecondPass; emtCuFlag++)
            {
              if (m_pcEncCfg->getFastInterEMT() && emtCuFlag && skipSecondEmtPass)
              {
                continue;
              }
    
              tempCS->getCU(tempCS->chType)->emtFlag = emtCuFlag;
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
              m_pcInterSearch->encodeResAndCalcRdInterCU(*tempCS, partitioner, false, true, chroma);
    
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    #if !JVET_M0464_UNI_MTS
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
              if (m_pcEncCfg->getFastInterEMT())
              {
                emtFirstPassCost = (!emtCuFlag) ? tempCS->cost : emtFirstPassCost;
              }
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
              xEncodeDontSplit(*tempCS, partitioner);
    
    
    #if ENABLE_QPA_SUB_CTU
              xCheckDQP (*tempCS, partitioner);
    #else
              // this if-check is redundant
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
              if (tempCS->pps->getUseDQP() && (partitioner.currDepth) <= tempCS->pps->getMaxCuDQPDepth())
              {
                xCheckDQP(*tempCS, partitioner);
              }
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    
    
    Nan Hu's avatar
    Nan Hu committed
    #if JVET_M0428_ENC_DB_OPT
              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
    #endif
    
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
              DTRACE_MODE_COST(*tempCS, m_pcRdCost->getLambda());
              xCheckBestMode(tempCS, bestCS, partitioner, encTestMode);
    
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    #if !JVET_M0464_UNI_MTS
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
              //now we check whether the second pass should be skipped or not
              if (!emtCuFlag && considerEmtSecondPass)
              {
                static const double thresholdToSkipEmtSecondPass = 1.1; // Skip checking EMT transforms
                if (m_pcEncCfg->getFastInterEMT() && (!cu.firstTU->cbf[COMPONENT_Y] || emtFirstPassCost > bestCost * thresholdToSkipEmtSecondPass))
                {
                  skipSecondEmtPass = true;
                }
                else //EMT will be checked
                {
                  if (bestCost == bestCS->cost) //The first EMT pass didn't become the bestCS, so we clear the TUs generated
                  {
                    tempCS->clearTUs();
                  }
                  else
                  {
                    tempCS->initStructData(bestCS->currQP[bestCS->chType], bestCS->isLossless);
    
                    tempCS->copyStructure(*bestCS, partitioner.chType);
                    tempCS->getPredBuf().copyFrom(bestCS->getPredBuf());
                  }
    
                  //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
    #if JVET_M0428_ENC_DB_OPT
                  tempCS->costDbOffset = 0;
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
                }
              }
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
            }
    
          } // bValid
          else
          {
            tempCS->dist = 0;
            tempCS->fracBits = 0;
            tempCS->cost = MAX_DOUBLE;
    
    Nan Hu's avatar
    Nan Hu committed
    #if JVET_M0428_ENC_DB_OPT
            tempCS->costDbOffset = 0;
    #endif
    
    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
    #if JVET_M0428_ENC_DB_OPT
            tempCS->useDbCost = m_pcEncCfg->getUseEncDbOpt();
    
    Nan Hu's avatar
    Nan Hu committed
            if ( m_bestModeUpdated )
            {
              xCalDebCost( *tempCS, partitioner );
            }
    
    Nan Hu's avatar
    Nan Hu committed
    #endif
    
    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
    #if JVET_M0428_ENC_DB_OPT
            tempCS->costDbOffset = 0;
    #endif
    
    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);