转载于http://blog.csdn.net/mashiying2013/article/details/10068927
VoidTEncCu::xCheckRDCostMerge2Nx2N( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, Bool*earlyDetectionSkipMode )
{
assert( rpcTempCU->getSlice()->getSliceType() !=I_SLICE ); //确定该片是P Slice 或者 B Slice
//#define MRG_MAX_NUM_CANDS 5
//由于是两个列表所以这里要左移一位
TComMvField cMvFieldNeighbours[MRG_MAX_NUM_CANDS << 1]; //double length for mv of both lists
//
UChar uhInterDirNeighbours[MRG_MAX_NUM_CANDS];
Int numValidMergeCand = 0;
//初始化,rpcTempCU->getSlice()->getMaxNumMergeCand()== 5
for( UInt ui = 0; ui < rpcTempCU->getSlice()->getMaxNumMergeCand();++ui ){
uhInterDirNeighbours[ui] = 0;
}
//计算该CU所在的深度
UChar uhDepth = rpcTempCU->getDepth( 0 );
//根据当前CU的深度,做相应的初始化,以4x4块为单位
//memset( m_pePartSize +uiAbsPartIdx, eMode, m_pcPic->getNumPartInCU() >> ( 2 * uiDepth ) );
// Char* m_pePartSize; ///< array of partition sizes
// 给 PU 中相应的partition 写入分割模式
rpcTempCU->setPartSizeSubParts( SIZE_2Nx2N, 0, uhDepth ); // interprets depth relative toLCU level
//memset( m_CUTransquantBypass +uiAbsPartIdx, flag, m_pcPic->getNumPartInCU() >> ( 2 * uiDepth ) );
//m_CUTransquantBypass : array ofcu_transquant_bypass flags
//
rpcTempCU->setCUTransquantBypassSubParts(m_pcEncCfg->getCUTransquantBypassFlagValue(), 0, uhDepth );
//设置cMvFieldNeighbours,uhInterDirNeighbours,numValidMergeCand 等
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;
//!< 默认为false
if ( rpcTempCU->isLosslessCoded(0)) {
iteration = 1;
} else {
iteration = 2;
}
//代码结构分析
//第一次不理skip模式,bestIsSkip 初始值为 false;
//第二次不处理mergeCandBuffer[uiMergeCand]==1的情况
//遍历两次:第一次是对残差不编码;第二次对残差编码.
for( UInt uiNoResidual = 0; uiNoResidual <iteration; ++uiNoResidual ){
//!< 遍历所有merging candidates
for( UInt uiMergeCand = 0; uiMergeCand <numValidMergeCand; ++uiMergeCand ) {
{
//!((uiNoResidual==1 &&mergeCandBuffer[uiMergeCand]==1) || (bestIsSkip && uiNoResidual == 0))
//!< uiNoResidual等于0或者mergeCandBuffer[uiMergeCand]等于0时条件成立
if(!(uiNoResidual==1 &&mergeCandBuffer[uiMergeCand]==1)){
//!< bestIsSkip等于false或者uiNoResidual等于1时条件成立
if( !(bestIsSkip &&uiNoResidual == 0) ){
// set MC parameters
// interprets depth relative to LCUlevel 设置变量 m_pePredMode
//memset( m_pePredMode +uiAbsPartIdx(0), eMode, m_pcPic->getNumPartInCU() >> ( 2 * uiDepth ));
rpcTempCU->setPredModeSubParts( MODE_INTER, 0, uhDepth );
// 设置变量 m_CUTransquantBypass
// memset( m_CUTransquantBypass +uiAbsPartIdx, flag, m_pcPic->getNumPartInCU() >> ( 2 * uiDepth ) );
rpcTempCU->setCUTransquantBypassSubParts(m_pcEncCfg->getCUTransquantBypassFlagValue(), 0, uhDepth );
// interprets depth relative to LCUlevel 设置变量 m_pePartSize
//memset( m_pePartSize +uiAbsPartIdx, eMode, m_pcPic->getNumPartInCU() >> ( 2 * uiDepth ) );
rpcTempCU->setPartSizeSubParts( SIZE_2Nx2N, 0, uhDepth );
// interprets depth relative to LCUlevel
rpcTempCU->setMergeFlagSubParts( true, 0, 0, uhDepth );
// interprets depth relative to LCUlevel
rpcTempCU->setMergeIndexSubParts(uiMergeCand, 0, 0, uhDepth );
// interprets depth relative to LCUlevel
rpcTempCU->setInterDirSubParts(uhInterDirNeighbours[uiMergeCand], 0, 0, uhDepth );
// interprets depth relative torpcTempCU level
rpcTempCU->getCUMvField( REF_PIC_LIST_0 )->setAllMvField(cMvFieldNeighbours[0 + 2*uiMergeCand], SIZE_2Nx2N, 0, 0 );
// interprets depth relative torpcTempCU level
rpcTempCU->getCUMvField( REF_PIC_LIST_1 )->setAllMvField(cMvFieldNeighbours[1 + 2*uiMergeCand], SIZE_2Nx2N, 0, 0 );
//运动补偿
m_pcPredSearch->motionCompensation ( rpcTempCU, m_ppcPredYuvTemp[uhDepth] );
// estimate residual and encodeeverything
m_pcPredSearch->encodeResAndCalcRdInterCU(
rpcTempCU,
m_ppcOrigYuv [uhDepth],
m_ppcPredYuvTemp[uhDepth],
m_ppcResiYuvTemp[uhDepth],
m_ppcResiYuvBest[uhDepth],
m_ppcRecoYuvTemp[uhDepth],
//!< 对残差进行编码并计算RDCost
(uiNoResidual? true:false));
//第一次修改,
if(uiNoResidual==0){
//!< CBF为0,说明变换系数全为0
if(rpcTempCU->getQtRootCbf(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);
//!< m_useFastDecisionForMerge默认为true
if(m_pcEncCfg->getUseFastDecisionForMerge() && !bestIsSkip ) {
bestIsSkip = rpcBestCU->getQtRootCbf(0) == 0;
}
}
}
}
}
// 不处理
if(uiNoResidual == 0 &&m_pcEncCfg->getUseEarlySkipDetection())
{
if(rpcBestCU->getQtRootCbf( 0 ) == 0) //!< earlyDetectionSkip 算法
{
if( rpcBestCU->getMergeFlag( 0 ))
{
*earlyDetectionSkipMode = true;
}
else
{
Int absoulte_MV=0;
for ( UInt uiRefListIdx = 0; uiRefListIdx <2; uiRefListIdx++ )
{
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;
}
}
}
assert(0);
}
}
}