参考:https://blog.csdn.net/nb_vol_1/article/category/6179825/1?

1、源代码:

Void TEncCu::xCheckRDCostIntra( TComDataCU *&rpcBestCU,TComDataCU *&rpcTempCU,Double      &cost,PartSize     eSizeDEBUG_STRING_FN_DECLARE(sDebug) )
{DEBUG_STRING_NEW(sTest)UInt uiDepth = rpcTempCU->getDepth( 0 );rpcTempCU->setSkipFlagSubParts( false, 0, uiDepth );rpcTempCU->setPartSizeSubParts( eSize, 0, uiDepth );rpcTempCU->setPredModeSubParts( MODE_INTRA, 0, uiDepth );rpcTempCU->setChromaQpAdjSubParts( rpcTempCU->getCUTransquantBypass(0) ? 0 : m_ChromaQpAdjIdc, 0, uiDepth );Bool bSeparateLumaChroma = true; // choose estimation mode
Distortion uiPreCalcDistC = 0;if (rpcBestCU->getPic()->getChromaFormat()==CHROMA_400){bSeparateLumaChroma=true;}Pel resiLuma[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE];if( !bSeparateLumaChroma ){// after this function, the direction will be PLANAR, DC, HOR or VER// however, if Luma ends up being one of those, the chroma dir must be later changed to DM_CHROMA.m_pcPredSearch->preestChromaPredMode( rpcTempCU, m_ppcOrigYuv[uiDepth], m_ppcPredYuvTemp[uiDepth] );} // 亮度块的帧内预测m_pcPredSearch->estIntraPredQT( rpcTempCU, m_ppcOrigYuv[uiDepth], m_ppcPredYuvTemp[uiDepth], m_ppcResiYuvTemp[uiDepth], m_ppcRecoYuvTemp[uiDepth], resiLuma, uiPreCalcDistC, bSeparateLumaChroma DEBUG_STRING_PASS_INTO(sTest) );m_ppcRecoYuvTemp[uiDepth]->copyToPicComponent(COMPONENT_Y, rpcTempCU->getPic()->getPicYuvRec(), rpcTempCU->getAddr(), rpcTempCU->getZorderIdxInCU() );if (rpcBestCU->getPic()->getChromaFormat()!=CHROMA_400){  // 色度块的帧内预测m_pcPredSearch->estIntraPredChromaQT( rpcTempCU, m_ppcOrigYuv[uiDepth], m_ppcPredYuvTemp[uiDepth], m_ppcResiYuvTemp[uiDepth], m_ppcRecoYuvTemp[uiDepth], resiLuma, uiPreCalcDistC DEBUG_STRING_PASS_INTO(sTest) );}m_pcEntropyCoder->resetBits();if ( rpcTempCU->getSlice()->getPPS()->getTransquantBypassEnableFlag()){m_pcEntropyCoder->encodeCUTransquantBypassFlag( rpcTempCU, 0,          true );}m_pcEntropyCoder->encodeSkipFlag ( rpcTempCU, 0,          true );m_pcEntropyCoder->encodePredMode( rpcTempCU, 0,          true );m_pcEntropyCoder->encodePartSize( rpcTempCU, 0, uiDepth, true );m_pcEntropyCoder->encodePredInfo( rpcTempCU, 0 );m_pcEntropyCoder->encodeIPCMInfo(rpcTempCU, 0, true );// Encode CoefficientsBool bCodeDQP = getdQPFlag();Bool codeChromaQpAdjFlag = getCodeChromaQpAdjFlag();m_pcEntropyCoder->encodeCoeff( rpcTempCU, 0, uiDepth, bCodeDQP, codeChromaQpAdjFlag );setCodeChromaQpAdjFlag( codeChromaQpAdjFlag );setdQPFlag( bCodeDQP );m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[uiDepth][CI_TEMP_BEST]);rpcTempCU->getTotalBits() = m_pcEntropyCoder->getNumberOfWrittenBits();rpcTempCU->getTotalBins() = ((TEncBinCABAC *)((TEncSbac*)m_pcEntropyCoder->m_pcEntropyCoderIf)->getEncBinIf())->getBinsCoded();rpcTempCU->getTotalCost() = m_pcRdCost->calcRdCost( rpcTempCU->getTotalBits(), rpcTempCU->getTotalDistortion() );xCheckDQP( rpcTempCU );cost = rpcTempCU->getTotalCost();xCheckBestMode(rpcBestCU, rpcTempCU, uiDepth DEBUG_STRING_PASS_INTO(sDebug) DEBUG_STRING_PASS_INTO(sTest));
}

2、estIntraPredQT(亮度块的帧内预测):

Void
TEncSearch::estIntraPredQT(TComDataCU* pcCU,TComYuv*    pcOrgYuv,TComYuv*    pcPredYuv,TComYuv*    pcResiYuv,TComYuv*    pcRecoYuv,Pel         resiLuma[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE],Distortion& ruiDistC,Bool        bLumaOnlyDEBUG_STRING_FN_DECLARE(sDebug))
{const UInt         uiDepth               = pcCU->getDepth(0);const UInt         uiInitTrDepth         = pcCU->getPartitionSize(0) == SIZE_2Nx2N ? 0 : 1;const UInt         uiInitTrDepthC        = pcCU->getPartitionSize(0) != SIZE_2Nx2N && enable4ChromaPUsInIntraNxNCU(pcOrgYuv->getChromaFormat()) ? 1 : 0;const UInt         uiNumPU               = 1<<(2*uiInitTrDepth);const UInt         uiQNumParts           = pcCU->getTotalNumPart() >> 2;const UInt         uiWidthBit            = pcCU->getIntraSizeIdx(0);const ChromaFormat chFmt                 = pcCU->getPic()->getChromaFormat();const UInt         numberValidComponents = getNumberValidComponents(chFmt);Distortion   uiOverallDistY        = 0;Distortion   uiOverallDistC        = 0;UInt         CandNum;Double       CandCostList[ FAST_UDI_MAX_RDMODE_NUM ]; // 候选的Cost列表Pel          resiLumaPU[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE];Bool    bMaintainResidual[NUMBER_OF_STORED_RESIDUAL_TYPES];for (UInt residualTypeIndex = 0; residualTypeIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; residualTypeIndex++){bMaintainResidual[residualTypeIndex] = true; //assume true unless specified otherwise
        }bMaintainResidual[RESIDUAL_ENCODER_SIDE] = !(m_pcEncCfg->getUseReconBasedCrossCPredictionEstimate());//NOTE: RExt - Lambda calculation at equivalent Qp of 4 is recommended because at that Qp, the quantisation divisor is 1.
#if FULL_NBITconst Double sqrtLambdaForFirstPass= (m_pcEncCfg->getCostMode()==COST_MIXED_LOSSLESS_LOSSY_CODING && pcCU->getCUTransquantBypass(0)) ?sqrt(0.57 * pow(2.0, ((RExt__LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP_PRIME - 12) / 3.0))): m_pcRdCost->getSqrtLambda();
#elseconst Double sqrtLambdaForFirstPass= (m_pcEncCfg->getCostMode()==COST_MIXED_LOSSLESS_LOSSY_CODING && pcCU->getCUTransquantBypass(0)) ?sqrt(0.57 * pow(2.0, ((RExt__LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP_PRIME - 12 - 6 * (g_bitDepth[CHANNEL_TYPE_LUMA] - 8)) / 3.0))): m_pcRdCost->getSqrtLambda();
#endif//===== set QP and clear Cbf =====  // 设置QP参数,清理Cbf  if ( pcCU->getSlice()->getPPS()->getUseDQP() == true){pcCU->setQPSubParts( pcCU->getQP(0), 0, uiDepth );}else{   // 进入此处pcCU->setQPSubParts( pcCU->getSlice()->getSliceQp(), 0, uiDepth );}//===== loop over partitions =====TComTURecurse tuRecurseCU(pcCU, 0);TComTURecurse tuRecurseWithPU(tuRecurseCU, false, (uiInitTrDepth==0)?TComTU::DONT_SPLIT : TComTU::QUAD_SPLIT);do{const UInt uiPartOffset=tuRecurseWithPU.GetAbsPartIdxTU();
//  for( UInt uiPU = 0, uiPartOffset=0; uiPU < uiNumPU; uiPU++, uiPartOffset += uiQNumParts )//{//===== init pattern for luma prediction =====Bool bAboveAvail = false; // 上面的块是否有效Bool bLeftAvail  = false; // 左边的块是否有效DEBUG_STRING_NEW(sTemp2)//===== determine set of modes to be tested (using prediction signal only) =====    // 35种帧内预测模式Int numModesAvailable     = 35; //total number of Intra modes
    UInt uiRdModeList[FAST_UDI_MAX_RDMODE_NUM];Int numModesForFullRD = g_aucIntraModeNumFast[ uiWidthBit ];if (tuRecurseWithPU.ProcessComponentSection(COMPONENT_Y))    // 使用重建后的YUV图像对当前PU的相邻样点进行滤波,提供参考样本值initAdiPatternChType( tuRecurseWithPU, bAboveAvail, bLeftAvail, COMPONENT_Y, true DEBUG_STRING_PASS_INTO(sTemp2) );Bool doFastSearch = (numModesForFullRD != numModesAvailable);if (doFastSearch){assert(numModesForFullRD < numModesAvailable);for( Int i=0; i < numModesForFullRD; i++ ){        // 用于存储每一种模式的消耗CandCostList[ i ] = MAX_DOUBLE;}CandNum = 0;const TComRectangle &puRect=tuRecurseWithPU.getRect(COMPONENT_Y);const UInt uiAbsPartIdx=tuRecurseWithPU.GetAbsPartIdxTU();      // 在原始的YUV中获取亮度的地址 Pel* piOrg         = pcOrgYuv ->getAddr( COMPONENT_Y, uiAbsPartIdx );      // 在预测的YUV中获取亮度的地址Pel* piPred        = pcPredYuv->getAddr( COMPONENT_Y, uiAbsPartIdx );UInt uiStride      = pcPredYuv->getStride( COMPONENT_Y ); // 偏移DistParam distParam;const Bool bUseHadamard=pcCU->getCUTransquantBypass(0) == 0;m_pcRdCost->setDistParam(distParam, g_bitDepth[CHANNEL_TYPE_LUMA], piOrg, uiStride, piPred, uiStride, puRect.width, puRect.height, bUseHadamard);distParam.bApplyWeight = false;      // 遍历35种帧内预测模式,选取若干个代价比较小的模式作为后续处理的模式for( Int modeIdx = 0; modeIdx < numModesAvailable; modeIdx++ ){UInt       uiMode = modeIdx;Distortion uiSad  = 0;const Bool bUseFilter=TComPrediction::filteringIntraReferenceSamples(COMPONENT_Y, uiMode, puRect.width, puRect.height, chFmt, pcCU->getSlice()->getSPS()->getDisableIntraReferenceSmoothing());
        // 对亮度块进行预测predIntraAng( COMPONENT_Y, uiMode, piOrg, uiStride, piPred, uiStride, tuRecurseWithPU, bAboveAvail, bLeftAvail, bUseFilter, TComPrediction::UseDPCMForFirstPassIntraEstimation(tuRecurseWithPU, uiMode) );// use hadamard transform here        // 使用hadamard变换,计算SATD的值uiSad+=distParam.DistFunc(&distParam);UInt   iModeBits = 0;// NB xModeBitsIntra will not affect the mode for chroma that may have already been pre-estimated.iModeBits+=xModeBitsIntra( pcCU, uiMode, uiPartOffset, uiDepth, uiInitTrDepth, CHANNEL_TYPE_LUMA );
        // 计算此种模式的代价Double cost      = (Double)uiSad + (Double)iModeBits * sqrtLambdaForFirstPass;#ifdef DEBUG_INTRA_SEARCH_COSTSstd::cout << "1st pass mode " << uiMode << " SAD = " << uiSad << ", mode bits = " << iModeBits << ", cost = " << cost << "\n";
#endif// 更新候选列表CandNum += xUpdateCandList( uiMode, cost, numModesForFullRD, uiRdModeList, CandCostList );}#if FAST_UDI_USE_MPMInt uiPreds[NUM_MOST_PROBABLE_MODES] = {-1, -1, -1};Int iMode = -1;      // 根据相邻块的预测模式来对当前块的模式进行预测,得到若干模式(称为预测模式),存放在uiPreds中Int numCand = pcCU->getIntraDirPredictor( uiPartOffset, uiPreds, COMPONENT_Y, &iMode );if( iMode >= 0 ){        // 将候选列表的索引设置为此模式numCand = iMode;}
      // 遍历预测模式,如果它不在模式候选列表中,那么把它添加到其中for( Int j=0; j < numCand; j++){Bool mostProbableModeIncluded = false;Int mostProbableMode = uiPreds[j];for( Int i=0; i < numModesForFullRD; i++){mostProbableModeIncluded |= (mostProbableMode == uiRdModeList[i]);}if (!mostProbableModeIncluded){uiRdModeList[numModesForFullRD++] = mostProbableMode;}}
#endif // FAST_UDI_USE_MPM}else{for( Int i=0; i < numModesForFullRD; i++){uiRdModeList[i] = i;}}//===== check modes (using r-d costs) =====
#if HHI_RQT_INTRA_SPEEDUP_MODUInt   uiSecondBestMode  = MAX_UINT;Double dSecondBestPUCost = MAX_DOUBLE;
#endifDEBUG_STRING_NEW(sPU)UInt       uiBestPUMode  = 0;Distortion uiBestPUDistY = 0;Distortion uiBestPUDistC = 0;Double     dBestPUCost   = MAX_DOUBLE;#if RExt__ENVIRONMENT_VARIABLE_DEBUG_AND_TESTUInt max=numModesForFullRD;if (DebugOptionList::ForceLumaMode.isSet()) max=0;  // we are forcing a direction, so don't bother with mode checkfor ( UInt uiMode = 0; uiMode < max; uiMode++)
#else    // 遍历候选集中的模式for( UInt uiMode = 0; uiMode < numModesForFullRD; uiMode++ )
#endif{// set luma prediction modeUInt uiOrgMode = uiRdModeList[uiMode];pcCU->setIntraDirSubParts ( CHANNEL_TYPE_LUMA, uiOrgMode, uiPartOffset, uiDepth + uiInitTrDepth );DEBUG_STRING_NEW(sMode)// set context models      // 设置上下文模型m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] );// determine residual for partitionDistortion uiPUDistY = 0;Distortion uiPUDistC = 0;Double     dPUCost   = 0.0;
#if HHI_RQT_INTRA_SPEEDUP      // 通过多候选模式进行预测、变换、量化等操作来计算代价      // 注意倒数第三个参数bCheckFirst是true,表示会继续按照四叉树的方式向下划分xRecurIntraCodingQT( bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaPU, uiPUDistY, uiPUDistC, true, dPUCost, tuRecurseWithPU DEBUG_STRING_PASS_INTO(sMode) );
#elsexRecurIntraCodingQT( bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaPU, uiPUDistY, uiPUDistC, dPUCost, tuRecurseWithPU DEBUG_STRING_PASS_INTO(sMode) );
#endif#ifdef DEBUG_INTRA_SEARCH_COSTSstd::cout << "2nd pass [luma,chroma] mode [" << Int(pcCU->getIntraDir(CHANNEL_TYPE_LUMA, uiPartOffset)) << "," << Int(pcCU->getIntraDir(CHANNEL_TYPE_CHROMA, uiPartOffset)) << "] cost = " << dPUCost << "\n";
#endif// check r-d cost      // 从候选列表中选取最优的模式if( dPUCost < dBestPUCost ){DEBUG_STRING_SWAP(sPU, sMode)
#if HHI_RQT_INTRA_SPEEDUP_MODuiSecondBestMode  = uiBestPUMode;dSecondBestPUCost = dBestPUCost;
#endifuiBestPUMode  = uiOrgMode;uiBestPUDistY = uiPUDistY;uiBestPUDistC = uiPUDistC;dBestPUCost   = dPUCost;xSetIntraResultQT( bLumaOnly, pcRecoYuv, tuRecurseWithPU );if (pcCU->getSlice()->getPPS()->getUseCrossComponentPrediction()){const Int xOffset = tuRecurseWithPU.getRect( COMPONENT_Y ).x0;const Int yOffset = tuRecurseWithPU.getRect( COMPONENT_Y ).y0;for (UInt storedResidualIndex = 0; storedResidualIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; storedResidualIndex++){if (bMaintainResidual[storedResidualIndex]){xStoreCrossComponentPredictionResult(resiLuma[storedResidualIndex], resiLumaPU[storedResidualIndex], tuRecurseWithPU, xOffset, yOffset, MAX_CU_SIZE, MAX_CU_SIZE );}}}UInt uiQPartNum = tuRecurseWithPU.GetAbsPartIdxNumParts();::memcpy( m_puhQTTempTrIdx,  pcCU->getTransformIdx()       + uiPartOffset, uiQPartNum * sizeof( UChar ) );for (UInt component = 0; component < numberValidComponents; component++){const ComponentID compID = ComponentID(component);::memcpy( m_puhQTTempCbf[compID], pcCU->getCbf( compID  ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );::memcpy( m_puhQTTempTransformSkipFlag[compID],  pcCU->getTransformSkip(compID)  + uiPartOffset, uiQPartNum * sizeof( UChar ) );}}
#if HHI_RQT_INTRA_SPEEDUP_MODelse if( dPUCost < dSecondBestPUCost ){uiSecondBestMode  = uiOrgMode;dSecondBestPUCost = dPUCost;}
#endif} // Mode loop#if HHI_RQT_INTRA_SPEEDUP
#if HHI_RQT_INTRA_SPEEDUP_MODfor( UInt ui =0; ui < 2; ++ui )
#endif{
#if HHI_RQT_INTRA_SPEEDUP_MODUInt uiOrgMode   = ui ? uiSecondBestMode  : uiBestPUMode;if( uiOrgMode == MAX_UINT ){break;}
#elseUInt uiOrgMode = uiBestPUMode;
#endif#if RExt__ENVIRONMENT_VARIABLE_DEBUG_AND_TESTif (DebugOptionList::ForceLumaMode.isSet())uiOrgMode = DebugOptionList::ForceLumaMode.getInt();
#endifpcCU->setIntraDirSubParts ( CHANNEL_TYPE_LUMA, uiOrgMode, uiPartOffset, uiDepth + uiInitTrDepth );DEBUG_STRING_NEW(sModeTree)// set context modelsm_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] );// determine residual for partitionDistortion uiPUDistY = 0;Distortion uiPUDistC = 0;Double     dPUCost   = 0.0;
      // 使用最优模式对PU进行预测,然后变换量化等,计算代价      // 注意倒数第三个参数bCheckFirst是false,表示当前PU不再进行划分,即只处理当前深度的PUxRecurIntraCodingQT( bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaPU, uiPUDistY, uiPUDistC, false, dPUCost, tuRecurseWithPU DEBUG_STRING_PASS_INTO(sModeTree));// check r-d cost      // 检测同一种模式下,bCheckFirst为true和false的情况下,哪个的代价更低if( dPUCost < dBestPUCost ){DEBUG_STRING_SWAP(sPU, sModeTree)uiBestPUMode  = uiOrgMode;uiBestPUDistY = uiPUDistY;uiBestPUDistC = uiPUDistC;dBestPUCost   = dPUCost;xSetIntraResultQT( bLumaOnly, pcRecoYuv, tuRecurseWithPU );if (pcCU->getSlice()->getPPS()->getUseCrossComponentPrediction()){const Int xOffset = tuRecurseWithPU.getRect( COMPONENT_Y ).x0;const Int yOffset = tuRecurseWithPU.getRect( COMPONENT_Y ).y0;for (UInt storedResidualIndex = 0; storedResidualIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; storedResidualIndex++){if (bMaintainResidual[storedResidualIndex]){xStoreCrossComponentPredictionResult(resiLuma[storedResidualIndex], resiLumaPU[storedResidualIndex], tuRecurseWithPU, xOffset, yOffset, MAX_CU_SIZE, MAX_CU_SIZE );}}}const UInt uiQPartNum = tuRecurseWithPU.GetAbsPartIdxNumParts();::memcpy( m_puhQTTempTrIdx,  pcCU->getTransformIdx()       + uiPartOffset, uiQPartNum * sizeof( UChar ) );for (UInt component = 0; component < numberValidComponents; component++){const ComponentID compID = ComponentID(component);::memcpy( m_puhQTTempCbf[compID], pcCU->getCbf( compID  ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );::memcpy( m_puhQTTempTransformSkipFlag[compID],  pcCU->getTransformSkip(compID)  + uiPartOffset, uiQPartNum * sizeof( UChar ) );}}} // Mode loop
#endifDEBUG_STRING_APPEND(sDebug, sPU)//--- update overall distortion ---uiOverallDistY += uiBestPUDistY;uiOverallDistC += uiBestPUDistC;//--- update transform index and cbf ---const UInt uiQPartNum = tuRecurseWithPU.GetAbsPartIdxNumParts();::memcpy( pcCU->getTransformIdx()       + uiPartOffset, m_puhQTTempTrIdx,  uiQPartNum * sizeof( UChar ) );for (UInt component = 0; component < numberValidComponents; component++){const ComponentID compID = ComponentID(component);::memcpy( pcCU->getCbf( compID  ) + uiPartOffset, m_puhQTTempCbf[compID], uiQPartNum * sizeof( UChar ) );::memcpy( pcCU->getTransformSkip( compID  ) + uiPartOffset, m_puhQTTempTransformSkipFlag[compID ], uiQPartNum * sizeof( UChar ) );}//--- set reconstruction for next intra prediction blocks ---    // 变换量化/反变换反量化都已经处理完成了,那么设置重建块if( !tuRecurseWithPU.IsLastSection() ){const Bool bSkipChroma  = tuRecurseWithPU.ProcessChannelSection(CHANNEL_TYPE_CHROMA);const UInt numChannelToProcess = (bLumaOnly || bSkipChroma) ? 1 : getNumberValidComponents(pcCU->getPic()->getChromaFormat());for (UInt ch=0; ch<numChannelToProcess; ch++){const ComponentID compID = ComponentID(ch);const TComRectangle &puRect=tuRecurseWithPU.getRect(compID);const UInt  uiCompWidth   = puRect.width;const UInt  uiCompHeight  = puRect.height;const UInt  uiZOrder      = pcCU->getZorderIdxInCU() + uiPartOffset;Pel*  piDes         = pcCU->getPic()->getPicYuvRec()->getAddr( compID, pcCU->getAddr(), uiZOrder );const UInt  uiDesStride   = pcCU->getPic()->getPicYuvRec()->getStride( compID);const Pel*  piSrc         = pcRecoYuv->getAddr( compID, uiPartOffset );const UInt  uiSrcStride   = pcRecoYuv->getStride( compID);for( UInt uiY = 0; uiY < uiCompHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride ){for( UInt uiX = 0; uiX < uiCompWidth; uiX++ ){piDes[ uiX ] = piSrc[ uiX ];}}}}//=== update PU data ====pcCU->setIntraDirSubParts     ( CHANNEL_TYPE_LUMA, uiBestPUMode, uiPartOffset, uiDepth + uiInitTrDepth );if (!bLumaOnly && getChromasCorrespondingPULumaIdx(uiPartOffset, chFmt)==uiPartOffset){UInt chromaDir=pcCU->getIntraDir(CHANNEL_TYPE_CHROMA, getChromasCorrespondingPULumaIdx(uiPartOffset, chFmt));if (chromaDir == uiBestPUMode && tuRecurseWithPU.ProcessChannelSection(CHANNEL_TYPE_CHROMA)){pcCU->setIntraDirSubParts     ( CHANNEL_TYPE_CHROMA, DM_CHROMA_IDX, getChromasCorrespondingPULumaIdx(uiPartOffset, chFmt), uiDepth + uiInitTrDepthC );}}//pcCU->copyToPic                   ( uiDepth, uiPU, uiInitTrDepth ); // Unnecessary copy?} while (tuRecurseWithPU.nextSection(tuRecurseCU));if( uiNumPU > 1 ){ // set Cbf for all blocksUInt uiCombCbfY = 0;UInt uiCombCbfU = 0;UInt uiCombCbfV = 0;UInt uiPartIdx  = 0;for( UInt uiPart = 0; uiPart < 4; uiPart++, uiPartIdx += uiQNumParts ){uiCombCbfY |= pcCU->getCbf( uiPartIdx, COMPONENT_Y,  1 );uiCombCbfU |= pcCU->getCbf( uiPartIdx, COMPONENT_Cb, 1 );uiCombCbfV |= pcCU->getCbf( uiPartIdx, COMPONENT_Cr, 1 );}for( UInt uiOffs = 0; uiOffs < 4 * uiQNumParts; uiOffs++ ){pcCU->getCbf( COMPONENT_Y  )[ uiOffs ] |= uiCombCbfY;pcCU->getCbf( COMPONENT_Cb )[ uiOffs ] |= uiCombCbfU;pcCU->getCbf( COMPONENT_Cr )[ uiOffs ] |= uiCombCbfV;}}//===== reset context models =====m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]);//===== set distortion (rate and r-d costs are determined later) =====ruiDistC                   = uiOverallDistC;pcCU->getTotalDistortion() = uiOverallDistY + uiOverallDistC;
}

