本文将对实现merge模式的主函数xCheckRDCostMerge2Nx2N进行分析,方便理清merge模式的整个过程。之前的一篇分析了getInterMergeCandidates的具体实现,还有两个比较重要的函数motionCompensation和encodeResAndCalcRdInterCU,将留在后面陆续进行分析,但是根据它们的命名就不难猜出它们的作用,而且事实也是这样,因此对理解merge模式的整个过程没有影响,可以暂时不用去细究具体实现。下面仍然以贴代码及注释的方式来进行分析:
[cpp]
Void TEncCu::xCheckRDCostMerge2Nx2N( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, Bool *earlyDetectionSkipMode )
{
assert( rpcTempCU->getSlice()->getSliceType() != I_SLICE );
TComMvField cMvFieldNeighbours[MRG_MAX_NUM_CANDS << 1]; // double length for mv of both lists
UChar uhInterDirNeighbours[MRG_MAX_NUM_CANDS];
Int numValidMergeCand = 0;
for( UInt ui = 0; ui < rpcTempCU->getSlice()->getMaxNumMergeCand(); ++ui )
{
uhInterDirNeighbours[ui] = 0;
}
UChar uhDepth = rpcTempCU->getDepth( 0 );
rpcTempCU->setPartSizeSubParts( SIZE_2Nx2N, 0, uhDepth ); // interprets depth relative to LCU level
rpcTempCU->setCUTransquantBypassSubParts( m_pcEncCfg->getCUTransquantBypassFlagValue(), 0, uhDepth );
rpcTempCU->getInterMergeCandidates( 0, 0, cMvFieldNeighbours,uhInterDirNeighbours, numValidMergeCand );
//! 创建一个merging candidates的列表
Int mergeCandBuffer[MRG_MAX_NUM_CANDS];
for( UInt ui = 0; ui < rpcTempCU->getSlice()->getMaxNumMergeCand(); ++ui )
{
mergeCandBuffer[ui] = 0;
}
Bool bestIsSkip = false;
UInt iteration;
if ( rpcTempCU->isLosslessCoded(0)) //!< 默认为false
{
iteration = 1;
}
else
{
iteration = 2;
}
for( UInt uiNoResidual = 0; uiNoResidual < iteration; ++uiNoResidual )
{
for( UInt uiMergeCand = 0; uiMergeCand < numValidMergeCand; ++uiMergeCand ) //!< 遍历所有merging candidates
{
{
if(!(uiNoResidual==1 && mergeCandBuffer[uiMergeCand]==1)) //!< uiNoResidual等于0或者mergeCandBuffer[uiMergeCand]等于0时条件成立
{
if( !(bestIsSkip && uiNoResidual == 0) ) //!< bestIsSkip等于false或者uiNoResidual等于1时条件成立
{
// set MC parameters
rpcTempCU->setPredModeSubParts( MODE_INTER, 0, uhDepth ); // interprets depth relative to LCU level
rpcTempCU->setCUTransquantBypassSubParts( m_pcEncCfg->getCUTransquantBypassFlagValue(), 0, uhDepth );
rpcTempCU->setPartSizeSubParts( SIZE_2Nx2N, 0, uhDepth ); // interprets depth relative to LCU level
rpcTempCU->setMergeFlagSubParts( true, 0, 0, uhDepth ); // interprets depth relative to LCU level
rpcTempCU->setMergeIndexSubParts( uiMergeCand, 0, 0, uhDepth ); // interprets depth relative to LCU level
rpcTempCU->setInterDirSubParts( uhInterDirNeighbours[uiMergeCand], 0, 0, uhDepth ); // interprets depth relative to LCU level
rpcTempCU->getCUMvField( REF_PIC_LIST_0 )->setAllMvField( cMvFieldNeighbours[0 + 2*uiMergeCand], SIZE_2Nx2N, 0, 0 ); // interprets depth relative to rpcTempCU level
rpcTempCU->getCUMvField( REF_PIC_LIST_1 )->setAllMvField( cMvFieldNeighbours[1 + 2*uiMergeCand], SIZE_2Nx2N, 0, 0 ); // interprets depth relative to rpcTempCU level
// do MC
m_pcPredSearch->motionCompensation ( rpcTempCU, m_ppcPredYuvTemp[uhDepth] ); //!< 运动补偿
// estimate residual and encode everything
m_pcPredSearch->encodeResAndCalcRdInterCU( rpcTempCU,
m_ppcOrigYuv [uhDepth],
m_ppcPredYuvTemp[uhDepth],
m_ppcResiYuvTemp[uhDepth],
m_ppcResiYuvBest[uhDepth],
m_ppcRecoYuvTemp[uhDepth],
(uiNoResidual true:false)); //!< 对残差进行编码并计算RDCost
if(uiNoResidual==0)
{
if(rpcTempCU->getQtRootCbf(0) == 0) /