xRecurIntraChromaCodingQT在estIntraPredChromaQT函数中被调用,用来计算每个帧内色度预测模式时的cost。
xRecurIntraChromaCodingQT函数通过调用xIntraCodingTUBlock函数,对每个色度预测模式进行预测变换量化反量化反变换之后,获得到resi和pred像素,继而得到reco像素,就可计算失真和cost。
xRecurIntraChromaCodingQT的函数流程其实和xRecurIntraCodingLumaQT函数类似,只是luma中test的是变换模式,chroma中则test的是"是/否TS模式+是/否跨组件预测"的组合模式。
流程:
首先判断tu是否需要划分,若tu划分时,对每个划分出的小tu递归调用本函数,计算每个小tu的在chromaIntra模式下的最优的cost,最后求和;
如果tu不划分,分别对Cb和Cr通道进行处理。对于每个通道,是/否TS模式+是/否跨组件预测可以构成4种模式,分别对4种模式调用xIntraCodingTUBlock函数进行预测变换量化反量化反变换,得到reco像素和cost,按照cost选取TU的最优模式。选择的最优cost即当前test的chromaIntra模式的最优的cost。
ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT(CodingStructure &cs, Partitioner& partitioner)
{
UnitArea currArea = partitioner.currArea();
const bool keepResi = KEEP_PRED_AND_RESI_SIGNALS;
if( !currArea.Cb().valid() ) return ChromaCbfs( false );
//色度tu、色度pu、lumaTU
TransformUnit &currTU = *cs.getTU( currArea.chromaPos(), CHANNEL_TYPE_CHROMA );
const PredictionUnit &pu = *cs.getPU( currArea.chromaPos(), CHANNEL_TYPE_CHROMA );
const TransformUnit &currTULuma = CS::isDualITree( cs ) ? *cs.picture->cs->getTU( currArea.lumaPos(), CHANNEL_TYPE_LUMA ) : currTU;
//CS::isDualITree()为true时,亮度和色度域有不同的划分树,就必须特别的getLumaTU;如果不是DualITree,直接用currTU
#if HEVC_USE_RQT || ENABLE_BMS
UInt currDepth = partitioner.currTrDepth; //tu的划分深度
#endif
const PPS &pps = *cs.pps;
ChromaCbfs cbfs ( false );
#if HEVC_USE_RQT || ENABLE_BMS
if (currDepth == currTU.depth) //tu划分深度已达到partitioner.currTrDepth,不再划分
#endif
{
if (!currArea.Cb().valid() || !currArea.Cr().valid()) //Cb/Cr分量可用
{
return cbfs;
}
Bool checkTransformSkip = pps.getUseTransformSkip(); //Cb是否TS模式
checkTransformSkip &= TU::hasTransformSkipFlag( *currTU.cs, partitioner.currArea().Cb() );
if( m_pcEncCfg->getUseTransformSkipFast() ) //Y的TS模式
{
checkTransformSkip &= TU::hasTransformSkipFlag( *currTU.cs, partitioner.currArea().Y() );
if( checkTransformSkip && cs.pcv->noChroma2x2 )
{
Int nbLumaSkip = currTULuma.transformSkip[0] ? 1 : 0;
#if HEVC_USE_RQT
if( !TU::isProcessingAllQuadrants( currArea ) )
#endif
{
// the chroma blocks are co-located with the last luma block, so backwards references are needed
nbLumaSkip += cs.getTU( currTULuma.Y().topLeft().offset( -