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 eSize
DEBUG_STRING_FN_DECLARE(sDebug) )
{
DEBUG_STRING_NEW(sTest) UInt uiDepth = rpcTempCU->getDepth( ); rpcTempCU->setSkipFlagSubParts( false, , uiDepth ); rpcTempCU->setPartSizeSubParts( eSize, , uiDepth );
rpcTempCU->setPredModeSubParts( MODE_INTRA, , uiDepth );
rpcTempCU->setChromaQpAdjSubParts( rpcTempCU->getCUTransquantBypass() ? : m_ChromaQpAdjIdc, , uiDepth ); Bool bSeparateLumaChroma = true; // choose estimation mode Distortion uiPreCalcDistC = ;
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, , true );
} m_pcEntropyCoder->encodeSkipFlag ( rpcTempCU, , true );
m_pcEntropyCoder->encodePredMode( rpcTempCU, , true );
m_pcEntropyCoder->encodePartSize( rpcTempCU, , uiDepth, true );
m_pcEntropyCoder->encodePredInfo( rpcTempCU, );
m_pcEntropyCoder->encodeIPCMInfo(rpcTempCU, , true ); // Encode Coefficients
Bool bCodeDQP = getdQPFlag();
Bool codeChromaQpAdjFlag = getCodeChromaQpAdjFlag();
m_pcEntropyCoder->encodeCoeff( rpcTempCU, , 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();
const UInt uiInitTrDepth = pcCU->getPartitionSize() == SIZE_2Nx2N ? : ;
const UInt uiInitTrDepthC = pcCU->getPartitionSize() != SIZE_2Nx2N && enable4ChromaPUsInIntraNxNCU(pcOrgYuv->getChromaFormat()) ? : ;
const UInt uiNumPU = <<(*uiInitTrDepth);
const UInt uiQNumParts = pcCU->getTotalNumPart() >> ;
const UInt uiWidthBit = pcCU->getIntraSizeIdx();
const ChromaFormat chFmt = pcCU->getPic()->getChromaFormat();
const UInt numberValidComponents = getNumberValidComponents(chFmt);
Distortion uiOverallDistY = ;
Distortion uiOverallDistC = ;
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 = ; 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()) ?
sqrt(0.57 * pow(2.0, ((RExt__LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP_PRIME - ) / 3.0)))
: m_pcRdCost->getSqrtLambda();
#else
const Double sqrtLambdaForFirstPass= (m_pcEncCfg->getCostMode()==COST_MIXED_LOSSLESS_LOSSY_CODING && pcCU->getCUTransquantBypass()) ?
sqrt(0.57 * pow(2.0, ((RExt__LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP_PRIME - - * (g_bitDepth[CHANNEL_TYPE_LUMA] - )) / 3.0)))
: m_pcRdCost->getSqrtLambda();
#endif //===== set QP and clear Cbf =====
// 设置QP参数,清理Cbf
if ( pcCU->getSlice()->getPPS()->getUseDQP() == true)
{
pcCU->setQPSubParts( pcCU->getQP(), , uiDepth );
}
else
{
// 进入此处
pcCU->setQPSubParts( pcCU->getSlice()->getSliceQp(), , uiDepth );
} //===== loop over partitions =====
TComTURecurse tuRecurseCU(pcCU, );
TComTURecurse tuRecurseWithPU(tuRecurseCU, false, (uiInitTrDepth==)?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 = ; //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=; i < numModesForFullRD; i++ )
{
// 用于存储每一种模式的消耗
CandCostList[ i ] = MAX_DOUBLE;
}
CandNum = ; 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() == ;
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 = ; modeIdx < numModesAvailable; modeIdx++ )
{
UInt uiMode = modeIdx;
Distortion uiSad = ; 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 = ; // 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] = {-, -, -}; Int iMode = -;
// 根据相邻块的预测模式来对当前块的模式进行预测,得到若干模式(称为预测模式),存放在uiPreds中
Int numCand = pcCU->getIntraDirPredictor( uiPartOffset, uiPreds, COMPONENT_Y, &iMode ); if( iMode >= )
{
// 将候选列表的索引设置为此模式
numCand = iMode;
}
// 遍历预测模式,如果它不在模式候选列表中,那么把它添加到其中
for( Int j=; j < numCand; j++)
{
Bool mostProbableModeIncluded = false;
Int mostProbableMode = uiPreds[j]; for( Int i=; i < numModesForFullRD; i++)
{
mostProbableModeIncluded |= (mostProbableMode == uiRdModeList[i]);
}
if (!mostProbableModeIncluded)
{
uiRdModeList[numModesForFullRD++] = mostProbableMode;
}
}
#endif // FAST_UDI_USE_MPM
}
else
{
for( Int i=; 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 = ;
Distortion uiBestPUDistY = ;
Distortion uiBestPUDistC = ;
Double dBestPUCost = MAX_DOUBLE; #if RExt__ENVIRONMENT_VARIABLE_DEBUG_AND_TEST
UInt max=numModesForFullRD; if (DebugOptionList::ForceLumaMode.isSet()) max=; // we are forcing a direction, so don't bother with mode check
for ( UInt uiMode = ; uiMode < max; uiMode++)
#else
// 遍历候选集中的模式
for( UInt uiMode = ; 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 = ;
Distortion uiPUDistC = ;
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) );
#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 = ; 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 = ; 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 =; ui < ; ++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 = ;
Distortion uiPUDistC = ;
Double dPUCost = 0.0;
// 使用最优模式对PU进行预测,然后变换量化等,计算代价
// 注意倒数第三个参数bCheckFirst是false,表示当前PU不再进行划分,即只处理当前深度的PU
xRecurIntraCodingQT( 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 = ; 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 = ; 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 = ; 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) ? : getNumberValidComponents(pcCU->getPic()->getChromaFormat()); for (UInt ch=; 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 = ; uiY < uiCompHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride )
{
for( UInt uiX = ; 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 > )
{ // set Cbf for all blocks
UInt uiCombCbfY = ;
UInt uiCombCbfU = ;
UInt uiCombCbfV = ;
UInt uiPartIdx = ;
for( UInt uiPart = ; uiPart < ; uiPart++, uiPartIdx += uiQNumParts )
{
uiCombCbfY |= pcCU->getCbf( uiPartIdx, COMPONENT_Y, );
uiCombCbfU |= pcCU->getCbf( uiPartIdx, COMPONENT_Cb, );
uiCombCbfV |= pcCU->getCbf( uiPartIdx, COMPONENT_Cr, );
}
for( UInt uiOffs = ; uiOffs < * 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_SPEEDUP
Bool bCheckFirst,
#endif
Double& dRDCost,
TComTU& rTu
DEBUG_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) ? : 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 = ; 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_SPEEDUP
Int 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 size
Bool 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 slice
noSplitIntraMaxTuSize = ( uiLog2TrSize <= min(maxTuSize,) ); // if maximum RD-penalty don't check TU size 32x32
if(m_pcEncCfg->getRDpenalty()==)
{
bCheckFull = ( uiLog2TrSize <= min(maxTuSize,));
}
}
if( bCheckFirst && noSplitIntraMaxTuSize ) {
bCheckSplit = false;
}
#else
Int maxTuSize = pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize();
Int isIntraSlice = (pcCU->getSlice()->getSliceType() == I_SLICE);
// if maximum RD-penalty don't check TU size 32x32
if((m_pcEncCfg->getRDpenalty()==) && !isIntraSlice)
{
bCheckFull = ( uiLog2TrSize <= min(maxTuSize,));
}
#endif
Double dSingleCost = MAX_DOUBLE;
Distortion uiSingleDist[MAX_NUM_CHANNEL_TYPE] = {,};
UInt uiSingleCbf[MAX_NUM_COMPONENT] = {,,};
Bool checkTransformSkip = pcCU->getSlice()->getPPS()->getUseTransformSkip();
Int bestModeId[MAX_NUM_COMPONENT] = { , , };
checkTransformSkip &= TUCompRectHasAssociatedTransformSkipFlag(rTu.getRect(COMPONENT_Y), pcCU->getSlice()->getPPS()->getTransformSkipLog2MaxSize());
checkTransformSkip &= (!pcCU->getCUTransquantBypass()); 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] = { , };
UInt singleCbfTmp[MAX_NUM_COMPONENT] = { , , };
Double singleCostTmp = ;
Int firstCheckId = ;
// 遍历两次是为了选取最优模式,modeId能够决定xIntraCodingTUBlock的最后一个参数,该参数控制了预测像素如何生成
for(Int modeId = firstCheckId; modeId < ; modeId ++)
{
DEBUG_STRING_NEW(sModeString)
Int default0Save1Load2 = ;
singleDistTmp[]=singleDistTmp[]=;
if(modeId == firstCheckId)
{
default0Save1Load2 = ;
}
else
{
default0Save1Load2 = ;
} 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 == && singleCbfTmp[COMPONENT_Y] == )
{
//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=; 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 = ; 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] == )
{
//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] == )
{
const ComponentID compID=ComponentID(ch);
const UInt totalAdjustedDepthChan = rTu.GetTransformDepthTotalAdj(compID);
pcCU ->setTransformSkipSubParts ( , compID, uiAbsPartIdx, totalAdjustedDepthChan);
bestModeId[ch] = ;
}
}
}
}
}
// 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 ( , 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==) && !isIntraSlice)
{
uiSingleBits=uiSingleBits*;
} 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 = ; 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] = {,};
UInt uiSplitCbf[MAX_NUM_COMPONENT] = {,,}; 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[], uiSplitDist[], bCheckFirst, dSplitCost, tuRecurseChild DEBUG_STRING_PASS_INTO(sChild) );
#else
xRecurIntraCodingQT( bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaSplit, uiSplitDist[], uiSplitDist[], dSplitCost, tuRecurseChild DEBUG_STRING_PASS_INTO(sChild) );
#endif
DEBUG_STRING_APPEND(sSplit, sChild)
for(UInt ch=; 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=<<uiTrDepth;
const ComponentID compID=ComponentID(ch);
UChar *pBase=pcCU->getCbf( compID );
for( UInt uiOffs = ; 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 = ; 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=; 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 = ; uiY < uiHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride )
{
for( UInt uiX = ; 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& rTu
DEBUG_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_SELECTION
TCoeff* pcArlCoeff = m_ppcQTTempArlCoeff[compID][ uiQTLayer ] + rTu.getCoefficientOffset(compID);
#endif const 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_STRING
const 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 != )
#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 == )
{
Pel* pPred = piPred;
Pel* pPredBuf = m_pSharedPredTransformSkip[compID];
Int k = ;
for( UInt uiY = ; uiY < uiHeight; uiY++ )
{
for( UInt uiX = ; uiX < uiWidth; uiX++ )
{
pPredBuf[ k ++ ] = pPred[ uiX ];
}
pPred += uiStride;
}
}
}
#ifndef DEBUG_STRING
else
{
// load prediction
// 直接计算预测值
Pel* pPred = piPred;
Pel* pPredBuf = m_pSharedPredTransformSkip[compID];
Int k = ;
for( UInt uiY = ; uiY < uiHeight; uiY++ )
{
for( UInt uiX = ; 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 = ; uiY < uiHeight; uiY++ )
{
for( UInt uiX = ; 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 ) == ) 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, , , 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 = ;
if (bIsLuma)
{
pcCU ->setTrIdxSubParts ( uiTrDepth, uiAbsPartIdx, uiFullDepth );
} const QpParam cQP(*pcCU, compID); #if RDOQ_CHROMA_LAMBDA
m_pcTrQuant->selectLambda (compID);
#endif
// 变换(连同量化一起)
m_pcTrQuant->transformNxN ( rTu, compID, piResi, uiStride, pcCoeff,
#if ADAPTIVE_QP_SELECTION
pcArlCoeff,
#endif
uiAbsSum, cQP
); //--- inverse transform ---
// uiAbsSum表示变换系数的绝对值之和
#ifdef DEBUG_STRING
if ( (uiAbsSum > ) || (DebugOptionList::DebugString_InvTran.getInt()&debugPredModeMask) )
#else
if ( uiAbsSum > )
#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, , sizeof( TCoeff ) * uiWidth * uiHeight );
for( UInt uiY = ; uiY < uiHeight; uiY++ )
{
memset( pResi, , 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, , , MAX_CU_SIZE, uiStride );
}
} #ifdef DEBUG_STRING
std::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 = ; uiY < uiHeight; uiY++ )
{
ss << "###: ";
if (bDebugPred)
{
ss << " - pred: ";
for( UInt uiX = ; uiX < uiWidth; uiX++ )
{
ss << pPred[ uiX ] << ", ";
}
}
if (bDebugResi) ss << " - resi: ";
for( UInt uiX = ; 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 = ; 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 = ; uiY < uiHeight; uiY++ )
{
for( UInt uiX = ; 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(); // 获得图片格式,一般为YUV420
const 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 ] >= ); // 4x 4
assert( g_aucConvertToBit[ iWidth ] <= ); // 128x128
//assert( iWidth == iHeight ); Pel *pDst = piPred; // 预测值的首地址 // get starting pixel in block
// 获取块中的开始像素
const Int sw = ( * iWidth + );
// 如果预测方式为垂直或水平,则bUseLosslessDPCM为true
if ( 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=; y<iHeight; y++)
{
piPred[y*uiStride+] = ptrSrc[(y+)*sw];
}
if (piOrg!=)
{
piPred+=; // miss off first column
for(Int y=; y<iHeight; y++, piPred+=uiStride, piOrg+=uiOrgStride)
{
memcpy(piPred, piOrg, (iWidth-)*sizeof(Pel));
}
}
}
// 垂直模式预测
else // VER_IDX
{
// top row filled with reference samples
// remaining rows filled with piOrd data (if available)
for(Int x=; x<iWidth; x++)
{
piPred[x] = ptrSrc[x+];
}
if (piOrg!=)
{
piPred+=uiStride; // miss off the first row
for(Int y=; 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+, sw, pDst, uiStride, iWidth, iHeight, channelType, format );
}
else
{
// Create the prediction
TComDataCU *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+, sw, pDst, uiStride, iWidth, iHeight, channelType, format, uiDirMode, bAbove, bLeft, enableEdgeFilters );
#else
xPredIntraAng( g_bitDepth[channelType], ptrSrc+sw+, sw, pDst, uiStride, iWidth, iHeight, channelType, format, uiDirMode, bAbove, bLeft, enableEdgeFilters );
#endif if(( uiDirMode == DC_IDX ) && bAbove && bLeft )
{
// DC模式
xDCPredFiltering( ptrSrc+sw+, 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 uiPreCalcDistC
DEBUG_STRING_FN_DECLARE(sDebug))
{
pcCU->getTotalDistortion () -= uiPreCalcDistC; //const UInt uiDepthCU = pcCU->getDepth(0);
const UInt uiInitTrDepth = pcCU->getPartitionSize() != SIZE_2Nx2N && enable4ChromaPUsInIntraNxNCU(pcOrgYuv->getChromaFormat()) ? : ;
// const UInt uiNumPU = 1<<(2*uiInitTrDepth); TComTURecurse tuRecurseCU(pcCU, );
TComTURecurse tuRecurseWithPU(tuRecurseCU, false, (uiInitTrDepth==)?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 = ;
Distortion uiBestDist = ;
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 = ;
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]==) uiMinMode=; // if the fixed mode has been renumbered because DM_CHROMA covers it, use DM_CHROMA.
uiMaxMode=uiMinMode+;
}
#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 = ;
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 = ; uiY < uiCompHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride )
{
for( UInt uiX = ; 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 != )
{ // set Cbf for all blocks
UInt uiCombCbfU = ;
UInt uiCombCbfV = ;
UInt uiPartIdx = ;
for( UInt uiPart = ; uiPart < ; uiPart++, uiPartIdx += uiQNumParts )
{
uiCombCbfU |= pcCU->getCbf( uiPartIdx, COMPONENT_Cb, );
uiCombCbfV |= pcCU->getCbf( uiPartIdx, COMPONENT_Cr, );
}
for( UInt uiOffs = ; uiOffs < * 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& rTu
DEBUG_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 = ;
const UInt maxAbsPartIdxSub=uiAbsPartIdx + (rTu.ProcessingAllQuadrants(COMPONENT_Cb)?:);
for(UInt absPartIdxSub = uiAbsPartIdx; absPartIdxSub < maxAbsPartIdxSub; absPartIdxSub ++)
{
nbLumaSkip += pcCU->getTransformSkip(absPartIdxSub, COMPONENT_Y);
}
checkTransformSkip &= (nbLumaSkip > );
}
} 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 TS
m_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 = ;
Distortion singleDistC = ;
UInt singleCbfC = ;
Distortion singleDistCTmp = ;
Double singleCostTmp = ;
UInt singleCbfCTmp = ;
Char bestCrossCPredictionAlpha = ;
Int bestTransformSkipMode = ; const Bool checkCrossComponentPrediction = (pcCU->getIntraDir(CHANNEL_TYPE_CHROMA, subTUAbsPartIdx) == DM_CHROMA_IDX)
&& pcCU->getSlice()->getPPS()->getUseCrossComponentPrediction()
&& (pcCU->getCbf(subTUAbsPartIdx, COMPONENT_Y, uiTrDepth) != ); const Int crossCPredictionModesToTest = checkCrossComponentPrediction ? : ;
const Int transformSkipModesToTest = checkTransformSkip ? : ;
const Int totalModesToTest = crossCPredictionModesToTest * transformSkipModesToTest;
Int currModeId = ;
Int default0Save1Load2 = ; for(Int transformSkipModeId = ; transformSkipModeId < transformSkipModesToTest; transformSkipModeId++)
{
for(Int crossCPredictionModeId = ; crossCPredictionModeId < crossCPredictionModesToTest; crossCPredictionModeId++)
{
pcCU->setCrossComponentPredictionAlphaPartRange(, compID, subTUAbsPartIdx, partIdxesPerSubTU);
DEBUG_STRING_NEW(sDebugMode)
pcCU->setTransformSkipPartRange( transformSkipModeId, compID, subTUAbsPartIdx, partIdxesPerSubTU );
currModeId++; const Bool isOneMode = (totalModesToTest == );
const Bool isLastMode = (currModeId == totalModesToTest); //NOTE: RExt - currModeId is indexed from 1 if (isOneMode)
{
default0Save1Load2 = ;
}
else if (!isOneMode && (transformSkipModeId == ) && (crossCPredictionModeId == ))
{
default0Save1Load2 = ; //save prediction on first mode
}
else
{
default0Save1Load2 = ; //load it on subsequent modes
} singleDistCTmp = ; xIntraCodingTUBlock( pcOrgYuv, pcPredYuv, pcResiYuv, resiLuma, (crossCPredictionModeId != ), singleDistCTmp, compID, TUIterator DEBUG_STRING_PASS_INTO(sDebugMode), default0Save1Load2);
singleCbfCTmp = pcCU->getCbf( subTUAbsPartIdx, compID, uiTrDepth); if ( ((crossCPredictionModeId == ) && (pcCU->getCrossComponentPredictionAlpha(subTUAbsPartIdx, compID) == ))
|| ((transformSkipModeId == ) && (singleCbfCTmp == ))) //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 != ) ? pcCU->getCrossComponentPredictionAlpha(subTUAbsPartIdx, compID) : ;
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] = {,,}; 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=<<uiTrDepth;
ComponentID compID=ComponentID(ch);
UChar *pBase=pcCU->getCbf( compID );
for( UInt uiOffs = ; uiOffs < uiPartsDiv; uiOffs++ )
{
pBase[ uiAbsPartIdx + uiOffs ] |= flag;
}
}
}
}
}
HM16.0之帧内模式——xCheckRDCostIntra()函数的更多相关文章
- HM16.0之帧间预测——xCheckRDCostInter()函数
参考:https://blog.csdn.net/nb_vol_1/article/category/6179825/1? 1.源代码: #if AMP_MRG Void TEncCu::xCheck ...
- HM16.0之帧间Merge模式——xCheckRDCostMerge2Nx2N
参考:https://blog.csdn.net/nb_vol_1/article/details/51163625 1.源代码: /** check RD costs for a CU block ...
- HM16.0 TAppEncoder
参考: https://www.cnblogs.com/tiansha/p/6458573.html https://blog.csdn.net/liangjiubujiu/article/deta ...
- Python3.0科学计算学习之函数
函数 函数允许程序的控制在不同的代码片段之间切换,函数的重要意义在于可以在程序中清晰地分离不同的任务,将复杂的问题分解为几个相对简单的子问题,并逐个解决.即"分而治之". Pyth ...
- 使用HM16.0对视频编码
1.编译HM16.0源码: 步骤参照:https://www.vcodex.com/hevc-and-vp9-codecs-try-them-yourself/(可设置pq等参数) [编译过程中遇到l ...
- HM16.0之PCM模式——xCheckIntraPCM
参考:https://blog.csdn.net/cxy19931018/article/details/79781042 1.源代码: /** Check R-D costs for a CU wi ...
- HM16.0帧内预测重要函数笔记
Void TEncSearch::estIntraPredQT 亮度块的帧内预测入口函数 Void TComPrediction::initAdiPatternChType 获取参考样本点并滤波 ...
- VB6.0和VB.Net的函数等对照表
VB6.0和VB.Net的对照表 VB6.0 VB.NET AddItem Object名.AddItem Object名.Items.Add ListBox1.Items.Add ComboBox1 ...
- cocos2d-x 2.0.2升级后某些函数变化(转)
最近看cocos2d-x 2.0.2发布后升级了一下,升级后发现又出现了很多错误,原来有一些地方的代码用法改变了.在修改代码的过程中,简单做了一些记录,当做是一个备忘录. 1.CCScene和CCLa ...
随机推荐
- HTML5其他标签应用
HTML5 是下一代 HTML 标准. HTML5 多媒体 音频标签 <audio src=" "></audio> 视频标签 <video src= ...
- 大数据(hadoop)
大数据 一.概述 二.大数据特点 三.大数据部门组织结构 hadoop框架 一.hadoop是什么 Hadoop是一个由Apache基金会所开发的分布式系统基础架构. 主要解决,海量数据的存储和海量数 ...
- Spring Cache缓存注解
目录 Spring Cache缓存注解 @Cacheable 键生成器 @CachePut @CacheEvict @Caching @CacheConfig Spring Cache缓存注解 本篇文 ...
- PHP simplexml_import_dom() 函数
实例 获取 DOM 文档节点并转换为 SimpleXML 节点: <?php$dom=new domDocument;高佣联盟 www.cgewang.com$dom->loadXML(& ...
- PHP attributes() 函数
实例 返回 XML 的 body 元素的属性和值: <?php$note=<<<XML<note><to>Tove</to>高佣联盟 www ...
- 使用idea 时出现classnotfound
如果是web项目,而且确定包在.. 不用担心,点开Project structure 在artifacts 选择就好了..双击就可以 包就进lib下了
- requests入门实践01_下载2560*1080的电脑壁纸
新版本移步:https://www.cnblogs.com/zy7y/p/13376228.html 附上代码 # !usr/bin/env python # -*- coding:utf-8 -*- ...
- yum自建离线仓库
1.步骤 centOS的安装包,完整版最好--everyhing版本 解压缩 将文件夹内Packages文件导入系统 执行命令如下: 1. mv ./Packages/ /mnt/ 2. create ...
- 3行!仅3行代码就能抓取B站(弹幕、评论、用户)数据
今天介绍一个获取B站数据的Python扩展库-bilibili_api 可以获取的数据包括: video-视频模块 user-用户模块 dynamic-动态模块 这次用“Running Man”十周年 ...
- MYSQL 按某个字段分组,然后取每组前3条记录
先初始化一些数据,表名为 test ,字段及数据为: SQL执行结果为:每个 uid 都只有 3 条记录. SQL语句为: SELECT * FROM test main WHERE ...