estIntraPredChromaQT函数在xCheckRDCostIntra中被调用,以获取最优的色度帧内模式。
getIntraChromaCandModes调用getIntraChromaCandModes函数得到色度的5个候选模式,5个候选通过RDO选取最优色度帧内模式。
Void IntraSearch::estIntraPredChromaQT(CodingUnit &cu, Partitioner &partitioner)
{
const ChromaFormat format = cu.chromaFormat;
const UInt numberValidComponents = getNumberValidComponents(format);
CodingStructure &cs = *cu.cs;
const TempCtx ctxStart ( m_CtxCache, m_CABACEstimator->getCtx() );
cs.setDecomp( cs.area.Cb(), false );
auto &pu = *cu.firstPU;
{
UInt uiBestMode = 0;
Distortion uiBestDist = 0;
Double dBestCost = MAX_DOUBLE;
//----- init mode list ----
{
UInt uiMinMode = 0;
UInt uiMaxMode = NUM_CHROMA_MODE; //5
//----- check chroma modes -----
UInt chromaCandModes[ NUM_CHROMA_MODE ];
PU::getIntraChromaCandModes( pu, chromaCandModes ); //得到5个色度候选模式
// create a temporary CS
CodingStructure &saveCS = *m_pSaveCS[0]; //saveCS用于存储RDO过程中最优模式的数据
saveCS.pcv = cs.pcv;
saveCS.picture = cs.picture;
saveCS.area.repositionTo( cs.area );
saveCS.clearTUs();
if( CS::isDualITree( cs ) )
{
#if ENABLE_BMS
if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) ) //当前cu是否可以划分为多个tu来处理
{
partitioner.splitCurrArea( TU_MAX_TR_SPLIT, cs );
do
{
cs.addTU( CS::getArea( cs, partitioner.currArea(), partitioner.chType ), partitioner.chType ).depth = partitioner.currTrDepth;
} while( partitioner.nextPart( cs ) );
partitioner.exitCurrSplit();
}
else
#endif
cs.addTU( CS::getArea( cs, partitioner.currArea(), partitioner.chType ), partitioner.chType ); //cu和tu大小一样,没划分
}
std::vector<TransformUnit*> orgTUs;
// create a store for the TUs
for( const auto &ptu : cs.tus )
{
// for split TUs in HEVC, add the TUs without Chroma parts for correct setting of Cbfs
if( pu.contains( *ptu, CHANNEL_TYPE_CHROMA ) || ( !cs.pcv->noRQT && !ptu->Cb().valid() && !ptu->Cr().valid() ) )
{
saveCS.addTU( *ptu, partitioner.chType );
orgTUs.push_back( ptu ); //orgTUs中就是cs的tu
}
}
// save the dist
Distortion baseDist = cs.dist;
for (UInt uiMode = uiMinMode; uiMode < uiMaxMode; uiMode++) //对5个色度候选模式RDO选最优
{
const int chromaIntraMode = chromaCandModes[uiMode];
cs.setDecomp( pu.Cb(), false );
cs.dist = baseDist;
//----- restore context models -----
m_CABACEstimator->getCtx() = ctxStart;
//----- chroma coding -----
pu.intraDir[1] = chromaIntraMode;
xRecurIntraChromaCodingQT( cs, partitioner ); //预测得到各色度模式的pred像素,从而得到残差,经过变换反变换得到reco像素
//由orig和reco,得到失真,从而得到cost
if (cs.pps->getUseTransformSkip())
{
m_CABACEstimator->getCtx() = ctxStart;
}
UInt64 fracBits = xGetIntraFracBitsQT( cs, partitioner, false, true ); //编码比特数
Distortion uiDist = cs.dist;
Double dCost = m_pcRdCost->calcRdCost( fracBits, uiDist - baseDist ); //cost
//----- compare -----
if( dCost < dBestCost ) //将最优模式数据存入saveCS,包括reco、pred、resi像素和tu信息
{
for( UInt i = getFirstComponentOfChannel( CHANNEL_TYPE_CHROMA ); i < numberValidComponents; i++ )
{
const CompArea &area = pu.blocks[i];
saveCS.getRecoBuf ( area ).copyFrom( cs.getRecoBuf ( area ) );
#if KEEP_PRED_AND_RESI_SIGNALS
saveCS.getPredBuf ( area ).copyFrom( cs.getPredBuf ( area ) );
saveCS.getResiBuf ( area ).copyFrom( cs.getResiBuf ( area ) );
#endif
cs.picture->getRecoBuf( area ).copyFrom( cs.getRecoBuf( area ) );
for( UInt j = 0; j < saveCS.tus.size(); j++ )
{
saveCS.tus[j]->copyComponentFrom( *orgTUs[j], area.compID ); //将最优的tu信息存入saveCS
#if ENABLE_CHROMA_422
if( cs.pcv->multiBlock422 )
{
saveCS.tus[ j ]->copyComponentFrom( *orgTUs[ j ], ComponentID( area.compID + SCND_TBLOCK_OFFSET ) );
}
#endif
}
}
dBestCost = dCost; //更新记录最优的失真cost和色度模式
uiBestDist = uiDist;
uiBestMode = chromaIntraMode;
}
}
//将saveCS中存储的最优色度模式相关信息,copy到cs中去,即xCheckRDCostIntra函数中的tempCS
for( UInt i = getFirstComponentOfChannel( CHANNEL_TYPE_CHROMA ); i < numberValidComponents; i++ )
{
const CompArea &area = pu.blocks[i];
cs.getRecoBuf ( area ).copyFrom( saveCS.getRecoBuf( area ) ); //将saveCS最优信息copy给cs
cs.picture->getRecoBuf( area ).copyFrom( cs. getRecoBuf( area ) );
for( UInt j = 0; j < saveCS.tus.size(); j++ )
{
orgTUs[ j ]->copyComponentFrom( *saveCS.tus[ j ], area.compID );
}
}
}
pu.intraDir[1] = uiBestMode;
cs.dist = uiBestDist;
}
//----- restore context models -----
m_CABACEstimator->getCtx() = ctxStart;
}