Skip to content
Snippets Groups Projects
IntraSearch.cpp 367 KiB
Newer Older
  • Learn to ignore specific revisions
  • Che-Wei Kuo's avatar
    Che-Wei Kuo committed
    
                // 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 JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS && (JVET_AB0143_CCCM_TS || JVET_AC0119_LM_CHROMA_FUSION)
                                         , UnitBuf<Pel>()
    #endif
    #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
                                         , pcInterPred
    #endif
                );
    
    Che-Wei Kuo's avatar
    Che-Wei Kuo 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 ) );
                    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
    
    #if JVET_AC0119_LM_CHROMA_FUSION
          uint32_t uiFusionModeNum = 2;
    #if MMLM
          uiFusionModeNum += 1;
    #endif
          bool fusionModeIsEnable[6] = { false };
          int32_t fusionModeMap[6][2];
          Distortion satdChromaFusionCost[6];
          int satdChromaFusionModeList[6];
          for (int i = 0; i < 6; i++)
          {
            satdChromaFusionCost[i] = MAX_UINT64; // for the mode not pre-select by SATD, do RDO by default, so set the initial value 0.
            satdChromaFusionModeList[i] = i;
          }
    
          Distortion sad = 0;
          Distortion sadCb = 0, satdCb = 0;
          Distortion sadCr = 0, satdCr = 0;
          CodingStructure& cs = *(pu.cs);
    
          DistParam distParamSadCb, distParamSatdCb;
          DistParam distParamSadCr, distParamSatdCr;
    
          m_pcRdCost->setDistParam(distParamSadCb, cs.getOrgBuf(pu.Cb()), fusionStorage[0].Cb(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_CHROMA), COMPONENT_Cb, false);
          m_pcRdCost->setDistParam(distParamSatdCb, cs.getOrgBuf(pu.Cb()), fusionStorage[0].Cb(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_CHROMA), COMPONENT_Cb, true);
          m_pcRdCost->setDistParam(distParamSadCr, cs.getOrgBuf(pu.Cr()), fusionStorage[0].Cr(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_CHROMA), COMPONENT_Cr, false);
          m_pcRdCost->setDistParam(distParamSatdCr, cs.getOrgBuf(pu.Cr()), fusionStorage[0].Cr(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_CHROMA), COMPONENT_Cr, true);
    
          distParamSadCb.applyWeight = false;
          distParamSatdCb.applyWeight = false;
          distParamSadCr.applyWeight = false;
          distParamSatdCr.applyWeight = false;
    
          xCflmCreateLumaRef(pu, pu.Cb());
    
          for (int32_t uiMode = 0; uiMode < 2; uiMode++)
          {
            int chromaIntraMode = (uiMode == 0) ? bestNonLmMode : secondNonLmMode;
            if (chromaIntraMode == -1)
            {
              continue;
            }
    
            if (PU::hasChromaFusionFlag(pu, chromaIntraMode))
            {
              pu.intraDir[1] = chromaIntraMode;
              if (!xCflmCreateChromaPred(pu, COMPONENT_Cb, predStorage[uiMode].Cb()) ||
                !xCflmCreateChromaPred(pu, COMPONENT_Cr, predStorage[uiMode].Cr()))
              {
                break;
              }
    
              initIntraPatternChType(cu, pu.Cb());
              initIntraPatternChType(cu, pu.Cr());
    
              fusionStorage[uiMode * uiFusionModeNum].Cb().copyFrom(predStorage[uiMode].Cb());
              fusionStorage[uiMode * uiFusionModeNum].Cr().copyFrom(predStorage[uiMode].Cr());
    
              for (int32_t fusionMode = 0; fusionMode < uiFusionModeNum; fusionMode++)
              {
                pu.intraDir[1] = chromaIntraMode;
                pu.isChromaFusion = fusionMode + 1;
                int idx = uiMode * uiFusionModeNum + fusionMode;
    
                geneChromaFusionPred(COMPONENT_Cb, fusionStorage[idx].Cb(), pu);
                geneChromaFusionPred(COMPONENT_Cr, fusionStorage[idx].Cr(), pu);
    
                distParamSadCb.cur = fusionStorage[idx].Cb();
                distParamSatdCb.cur = fusionStorage[idx].Cb();
                distParamSadCr.cur = fusionStorage[idx].Cr();
                distParamSatdCr.cur = fusionStorage[idx].Cr();
    
                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);
    
                fusionModeMap[idx][0] = chromaIntraMode;
                fusionModeMap[idx][1] = fusionMode + 1;
                satdChromaFusionCost[idx] = sad;
                fusionModeIsEnable[idx] = true;
              }
            }
          }
    
          for (int i = 0; i < 3; i++)
          {
            for (int j = i + 1; j < 6; j++)
            {
              if (satdChromaFusionCost[j] < satdChromaFusionCost[i])
              {
                tempIdx = satdChromaFusionModeList[i];
                satdChromaFusionModeList[i] = satdChromaFusionModeList[j];
                satdChromaFusionModeList[j] = tempIdx;
    
                tempCost = satdChromaFusionCost[i];
                satdChromaFusionCost[i] = satdChromaFusionCost[j];
                satdChromaFusionCost[j] = tempCost;
              }
            }
          }
    
          for (int i = 0; i < 3; i++)
          {
            fusionModeIsEnable[satdChromaFusionModeList[6 - 1 - i]] = false;
          }
    #endif
    
    
          // RDO for chroma fusion mode
    
    #if JVET_AC0119_LM_CHROMA_FUSION
          for (int32_t lstIdx = 0; lstIdx < 6; lstIdx++)
          {
            int iModedx = satdChromaFusionModeList[lstIdx];
            if (!fusionModeIsEnable[iModedx])
              break;
    
            int chromaIntraMode = fusionModeMap[iModedx][0];
            pu.isChromaFusion = fusionModeMap[iModedx][1];
    #else
    
          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 JVET_AC0119_LM_CHROMA_FUSION
                , fusionStorage[iModedx]
    
    #elif JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS && (JVET_AB0143_CCCM_TS && !JVET_AC0119_LM_CHROMA_FUSION)
                , UnitBuf<Pel>()
    #endif
    #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
                , pcInterPred
    
              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
    
    #if !JVET_AC0119_LM_CHROMA_FUSION
    
    #if JVET_AC0119_LM_CHROMA_FUSION
          pu.isChromaFusion = 0;
    #else
    
          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
    
    #if JVET_AC0119_LM_CHROMA_FUSION
                pu.isChromaFusion = 0;
    #else
    
                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 JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS && (JVET_AB0143_CCCM_TS || JVET_AC0119_LM_CHROMA_FUSION)
                                         , UnitBuf<Pel>()
    #endif
    #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
                                         , pcInterPred
    #endif
                );
    
                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_AC0054_GLCCCM
            pu.glCccmFlag = 0;
            if (uiMode >= CCCM_NUM_MODES / 2)
            {
              pu.glCccmFlag = 1;
    #if MMLM
              chromaIntraModeInCCCM = uiMode == 6 ? LM_CHROMA_IDX
              : uiMode == 7 ? MDLM_L_IDX
              : uiMode == 8 ? MDLM_T_IDX
              : uiMode == 9 ? MMLM_CHROMA_IDX
              : uiMode == 10 ? MMLM_L_IDX : MMLM_T_IDX;
              isCCCMEnabled = uiMode == 6 ? isCccmFullEnabled
              : uiMode == 7 ? isCccmLeftEnabled
              : uiMode == 8 ? isCccmTopEnabled
              : uiMode == 9 ? isMultiCccmFullEnabled
              : uiMode == 10 ? isMultiCccmLeftEnabled : isMultiCccmTopEnabled;
              pu.cccmFlag =   uiMode == 6 ? 1
              : uiMode == 7 ? 2
              : uiMode == 8 ? 3
              : uiMode == 9 ? 1
              : uiMode == 10 ? 2 : 3;
    #else
              chromaIntraModeInCCCM = uiMode == 3 ? LM_CHROMA_IDX
              : uiMode == 4 ? MDLM_L_IDX : MDLM_T_IDX;
              isCCCMEnabled = uiMode == 3 ? isCccmFullEnabled
              : uiMode == 4 ? isCccmLeftEnabled : isCccmTopEnabled;
              pu.cccmFlag  =  uiMode == 3 ? 1
              : uiMode == 4 ? 2 : 3;
    #endif
              if (!isGlCccmModeEnabledInRdo[chromaIntraModeInCCCM])
              {
                continue;
              }
            }
    
    #endif // JVET_AC0054_GLCCCM
    
    #if JVET_AC0147_CCCM_NO_SUBSAMPLING
    
              if (!isCccmModeEnabledInRdo[0][chromaIntraModeInCCCM] && !isCccmModeEnabledInRdo[1][chromaIntraModeInCCCM])
    
              if (!isCccmModeEnabledInRdo[chromaIntraModeInCCCM])
    
            if (isCCCMEnabled)
            {
    #else
    
    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++)
              {
    
    #if JVET_AD0202_CCCM_MDF
                for (int32_t filterIdx = 0; filterIdx < CCCM_NUM_PRED_FILTER; filterIdx++)
                {
                  if (filterIdx > 0 && (sub == 1 || uiMode > 5))
                  {
                    continue;
                  }
                  pu.cccmMultiFilterIdx = filterIdx;
    #endif
    
                  pu.cccmNoSubFlag = sub;
    #if JVET_AC0054_GLCCCM
                  if (sub && ((uiMode >= CCCM_NUM_MODES / 2) || pu.glCccmFlag))
                  {
                    continue;
                  }
    
    #if JVET_AD0202_CCCM_MDF
                  else if (sub == 0 && uiMode < 6)
                  {
                    if (!isCccmWithMulDownSamplingEnabledInRdo[chromaIntraModeInCCCM][filterIdx])
                    {
                      continue;
                    }
                  }
                  else if (sub)
    #else
    
                  {
                    if (!isCccmModeEnabledInRdo[sub][chromaIntraModeInCCCM])
                    {
                      continue;
                    }
                  }
    #else // else of JVET_AC0054_GLCCCM
                  if (!isCccmModeEnabledInRdo[sub][chromaIntraModeInCCCM])
                  {
                    continue;
                  }
    #endif // end of JVET_AC0054_GLCCCM
    
    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
    
    #if JVET_AD0202_CCCM_MDF
              const int cccmBufferIdx = filterIdx * CCCM_NUM_MODES + uiMode;
    
              xRecurIntraChromaCodingQT(cs, partitioner, bestCostSoFar, ispType, cccmStorage[sub][cccmBufferIdx]
    #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
                                      , pcInterPred
    #endif
    		  );
    
              xRecurIntraChromaCodingQT(cs, partitioner, bestCostSoFar, ispType, cccmStorage[sub][uiMode]
    #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
                                      , pcInterPred
    #endif
    	      );
    
              xRecurIntraChromaCodingQT(cs, partitioner, bestCostSoFar, ispType, cccmStorage[uiMode]
    #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
                                      , pcInterPred
    #endif
              );
    
    Jani Lainema's avatar
    Jani Lainema committed
              pu.intraDir[1] = chromaIntraMode;
    
    
              xRecurIntraChromaCodingQT( cs, partitioner, bestCostSoFar, ispType 
    #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS && JVET_AC0119_LM_CHROMA_FUSION
                                       , UnitBuf<Pel>()
    #endif
    #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
                                       , pcInterPred
    #endif
              );
    
    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_AC0054_GLCCCM
                glCccmBest      = pu.glCccmFlag;
    #endif
    
    #if JVET_AD0202_CCCM_MDF
                cccmMultiFilterIdxBest = pu.cccmMultiFilterIdx;
    #endif
    
    #if JVET_AC0147_CCCM_NO_SUBSAMPLING 
                cccmNoSubBest  = pu.cccmNoSubFlag;
                }
    
    Jani Lainema's avatar
    Jani Lainema committed
              }
            }
          }
            
          pu.cccmFlag = 0;
    
    #if JVET_AD0202_CCCM_MDF
          pu.cccmMultiFilterIdx = 0;
    #endif
    
    Jani Lainema's avatar
    Jani Lainema committed
    #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
    
    #if JVET_AC0054_GLCCCM
        pu.glCccmFlag = glCccmBest;
    #endif
    
    #if JVET_AD0202_CCCM_MDF
        pu.cccmMultiFilterIdx = cccmMultiFilterIdxBest;
    #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);
          
          if ( sadThis < sadBest )
          {
            sadBest   = sadThis;
            deltaBest = offset;
          }
          else
          {
            break;
          }
        }
      }
    }
    #endif
    
    
    Che-Wei Kuo's avatar
    Che-Wei Kuo committed
    #if JVET_AA0126_GLM
    void IntraSearch::xFindBestGlmIdcSATD(PredictionUnit &pu, ComponentID compID, int &idcBest, int64_t &sadBest )
    {
      CodingStructure& cs = *(pu.cs);
      CompArea       area = compID == COMPONENT_Cb ? pu.Cb() : pu.Cr();
      PelBuf       orgBuf = cs.getOrgBuf(area);
      PelBuf      predBuf = cs.getPredBuf(area);
    
    #if JVET_AB0092_GLM_WITH_LUMA
      int          maxIdc = NUM_GLM_PATTERN * NUM_GLM_WEIGHT;
    #else
    
    Che-Wei Kuo's avatar
    Che-Wei Kuo committed
      int          maxIdc = NUM_GLM_IDC - 1;
    
    Che-Wei Kuo's avatar
    Che-Wei Kuo committed
      int            mode = pu.intraDir[1];
    
      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;
    
    
    #if JVET_AB0092_GLM_WITH_LUMA
      CompArea       areacr = pu.Cr();
      PelBuf       orgBufcr = cs.getOrgBuf(areacr);
      PelBuf      predBufcr = cs.getPredBuf(areacr);
    
      DistParam distParamSadcr;
      DistParam distParamSatdcr;
    
      m_pcRdCost->setDistParam(distParamSadcr, orgBufcr, predBufcr, pu.cs->sps->getBitDepth(CHANNEL_TYPE_CHROMA), COMPONENT_Cr, false);
      m_pcRdCost->setDistParam(distParamSatdcr, orgBufcr, predBufcr, pu.cs->sps->getBitDepth(CHANNEL_TYPE_CHROMA), COMPONENT_Cr, true);
    
      distParamSadcr.applyWeight = false;
      distParamSatdcr.applyWeight = false;
    #endif
    
    
    Che-Wei Kuo's avatar
    Che-Wei Kuo committed
      // Search positive idcs
      for ( int idc = 0; idc <= maxIdc; idc++ )
      {
        pu.glmIdc.setIdc(compID, 0, idc);
        pu.glmIdc.setIdc(compID, 1, idc);
    
        predIntraChromaLM( compID, predBuf, pu, area, mode );
        
        int64_t sad     = distParamSad.distFunc(distParamSad) * 2;
        int64_t satd    = distParamSatd.distFunc(distParamSatd);
        int64_t sadThis = std::min(sad, satd);
    
    
    #if JVET_AB0092_GLM_WITH_LUMA
        pu.glmIdc.setIdc(COMPONENT_Cr, 0, idc);
        pu.glmIdc.setIdc(COMPONENT_Cr, 1, idc);
    
        predIntraChromaLM(COMPONENT_Cr, predBufcr, pu, areacr, mode);
    
        int64_t sadcr = distParamSadcr.distFunc(distParamSadcr) * 2;
        int64_t satdcr = distParamSatdcr.distFunc(distParamSatdcr);
        int64_t sadThiscr = std::min(sadcr, satdcr);
        sadThis += sadThiscr;
    #endif
    
    Che-Wei Kuo's avatar
    Che-Wei Kuo committed
        
        if ( sadBest == -1 || sadThis < sadBest )
        {
          sadBest   = sadThis;
          idcBest   = idc;
        }
      }
    }
    #endif
    
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
    
    void IntraSearch::saveCuAreaCostInSCIPU( Area area, double cost )
    {
      if( m_numCuInSCIPU < NUM_INTER_CU_INFO_SAVE )
      {
        m_cuAreaInSCIPU[m_numCuInSCIPU] = area;
        m_cuCostInSCIPU[m_numCuInSCIPU] = cost;
        m_numCuInSCIPU++;
      }
    }
    
    void IntraSearch::initCuAreaCostInSCIPU()
    {
      for( int i = 0; i < NUM_INTER_CU_INFO_SAVE; i++ )
      {
        m_cuAreaInSCIPU[i] = Area();
        m_cuCostInSCIPU[i] = 0;
      }
      m_numCuInSCIPU = 0;
    }
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    
    void IntraSearch::PLTSearch(CodingStructure &cs, Partitioner& partitioner, ComponentID compBegin, uint32_t numComp)
    
      CodingUnit    &cu = *cs.getCU(partitioner.chType);
    
      TransformUnit &tu = *cs.getTU(partitioner.chType);
    
      uint32_t height = cu.block(compBegin).height;
      uint32_t width = cu.block(compBegin).width;
    
      if (m_pcEncCfg->getLmcs() && (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()))
    
      {
        cs.getPredBuf().copyFrom(cs.getOrgBuf());
        cs.getPredBuf().Y().rspSignal(m_pcReshape->getFwdLUT());
      }
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
    
      if( cu.isLocalSepTree() )
    
        cs.prevPLT.curPLTSize[compBegin] = cs.prevPLT.curPLTSize[COMPONENT_Y];
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    
      cu.lastPLTSize[compBegin] = cs.prevPLT.curPLTSize[compBegin];
      //derive palette
      derivePLTLossy(cs, partitioner, compBegin, numComp);
      reorderPLT(cs, partitioner, compBegin, numComp);
    
      bool idxExist[MAXPLTSIZE + 1] = { false };
    
      preCalcPLTIndexRD(cs, partitioner, compBegin, numComp); // Pre-calculate distortions for each pixel
    
      double rdCost = MAX_DOUBLE;
    
      deriveIndexMap(cs, partitioner, compBegin, numComp, PLT_SCAN_HORTRAV, rdCost, idxExist); // Optimize palette index map (horizontal scan)
    
      if ((cu.curPLTSize[compBegin] + cu.useEscape[compBegin]) > 1)
      {
    
        deriveIndexMap(cs, partitioner, compBegin, numComp, PLT_SCAN_VERTRAV, rdCost, idxExist); // Optimize palette index map (vertical scan)
      }
      // Remove unused palette entries
      uint8_t newPLTSize = 0;
      int idxMapping[MAXPLTSIZE + 1];
      memset(idxMapping, -1, sizeof(int) * (MAXPLTSIZE + 1));
      for (int i = 0; i < cu.curPLTSize[compBegin]; i++)
      {
        if (idxExist[i])
        {
          idxMapping[i] = newPLTSize;
          newPLTSize++;
        }
    
      idxMapping[cu.curPLTSize[compBegin]] = cu.useEscape[compBegin]? newPLTSize: -1;
      if (newPLTSize != cu.curPLTSize[compBegin]) // there exist unused palette entries
      { // update palette table and reuseflag
        Pel curPLTtmp[MAX_NUM_COMPONENT][MAXPLTSIZE];
        int reuseFlagIdx = 0, curPLTtmpIdx = 0, reuseEntrySize = 0;
        memset(cu.reuseflag[compBegin], false, sizeof(bool) * MAXPLTPREDSIZE);
    
        int compBeginTmp = compBegin;
        int numCompTmp   = numComp;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
    
        if( cu.isLocalSepTree() )
    
          memset(cu.reuseflag[COMPONENT_Y], false, sizeof(bool) * MAXPLTPREDSIZE);
    
          compBeginTmp = COMPONENT_Y;
          numCompTmp   = (cu.chromaFormat != CHROMA_400) ? 3 : 1;
        }
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    
        for (int curIdx = 0; curIdx < cu.curPLTSize[compBegin]; curIdx++)
        {
          if (idxExist[curIdx])
          {
    
            for (int comp = compBeginTmp; comp < (compBeginTmp + numCompTmp); comp++)
    
              curPLTtmp[comp][curPLTtmpIdx] = cu.curPLT[comp][curIdx];
    
            // Update reuse flags
            if (curIdx < cu.reusePLTSize[compBegin])
            {
              bool match = false;
              for (; reuseFlagIdx < cs.prevPLT.curPLTSize[compBegin]; reuseFlagIdx++)
              {
                bool matchTmp = true;
                for (int comp = compBegin; comp < (compBegin + numComp); comp++)
                {
                  matchTmp = matchTmp && (curPLTtmp[comp][curPLTtmpIdx] == cs.prevPLT.curPLT[comp][reuseFlagIdx]);
                }
                if (matchTmp)
                {
                  match = true;
                  break;
                }
              }
              if (match)
              {
                cu.reuseflag[compBegin][reuseFlagIdx] = true;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
    
                if( cu.isLocalSepTree() )
    
                  cu.reuseflag[COMPONENT_Y][reuseFlagIdx] = true;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    
                reuseEntrySize++;
              }
            }
            curPLTtmpIdx++;
          }
        }
        cu.reusePLTSize[compBegin] = reuseEntrySize;
        // update palette table
        cu.curPLTSize[compBegin] = newPLTSize;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
    
        if( cu.isLocalSepTree() )
    
          cu.curPLTSize[COMPONENT_Y] = newPLTSize;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    
        for (int comp = compBeginTmp; comp < (compBeginTmp + numCompTmp); comp++)
    
          memcpy( cu.curPLT[comp], curPLTtmp[comp], sizeof(Pel)*cu.curPLTSize[compBegin]);
    
    Yung-Hsuan Chao (Jessie)'s avatar
    Yung-Hsuan Chao (Jessie) committed
      cu.useRotation[compBegin] = m_bestScanRotationMode;
    
      int indexMaxSize = cu.useEscape[compBegin] ? (cu.curPLTSize[compBegin] + 1) : cu.curPLTSize[compBegin];