Void
TEncSearch::xRecurIntraCodingQT(Bool        bLumaOnly,TComYuv*    pcOrgYuv,TComYuv*    pcPredYuv,TComYuv*    pcResiYuv,Pel         resiLuma[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE],Distortion& ruiDistY,Distortion& ruiDistC,
#if HHI_RQT_INTRA_SPEEDUPBool        bCheckFirst,
#endifDouble&     dRDCost,TComTU&     rTuDEBUG_STRING_FN_DECLARE(sDebug))
{TComDataCU   *pcCU          = rTu.getCU();const UInt    uiAbsPartIdx  = rTu.GetAbsPartIdxTU();const UInt    uiFullDepth   = rTu.GetTransformDepthTotal();const UInt    uiTrDepth     = rTu.GetTransformDepthRel();const UInt    uiLog2TrSize  = rTu.GetLog2LumaTrSize();Bool    bCheckFull    = ( uiLog2TrSize  <= pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() );Bool    bCheckSplit   = ( uiLog2TrSize  >  pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx) );const UInt    numValidComp  = (bLumaOnly) ? 1 : pcOrgYuv->getNumberValidComponents();Pel     resiLumaSplit [NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE];Pel     resiLumaSingle[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE];Bool    bMaintainResidual[NUMBER_OF_STORED_RESIDUAL_TYPES];for (UInt residualTypeIndex = 0; residualTypeIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; residualTypeIndex++){bMaintainResidual[residualTypeIndex] = true; //assume true unless specified otherwise
        }bMaintainResidual[RESIDUAL_ENCODER_SIDE] = !(m_pcEncCfg->getUseReconBasedCrossCPredictionEstimate());#if HHI_RQT_INTRA_SPEEDUPInt maxTuSize = pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize();Int isIntraSlice = (pcCU->getSlice()->getSliceType() == I_SLICE);// don't check split if TU size is less or equal to max TU sizeBool noSplitIntraMaxTuSize = bCheckFull;if(m_pcEncCfg->getRDpenalty() && ! isIntraSlice){// in addition don't check split if TU size is less or equal to 16x16 TU size for non-intra slicenoSplitIntraMaxTuSize = ( uiLog2TrSize  <= min(maxTuSize,4) );// if maximum RD-penalty don't check TU size 32x32if(m_pcEncCfg->getRDpenalty()==2){bCheckFull    = ( uiLog2TrSize  <= min(maxTuSize,4));}}if( bCheckFirst && noSplitIntraMaxTuSize ){bCheckSplit = false;}
#elseInt maxTuSize = pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize();Int isIntraSlice = (pcCU->getSlice()->getSliceType() == I_SLICE);// if maximum RD-penalty don't check TU size 32x32if((m_pcEncCfg->getRDpenalty()==2)  && !isIntraSlice){bCheckFull    = ( uiLog2TrSize  <= min(maxTuSize,4));}
#endifDouble     dSingleCost                        = MAX_DOUBLE;Distortion uiSingleDist[MAX_NUM_CHANNEL_TYPE] = {0,0};UInt       uiSingleCbf[MAX_NUM_COMPONENT]     = {0,0,0};Bool       checkTransformSkip  = pcCU->getSlice()->getPPS()->getUseTransformSkip();Int        bestModeId[MAX_NUM_COMPONENT] = { 0, 0, 0};checkTransformSkip           &= TUCompRectHasAssociatedTransformSkipFlag(rTu.getRect(COMPONENT_Y), pcCU->getSlice()->getPPS()->getTransformSkipLog2MaxSize());checkTransformSkip           &= (!pcCU->getCUTransquantBypass(0));if ( m_pcEncCfg->getUseTransformSkipFast() ){checkTransformSkip       &= (pcCU->getPartitionSize(uiAbsPartIdx)==SIZE_NxN);}if( bCheckFull ){    // TransformSkip模式为true,表示将会跳过变换步骤if(checkTransformSkip == true){//----- store original entropy coding status -----m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_ROOT ] );Distortion singleDistTmp[MAX_NUM_CHANNEL_TYPE]  = { 0, 0 };UInt       singleCbfTmp[MAX_NUM_COMPONENT]      = { 0, 0, 0 };Double     singleCostTmp                        = 0;Int        firstCheckId                         = 0;
      // 遍历两次是为了选取最优模式,modeId能够决定xIntraCodingTUBlock的最后一个参数,该参数控制了预测像素如何生成for(Int modeId = firstCheckId; modeId < 2; modeId ++){DEBUG_STRING_NEW(sModeString)Int  default0Save1Load2 = 0;singleDistTmp[0]=singleDistTmp[1]=0;if(modeId == firstCheckId){default0Save1Load2 = 1;}else{default0Save1Load2 = 2;}for(UInt ch=COMPONENT_Y; ch<numValidComp; ch++){const ComponentID compID = ComponentID(ch);if (rTu.ProcessComponentSection(compID)){const UInt totalAdjustedDepthChan = rTu.GetTransformDepthTotalAdj(compID);pcCU->setTransformSkipSubParts ( modeId, compID, uiAbsPartIdx, totalAdjustedDepthChan );
            // 亮度块的预测和量化xIntraCodingTUBlock( pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaSingle, false, singleDistTmp[toChannelType(compID)], compID, rTu DEBUG_STRING_PASS_INTO(sModeString), default0Save1Load2 );}singleCbfTmp[compID] = pcCU->getCbf( uiAbsPartIdx, compID, uiTrDepth );}//----- determine rate and r-d cost -----if(modeId == 1 && singleCbfTmp[COMPONENT_Y] == 0){//In order not to code TS flag when cbf is zero, the case for TS with cbf being zero is forbidden.singleCostTmp = MAX_DOUBLE;}else{UInt uiSingleBits = xGetIntraBitsQT( rTu, true, !bLumaOnly, false );singleCostTmp     = m_pcRdCost->calcRdCost( uiSingleBits, singleDistTmp[CHANNEL_TYPE_LUMA] + singleDistTmp[CHANNEL_TYPE_CHROMA] );}        // 代价更新if(singleCostTmp < dSingleCost){DEBUG_STRING_SWAP(sDebug, sModeString)dSingleCost   = singleCostTmp;uiSingleDist[CHANNEL_TYPE_LUMA] = singleDistTmp[CHANNEL_TYPE_LUMA];uiSingleDist[CHANNEL_TYPE_CHROMA] = singleDistTmp[CHANNEL_TYPE_CHROMA];for (UInt ch=0; ch<MAX_NUM_COMPONENT; ch++)uiSingleCbf[ch] = singleCbfTmp[ch];bestModeId[COMPONENT_Y] = modeId;if(bestModeId[COMPONENT_Y] == firstCheckId){xStoreIntraResultQT(COMPONENT_Y, bLumaOnly?COMPONENT_Y:COMPONENT_Cr, rTu );m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ uiFullDepth ][ CI_TEMP_BEST ] );}if (pcCU->getSlice()->getPPS()->getUseCrossComponentPrediction()){const Int xOffset = rTu.getRect( COMPONENT_Y ).x0;const Int yOffset = rTu.getRect( COMPONENT_Y ).y0;for (UInt storedResidualIndex = 0; storedResidualIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; storedResidualIndex++){if (bMaintainResidual[storedResidualIndex]){xStoreCrossComponentPredictionResult(resiLuma[storedResidualIndex], resiLumaSingle[storedResidualIndex], rTu, xOffset, yOffset, MAX_CU_SIZE, MAX_CU_SIZE);}}}}if (modeId == firstCheckId){m_pcRDGoOnSbacCoder->load ( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_ROOT ] );}}for(UInt ch=COMPONENT_Y; ch<numValidComp; ch++){const ComponentID compID=ComponentID(ch);if (rTu.ProcessComponentSection(compID)){const UInt totalAdjustedDepthChan   = rTu.GetTransformDepthTotalAdj(compID);pcCU ->setTransformSkipSubParts ( bestModeId[COMPONENT_Y], compID, uiAbsPartIdx, totalAdjustedDepthChan );}}if(bestModeId[COMPONENT_Y] == firstCheckId){xLoadIntraResultQT(COMPONENT_Y, bLumaOnly?COMPONENT_Y:COMPONENT_Cr, rTu );for(UInt ch=COMPONENT_Y; ch< numValidComp; ch++){const ComponentID compID=ComponentID(ch);if (rTu.ProcessComponentSection(compID))pcCU->setCbfSubParts  ( uiSingleCbf[compID] << uiTrDepth, compID, uiAbsPartIdx, rTu.GetTransformDepthTotalAdj(compID) );}m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiFullDepth ][ CI_TEMP_BEST ] );}if( !bLumaOnly ){bestModeId[COMPONENT_Cb] = bestModeId[COMPONENT_Cr] = bestModeId[COMPONENT_Y];if (rTu.ProcessComponentSection(COMPONENT_Cb) && bestModeId[COMPONENT_Y] == 1){//In order not to code TS flag when cbf is zero, the case for TS with cbf being zero is forbidden.for (UInt ch=COMPONENT_Cb; ch<numValidComp; ch++){if (uiSingleCbf[ch] == 0){const ComponentID compID=ComponentID(ch);const UInt totalAdjustedDepthChan = rTu.GetTransformDepthTotalAdj(compID);pcCU ->setTransformSkipSubParts ( 0, compID, uiAbsPartIdx, totalAdjustedDepthChan);bestModeId[ch] = 0;}}}}}    // TransformSkip模式为false,表示不会跳过变换步骤else{//----- store original entropy coding status -----if( bCheckSplit ){m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_ROOT ] );}//----- code luma/chroma block with given intra prediction mode and store Cbf-----dSingleCost   = 0.0;for (UInt ch=COMPONENT_Y; ch<numValidComp; ch++){const ComponentID compID = ComponentID(ch);if (rTu.ProcessComponentSection(compID)){const UInt totalAdjustedDepthChan   = rTu.GetTransformDepthTotalAdj(compID);pcCU ->setTransformSkipSubParts ( 0, compID, uiAbsPartIdx, totalAdjustedDepthChan );}
        // 亮度块的预测、变换和量化xIntraCodingTUBlock( pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaSingle, false, uiSingleDist[toChannelType(compID)], compID, rTu DEBUG_STRING_PASS_INTO(sDebug));if( bCheckSplit ){uiSingleCbf[compID] = pcCU->getCbf( uiAbsPartIdx, compID, uiTrDepth );}}//----- determine rate and r-d cost -----UInt uiSingleBits = xGetIntraBitsQT( rTu, true, !bLumaOnly, false );if(m_pcEncCfg->getRDpenalty() && (uiLog2TrSize==5) && !isIntraSlice){uiSingleBits=uiSingleBits*4;}dSingleCost       = m_pcRdCost->calcRdCost( uiSingleBits, uiSingleDist[CHANNEL_TYPE_LUMA] + uiSingleDist[CHANNEL_TYPE_CHROMA] );if (pcCU->getSlice()->getPPS()->getUseCrossComponentPrediction()){const Int xOffset = rTu.getRect( COMPONENT_Y ).x0;const Int yOffset = rTu.getRect( COMPONENT_Y ).y0;for (UInt storedResidualIndex = 0; storedResidualIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; storedResidualIndex++){if (bMaintainResidual[storedResidualIndex]){xStoreCrossComponentPredictionResult(resiLuma[storedResidualIndex], resiLumaSingle[storedResidualIndex], rTu, xOffset, yOffset, MAX_CU_SIZE, MAX_CU_SIZE);}}}}}
  // 当前块是否向下继续划分为4个子块,如果是,那么就递归处理if( bCheckSplit ){//----- store full entropy coding status, load original entropy coding status -----if( bCheckFull ){m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_TEST ] );m_pcRDGoOnSbacCoder->load ( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_ROOT ] );}else{m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_ROOT ] );}//----- code splitted block -----Double     dSplitCost                         = 0.0;Distortion uiSplitDist[MAX_NUM_CHANNEL_TYPE]  = {0,0};UInt       uiSplitCbf[MAX_NUM_COMPONENT]      = {0,0,0};TComTURecurse tuRecurseChild(rTu, false);DEBUG_STRING_NEW(sSplit)do{DEBUG_STRING_NEW(sChild)
#if HHI_RQT_INTRA_SPEEDUP      // 递归调用xRecurIntraCodingQT( bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaSplit, uiSplitDist[0], uiSplitDist[1], bCheckFirst, dSplitCost, tuRecurseChild DEBUG_STRING_PASS_INTO(sChild) );
#elsexRecurIntraCodingQT( bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaSplit, uiSplitDist[0], uiSplitDist[1], dSplitCost, tuRecurseChild DEBUG_STRING_PASS_INTO(sChild) );
#endifDEBUG_STRING_APPEND(sSplit, sChild)for(UInt ch=0; ch<numValidComp; ch++){uiSplitCbf[ch] |= pcCU->getCbf( tuRecurseChild.GetAbsPartIdxTU(), ComponentID(ch), tuRecurseChild.GetTransformDepthRel() );}} while (tuRecurseChild.nextSection(rTu) );UInt    uiPartsDiv     = rTu.GetAbsPartIdxNumParts();for(UInt ch=COMPONENT_Y; ch<numValidComp; ch++){if (uiSplitCbf[ch]){const UInt flag=1<<uiTrDepth;const ComponentID compID=ComponentID(ch);UChar *pBase=pcCU->getCbf( compID );for( UInt uiOffs = 0; uiOffs < uiPartsDiv; uiOffs++ ){pBase[ uiAbsPartIdx + uiOffs ] |= flag;}}}//----- restore context states -----m_pcRDGoOnSbacCoder->load ( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_ROOT ] );//----- determine rate and r-d cost -----UInt uiSplitBits = xGetIntraBitsQT( rTu, true, !bLumaOnly, false );dSplitCost       = m_pcRdCost->calcRdCost( uiSplitBits, uiSplitDist[CHANNEL_TYPE_LUMA] + uiSplitDist[CHANNEL_TYPE_CHROMA] );//===== compare and set best =====if( dSplitCost < dSingleCost ){//--- update cost ---
      DEBUG_STRING_SWAP(sSplit, sDebug)ruiDistY += uiSplitDist[CHANNEL_TYPE_LUMA];ruiDistC += uiSplitDist[CHANNEL_TYPE_CHROMA];dRDCost  += dSplitCost;if (pcCU->getSlice()->getPPS()->getUseCrossComponentPrediction()){const Int xOffset = rTu.getRect( COMPONENT_Y ).x0;const Int yOffset = rTu.getRect( COMPONENT_Y ).y0;for (UInt storedResidualIndex = 0; storedResidualIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; storedResidualIndex++){if (bMaintainResidual[storedResidualIndex]){xStoreCrossComponentPredictionResult(resiLuma[storedResidualIndex], resiLumaSplit[storedResidualIndex], rTu, xOffset, yOffset, MAX_CU_SIZE, MAX_CU_SIZE);}}}return;}//----- set entropy coding status -----m_pcRDGoOnSbacCoder->load ( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_TEST ] );//--- set transform index and Cbf values ---pcCU->setTrIdxSubParts( uiTrDepth, uiAbsPartIdx, uiFullDepth );for(UInt ch=0; ch<numValidComp; ch++){const ComponentID compID=ComponentID(ch);const TComRectangle &tuRect=rTu.getRect(compID);const UInt totalAdjustedDepthChan   = rTu.GetTransformDepthTotalAdj(compID);pcCU->setCbfSubParts  ( uiSingleCbf[compID] << uiTrDepth, compID, uiAbsPartIdx, totalAdjustedDepthChan );pcCU ->setTransformSkipSubParts  ( bestModeId[compID], compID, uiAbsPartIdx, totalAdjustedDepthChan );//--- set reconstruction for next intra prediction blocks ---      // 执行像素块的重建操作const UInt  uiQTLayer   = pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() - uiLog2TrSize;const UInt  uiZOrder    = pcCU->getZorderIdxInCU() + uiAbsPartIdx;const UInt  uiWidth     = tuRect.width;const UInt  uiHeight    = tuRect.height;Pel*  piSrc       = m_pcQTTempTComYuv[ uiQTLayer ].getAddr( compID, uiAbsPartIdx );UInt  uiSrcStride = m_pcQTTempTComYuv[ uiQTLayer ].getStride  ( compID );Pel*  piDes       = pcCU->getPic()->getPicYuvRec()->getAddr( compID, pcCU->getAddr(), uiZOrder );UInt  uiDesStride = pcCU->getPic()->getPicYuvRec()->getStride  ( compID );for( UInt uiY = 0; uiY < uiHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride ){for( UInt uiX = 0; uiX < uiWidth; uiX++ ){piDes[ uiX ] = piSrc[ uiX ];}}}}ruiDistY += uiSingleDist[CHANNEL_TYPE_LUMA];ruiDistC += uiSingleDist[CHANNEL_TYPE_CHROMA];dRDCost  += dSingleCost;
}

