1、源代码:
Void TEncCu::xCheckRDCostIntra( TComDataCU *&rpcBestCU, TComDataCU *&rpcTempCU, Double &cost, PartSize eSize DEBUG_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 Coefficients Bool 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 bLumaOnly DEBUG_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 ]; 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_NBIT const 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(); #else const 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 ===== 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) ===== 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)) 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(); Pel* piOrg = pcOrgYuv ->getAddr( COMPONENT_Y, uiAbsPartIdx ); 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; 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 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_COSTS std::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_MPM Int uiPreds[NUM_MOST_PROBABLE_MODES] = {-1, -1, -1}; Int iMode = -1; 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_MOD UInt uiSecondBestMode = MAX_UINT; Double dSecondBestPUCost = MAX_DOUBLE; #endif DEBUG_STRING_NEW(sPU) UInt uiBestPUMode = 0; Distortion uiBestPUDistY = 0; Distortion uiBestPUDistC = 0; Double dBestPUCost = MAX_DOUBLE; #if RExt__ENVIRONMENT_VARIABLE_DEBUG_AND_TEST UInt max=numModesForFullRD; if (DebugOptionList::ForceLumaMode.isSet()) max=0; // we are forcing a direction, so don't bother with mode check for ( UInt uiMode = 0; uiMode < max; uiMode++) #else for( UInt uiMode = 0; uiMode < numModesForFullRD; uiMode++ ) #endif { // set luma prediction mode UInt 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 partition Distortion uiPUDistY = 0; Distortion uiPUDistC = 0; Double dPUCost = 0.0; #if HHI_RQT_INTRA_SPEEDUP xRecurIntraCodingQT( bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaPU, uiPUDistY, uiPUDistC, true, dPUCost, tuRecurseWithPU DEBUG_STRING_PASS_INTO(sMode) ); #else xRecurIntraCodingQT( bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaPU, uiPUDistY, uiPUDistC, dPUCost, tuRecurseWithPU DEBUG_STRING_PASS_INTO(sMode) ); #endif #ifdef DEBUG_INTRA_SEARCH_COSTS std::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_MOD uiSecondBestMode = uiBestPUMode; dSecondBestPUCost = dBestPUCost; #endif 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 ); } } } 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_MOD else if( dPUCost < dSecondBestPUCost ) { uiSecondBestMode = uiOrgMode; dSecondBestPUCost = dPUCost; } #endif } // Mode loop #if HHI_RQT_INTRA_SPEEDUP #if HHI_RQT_INTRA_SPEEDUP_MOD for( UInt ui =0; ui < 2; ++ui ) #endif { #if HHI_RQT_INTRA_SPEEDUP_MOD UInt uiOrgMode = ui ? uiSecondBestMode : uiBestPUMode; if( uiOrgMode == MAX_UINT ) { break; } #else UInt uiOrgMode = uiBestPUMode; #endif #if RExt__ENVIRONMENT_VARIABLE_DEBUG_AND_TEST if (DebugOptionList::ForceLumaMode.isSet()) uiOrgMode = DebugOptionList::ForceLumaMode.getInt(); #endif pcCU->setIntraDirSubParts ( CHANNEL_TYPE_LUMA, uiOrgMode, uiPartOffset, uiDepth + uiInitTrDepth ); DEBUG_STRING_NEW(sModeTree) // set context models m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] ); // determine residual for partition Distortion uiPUDistY = 0; Distortion uiPUDistC = 0; Double dPUCost = 0.0; xRecurIntraCodingQT( bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaPU, uiPUDistY, uiPUDistC, false, dPUCost, tuRecurseWithPU DEBUG_STRING_PASS_INTO(sModeTree)); // check r-d cost 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 #endif DEBUG_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 blocks UInt 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; }
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 uiPreCalcDistC DEBUG_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_TEST if (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; } #endif DEBUG_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 blocks UInt 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] ); }