本文將對實現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) //!< CBF為0,說明變換系數全為0 { mergeCandBuffer[uiMergeCand] = 1; } }
rpcTempCU->setSkipFlagSubParts( rpcTempCU->getQtRootCbf(0) == 0, 0, uhDepth );
Int orgQP = rpcTempCU->getQP( 0 ); xCheckDQP( rpcTempCU ); xCheckBestMode(rpcBestCU, rpcTempCU, uhDepth); //!< 更新最佳模式 rpcTempCU->initEstData( uhDepth, orgQP ); //!< 重新初始化預測參數,為下一次預測做准備
if( m_pcEncCfg->getUseFastDecisionForMerge() && !bestIsSkip ) //!< m_useFastDecisionForMerge默認為true { bestIsSkip = rpcBestCU->getQtRootCbf(0) == 0; }
}//!< if( !(bestIsSkip && uiNoResidual == 0) )
}//!< if(!(uiNoResidual==1 && mergeCandBuffer[uiMergeCand]==1)) }//!< }//!< for( UInt uiMergeCand = 0; uiMergeCand < numValidMergeCand; ++uiMergeCand )
if(uiNoResidual == 0 && m_pcEncCfg->getUseEarlySkipDetection()) //!< 第一次對merging candidates迭代後
{ if(rpcBestCU->getQtRootCbf( 0 ) == 0) //!< earlyDetectionSkip 算法 { if( rpcBestCU->getMergeFlag( 0 )) { *earlyDetectionSkipMode = true; } else { Int absoulte_MV=0; for ( UInt uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ ) { www.2cto.com if ( rpcBestCU->getSlice()->getNumRefIdx( RefPicList( uiRefListIdx ) ) > 0 ) { TComCUMvField* pcCUMvField = rpcBestCU->getCUMvField(RefPicList( uiRefListIdx )); Int iHor = pcCUMvField->getMvd( 0 ).getAbsHor(); Int iVer = pcCUMvField->getMvd( 0 ).getAbsVer(); absoulte_MV+=iHor+iVer; } }
if(absoulte_MV == 0)
{ *earlyDetectionSkipMode = true; } }//!< else }//!< if(rpcBestCU->getQtRootCbf( 0 ) == 0) }//!< if(uiNoResidual == 0 && m_pcEncCfg->getUseEarlySkipDetection()) }//!< for( UInt uiNoResidual = 0; uiNoResidual < iteration; ++uiNoResidual ) }