bool EncCu::xCheckBestMode( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
{
//上传best
bool bestCSUpdated = false;
if( !tempCS->cus.empty() )
{
if( tempCS->cus.size() == 1 )
{
//返回可变序列的第一位作为CU,检查是否有merge标志位
const CodingUnit& cu = *tempCS->cus.front();
CHECK( cu.skip && !cu.firstPU->mergeFlag, "Skip flag without a merge flag is not allowed!" );
}
#if WCG_EXT
DTRACE_BEST_MODE( tempCS, bestCS, m_pcRdCost->getLambda( true ) );
#else
DTRACE_BEST_MODE( tempCS, bestCS, m_pcRdCost->getLambda() );
#endif
if( m_modeCtrl->useModeResult( encTestMode, tempCS, partitioner ) )
{
std::swap( tempCS, bestCS );
// store temp best CI for next CU coding
m_CurrCtx->best = m_CABACEstimator->getCtx();
m_bestModeUpdated = true;
bestCSUpdated = true;
}
}
// reset context states
m_CABACEstimator->getCtx() = m_CurrCtx->start;
return bestCSUpdated;
}
if语句:如果当前CU的子CU数不为0。 以{area={x = 0, y = 0, width = 16, height = 4} 为例,子CU有两个,
名称 | 值 | 类型 | |
---|---|---|---|
▶ | tempCS->cus | { size=2 } | std::vector<CodingUnit *,std::allocator<CodingUnit *> > |
所以满足条件。具体可以之后再看其他的CU验证
2.useModeResult()函数决定了是否上传最佳bestCS
bool EncModeCtrlMTnoRQT::useModeResult( const EncTestMode& encTestmode, CodingStructure*& tempCS, Partitioner& partitioner )
{
xExtractFeatures( encTestmode, *tempCS );
ComprCUCtx& cuECtx = m_ComprCUCtxList.back();
if( encTestmode.type == ETM_SPLIT_BT_H )
{
cuECtx.set( BEST_HORZ_SPLIT_COST, tempCS->cost );
}
else if( encTestmode.type == ETM_SPLIT_BT_V )
{
cuECtx.set( BEST_VERT_SPLIT_COST, tempCS->cost );
}
else if( encTestmode.type == ETM_SPLIT_TT_H )
{
cuECtx.set( BEST_TRIH_SPLIT_COST, tempCS->cost );
}
else if( encTestmode.type == ETM_SPLIT_TT_V )
{
cuECtx.set( BEST_TRIV_SPLIT_COST, tempCS->cost );
}
else if( encTestmode.type == ETM_INTRA )
{
const CodingUnit cu = *tempCS->getCU( partitioner.chType );
if( !cu.mtsFlag )
{
cuECtx.bestMtsSize2Nx2N1stPass = tempCS->cost;
}
if( !cu.ispMode )
{
cuECtx.bestCostMtsFirstPassNoIsp = tempCS->cost;
}
}
if( m_pcEncCfg->getIMV4PelFast() && m_pcEncCfg->getIMV() && encTestmode.type == ETM_INTER_ME )
{
int imvMode = ( encTestmode.opts & ETO_IMV ) >> ETO_IMV_SHIFT;
if( imvMode == 1 )
{
if( tempCS->cost < cuECtx.get<double>( BEST_IMV_COST ) )
{
cuECtx.set( BEST_IMV_COST, tempCS->cost );
}
}
else if( imvMode == 0 )
{
if( tempCS->cost < cuECtx.get<double>( BEST_NO_IMV_COST ) )
{
cuECtx.set( BEST_NO_IMV_COST, tempCS->cost );
}
}
}
if( encTestmode.type == ETM_SPLIT_QT )
{
int maxQtD = 0;
for( const auto& cu : tempCS->cus )
{
maxQtD = std::max<int>( maxQtD, cu->qtDepth );
}
cuECtx.set( MAX_QT_SUB_DEPTH, maxQtD );
}
int maxMtD = tempCS->pcv->getMaxBtDepth( *tempCS->slice, partitioner.chType ) + partitioner.currImplicitBtDepth;
if( encTestmode.type == ETM_SPLIT_BT_H )
{
if( tempCS->cus.size() > 2 )
{
int h_2 = tempCS->area.blocks[partitioner.chType].height / 2;
int cu1_h = tempCS->cus.front()->blocks[partitioner.chType].height;
int cu2_h = tempCS->cus.back() ->blocks[partitioner.chType].height;
cuECtx.set( DO_TRIH_SPLIT, cu1_h < h_2 || cu2_h < h_2 || partitioner.currMtDepth + 1 == maxMtD );
}
}
else if( encTestmode.type == ETM_SPLIT_BT_V )
{
if( tempCS->cus.size() > 2 )
{
int w_2 = tempCS->area.blocks[partitioner.chType].width / 2;
int cu1_w = tempCS->cus.front()->blocks[partitioner.chType].width;
int cu2_w = tempCS->cus.back() ->blocks[partitioner.chType].width;
cuECtx.set( DO_TRIV_SPLIT, cu1_w < w_2 || cu2_w < w_2 || partitioner.currMtDepth + 1 == maxMtD );
}
}
// for now just a simple decision based on RD-cost or choose tempCS if bestCS is not yet coded
if( tempCS->features[ENC_FT_RD_COST] != MAX_DOUBLE && ( !cuECtx.bestCS || ( ( tempCS->features[ENC_FT_RD_COST] + ( tempCS->useDbCost ? tempCS->costDbOffset : 0 ) ) < ( cuECtx.bestCS->features[ENC_FT_RD_COST] + ( tempCS->useDbCost ? cuECtx.bestCS->costDbOffset : 0 ) ) ) ) )
{
cuECtx.bestCS = tempCS;
cuECtx.bestCU = tempCS->cus[0];
cuECtx.bestTU = cuECtx.bestCU->firstTU;
if( isModeInter( encTestmode ) )
{
//Here we take the best cost of both inter modes. We are assuming only the inter modes (and all of them) have come before the intra modes!!!
cuECtx.bestInterCost = cuECtx.bestCS->cost;
}
return true;
}
else
{
return false;
}
}