// 帧内预测的一整套流程:预测+变换量化+反变换反量化+重建像素Void TEncSearch::xIntraCodingTUBlock(       TComYuv*    pcOrgYuv,TComYuv*    pcPredYuv,TComYuv*    pcResiYuv,Pel         resiLuma[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE],const Bool        checkCrossCPrediction,Distortion& ruiDist,const ComponentID compID,TComTU&     rTuDEBUG_STRING_FN_DECLARE(sDebug),Int         default0Save1Load2)
{if (!rTu.ProcessComponentSection(compID)) return;const Bool       bIsLuma = isLuma(compID);const TComRectangle &rect= rTu.getRect(compID);TComDataCU *pcCU=rTu.getCU();const UInt uiAbsPartIdx=rTu.GetAbsPartIdxTU();const UInt uiTrDepth=rTu.GetTransformDepthRelAdj(compID);const UInt uiFullDepth   = rTu.GetTransformDepthTotal(); // 获取深度const UInt uiLog2TrSize  = rTu.GetLog2LumaTrSize();const ChromaFormat chFmt = pcOrgYuv->getChromaFormat();const ChannelType chType = toChannelType(compID);const UInt    uiWidth           = rect.width; // 获取宽度const UInt    uiHeight          = rect.height; // 获取高度const UInt    uiStride          = pcOrgYuv ->getStride (compID); // 获取偏移Pel*    piOrg             = pcOrgYuv ->getAddr( compID, uiAbsPartIdx ); // 原始的像素地址Pel*    piPred            = pcPredYuv->getAddr( compID, uiAbsPartIdx ); // 预测的像素地址Pel*    piResi            = pcResiYuv->getAddr( compID, uiAbsPartIdx ); // 残差的像素地址Pel*    piReco            = pcPredYuv->getAddr( compID, uiAbsPartIdx ); // 重建的像素地址const UInt    uiQTLayer           = pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() - uiLog2TrSize;Pel*    piRecQt           = m_pcQTTempTComYuv[ uiQTLayer ].getAddr( compID, uiAbsPartIdx );const UInt    uiRecQtStride     = m_pcQTTempTComYuv[ uiQTLayer ].getStride(compID);const UInt    uiZOrder            = pcCU->getZorderIdxInCU() + uiAbsPartIdx; // Z扫描的顺序Pel*    piRecIPred        = pcCU->getPic()->getPicYuvRec()->getAddr( compID, pcCU->getAddr(), uiZOrder );UInt    uiRecIPredStride  = pcCU->getPic()->getPicYuvRec()->getStride  ( compID );TCoeff* pcCoeff           = m_ppcQTTempCoeff[compID][uiQTLayer] + rTu.getCoefficientOffset(compID); // 系数Bool    useTransformSkip  = pcCU->getTransformSkip(uiAbsPartIdx, compID);#if ADAPTIVE_QP_SELECTIONTCoeff*    pcArlCoeff     = m_ppcQTTempArlCoeff[compID][ uiQTLayer ] + rTu.getCoefficientOffset(compID);
#endifconst UInt uiChPredMode         = pcCU->getIntraDir( chType, uiAbsPartIdx ); // 获取预测模式const UInt uiChCodedMode        = (uiChPredMode==DM_CHROMA_IDX && !bIsLuma) ? pcCU->getIntraDir(CHANNEL_TYPE_LUMA, getChromasCorrespondingPULumaIdx(uiAbsPartIdx, chFmt)) : uiChPredMode;const UInt uiChFinalMode        = ((chFmt == CHROMA_422)       && !bIsLuma) ? g_chroma422IntraAngleMappingTable[uiChCodedMode] : uiChCodedMode;const Int         blkX                                 = g_auiRasterToPelX[ g_auiZscanToRaster[ uiAbsPartIdx ] ];const Int         blkY                                 = g_auiRasterToPelY[ g_auiZscanToRaster[ uiAbsPartIdx ] ];const Int         bufferOffset                         = blkX + (blkY * MAX_CU_SIZE);Pel  *const encoderLumaResidual                  = resiLuma[RESIDUAL_ENCODER_SIDE ] + bufferOffset;Pel  *const reconstructedLumaResidual            = resiLuma[RESDIUAL_RECONSTRUCTED] + bufferOffset;const Bool        bUseCrossCPrediction                 = isChroma(compID) && (uiChPredMode == DM_CHROMA_IDX) && checkCrossCPrediction;const Bool        bUseReconstructedResidualForEstimate = m_pcEncCfg->getUseReconBasedCrossCPredictionEstimate();Pel *const  lumaResidualForEstimate              = bUseReconstructedResidualForEstimate ? reconstructedLumaResidual : encoderLumaResidual;#ifdef DEBUG_STRINGconst Int debugPredModeMask=DebugStringGetPredModeMask(MODE_INTRA);
#endif//===== init availability pattern =====Bool  bAboveAvail = false; // 上方是否有效Bool  bLeftAvail  = false; // 左侧是否有效DEBUG_STRING_NEW(sTemp)#ifndef DEBUG_STRING  // default0Save1Load2参数控制了预测像素的生成方式if( default0Save1Load2 != 2 )
#endif{const Bool bUseFilteredPredictions=TComPrediction::filteringIntraReferenceSamples(compID, uiChFinalMode, uiWidth, uiHeight, chFmt, pcCU->getSlice()->getSPS()->getDisableIntraReferenceSmoothing());initAdiPatternChType( rTu, bAboveAvail, bLeftAvail, compID, bUseFilteredPredictions DEBUG_STRING_PASS_INTO(sDebug) );//===== get prediction signal =====    // 预测操作
    predIntraAng( compID, uiChFinalMode, piOrg, uiStride, piPred, uiStride, rTu, bAboveAvail, bLeftAvail, bUseFilteredPredictions );// save prediction    // 保存预测信息if( default0Save1Load2 == 1 ){Pel*  pPred   = piPred;Pel*  pPredBuf = m_pSharedPredTransformSkip[compID];Int k = 0;for( UInt uiY = 0; uiY < uiHeight; uiY++ ){for( UInt uiX = 0; uiX < uiWidth; uiX++ ){pPredBuf[ k ++ ] = pPred[ uiX ];}pPred += uiStride;}}}
#ifndef DEBUG_STRINGelse{// load prediction    // 直接计算预测值Pel*  pPred   = piPred;Pel*  pPredBuf = m_pSharedPredTransformSkip[compID];Int k = 0;for( UInt uiY = 0; uiY < uiHeight; uiY++ ){for( UInt uiX = 0; uiX < uiWidth; uiX++ ){pPred[ uiX ] = pPredBuf[ k ++ ];}pPred += uiStride;}}
#endif//===== get residual signal =====
  {// get residual    // 计算残差Pel*  pOrg    = piOrg;Pel*  pPred   = piPred;Pel*  pResi   = piResi;for( UInt uiY = 0; uiY < uiHeight; uiY++ ){for( UInt uiX = 0; uiX < uiWidth; uiX++ ){        // 此处计算残差数据pResi[ uiX ] = pOrg[ uiX ] - pPred[ uiX ];}pOrg  += uiStride;pResi += uiStride;pPred += uiStride;}}if (pcCU->getSlice()->getPPS()->getUseCrossComponentPrediction()){if (bUseCrossCPrediction){if (xCalcCrossComponentPredictionAlpha( rTu, compID, lumaResidualForEstimate, piResi, uiWidth, uiHeight, MAX_CU_SIZE, uiStride ) == 0) return;TComTrQuant::crossComponentPrediction ( rTu, compID, reconstructedLumaResidual, piResi, piResi, uiWidth, uiHeight, MAX_CU_SIZE, uiStride, uiStride, false );}else if (isLuma(compID) && !bUseReconstructedResidualForEstimate){xStoreCrossComponentPredictionResult( encoderLumaResidual, piResi, rTu, 0, 0, MAX_CU_SIZE, uiStride );}}//===== transform and quantization =====  // 变换和量化//--- init rate estimation arrays for RDOQ ---  // 是否跳过变换操作if( useTransformSkip ? m_pcEncCfg->getUseRDOQTS() : m_pcEncCfg->getUseRDOQ() ){    // 比特数估计m_pcEntropyCoder->estimateBit( m_pcTrQuant->m_pcEstBitsSbac, uiWidth, uiHeight, chType );}//--- transform and quantization ---TCoeff uiAbsSum = 0;if (bIsLuma){pcCU       ->setTrIdxSubParts ( uiTrDepth, uiAbsPartIdx, uiFullDepth );}const QpParam cQP(*pcCU, compID);#if RDOQ_CHROMA_LAMBDAm_pcTrQuant->selectLambda     (compID);
#endif  // 变换(连同量化一起)m_pcTrQuant->transformNxN     ( rTu, compID, piResi, uiStride, pcCoeff,
#if ADAPTIVE_QP_SELECTIONpcArlCoeff,
#endifuiAbsSum, cQP);//--- inverse transform ---// uiAbsSum表示变换系数的绝对值之和
#ifdef DEBUG_STRINGif ( (uiAbsSum > 0) || (DebugOptionList::DebugString_InvTran.getInt()&debugPredModeMask) )
#elseif ( uiAbsSum > 0 )
#endif{    // 反变换m_pcTrQuant->invTransformNxN ( rTu, compID, piResi, uiStride, pcCoeff, cQP DEBUG_STRING_PASS_INTO_OPTIONAL(&sDebug, (DebugOptionList::DebugString_InvTran.getInt()&debugPredModeMask)) );}else{Pel* pResi = piResi;memset( pcCoeff, 0, sizeof( TCoeff ) * uiWidth * uiHeight );for( UInt uiY = 0; uiY < uiHeight; uiY++ ){memset( pResi, 0, sizeof( Pel ) * uiWidth );pResi += uiStride;}}//===== reconstruction =====  // 图像重建
  {Pel* pPred      = piPred;Pel* pResi      = piResi;Pel* pReco      = piReco;Pel* pRecQt     = piRecQt;Pel* pRecIPred  = piRecIPred;const UInt clipbd=g_bitDepth[chType];if (pcCU->getSlice()->getPPS()->getUseCrossComponentPrediction()){if (bUseCrossCPrediction){TComTrQuant::crossComponentPrediction( rTu, compID, reconstructedLumaResidual, piResi, piResi, uiWidth, uiHeight, MAX_CU_SIZE, uiStride, uiStride, true );}else if (isLuma(compID)){xStoreCrossComponentPredictionResult( reconstructedLumaResidual, piResi, rTu, 0, 0, MAX_CU_SIZE, uiStride );}}#ifdef DEBUG_STRINGstd::stringstream ss(stringstream::out);const Bool bDebugPred=((DebugOptionList::DebugString_Pred.getInt()&debugPredModeMask) && DEBUG_STRING_CHANNEL_CONDITION(compID));const Bool bDebugResi=((DebugOptionList::DebugString_Resi.getInt()&debugPredModeMask) && DEBUG_STRING_CHANNEL_CONDITION(compID));const Bool bDebugReco=((DebugOptionList::DebugString_Reco.getInt()&debugPredModeMask) && DEBUG_STRING_CHANNEL_CONDITION(compID));if (bDebugPred || bDebugResi || bDebugReco){ss << "###: " << "CompID: " << compID << " pred mode (ch/fin): " << uiChPredMode << "/" << uiChFinalMode << " absPartIdx: " << rTu.GetAbsPartIdxTU() << "\n";for( UInt uiY = 0; uiY < uiHeight; uiY++ ){ss << "###: ";if (bDebugPred){ss << " - pred: ";for( UInt uiX = 0; uiX < uiWidth; uiX++ ){ss << pPred[ uiX ] << ", ";}}if (bDebugResi) ss << " - resi: ";for( UInt uiX = 0; uiX < uiWidth; uiX++ ){if (bDebugResi) ss << pResi[ uiX ] << ", ";pReco    [ uiX ] = Pel(ClipBD<Int>( Int(pPred[uiX]) + Int(pResi[uiX]), clipbd ));pRecQt   [ uiX ] = pReco[ uiX ];pRecIPred[ uiX ] = pReco[ uiX ];}if (bDebugReco){ss << " - reco: ";for( UInt uiX = 0; uiX < uiWidth; uiX++ ){ss << pReco[ uiX ] << ", ";}}pPred     += uiStride;pResi     += uiStride;pReco     += uiStride;pRecQt    += uiRecQtStride;pRecIPred += uiRecIPredStride;ss << "\n";}DEBUG_STRING_APPEND(sDebug, ss.str())}else
#endif{for( UInt uiY = 0; uiY < uiHeight; uiY++ ){for( UInt uiX = 0; uiX < uiWidth; uiX++ ){pReco    [ uiX ] = Pel(ClipBD<Int>( Int(pPred[uiX]) + Int(pResi[uiX]), clipbd ));pRecQt   [ uiX ] = pReco[ uiX ];pRecIPred[ uiX ] = pReco[ uiX ];}pPred     += uiStride;pResi     += uiStride;pReco     += uiStride;pRecQt    += uiRecQtStride;pRecIPred += uiRecIPredStride;}}}//===== update distortion =====  // 失真代价更新ruiDist += m_pcRdCost->getDistPart( g_bitDepth[chType], piReco, uiStride, piOrg, uiStride, uiWidth, uiHeight, compID );
}

Void TComPrediction::predIntraAng( const ComponentID compID, UInt uiDirMode, Pel* piOrg /* Will be null for decoding */, UInt uiOrgStride, Pel* piPred, UInt uiStride, TComTU &rTu, Bool bAbove, Bool bLeft, const Bool bUseFilteredPredSamples, const Bool bUseLosslessDPCM )
{const ChromaFormat   format      = rTu.GetChromaFormat(); // 获得图片格式,一般为YUV420const ChannelType    channelType = toChannelType(compID);const TComRectangle &rect        = rTu.getRect(isLuma(compID) ? COMPONENT_Y : COMPONENT_Cb);const Int            iWidth      = rect.width;  // TU的宽const Int            iHeight     = rect.height; // TU的高assert( g_aucConvertToBit[ iWidth ] >= 0 ); //   4x  4assert( g_aucConvertToBit[ iWidth ] <= 5 ); // 128x128//assert( iWidth == iHeight  );
Pel *pDst = piPred; // 预测值的首地址// get starting pixel in block  // 获取块中的开始像素const Int sw = (2 * iWidth + 1);
  // 如果预测方式为垂直或水平,则bUseLosslessDPCM为trueif ( bUseLosslessDPCM ){    // 得到参考块的左上方地址(不在参考块内)const Pel *ptrSrc = getPredictorPtr( compID, false );// Sample Adaptive intra-Prediction (SAP)    // 水平模式预测if (uiDirMode==HOR_IDX){// left column filled with reference samples// remaining columns filled with piOrg data (if available).for(Int y=0; y<iHeight; y++){piPred[y*uiStride+0] = ptrSrc[(y+1)*sw];}if (piOrg!=0){piPred+=1; // miss off first columnfor(Int y=0; y<iHeight; y++, piPred+=uiStride, piOrg+=uiOrgStride){memcpy(piPred, piOrg, (iWidth-1)*sizeof(Pel));}}}    // 垂直模式预测else // VER_IDX
    {// top row filled with reference samples// remaining rows filled with piOrd data (if available)for(Int x=0; x<iWidth; x++){piPred[x] = ptrSrc[x+1];}if (piOrg!=0){piPred+=uiStride; // miss off the first rowfor(Int y=1; y<iHeight; y++, piPred+=uiStride, piOrg+=uiOrgStride){memcpy(piPred, piOrg, iWidth*sizeof(Pel));}}}}else{const Pel *ptrSrc = getPredictorPtr( compID, bUseFilteredPredSamples );if ( uiDirMode == PLANAR_IDX ){      // Planar模式xPredIntraPlanar( ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight, channelType, format );}else{// Create the predictionTComDataCU *const pcCU              = rTu.getCU();const UInt              uiAbsPartIdx      = rTu.GetAbsPartIdxTU();const Bool              enableEdgeFilters = !(pcCU->isRDPCMEnabled(uiAbsPartIdx) && pcCU->getCUTransquantBypass(uiAbsPartIdx));#if RExt__O0043_BEST_EFFORT_DECODING      // 角度模式xPredIntraAng( g_bitDepthInStream[channelType], ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight, channelType, format, uiDirMode, bAbove, bLeft, enableEdgeFilters );
#elsexPredIntraAng( g_bitDepth[channelType], ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight, channelType, format, uiDirMode, bAbove, bLeft, enableEdgeFilters );
#endifif(( uiDirMode == DC_IDX ) && bAbove && bLeft ){        // DC模式xDCPredFiltering( ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight, channelType );}}}}

3、estIntraPredChromaQT(色度块的帧内预测):

Void
TEncSearch::estIntraPredChromaQT(TComDataCU* pcCU,TComYuv*    pcOrgYuv,TComYuv*    pcPredYuv,TComYuv*    pcResiYuv,TComYuv*    pcRecoYuv,Pel         resiLuma[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE],Distortion  uiPreCalcDistCDEBUG_STRING_FN_DECLARE(sDebug))
{pcCU->getTotalDistortion      () -= uiPreCalcDistC;//const UInt    uiDepthCU     = pcCU->getDepth(0);const UInt    uiInitTrDepth  = pcCU->getPartitionSize(0) != SIZE_2Nx2N && enable4ChromaPUsInIntraNxNCU(pcOrgYuv->getChromaFormat()) ? 1 : 0;
//  const UInt    uiNumPU        = 1<<(2*uiInitTrDepth);
TComTURecurse tuRecurseCU(pcCU, 0);TComTURecurse tuRecurseWithPU(tuRecurseCU, false, (uiInitTrDepth==0)?TComTU::DONT_SPLIT : TComTU::QUAD_SPLIT);const UInt    uiQNumParts    = tuRecurseWithPU.GetAbsPartIdxNumParts();const UInt    uiDepthCU=tuRecurseWithPU.getCUDepth();const UInt    numberValidComponents = pcCU->getPic()->getNumberValidComponents();do{UInt       uiBestMode  = 0;Distortion uiBestDist  = 0;Double     dBestCost   = MAX_DOUBLE;//----- init mode list -----if (tuRecurseWithPU.ProcessChannelSection(CHANNEL_TYPE_CHROMA)){UInt uiModeList[FAST_UDI_MAX_RDMODE_NUM];const UInt  uiQPartNum     = uiQNumParts;const UInt  uiPartOffset   = tuRecurseWithPU.GetAbsPartIdxTU();{UInt  uiMinMode = 0;UInt  uiMaxMode = NUM_CHROMA_MODE;//----- check chroma modes -----pcCU->getAllowedChromaDir( uiPartOffset, uiModeList );#if RExt__ENVIRONMENT_VARIABLE_DEBUG_AND_TESTif (DebugOptionList::ForceChromaMode.isSet()){uiMinMode=DebugOptionList::ForceChromaMode.getInt();if (uiModeList[uiMinMode]==34) uiMinMode=5; // if the fixed mode has been renumbered because DM_CHROMA covers it, use DM_CHROMA.uiMaxMode=uiMinMode+1;}
#endifDEBUG_STRING_NEW(sPU)for( UInt uiMode = uiMinMode; uiMode < uiMaxMode; uiMode++ ){//----- restore context models -----m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepthCU][CI_CURR_BEST] );DEBUG_STRING_NEW(sMode)//----- chroma coding -----Distortion uiDist = 0;pcCU->setIntraDirSubParts  ( CHANNEL_TYPE_CHROMA, uiModeList[uiMode], uiPartOffset, uiDepthCU+uiInitTrDepth );xRecurIntraChromaCodingQT       ( pcOrgYuv, pcPredYuv, pcResiYuv, resiLuma, uiDist, tuRecurseWithPU DEBUG_STRING_PASS_INTO(sMode) );if( pcCU->getSlice()->getPPS()->getUseTransformSkip() ){m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepthCU][CI_CURR_BEST] );}UInt    uiBits = xGetIntraBitsQT( tuRecurseWithPU, false, true, false );Double  dCost  = m_pcRdCost->calcRdCost( uiBits, uiDist );//----- compare -----if( dCost < dBestCost ){DEBUG_STRING_SWAP(sPU, sMode);dBestCost   = dCost;uiBestDist  = uiDist;uiBestMode  = uiModeList[uiMode];xSetIntraResultChromaQT( pcRecoYuv, tuRecurseWithPU );for (UInt componentIndex = COMPONENT_Cb; componentIndex < numberValidComponents; componentIndex++){const ComponentID compID = ComponentID(componentIndex);::memcpy( m_puhQTTempCbf[compID], pcCU->getCbf( compID )+uiPartOffset, uiQPartNum * sizeof( UChar ) );::memcpy( m_puhQTTempTransformSkipFlag[compID], pcCU->getTransformSkip( compID )+uiPartOffset, uiQPartNum * sizeof( UChar ) );::memcpy( m_phQTTempCrossComponentPredictionAlpha[compID], pcCU->getCrossComponentPredictionAlpha(compID)+uiPartOffset, uiQPartNum * sizeof( Char ) );}}}DEBUG_STRING_APPEND(sDebug, sPU)//----- set data -----for (UInt componentIndex = COMPONENT_Cb; componentIndex < numberValidComponents; componentIndex++){const ComponentID compID = ComponentID(componentIndex);::memcpy( pcCU->getCbf( compID )+uiPartOffset, m_puhQTTempCbf[compID], uiQPartNum * sizeof( UChar ) );::memcpy( pcCU->getTransformSkip( compID )+uiPartOffset, m_puhQTTempTransformSkipFlag[compID], uiQPartNum * sizeof( UChar ) );::memcpy( pcCU->getCrossComponentPredictionAlpha(compID)+uiPartOffset, m_phQTTempCrossComponentPredictionAlpha[compID], uiQPartNum * sizeof( Char ) );}}if( ! tuRecurseWithPU.IsLastSection() ){for (UInt ch=COMPONENT_Cb; ch<numberValidComponents; ch++){const ComponentID compID    = ComponentID(ch);const TComRectangle &tuRect = tuRecurseWithPU.getRect(compID);const UInt  uiCompWidth     = tuRect.width;const UInt  uiCompHeight    = tuRect.height;const UInt  uiZOrder        = pcCU->getZorderIdxInCU() + tuRecurseWithPU.GetAbsPartIdxTU();Pel*  piDes           = pcCU->getPic()->getPicYuvRec()->getAddr( compID, pcCU->getAddr(), uiZOrder );const UInt  uiDesStride     = pcCU->getPic()->getPicYuvRec()->getStride( compID);const Pel*  piSrc           = pcRecoYuv->getAddr( compID, uiPartOffset );const UInt  uiSrcStride     = pcRecoYuv->getStride( compID);for( UInt uiY = 0; uiY < uiCompHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride ){for( UInt uiX = 0; uiX < uiCompWidth; uiX++ ){piDes[ uiX ] = piSrc[ uiX ];}}}}pcCU->setIntraDirSubParts( CHANNEL_TYPE_CHROMA, uiBestMode, uiPartOffset, uiDepthCU+uiInitTrDepth );pcCU->getTotalDistortion      () += uiBestDist;}} while (tuRecurseWithPU.nextSection(tuRecurseCU));//----- restore context models -----if( uiInitTrDepth != 0 ){ // set Cbf for all blocksUInt uiCombCbfU = 0;UInt uiCombCbfV = 0;UInt uiPartIdx  = 0;for( UInt uiPart = 0; uiPart < 4; uiPart++, uiPartIdx += uiQNumParts ){uiCombCbfU |= pcCU->getCbf( uiPartIdx, COMPONENT_Cb, 1 );uiCombCbfV |= pcCU->getCbf( uiPartIdx, COMPONENT_Cr, 1 );}for( UInt uiOffs = 0; uiOffs < 4 * uiQNumParts; uiOffs++ ){pcCU->getCbf( COMPONENT_Cb )[ uiOffs ] |= uiCombCbfU;pcCU->getCbf( COMPONENT_Cr )[ uiOffs ] |= uiCombCbfV;}}m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepthCU][CI_CURR_BEST] );
}

Void
TEncSearch::xRecurIntraChromaCodingQT(TComYuv*    pcOrgYuv,TComYuv*    pcPredYuv,TComYuv*    pcResiYuv,Pel         resiLuma[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE],Distortion& ruiDist,TComTU&     rTuDEBUG_STRING_FN_DECLARE(sDebug))
{TComDataCU         *pcCU                  = rTu.getCU();const UInt          uiTrDepth             = rTu.GetTransformDepthRel();const UInt          uiAbsPartIdx          = rTu.GetAbsPartIdxTU();const ChromaFormat  format                = rTu.GetChromaFormat();UInt                uiTrMode              = pcCU->getTransformIdx( uiAbsPartIdx );const UInt          numberValidComponents = getNumberValidComponents(format);if(  uiTrMode == uiTrDepth ){if (!rTu.ProcessChannelSection(CHANNEL_TYPE_CHROMA)) return;const UInt uiFullDepth = rTu.GetTransformDepthTotal();Bool checkTransformSkip = pcCU->getSlice()->getPPS()->getUseTransformSkip();checkTransformSkip &= TUCompRectHasAssociatedTransformSkipFlag(rTu.getRect(COMPONENT_Cb), pcCU->getSlice()->getPPS()->getTransformSkipLog2MaxSize());if ( m_pcEncCfg->getUseTransformSkipFast() ){checkTransformSkip &= TUCompRectHasAssociatedTransformSkipFlag(rTu.getRect(COMPONENT_Y), pcCU->getSlice()->getPPS()->getTransformSkipLog2MaxSize());if (checkTransformSkip){Int nbLumaSkip = 0;const UInt maxAbsPartIdxSub=uiAbsPartIdx + (rTu.ProcessingAllQuadrants(COMPONENT_Cb)?1:4);for(UInt absPartIdxSub = uiAbsPartIdx; absPartIdxSub < maxAbsPartIdxSub; absPartIdxSub ++){nbLumaSkip += pcCU->getTransformSkip(absPartIdxSub, COMPONENT_Y);}checkTransformSkip &= (nbLumaSkip > 0);}}for (UInt ch=COMPONENT_Cb; ch<numberValidComponents; ch++){const ComponentID compID = ComponentID(ch);DEBUG_STRING_NEW(sDebugBestMode)//use RDO to decide whether Cr/Cb takes TSm_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[uiFullDepth][CI_QT_TRAFO_ROOT] );const Bool splitIntoSubTUs = rTu.getRect(compID).width != rTu.getRect(compID).height;TComTURecurse TUIterator(rTu, false, (splitIntoSubTUs ? TComTU::VERTICAL_SPLIT : TComTU::DONT_SPLIT), true, compID);const UInt partIdxesPerSubTU = TUIterator.GetAbsPartIdxNumParts(compID);do{const UInt subTUAbsPartIdx   = TUIterator.GetAbsPartIdxTU(compID);Double     dSingleCost               = MAX_DOUBLE;Int        bestModeId                = 0;Distortion singleDistC               = 0;UInt       singleCbfC                = 0;Distortion singleDistCTmp            = 0;Double     singleCostTmp             = 0;UInt       singleCbfCTmp             = 0;Char       bestCrossCPredictionAlpha = 0;Int        bestTransformSkipMode     = 0;const Bool checkCrossComponentPrediction =    (pcCU->getIntraDir(CHANNEL_TYPE_CHROMA, subTUAbsPartIdx) == DM_CHROMA_IDX)&&  pcCU->getSlice()->getPPS()->getUseCrossComponentPrediction()&& (pcCU->getCbf(subTUAbsPartIdx,  COMPONENT_Y, uiTrDepth) != 0);const Int  crossCPredictionModesToTest = checkCrossComponentPrediction ? 2 : 1;const Int  transformSkipModesToTest    = checkTransformSkip            ? 2 : 1;const Int  totalModesToTest            = crossCPredictionModesToTest * transformSkipModesToTest;Int  currModeId                  = 0;Int  default0Save1Load2          = 0;for(Int transformSkipModeId = 0; transformSkipModeId < transformSkipModesToTest; transformSkipModeId++){for(Int crossCPredictionModeId = 0; crossCPredictionModeId < crossCPredictionModesToTest; crossCPredictionModeId++){pcCU->setCrossComponentPredictionAlphaPartRange(0, compID, subTUAbsPartIdx, partIdxesPerSubTU);DEBUG_STRING_NEW(sDebugMode)pcCU->setTransformSkipPartRange( transformSkipModeId, compID, subTUAbsPartIdx, partIdxesPerSubTU );currModeId++;const Bool isOneMode  = (totalModesToTest == 1);const Bool isLastMode = (currModeId == totalModesToTest); //NOTE: RExt - currModeId is indexed from 1if (isOneMode){default0Save1Load2 = 0;}else if (!isOneMode && (transformSkipModeId == 0) && (crossCPredictionModeId == 0)){default0Save1Load2 = 1; //save prediction on first mode
            }else{default0Save1Load2 = 2; //load it on subsequent modes
            }singleDistCTmp = 0;xIntraCodingTUBlock( pcOrgYuv, pcPredYuv, pcResiYuv, resiLuma, (crossCPredictionModeId != 0), singleDistCTmp, compID, TUIterator DEBUG_STRING_PASS_INTO(sDebugMode), default0Save1Load2);singleCbfCTmp = pcCU->getCbf( subTUAbsPartIdx, compID, uiTrDepth);if (  ((crossCPredictionModeId == 1) && (pcCU->getCrossComponentPredictionAlpha(subTUAbsPartIdx, compID) == 0))|| ((transformSkipModeId    == 1) && (singleCbfCTmp == 0))) //In order not to code TS flag when cbf is zero, the case for TS with cbf being zero is forbidden.
            {singleCostTmp = MAX_DOUBLE;}else if (!isOneMode){UInt bitsTmp = xGetIntraBitsQTChroma( TUIterator, compID, false );singleCostTmp  = m_pcRdCost->calcRdCost( bitsTmp, singleDistCTmp);}if(singleCostTmp < dSingleCost){DEBUG_STRING_SWAP(sDebugBestMode, sDebugMode)dSingleCost               = singleCostTmp;singleDistC               = singleDistCTmp;bestCrossCPredictionAlpha = (crossCPredictionModeId != 0) ? pcCU->getCrossComponentPredictionAlpha(subTUAbsPartIdx, compID) : 0;bestTransformSkipMode     = transformSkipModeId;bestModeId                = currModeId;singleCbfC                = singleCbfCTmp;if (!isOneMode && !isLastMode){xStoreIntraResultQT(compID, compID, TUIterator);m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ uiFullDepth ][ CI_TEMP_BEST ] );}}if (!isOneMode && !isLastMode){m_pcRDGoOnSbacCoder->load ( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_ROOT ] );}}}if(bestModeId < totalModesToTest){xLoadIntraResultQT(compID, compID, TUIterator);pcCU->setCbfPartRange( singleCbfC << uiTrDepth, compID, subTUAbsPartIdx, partIdxesPerSubTU );m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiFullDepth ][ CI_TEMP_BEST ] );}DEBUG_STRING_APPEND(sDebug, sDebugBestMode)pcCU ->setTransformSkipPartRange                ( bestTransformSkipMode,     compID, subTUAbsPartIdx, partIdxesPerSubTU );pcCU ->setCrossComponentPredictionAlphaPartRange( bestCrossCPredictionAlpha, compID, subTUAbsPartIdx, partIdxesPerSubTU );ruiDist += singleDistC;}while (TUIterator.nextSection(rTu));if (splitIntoSubTUs) offsetSubTUCBFs(rTu, compID);}}else{UInt    uiSplitCbf[MAX_NUM_COMPONENT] = {0,0,0};TComTURecurse tuRecurseChild(rTu, false);const UInt uiTrDepthChild   = tuRecurseChild.GetTransformDepthRel();do{DEBUG_STRING_NEW(sChild)xRecurIntraChromaCodingQT( pcOrgYuv, pcPredYuv, pcResiYuv, resiLuma, ruiDist, tuRecurseChild DEBUG_STRING_PASS_INTO(sChild) );DEBUG_STRING_APPEND(sDebug, sChild)const UInt uiAbsPartIdxSub=tuRecurseChild.GetAbsPartIdxTU();for(UInt ch=COMPONENT_Cb; ch<numberValidComponents; ch++){uiSplitCbf[ch] |= pcCU->getCbf( uiAbsPartIdxSub, ComponentID(ch), uiTrDepthChild );}} while ( tuRecurseChild.nextSection(rTu) );UInt uiPartsDiv = rTu.GetAbsPartIdxNumParts();for(UInt ch=COMPONENT_Cb; ch<numberValidComponents; ch++){if (uiSplitCbf[ch]){const UInt flag=1<<uiTrDepth;ComponentID compID=ComponentID(ch);UChar *pBase=pcCU->getCbf( compID );for( UInt uiOffs = 0; uiOffs < uiPartsDiv; uiOffs++ ){pBase[ uiAbsPartIdx + uiOffs ] |= flag;}}}}
}

