HM16.0之帧内模式——xCheckRDCostIntra()函数
参考: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()函数相关推荐
- HM16.0之帧间预测——xCheckRDCostInter()函数
参考:https://blog.csdn.net/nb_vol_1/article/category/6179825/1? 1.源代码: #if AMP_MRG Void TEncCu::xCheck ...
- ECM技术学习:解码端帧内模式推导(Decoder-side Intra Mode Derivation )
解码端帧内模式推导(DIMD)技术是之前在VVC标准化的过程中提出的技术,因为其在解码端引入的复杂度较高,因此没有被VVC采纳.为了探索下一代压缩标准,JVET最近设立了最新的ECM参考平台,将DIM ...
- H.266/VVC技术学习之帧内模式编码
在HEVC中,支持33种角度模式.DC模式和Planar模式,为了减少编码比特,使用长度为3的最可能模式列表.在VVC中,引入了ISP模式.MRL模式.MIP模式等,帧内模式编码时需要先对这些模式的f ...
- sad代价计算_转载:H.264帧内模式选择以及代价计算相关知识
转自:http://blog.csdn.net/xingyu19871124/article/details/7721374 标签: h.264 优化 算法 c 测试 2012-07-06 10:57 ...
- 【VTM10.0】帧内之PDPC技术
PDPC (Position dependent intra prediction combination) 一种对预测值的修正的技术.部分帧内模式在进行帧内预测之后,进行PDPC的加权平均计算,得到 ...
- HM-16.0编码过程:将YUV文件编码成HEVC格式的码流
HM-16.0编码:将YUV文件编码成HEVC格式的码流 注: 1 为了快速优化运行(不调程序的时候),可以将程序的版本设为"release",否则还是设为"debu ...
- FFMpeg4.0相关结构体和函数
文章目录 相关指令 相关结构体 av_register_all() 已废弃无需添加 avformat_network_init() 初始化网络封装库 AVFormatContext结构体 AVDict ...
- ICASSP2021:AV1帧内模式编码改进
本文来自ICASSP2021论文<IMPROVED INTRA MODE CODING BEYOND AV1> AV1帧内预测 简介 在AV1中帧内预测模式分为角度帧内预测模式和非角度帧内 ...
- ECM技术学习:基于模板的帧内模式推导(Template based intra mode derivation )
和基于梯度的帧内模式推导类似,ECM中还使用了基于模板的帧内模式推导. 基本原理:对于当前待预测CU,在模板区域计算预测像素和重建像素的SATD,从MPM列表中选出两个SATD最小的预测模式mode1 ...
最新文章
- 2021年大数据常用语言Scala(五):基础语法学习 字符串
- 联想输入快捷键_UG软件F8快捷键和笔记本电脑F8快捷键冲突的解决方法
- 2018 CVPR GAN 相关论文调研 (自己分了下类,附地址哦)
- mysql超大数据库备份
- zabbix监控linux文件目录,zabbix之日志文件监控
- 【一起去大厂系列】深入理解MySQL中where 1 = 1的用处
- 集成Glide4.3.1出错!AbstractMethodError: abstract method void com.bumptech.glide.module
- HTTP基础(图解HTTP笔记)幕布
- gif分解工具_Python之GIF图倒放,沙雕快乐源泉!我已经笑了一天了!
- linux系统 锐捷_linux系统的锐捷安装
- SMA2.92高频连接器的主要特点​
- 时空序列预测之PredRNN(用ST-LSTM预测学习的循环神经网络)
- 小火狐进化_神奇宝贝:最强和最弱的御三家属于哪个世代?当然是这两代
- 微信小程序——消息推送配置
- Java中print()\println()\printf()的区别及用法
- Visual C++游戏编程基础之摩擦力、加速度、重力
- 武大博士后应聘社区社工引热议,内卷还是人各有志?
- 基于Android13的系统启动流程分析(三)之FirstStageMain阶段
- JAVA图片处理大全
- 阿里云轻量应用服务器配置frp内网穿透通过Mac远控Win10主机配置指南