Skip to content
Snippets Groups Projects
IntraSearch.cpp 336 KiB
Newer Older
  • Learn to ignore specific revisions
  •             int64_t sadCr = 0;
                int64_t satdCr = 0;
                CodingStructure& cs = *(pu.cs);
    
                DistParam distParamSadCb;
                DistParam distParamSatdCb;
                DistParam distParamSadCr;
                DistParam distParamSatdCr;
    
                cccmStorage[sub][idx] = m_cccmStorage[sub][idx].getBuf(localUnitArea);
    
                CompArea areaCb = pu.Cb();
                PelBuf orgCb = cs.getOrgBuf(areaCb);
                CompArea areaCr = pu.Cr();
                PelBuf orgCr = cs.getOrgBuf(areaCr);
    
                m_pcRdCost->setDistParam(distParamSadCb, orgCb, cccmStorage[sub][idx].Cb(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_CHROMA), COMPONENT_Cb, false);
                m_pcRdCost->setDistParam(distParamSatdCb, orgCb, cccmStorage[sub][idx].Cb(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_CHROMA), COMPONENT_Cb, true);
                distParamSadCb.applyWeight = false;
                distParamSatdCb.applyWeight = false;
                m_pcRdCost->setDistParam(distParamSadCr, orgCr, cccmStorage[sub][idx].Cr(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_CHROMA), COMPONENT_Cr, false);
                m_pcRdCost->setDistParam(distParamSatdCr, orgCr, cccmStorage[sub][idx].Cr(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_CHROMA), COMPONENT_Cr, true);
    
                distParamSadCr.applyWeight = false;
                distParamSatdCr.applyWeight = false;
    
                predIntraCCCM(pu, cccmStorage[sub][idx].Cb(), cccmStorage[sub][idx].Cr(), mode);
    
                sadCb = distParamSadCb.distFunc(distParamSadCb) * 2;
                satdCb = distParamSatdCb.distFunc(distParamSatdCb);
                sad += std::min(sadCb, satdCb);
                sadCr = distParamSadCr.distFunc(distParamSadCr) * 2;
                satdCr = distParamSatdCr.distFunc(distParamSatdCr);
                sad += std::min(sadCr, satdCr);
    
                satdCccmSortedCost[sub][idx] = sad;
    
                if (sad < bestCccmCost[sub])
                {
                  bestCccmCost[sub] = sad;
                }
              }
            }
          }
          int tempCccmIdx = 0;
          int64_t tempCccmCost = 0;
    #if MMLM
          for (int i = 1; i < 4; i++)
    #else
          for (int i = 1; i < 3; i++)
    #endif
          {
            for (int j = i + 1; j < CCCM_NUM_MODES; j++)
            {
              if (satdCccmSortedCost[0][j] < satdCccmSortedCost[0][i])
              {
                tempCccmIdx = satdCccmModeList[0][i];
                satdCccmModeList[0][i] = satdCccmModeList[0][j];
                satdCccmModeList[0][j] = tempCccmIdx;
    
                tempCccmCost = satdCccmSortedCost[0][i];
                satdCccmSortedCost[0][i] = satdCccmSortedCost[0][j];
                satdCccmSortedCost[0][j] = tempCccmCost;
              }
            }
          }
    
    #if MMLM
          bool isCccmModeEnabledInRdo[2][MMLM_T_IDX + 1] = { false };
          isCccmModeEnabledInRdo[0][satdCccmModeList[0][0]] = true;
          for (int i = 1; i < 4; i++)
    #else
          bool isCccmModeEnabledInRdo[MDLM_T_IDX + 1] = { false };
          isCccmModeEnabledInRdo[satdCccmModeList[0]] = true;
          for (int i = 1; i < 3; i++)
    #endif
          {
            if (satdCccmSortedCost[0][i] >= 1.15 * bestCccmCost[0])
            {
              break;
            }
            isCccmModeEnabledInRdo[0][satdCccmModeList[0][i]] = true;
          }
    
          if (pu.cu->slice->getSPS()->getUseCccm() == 2)
          {
            if (bestCccmCost[1] < bestCccmCost[0])
            {
    #if MMLM
              for (int i = 0; i < 4; i++)
    #else
              for (int i = 0; i < 3; i++)
    #endif
              {
                if (isCccmModeEnabledInRdo[0][satdCccmModeList[0][i]] && (satdCccmSortedCost[0][i] >= 1.2 * bestCccmCost[1]))
                {
                  isCccmModeEnabledInRdo[0][satdCccmModeList[0][i]] = false;
                }
                else
                {
                  bestCccmCost[0] = satdCccmSortedCost[0][i];
                }
              }
            }
            else
            {
              bestCccmCost[1] = bestCccmCost[0];
            }
    
            tempCccmIdx = 0;
            tempCccmCost = 0;
            for (int i = 1; i < 2; i++)
            {
              for (int j = i + 1; j < 6; j++)
              {
                if (satdCccmSortedCost[1][j] < satdCccmSortedCost[1][i])
                {
                  tempCccmIdx = satdCccmModeList[1][i];
                  satdCccmModeList[1][i] = satdCccmModeList[1][j];
                  satdCccmModeList[1][j] = tempCccmIdx;
    
                  tempCccmCost = satdCccmSortedCost[1][i];
                  satdCccmSortedCost[1][i] = satdCccmSortedCost[1][j];
                  satdCccmSortedCost[1][j] = tempCccmCost;
                }
              }
            }
    
            isCccmModeEnabledInRdo[1][satdCccmModeList[1][0]] = true;
            for (int i = 1; i < 2; i++)
            {
              if (satdCccmSortedCost[1][i] >= CCCM_NO_SUB_WEIGHT * bestCccmCost[1])
              {
                if (satdCccmSortedCost[1][i - 1] > bestCccmCost[0])
                {
                  bestCccmCost[0] = satdCccmSortedCost[1][i - 1];
                }
                bestCccmCost[1] = satdCccmSortedCost[1][i - 1];
                break;
              }
              isCccmModeEnabledInRdo[1][satdCccmModeList[1][i]] = true;
            }
            if (m_skipCCCMSATD == false)
            {
              m_skipCCCMSATD = true;
              for (int i = 0; i < (MMLM_T_IDX + 1); i++)
              {
                m_isCccmNoSubModeEnabledInRdo[i] = isCccmModeEnabledInRdo[1][i];
              }
            }
          }
          pu.cccmFlag = 0;
          pu.cccmNoSubFlag = 0;
    #else
    
    Vadim Seregin's avatar
    Vadim Seregin committed
          int64_t satdCccmSortedCost[CCCM_NUM_MODES];
          int satdCccmModeList[CCCM_NUM_MODES];
    
          for (int i = 0; i < CCCM_NUM_MODES; i++)
    
          {
            satdCccmSortedCost[i] = LLONG_MAX; // for the mode not pre-select by SATD, do RDO by default, so set the initial value 0.
            satdCccmModeList[i] = chromaCandCccmModes[i];
          }
          int64_t bestCccmCost = LLONG_MAX;
    
          bool isCccmFullEnabled = PU::cccmSingleModeAvail(pu, LM_CHROMA_IDX);
          bool isCccmLeftEnabled = PU::isLeftCccmMode(pu, MDLM_L_IDX);
          bool isCccmTopEnabled = PU::isTopCccmMode(pu, MDLM_T_IDX);
    #if MMLM
          bool isMultiCccmFullEnabled = PU::cccmMultiModeAvail(pu, MMLM_CHROMA_IDX);
          bool isMultiCccmLeftEnabled = PU::cccmMultiModeAvail(pu, MMLM_L_IDX);
          bool isMultiCccmTopEnabled = PU::cccmMultiModeAvail(pu, MMLM_T_IDX);
    #endif
    
          const UnitArea localUnitArea(cs.area.chromaFormat, Area(0, 0, (pu.Cb().width) << 1, (pu.Cb().height) << 1));
    
    Vadim Seregin's avatar
    Vadim Seregin committed
          PelUnitBuf cccmStorage[CCCM_NUM_MODES];
    
    
          pu.cccmFlag = 1;
          xGetLumaRecPixels(pu, pu.Cb());
    
    
    Vadim Seregin's avatar
    Vadim Seregin committed
          bool isCCCMEnabled = false;
    
          for (int idx = 0; idx < CCCM_NUM_MODES; idx++)
    
          {
            int mode = chromaCandCccmModes[idx];
            if (idx == 0)
            {
              isCCCMEnabled = isCccmFullEnabled;
              pu.cccmFlag = 1;
            }
            else if (idx == 1)
            {
              isCCCMEnabled = isCccmLeftEnabled;
              pu.cccmFlag = 2;
            }
            else if (idx == 2)
            {
              isCCCMEnabled = isCccmTopEnabled;
              pu.cccmFlag = 3;
            }
    #if MMLM
            else if (idx == 3)
            {
              isCCCMEnabled = isMultiCccmFullEnabled;
              pu.cccmFlag = 1;
            }
            else if (idx == 4)
            {
              isCCCMEnabled = isMultiCccmLeftEnabled;
              pu.cccmFlag = 2;
            }
            else if (idx == 5)
            {
              isCCCMEnabled = isMultiCccmTopEnabled;
              pu.cccmFlag = 3;
            }
    #endif
    
            if (isCCCMEnabled)
            {
              pu.intraDir[1] = mode; // temporary assigned, for SATD checking.
    
              int64_t sad = 0;
              int64_t sadCb = 0;
              int64_t satdCb = 0;
              int64_t sadCr = 0;
              int64_t satdCr = 0;
              CodingStructure& cs = *(pu.cs);
    
              DistParam distParamSadCb;
              DistParam distParamSatdCb;
              DistParam distParamSadCr;
              DistParam distParamSatdCr;
    
              cccmStorage[idx] = m_cccmStorage[idx].getBuf(localUnitArea);
    
              CompArea areaCb = pu.Cb();
              PelBuf orgCb = cs.getOrgBuf(areaCb);
              CompArea areaCr = pu.Cr();
              PelBuf orgCr = cs.getOrgBuf(areaCr);
    
              m_pcRdCost->setDistParam(distParamSadCb, orgCb, cccmStorage[idx].Cb(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_CHROMA), COMPONENT_Cb, false);
              m_pcRdCost->setDistParam(distParamSatdCb, orgCb, cccmStorage[idx].Cb(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_CHROMA), COMPONENT_Cb, true);
              distParamSadCb.applyWeight = false;
              distParamSatdCb.applyWeight = false;
              m_pcRdCost->setDistParam(distParamSadCr, orgCr, cccmStorage[idx].Cr(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_CHROMA), COMPONENT_Cr, false);
              m_pcRdCost->setDistParam(distParamSatdCr, orgCr, cccmStorage[idx].Cr(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_CHROMA), COMPONENT_Cr, true);
    
              distParamSadCr.applyWeight = false;
              distParamSatdCr.applyWeight = false;
    
              predIntraCCCM(pu, cccmStorage[idx].Cb(), cccmStorage[idx].Cr(), mode);
    
              sadCb = distParamSadCb.distFunc(distParamSadCb) * 2;
              satdCb = distParamSatdCb.distFunc(distParamSatdCb);
              sad += std::min(sadCb, satdCb);
              sadCr = distParamSadCr.distFunc(distParamSadCr) * 2;
              satdCr = distParamSatdCr.distFunc(distParamSatdCr);
              sad += std::min(sadCr, satdCr);
    
              satdCccmSortedCost[idx] = sad;
    
              if (sad < bestCccmCost)
              {
                bestCccmCost = sad;
              }
            }
          }
    
          int tempCccmIdx = 0;
          int64_t tempCccmCost = 0;
    #if MMLM
          for (int i = 1; i < 4; i++)
    #else
          for (int i = 1; i < 3; i++)
    #endif
          {
    
    Vadim Seregin's avatar
    Vadim Seregin committed
            for (int j = i + 1; j < CCCM_NUM_MODES; j++)
    
            {
              if (satdCccmSortedCost[j] < satdCccmSortedCost[i])
              {
                tempCccmIdx = satdCccmModeList[i];
                satdCccmModeList[i] = satdCccmModeList[j];
                satdCccmModeList[j] = tempCccmIdx;
    
                tempCccmCost = satdCccmSortedCost[i];
                satdCccmSortedCost[i] = satdCccmSortedCost[j];
                satdCccmSortedCost[j] = tempCccmCost;
              }
            }
          }
    
    #if MMLM
          bool isCccmModeEnabledInRdo[MMLM_T_IDX + 1] = { false };
          isCccmModeEnabledInRdo[satdCccmModeList[0]] = true;
          for (int i = 1; i < 4; i++)
    #else
          bool isCccmModeEnabledInRdo[MDLM_T_IDX + 1] = { false };
          isCccmModeEnabledInRdo[satdCccmModeList[0]] = true;
          for (int i = 1; i < 3; i++)
    #endif
          {
            if (satdCccmSortedCost[i] >= 1.15 * bestCccmCost)
            {
              break;
            }
            isCccmModeEnabledInRdo[satdCccmModeList[i]] = true;
          }
    
          pu.cccmFlag = 0;
    #endif
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if MMLM
          m_encPreRDRun = false;
    #endif
    
          // sort the mode based on the cost from small to large.
          int tempIdx = 0;
          int64_t tempCost = 0;
          for (int i = uiMinMode; i <= uiMaxMode - 1; i++)
          {
            for (int j = i + 1; j <= uiMaxMode - 1; j++)
            {
              if (satdSortedCost[j] < satdSortedCost[i])
              {
                tempIdx = satdModeList[i];
                satdModeList[i] = satdModeList[j];
                satdModeList[j] = tempIdx;
    
                tempCost = satdSortedCost[i];
                satdSortedCost[i] = satdSortedCost[j];
                satdSortedCost[j] = tempCost;
    
              }
            }
          }
          int reducedModeNumber = 2; // reduce the number of chroma modes
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if MMLM
          reducedModeNumber += 3;    // Match number of RDs with the anchor
    #endif
    
          for (int i = 0; i < reducedModeNumber; i++)
          {
            modeIsEnable[satdModeList[uiMaxMode - 1 - i]] = 0; // disable the last reducedModeNumber modes
          }
    
    #if JVET_AC0147_CCCM_NO_SUBSAMPLING
          if (pu.cu->slice->getSPS()->getUseCccm() == 2)
          {
            if (satdSortedCost[uiMaxMode - 1 - reducedModeNumber] > bestCccmCost[0])
            {
              modeIsEnable[satdModeList[uiMaxMode - 1 - reducedModeNumber]] = 0; // disable the last reducedModeNumber modes
            }
            else if (satdSortedCost[uiMaxMode - 1 - reducedModeNumber] < bestCccmCost[0])
            {
              for (int i = 3; i > 0; i--)
              {
                if ((satdCccmSortedCost[0][i] > satdSortedCost[uiMaxMode - 1 - reducedModeNumber]) && (isCccmModeEnabledInRdo[0][satdCccmModeList[0][i]]))
                {
                  isCccmModeEnabledInRdo[0][satdCccmModeList[0][i]] = false;
                  break;
                }
              }
            }
            if (satdSortedCost[uiMaxMode - 1 - reducedModeNumber] < bestCccmCost[1])
            {
              if ((satdCccmSortedCost[1][1] > satdSortedCost[uiMaxMode - 1 - reducedModeNumber]) && (isCccmModeEnabledInRdo[1][satdCccmModeList[1][1]]))
              {
                isCccmModeEnabledInRdo[1][satdCccmModeList[1][1]] = false;
              }
            }
          }
    #endif
    
          bool testBDPCM = true;
          testBDPCM = testBDPCM && CU::bdpcmAllowed(cu, COMPONENT_Cb) && cu.ispMode == 0 && cu.mtsFlag == 0 && cu.lfnstIdx == 0;
    
    #if JVET_Z0050_DIMD_CHROMA_FUSION
          double dBestNonLmCost = MAX_DOUBLE;
    #if ENABLE_DIMD
          int bestNonLmMode = (cu.slice->getSPS()->getUseDimd()) ? DIMD_CHROMA_IDX : DM_CHROMA_IDX;
    #else
          int bestNonLmMode = DM_CHROMA_IDX;
    #endif
    #endif
    
          for (int32_t uiMode = uiMinMode - (2 * int(testBDPCM)); uiMode < uiMaxMode; uiMode++)
    
            int chromaIntraMode;
    
    
            if (uiMode < 0)
            {
                cu.bdpcmModeChroma = -uiMode;
    
                chromaIntraMode = cu.bdpcmModeChroma == 2 ? chromaCandModes[1] : chromaCandModes[2];
    
              chromaIntraMode = chromaCandModes[uiMode];
    
    
              cu.bdpcmModeChroma = 0;
              if( PU::isLMCMode( chromaIntraMode ) && ! PU::isLMCModeEnabled( pu, chromaIntraMode ) )
              {
                continue;
              }
              if (!modeIsEnable[chromaIntraMode] && PU::isLMCModeEnabled(pu, chromaIntraMode)) // when CCLM is disable, then MDLM is disable. not use satd checking
              {
                continue;
              }
    
    #if JVET_Z0050_DIMD_CHROMA_FUSION && ENABLE_DIMD
              if (chromaIntraMode == DIMD_CHROMA_IDX && !cu.slice->getSPS()->getUseDimd()) // when DIMD is disable, then DIMD_CHROMA is disable.
              {
                continue;
              }
    
    #endif
    #if JVET_AC0071_DBV
              if (chromaIntraMode == DBV_CHROMA_IDX && !PU::hasChromaBvFlag(pu))
              {
                continue;
              }
    
            cs.setDecomp( pu.Cb(), false );
            cs.dist = baseDist;
            //----- restore context models -----
            m_CABACEstimator->getCtx() = ctxStart;
    
            //----- chroma coding -----
            pu.intraDir[1] = chromaIntraMode;
    
    
            xRecurIntraChromaCodingQT( cs, partitioner, bestCostSoFar, ispType );
            if( lumaUsesISP && cs.dist == MAX_UINT )
            {
              continue;
            }
    
            if (cs.sps->getTransformSkipEnabledFlag())
    
            uint64_t fracBits   = xGetIntraFracBitsQT( cs, partitioner, false, true, -1, ispType );
    
            Distortion uiDist = cs.dist;
            double    dCost   = m_pcRdCost->calcRdCost( fracBits, uiDist - baseDist );
    
            //----- compare -----
            if( dCost < dBestCost )
            {
    
              if( lumaUsesISP && dCost < bestCostSoFar )
              {
                bestCostSoFar = dCost;
              }
    
              for( uint32_t i = getFirstComponentOfChannel( CHANNEL_TYPE_CHROMA ); i < numberValidComponents; i++ )
              {
                const CompArea &area = pu.blocks[i];
    
                saveCS.getRecoBuf     ( area ).copyFrom( cs.getRecoBuf   ( area ) );
    #if KEEP_PRED_AND_RESI_SIGNALS
                saveCS.getPredBuf     ( area ).copyFrom( cs.getPredBuf   ( area ) );
                saveCS.getResiBuf     ( area ).copyFrom( cs.getResiBuf   ( area ) );
    
    Taoran Lu's avatar
    Taoran Lu committed
    #endif
                saveCS.getPredBuf     ( area ).copyFrom( cs.getPredBuf   (area ) );
                cs.picture->getPredBuf( area ).copyFrom( cs.getPredBuf   (area ) );
    
    Seungwook Hong's avatar
    Seungwook Hong committed
    #if JVET_Z0118_GDR
                cs.updateReconMotIPM(area);
    #else
    
                cs.picture->getRecoBuf( area ).copyFrom( cs.getRecoBuf( area ) );
    
    Seungwook Hong's avatar
    Seungwook Hong committed
    #endif
    
    
                for( uint32_t j = 0; j < saveCS.tus.size(); j++ )
                {
                  saveCS.tus[j]->copyComponentFrom( *orgTUs[j], area.compID );
                }
              }
    
              dBestCost  = dCost;
              uiBestDist = uiDist;
              uiBestMode = chromaIntraMode;
    
              bestBDPCMMode = cu.bdpcmModeChroma;
    
    #if JVET_Z0050_DIMD_CHROMA_FUSION
            bool findBestNonLm = !PU::isLMCMode(chromaIntraMode) && !cu.bdpcmModeChroma && pu.cs->slice->isIntra();
            if (findBestNonLm && dCost < dBestNonLmCost)
            {
              bestNonLmMode = chromaIntraMode;
              dBestNonLmCost = dCost;
            }
    #endif
    
    Che-Wei Kuo's avatar
    Che-Wei Kuo committed
    #if JVET_AA0126_GLM
          for (int32_t uiMode = 0; uiMode < NUM_LMC_MODE; uiMode++)
          {
            int chromaIntraMode = LM_CHROMA_IDX + uiMode;
            if ( PU::isLMCModeEnabled( pu, chromaIntraMode ) && PU::hasGlmFlag( pu, chromaIntraMode ) )
            {
              if ( satdGlmIdcBest[chromaIntraMode - LM_CHROMA_IDX].isActive() )
              {
                pu.intraDir[1] = chromaIntraMode;
                pu.glmIdc      = satdGlmIdcBest[chromaIntraMode - LM_CHROMA_IDX];
    
                // RD search replicated from above
                cs.setDecomp( pu.Cb(), false );
                cs.dist = baseDist;
                //----- restore context models -----
                m_CABACEstimator->getCtx() = ctxStart;
    
                xRecurIntraChromaCodingQT( cs, partitioner, bestCostSoFar, ispType );
                if( lumaUsesISP && cs.dist == MAX_UINT )
                {
                  continue;
                }
    
                if (cs.sps->getTransformSkipEnabledFlag())
                {
                  m_CABACEstimator->getCtx() = ctxStart;
                }
    
                uint64_t fracBits = xGetIntraFracBitsQT( cs, partitioner, false, true, -1, ispType );
                Distortion uiDist = cs.dist;
                double    dCost   = m_pcRdCost->calcRdCost( fracBits, uiDist - baseDist );
    
                //----- compare -----
                if( dCost < dBestCost )
                {
                  if( lumaUsesISP && dCost < bestCostSoFar )
                  {
                    bestCostSoFar = dCost;
                  }
                  for( uint32_t i = getFirstComponentOfChannel( CHANNEL_TYPE_CHROMA ); i < numberValidComponents; i++ )
                  {
                    const CompArea &area = pu.blocks[i];
    
                    saveCS.getRecoBuf     ( area ).copyFrom( cs.getRecoBuf   ( area ) );
    #if KEEP_PRED_AND_RESI_SIGNALS
                    saveCS.getPredBuf     ( area ).copyFrom( cs.getPredBuf   ( area ) );
                    saveCS.getResiBuf     ( area ).copyFrom( cs.getResiBuf   ( area ) );
    #endif
                    saveCS.getPredBuf     ( area ).copyFrom( cs.getPredBuf   (area ) );
                    cs.picture->getPredBuf( area ).copyFrom( cs.getPredBuf   (area ) );
                    cs.picture->getRecoBuf( area ).copyFrom( cs.getRecoBuf( area ) );
    
                    for( uint32_t j = 0; j < saveCS.tus.size(); j++ )
                    {
                      saveCS.tus[j]->copyComponentFrom( *orgTUs[j], area.compID );
                    }
                  }
    
                  dBestCost       = dCost;
                  uiBestDist      = uiDist;
                  uiBestMode      = chromaIntraMode;
                  bestBDPCMMode   = cu.bdpcmModeChroma;
                  bestGlmIdc      = pu.glmIdc;
                }
    
    #if !JVET_AB0092_GLM_WITH_LUMA
    
    Che-Wei Kuo's avatar
    Che-Wei Kuo committed
                if ( chromaIntraMode == LM_CHROMA_IDX && !bestGlmIdc.isActive() )
                {
                  break;
                }
    
    Che-Wei Kuo's avatar
    Che-Wei Kuo committed
              }
            }
          }
          
          pu.glmIdc.setAllZero();
    #endif
    
    
    #if JVET_Z0050_DIMD_CHROMA_FUSION
          // RDO for chroma fusion mode
          for (int32_t uiMode = 0; uiMode < 1; uiMode++)
          {
            int chromaIntraMode = bestNonLmMode;
    #if ENABLE_DIMD
    
            if (!pu.cs->slice->isIntra() && cu.slice->getSPS()->getUseDimd())
    
              chromaIntraMode = DIMD_CHROMA_IDX;
    
    #endif
            if (PU::hasChromaFusionFlag(pu, chromaIntraMode))
    
              pu.isChromaFusion = true;
              cs.setDecomp(pu.Cb(), false);
              cs.dist = baseDist;
              //----- restore context models -----
    
              m_CABACEstimator->getCtx() = ctxStart;
    
    
              //----- chroma coding -----
              pu.intraDir[1] = chromaIntraMode;
              xRecurIntraChromaCodingQT(cs, partitioner, bestCostSoFar, ispType);
              if (lumaUsesISP && cs.dist == MAX_UINT)
    
              if (cs.sps->getTransformSkipEnabledFlag())
    
                m_CABACEstimator->getCtx() = ctxStart;
              }
              uint64_t fracBits = xGetIntraFracBitsQT(cs, partitioner, false, true, -1, ispType);
              Distortion uiDist = cs.dist;
              double    dCost = m_pcRdCost->calcRdCost(fracBits, uiDist - baseDist);
              if (dCost < dBestCost)
              {
                if (lumaUsesISP && dCost < bestCostSoFar)
    
                  bestCostSoFar = dCost;
    
                for (uint32_t i = getFirstComponentOfChannel(CHANNEL_TYPE_CHROMA); i < numberValidComponents; i++)
                {
                  const CompArea &area = pu.blocks[i];
                  saveCS.getRecoBuf(area).copyFrom(cs.getRecoBuf(area));
                  saveCS.getPredBuf(area).copyFrom(cs.getPredBuf(area));
                  saveCS.getResiBuf(area).copyFrom(cs.getResiBuf(area));
                  saveCS.getPredBuf(area).copyFrom(cs.getPredBuf(area));
                  cs.picture->getPredBuf(area).copyFrom(cs.getPredBuf(area));
                  cs.picture->getRecoBuf(area).copyFrom(cs.getRecoBuf(area));
                  for (uint32_t j = 0; j < saveCS.tus.size(); j++)
                  {
                    saveCS.tus[j]->copyComponentFrom(*orgTUs[j], area.compID);
                  }
                }
                dBestCost = dCost;
                uiBestDist = uiDist;
                uiBestMode = chromaIntraMode;
                bestBDPCMMode = cu.bdpcmModeChroma;
                isChromaFusion = pu.isChromaFusion;
    
    Che-Wei Kuo's avatar
    Che-Wei Kuo committed
    #if JVET_AA0126_GLM
    
                bestGlmIdc = pu.glmIdc;
    
    Che-Wei Kuo's avatar
    Che-Wei Kuo committed
    #endif
    
            }
          }
          pu.isChromaFusion = false;
    #endif
    
    
    #if JVET_Z0050_CCLM_SLOPE
    #if MMLM
          for (int32_t uiMode = 0; uiMode < 2; uiMode++)
          {
            int chromaIntraMode = uiMode ? MMLM_CHROMA_IDX : LM_CHROMA_IDX;
    #else
          for (int32_t uiMode = 0; uiMode < 1; uiMode++)
          {
            int chromaIntraMode = LM_CHROMA_IDX;
    #endif
    
            if ( PU::isLMCModeEnabled( pu, chromaIntraMode ) && PU::hasCclmDeltaFlag( pu, chromaIntraMode ) )
            {
              if ( satdCclmOffsetsBest[chromaIntraMode - LM_CHROMA_IDX].isActive() )
              {
                pu.intraDir[1] = chromaIntraMode;
                pu.cclmOffsets = satdCclmOffsetsBest[chromaIntraMode - LM_CHROMA_IDX];
    #if JVET_Z0050_DIMD_CHROMA_FUSION
                pu.isChromaFusion = false;
    #endif
    
                // RD search replicated from above
                cs.setDecomp( pu.Cb(), false );
                cs.dist = baseDist;
                //----- restore context models -----
                m_CABACEstimator->getCtx() = ctxStart;
    
                xRecurIntraChromaCodingQT( cs, partitioner, bestCostSoFar, ispType );
                if( lumaUsesISP && cs.dist == MAX_UINT )
                {
                  continue;
                }
    
                if (cs.sps->getTransformSkipEnabledFlag())
                {
                  m_CABACEstimator->getCtx() = ctxStart;
                }
    
                uint64_t fracBits = xGetIntraFracBitsQT( cs, partitioner, false, true, -1, ispType );
                Distortion uiDist = cs.dist;
                double    dCost   = m_pcRdCost->calcRdCost( fracBits, uiDist - baseDist );
    
                //----- compare -----
                if( dCost < dBestCost )
                {
                  if( lumaUsesISP && dCost < bestCostSoFar )
                  {
                    bestCostSoFar = dCost;
                  }
                  for( uint32_t i = getFirstComponentOfChannel( CHANNEL_TYPE_CHROMA ); i < numberValidComponents; i++ )
                  {
                    const CompArea &area = pu.blocks[i];
    
                    saveCS.getRecoBuf     ( area ).copyFrom( cs.getRecoBuf   ( area ) );
    #if KEEP_PRED_AND_RESI_SIGNALS
                    saveCS.getPredBuf     ( area ).copyFrom( cs.getPredBuf   ( area ) );
                    saveCS.getResiBuf     ( area ).copyFrom( cs.getResiBuf   ( area ) );
    #endif
                    saveCS.getPredBuf     ( area ).copyFrom( cs.getPredBuf   (area ) );
                    cs.picture->getPredBuf( area ).copyFrom( cs.getPredBuf   (area ) );
                    cs.picture->getRecoBuf( area ).copyFrom( cs.getRecoBuf( area ) );
    
                    for( uint32_t j = 0; j < saveCS.tus.size(); j++ )
                    {
                      saveCS.tus[j]->copyComponentFrom( *orgTUs[j], area.compID );
                    }
                  }
    
                  dBestCost       = dCost;
                  uiBestDist      = uiDist;
                  uiBestMode      = chromaIntraMode;
                  bestBDPCMMode   = cu.bdpcmModeChroma;
                  bestCclmOffsets = pu.cclmOffsets;
    #if JVET_Z0050_DIMD_CHROMA_FUSION
                  isChromaFusion  = pu.isChromaFusion;
    
    Che-Wei Kuo's avatar
    Che-Wei Kuo committed
    #endif
    #if JVET_AA0126_GLM
                  bestGlmIdc      = pu.glmIdc;
    
    #endif
                }
              }
            }
          }
          
          pu.cclmOffsets.setAllZero();
    #endif
    
    
    Jani Lainema's avatar
    Jani Lainema committed
    #if JVET_AA0057_CCCM
    
    #if JVET_AB0143_CCCM_TS
          int chromaIntraModeInCCCM = LM_CHROMA_IDX;
    
    #if JVET_AC0147_CCCM_NO_SUBSAMPLING
          bool isCCCMEnabled = isCccmFullEnabled;
    #else
    
          isCCCMEnabled = isCccmFullEnabled;
    
          pu.cccmFlag = 1;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    
          for (int32_t uiMode = 0; uiMode < CCCM_NUM_MODES; uiMode++)
    
          {
            if (uiMode == 1)
            {
              chromaIntraModeInCCCM = MDLM_L_IDX;
              isCCCMEnabled = isCccmLeftEnabled;
              pu.cccmFlag = 2;
            }
            else if (uiMode == 2)
            {
              chromaIntraModeInCCCM = MDLM_T_IDX;
              isCCCMEnabled = isCccmTopEnabled;
              pu.cccmFlag = 3;
            }
    #if MMLM
            else if (uiMode == 3)
            {
              chromaIntraModeInCCCM = MMLM_CHROMA_IDX;
              isCCCMEnabled = isMultiCccmFullEnabled;
              pu.cccmFlag = 1;
            }
            else if (uiMode == 4)
            {
              chromaIntraModeInCCCM = MMLM_L_IDX;
              isCCCMEnabled = isMultiCccmLeftEnabled;
              pu.cccmFlag = 2;
            }
            else if (uiMode == 5)
            {
              chromaIntraModeInCCCM = MMLM_T_IDX;
              isCCCMEnabled = isMultiCccmTopEnabled;
              pu.cccmFlag = 3;
            }
    #endif
    
    #if JVET_AC0147_CCCM_NO_SUBSAMPLING
            if (!isCccmModeEnabledInRdo[0][chromaIntraModeInCCCM] && !isCccmModeEnabledInRdo[1][chromaIntraModeInCCCM])
    #else
    
            if (!isCccmModeEnabledInRdo[chromaIntraModeInCCCM])
    
    Jani Lainema's avatar
    Jani Lainema committed
    #if MMLM
          for (int32_t uiMode = 0; uiMode < 2; uiMode++)
          {
            int chromaIntraMode = uiMode ? MMLM_CHROMA_IDX : LM_CHROMA_IDX;
    #else
          for (int32_t uiMode = 0; uiMode < 1; uiMode++)
          {
            int chromaIntraMode = LM_CHROMA_IDX;
    #endif
    
            if ( PU::cccmSingleModeAvail(pu, chromaIntraMode) || PU::cccmMultiModeAvail(pu, chromaIntraMode) )
            {
              pu.cccmFlag = 1;
    
    Jani Lainema's avatar
    Jani Lainema committed
    
    
    #if JVET_AC0147_CCCM_NO_SUBSAMPLING
              for (int sub = 0; sub < pu.cu->slice->getSPS()->getUseCccm(); sub++)
              {
                pu.cccmNoSubFlag = sub;
                if (!isCccmModeEnabledInRdo[sub][chromaIntraModeInCCCM])
                {
                  continue;
                }
    #endif
    
    
    Jani Lainema's avatar
    Jani Lainema committed
              // Original RD check code replicated from above
              cs.setDecomp( pu.Cb(), false );
              cs.dist = baseDist;
              //----- restore context models -----
              m_CABACEstimator->getCtx() = ctxStart;
    
              //----- chroma coding -----
    
    #if JVET_AB0143_CCCM_TS
              pu.intraDir[1] = chromaIntraModeInCCCM;
    
    
    #if JVET_AC0147_CCCM_NO_SUBSAMPLING
              xRecurIntraChromaCodingQT(cs, partitioner, bestCostSoFar, ispType, cccmStorage[sub][uiMode]);
    #else
    
              xRecurIntraChromaCodingQT(cs, partitioner, bestCostSoFar, ispType, cccmStorage[uiMode]);
    
    Jani Lainema's avatar
    Jani Lainema committed
              pu.intraDir[1] = chromaIntraMode;
    
              xRecurIntraChromaCodingQT( cs, partitioner, bestCostSoFar, ispType );
    
    Jani Lainema's avatar
    Jani Lainema committed
              if( lumaUsesISP && cs.dist == MAX_UINT )
              {
                continue;
              }
    
              if (cs.sps->getTransformSkipEnabledFlag())
              {
                m_CABACEstimator->getCtx() = ctxStart;
              }
    
              uint64_t fracBits   = xGetIntraFracBitsQT( cs, partitioner, false, true, -1, ispType );
              Distortion uiDist = cs.dist;
              double    dCost   = m_pcRdCost->calcRdCost( fracBits, uiDist - baseDist );
    
              //----- compare -----
              if( dCost < dBestCost )
              {
                if( lumaUsesISP && dCost < bestCostSoFar )
                {
                  bestCostSoFar = dCost;
                }
                for( uint32_t i = getFirstComponentOfChannel( CHANNEL_TYPE_CHROMA ); i < numberValidComponents; i++ )
                {
                  const CompArea &area = pu.blocks[i];
    
                  saveCS.getRecoBuf     ( area ).copyFrom( cs.getRecoBuf   ( area ) );
    #if KEEP_PRED_AND_RESI_SIGNALS
                  saveCS.getPredBuf     ( area ).copyFrom( cs.getPredBuf   ( area ) );
                  saveCS.getResiBuf     ( area ).copyFrom( cs.getResiBuf   ( area ) );
    #endif
                  saveCS.getPredBuf     ( area ).copyFrom( cs.getPredBuf   (area ) );
                  cs.picture->getPredBuf( area ).copyFrom( cs.getPredBuf   (area ) );
    
    #if !JVET_AB0143_CCCM_TS
    
    Jani Lainema's avatar
    Jani Lainema committed
                  cs.picture->getRecoBuf( area ).copyFrom( cs.getRecoBuf( area ) );
    
    Jani Lainema's avatar
    Jani Lainema committed
    
                  for( uint32_t j = 0; j < saveCS.tus.size(); j++ )
                  {
                    saveCS.tus[j]->copyComponentFrom( *orgTUs[j], area.compID );
                  }
                }
    
                dBestCost  = dCost;
                uiBestDist = uiDist;
    
    #if JVET_AB0143_CCCM_TS
                uiBestMode = chromaIntraModeInCCCM;
    #else
    
    Jani Lainema's avatar
    Jani Lainema committed
                uiBestMode = chromaIntraMode;
    
    Jani Lainema's avatar
    Jani Lainema committed
                bestBDPCMMode = cu.bdpcmModeChroma;
    #if JVET_Z0050_DIMD_CHROMA_FUSION
                isChromaFusion  = pu.isChromaFusion;
    #endif
    #if JVET_Z0050_CCLM_SLOPE
                bestCclmOffsets = pu.cclmOffsets;
    #endif
                cccmModeBest    = pu.cccmFlag;
    
    Che-Wei Kuo's avatar
    Che-Wei Kuo committed
    #if JVET_AA0126_GLM
                bestGlmIdc      = pu.glmIdc;
    #endif 
    
    #if JVET_AC0147_CCCM_NO_SUBSAMPLING 
                cccmNoSubBest  = pu.cccmNoSubFlag;
                }
    #endif
    
    Jani Lainema's avatar
    Jani Lainema committed
              }
            }
          }
            
          pu.cccmFlag = 0;
    #endif
    
          for( uint32_t i = getFirstComponentOfChannel( CHANNEL_TYPE_CHROMA ); i < numberValidComponents; i++ )
          {
            const CompArea &area = pu.blocks[i];
    
            cs.getRecoBuf         ( area ).copyFrom( saveCS.getRecoBuf( area ) );
    #if KEEP_PRED_AND_RESI_SIGNALS
            cs.getPredBuf         ( area ).copyFrom( saveCS.getPredBuf( area ) );
            cs.getResiBuf         ( area ).copyFrom( saveCS.getResiBuf( area ) );
    #endif
    
    Taoran Lu's avatar
    Taoran Lu committed
            cs.getPredBuf         ( area ).copyFrom( saveCS.getPredBuf( area ) );
            cs.picture->getPredBuf( area ).copyFrom( cs.getPredBuf    ( area ) );
    
    
    Seungwook Hong's avatar
    Seungwook Hong committed
    #if JVET_Z0118_GDR
            cs.updateReconMotIPM(area);
    #else
    
            cs.picture->getRecoBuf( area ).copyFrom( cs.    getRecoBuf( area ) );
    
    Seungwook Hong's avatar
    Seungwook Hong committed
    #endif
    
    
            for( uint32_t j = 0; j < saveCS.tus.size(); j++ )
            {
              orgTUs[ j ]->copyComponentFrom( *saveCS.tus[ j ], area.compID );
            }
          }
        }
    
        pu.intraDir[1] = uiBestMode;
        cs.dist        = uiBestDist;
    
        cu.bdpcmModeChroma = bestBDPCMMode;
    
    #if JVET_Z0050_CCLM_SLOPE
        pu.cclmOffsets     = bestCclmOffsets;
    
    Jani Lainema's avatar
    Jani Lainema committed
    #if JVET_AA0057_CCCM
        pu.cccmFlag        = cccmModeBest;
    
    #if JVET_AC0147_CCCM_NO_SUBSAMPLING 
        pu.cccmNoSubFlag   = cccmNoSubBest;
    #endif
    
    Jani Lainema's avatar
    Jani Lainema committed
    #endif
    
    #if JVET_Z0050_DIMD_CHROMA_FUSION
        pu.isChromaFusion = isChromaFusion;
    
    Che-Wei Kuo's avatar
    Che-Wei Kuo committed
    #endif
    #if JVET_AA0126_GLM
        pu.glmIdc          = bestGlmIdc;
    
      }
    
      //----- restore context models -----
      m_CABACEstimator->getCtx() = ctxStart;
    
      if( lumaUsesISP && bestCostSoFar >= maxCostAllowed )
      {
        cu.ispMode = 0;
      }
    
    #if JVET_Z0050_CCLM_SLOPE
    void IntraSearch::xFindBestCclmDeltaSlopeSATD(PredictionUnit &pu, ComponentID compID, int cclmModel, int &deltaBest, int64_t &sadBest )
    {
      CclmModel cclmModelStored;
      CodingStructure& cs = *(pu.cs);
      CompArea       area = compID == COMPONENT_Cb ? pu.Cb() : pu.Cr();
      PelBuf       orgBuf = cs.getOrgBuf(area);
      PelBuf      predBuf = cs.getPredBuf(area);
      int       maxOffset = 4;
      int            mode = pu.intraDir[1];
      bool createNewModel = true;
    
      DistParam distParamSad;
      DistParam distParamSatd;
    
      m_pcRdCost->setDistParam(distParamSad,  orgBuf, predBuf, pu.cs->sps->getBitDepth(CHANNEL_TYPE_CHROMA), compID, false);
      m_pcRdCost->setDistParam(distParamSatd, orgBuf, predBuf, pu.cs->sps->getBitDepth(CHANNEL_TYPE_CHROMA), compID, true);
      
      distParamSad.applyWeight  = false;
      distParamSatd.applyWeight = false;
      
      sadBest = -1;
    
      // Search positive offsets
      for ( int offset = 0; offset <= maxOffset; offset++)
      {
        pu.cclmOffsets.setOffset(compID, cclmModel, offset);
        
        predIntraChromaLM( compID, predBuf, pu, area, mode, createNewModel, &cclmModelStored );
        
        createNewModel  = false; // Need to calculate the base model just once
        int64_t sad     = distParamSad.distFunc(distParamSad) * 2;
        int64_t satd    = distParamSatd.distFunc(distParamSatd);
        int64_t sadThis = std::min(sad, satd);
        
        if ( sadBest == -1 || sadThis < sadBest )
        {
          sadBest   = sadThis;
          deltaBest = offset;
        }
        else
        {
          break;
        }
      }
      
      // Search negative offsets only if positives didn't help
      if ( deltaBest == 0 )
      {
        for ( int offset = -1; offset >= -maxOffset; offset--)
        {
          pu.cclmOffsets.setOffset(compID, cclmModel, offset);
    
          predIntraChromaLM( compID, predBuf, pu, area, mode, createNewModel, &cclmModelStored );
          
          int64_t sad     = distParamSad.distFunc(distParamSad) * 2;
          int64_t satd    = distParamSatd.distFunc(distParamSatd);
          int64_t sadThis = std::min(sad, satd);