转载于:https://www.cnblogs.com/lucifer1997/p/10991046.html

HM16.0之帧内模式——xCheckRDCostIntra()函数相关推荐

  1. HM16.0之帧间预测——xCheckRDCostInter()函数

    参考:https://blog.csdn.net/nb_vol_1/article/category/6179825/1? 1.源代码: #if AMP_MRG Void TEncCu::xCheck ...

  2. ECM技术学习:解码端帧内模式推导(Decoder-side Intra Mode Derivation )

    解码端帧内模式推导(DIMD)技术是之前在VVC标准化的过程中提出的技术,因为其在解码端引入的复杂度较高,因此没有被VVC采纳.为了探索下一代压缩标准,JVET最近设立了最新的ECM参考平台,将DIM ...

  3. H.266/VVC技术学习之帧内模式编码

    在HEVC中,支持33种角度模式.DC模式和Planar模式,为了减少编码比特,使用长度为3的最可能模式列表.在VVC中,引入了ISP模式.MRL模式.MIP模式等,帧内模式编码时需要先对这些模式的f ...

  4. sad代价计算_转载:H.264帧内模式选择以及代价计算相关知识

    转自:http://blog.csdn.net/xingyu19871124/article/details/7721374 标签: h.264 优化 算法 c 测试 2012-07-06 10:57 ...

  5. 【VTM10.0】帧内之PDPC技术

    PDPC (Position dependent intra prediction combination) 一种对预测值的修正的技术.部分帧内模式在进行帧内预测之后,进行PDPC的加权平均计算,得到 ...

  6. HM-16.0编码过程:将YUV文件编码成HEVC格式的码流

    HM-16.0编码:将YUV文件编码成HEVC格式的码流 注: 1   为了快速优化运行(不调程序的时候),可以将程序的版本设为"release",否则还是设为"debu ...

  7. FFMpeg4.0相关结构体和函数

    文章目录 相关指令 相关结构体 av_register_all() 已废弃无需添加 avformat_network_init() 初始化网络封装库 AVFormatContext结构体 AVDict ...

  8. ICASSP2021:AV1帧内模式编码改进

    本文来自ICASSP2021论文<IMPROVED INTRA MODE CODING BEYOND AV1> AV1帧内预测 简介 在AV1中帧内预测模式分为角度帧内预测模式和非角度帧内 ...

  9. ECM技术学习:基于模板的帧内模式推导(Template based intra mode derivation )

    和基于梯度的帧内模式推导类似,ECM中还使用了基于模板的帧内模式推导. 基本原理:对于当前待预测CU,在模板区域计算预测像素和重建像素的SATD,从MPM列表中选出两个SATD最小的预测模式mode1 ...

最新文章

  1. 2021年大数据常用语言Scala(五):基础语法学习 字符串
  2. 联想输入快捷键_UG软件F8快捷键和笔记本电脑F8快捷键冲突的解决方法
  3. 2018 CVPR GAN 相关论文调研 (自己分了下类,附地址哦)
  4. mysql超大数据库备份
  5. zabbix监控linux文件目录,zabbix之日志文件监控
  6. 【一起去大厂系列】深入理解MySQL中where 1 = 1的用处
  7. 集成Glide4.3.1出错!AbstractMethodError: abstract method void com.bumptech.glide.module
  8. HTTP基础(图解HTTP笔记)幕布
  9. gif分解工具_Python之GIF图倒放,沙雕快乐源泉!我已经笑了一天了!
  10. linux系统 锐捷_linux系统的锐捷安装
  11. SMA2.92高频连接器的主要特点​
  12. 时空序列预测之PredRNN(用ST-LSTM预测学习的循环神经网络)
  13. 小火狐进化_神奇宝贝:最强和最弱的御三家属于哪个世代?当然是这两代
  14. 微信小程序——消息推送配置
  15. Java中print()\println()\printf()的区别及用法
  16. Visual C++游戏编程基础之摩擦力、加速度、重力
  17. 武大博士后应聘社区社工引热议,内卷还是人各有志?
  18. 基于Android13的系统启动流程分析(三)之FirstStageMain阶段
  19. JAVA图片处理大全
  20. 阿里云轻量应用服务器配置frp内网穿透通过Mac远控Win10主机配置指南

热门文章

  1. Html将Json对象在页面结构化显示与Json文件生成下载
  2. Chrome模拟微信浏览器UA访问教程
  3. IM即时通讯哇呼--解析
  4. 浅析GPU通信技术(中)-NVLink
  5. NVIDIA GPU A100 Ampere(安培) 架构深度解析
  6. Kotlin的圣光机甲——KtArmor通用流程篇 (二)
  7. 基于web的前后端分离nodejs和vue.js医院分诊系统
  8. 【2019总结篇】谈谈数字化时代,ERP如何坐稳数字化底座
  9. 初学建模者都在收藏的:3dmax常见的八十个问题汇总!
  10. Linux高阶命令使用