vtm编码划分_VTM代码学习(1)CU划分

新人上路,请多多指教。 一直想写博客,今天才开始写第一篇。--------------------------------------------------------------------------------------------------------------------------------------------------------------------------...
摘要由CSDN通过智能技术生成

新人上路,请多多指教。  一直想写博客,今天才开始写第一篇。

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

这次来讲一下VTM9.0中关于CU划分的部分,主要是两个函数xCompressCU和xCheckModeSplit。

xCompressCU主要针对当前CU可能进行的预测划分模式,完成相应的操作。主要分为以下几种模式(后面两种暂时还没学习,后面如果接触到会补充)

1划分模式:四叉树划分,水平二叉树划分,垂直二叉树划分,水平三叉树划分,垂直三叉树划分。通过调用函数xCompressCU完成。

2帧内预测:调用函数xCheckRDCostIntra完成。

3帧间预测:。。。。

4屏幕内容编码:。。。。

xCompressCU函数流程:初始化,调用函数initCULevel(),获取当前CU可能的预测和编码模式,并且按照顺序推入栈中。然后进入一循环,改循环会不断调取栈顶模式,将CU按照相应模式进行编码或划分,直至栈内不储存模式为止。具体代码如下:

void EncCu::xCompressCU( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& partitioner, double maxCostAllowed )

{

/*************************************** 初始化 ****************************************/

CHECK(maxCostAllowed < 0, "Wrong value of maxCostAllowed!");

#if ENABLE_SPLIT_PARALLELISM

CHECK( m_dataId != tempCS->picture->scheduler.getDataId(), "Working in the wrong dataId!" );

if( m_pcEncCfg->getNumSplitThreads() != 1 && tempCS->picture->scheduler.getSplitJobId() == 0 )

{

if( m_modeCtrl->isParallelSplit( *tempCS, partitioner ) )

{

m_modeCtrl->setParallelSplit( true );

xCompressCUParallel( tempCS, bestCS, partitioner );

return;

}

}

#endif

uint32_t compBegin;

uint32_t numComp;

bool jointPLT = false;

if (partitioner.isSepTree( *tempCS ))

{

#if JVET_Q0504_PLT_NON444

if( !CS::isDualITree(*tempCS) && partitioner.treeType != TREE_D )

{

compBegin = COMPONENT_Y;

numComp = (tempCS->area.chromaFormat != CHROMA_400)?3: 1;

jointPLT = true;

}

else

{

#endif

if (isLuma(partitioner.chType))

{

compBegin = COMPONENT_Y;

numComp = 1;

}

else

{

compBegin = COMPONENT_Cb;

numComp = 2;

}

#if JVET_Q0504_PLT_NON444

}

#endif

}

else

{

compBegin = COMPONENT_Y;

#if JVET_Q0504_PLT_NON444

numComp = (tempCS->area.chromaFormat != CHROMA_400) ? 3 : 1;

#else

numComp = 3;

#endif

jointPLT = true;

}

SplitSeries splitmode = -1;

uint8_t bestLastPLTSize[MAX_NUM_CHANNEL_TYPE];

Pel bestLastPLT[MAX_NUM_COMPONENT][MAXPLTPREDSIZE]; // store LastPLT for

uint8_t curLastPLTSize[MAX_NUM_CHANNEL_TYPE];

Pel curLastPLT[MAX_NUM_COMPONENT][MAXPLTPREDSIZE]; // store LastPLT if no partition

for (int i = compBegin; i < (compBegin + numComp); i++)

{

ComponentID comID = jointPLT ? (ComponentID)compBegin : ((i > 0) ? COMPONENT_Cb : COMPONENT_Y);

bestLastPLTSize[comID] = 0;

curLastPLTSize[comID] = tempCS->prevPLT.curPLTSize[comID];

memcpy(curLastPLT[i], tempCS->prevPLT.curPLT[i], tempCS->prevPLT.curPLTSize[comID] * sizeof(Pel));

}

Slice& slice = *tempCS->slice;

const PPS &pps = *tempCS->pps;

const SPS &sps = *tempCS->sps;

const uint32_t uiLPelX = tempCS->area.Y().lumaPos().x;

const uint32_t uiTPelY = tempCS->area.Y().lumaPos().y;

const ModeType modeTypeParent = partitioner.modeType;

const TreeType treeTypeParent = partitioner.treeType;

const ChannelType chTypeParent = partitioner.chType;

const UnitArea currCsArea = clipArea( CS::getArea( *bestCS, bestCS->area, partitioner.chType ), *tempCS->picture );

m_modeCtrl->initCULevel( partitioner, *tempCS );//初始化所有编码划分模式,为CU设置可能的编码划分模式

if( partitioner.currQtDepth == 0 && partitioner.currMtDepth == 0 && !tempCS->slice->isIntra() && ( sps.getUseSBT() || sps.getUseInterMTS() ) )

{

auto slsSbt = dynamic_cast( m_modeCtrl );

int maxSLSize = sps.getUseSBT() ? tempCS->slice->getSPS()->getMaxTbSize() : MTS_INTER_MAX_CU_SIZE;

slsSbt->resetSaveloadSbt( maxSLSize );

#if ENABLE_SPLIT_PARALLELISM

CHECK( tempCS->picture->scheduler.getSplitJobId() != 0, "The SBT search reset need to happen in sequential region." );

if (m_pcEncCfg->getNumSplitThreads() > 1)

{

for (int jId = 1; jId < NUM_RESERVERD_SPLIT_JOBS; jId++)

{

auto slsSbt = dynamic_cast(m_pcEncLib->getCuEncoder(jId)->m_modeCtrl);

slsSbt->resetSaveloadSbt(maxSLSize);

}

}

#endif

}

m_sbtCostSave[0] = m_sbtCostSave[1] = MAX_DOUBLE;

m_CurrCtx->start = m_CABACEstimator->getCtx();

/************************* 处理色度QP ***************************/

m_cuChromaQpOffsetIdxPlus1 = 0;

if( slice.getUseChromaQpAdj() )

{

// TODO M0133 : double check encoder decisions with respect to chroma QG detection and actual encode

int lgMinCuSize = sps.getLog2MinCodingBlockSize() +

#if JVET_Q0468_Q0469_MIN_LUMA_CB_AND_MIN_QT_FIX

std::max(0, floorLog2(sps.getCTUSize()) - sps.getLog2MinCodingBlockSize() - int(slice.getCuChromaQpOffsetSubdiv() / 2));

#else

std::max( 0, sps.getLog2DiffMaxMinCodingBlockSize() - int( slice.getCuChromaQpOffsetSubdiv()/2 ) );

#endif

#if JVET_Q0267_RESET_CHROMA_QP_OFFSET

if( partitioner.currQgChromaEnable() )

{

m_cuChromaQpOffsetIdxPlus1 = ( ( uiLPelX >> lgMinCuSize ) + ( uiTPelY >> lgMinCuSize ) ) % ( pps.getChromaQpOffsetListLen() + 1 );

}

#else

m_cuChromaQpOffsetIdxPlus1 = ( ( uiLPelX >> lgMinCuSize ) + ( uiTPelY >> lgMinCuSize ) ) % ( pps.getChromaQpOffsetListLen() + 1 );

#endif

}

if( !m_modeCtrl->anyMode() )

{

m_modeCtrl->finishCULevel( partitioner );

return;

}

DTRACE_UPDATE( g_trace_ctx, std::make_pair( "cux", uiLPelX ) );

DTRACE_UPDATE( g_trace_ctx, std::make_pair( "cuy", uiTPelY ) );

DTRACE_UPDATE( g_trace_ctx, std::make_pair( "cuw", tempCS->area.lwidth() ) );

DTRACE_UPDATE( g_trace_ctx, std::make_pair( "cuh", tempCS->area.lheight() ) );

DTRACE( g_trace_ctx, D_COMMON, "@(%4d,%4d) [%2dx%2d]\n", tempCS->area.lx(), tempCS->area.ly(), tempCS->area.lwidth(), tempCS->area.lheight() );

m_pcInterSearch->resetSavedAffineMotion();

double bestIntPelCost = MAX_DOUBLE;

if (tempCS->slice->getSPS()->getUseColorTrans())

{

tempCS->tmpColorSpaceCost = MAX_DOUBLE;

bestCS->tmpColorSpaceCost = MAX_DOUBLE;

tempCS->firstColorSpaceSelected = true;

bestCS->firstColorSpaceSelected = true;

}

if (tempCS->slice->getSPS()->getUseColorTrans() && !CS::isDualITree(*tempCS))

{

tempCS->firstColorSpaceTestOnly = false;

bestCS->firstColorSpaceTestOnly = false;

tempCS->tmpColorSpaceIntraCost[0] = MAX_DOUBLE;

tempCS->tmpColorSpaceIntraCost[1] = MAX_DOUBLE;

bestCS->tmpColorSpaceIntraCost[0] = MAX_DOUBLE;

bestCS->tmpColorSpaceIntraCost[1] = MAX_DOUBLE;

if (tempCS->bestParent && tempCS->bestParent->firstColorSpaceTestOnly)

{

tempCS->firstColorSpaceTestOnly = bestCS->firstColorSpaceTestOnly = true;

}

}

/***************************按照堆栈中的模式进行循环预测编码或划分,当循环结束时当前CU已选择最小的RDcost进行划分与编码****************************/

do//尝试当前编码器各种可用的模式:如skip,帧间,帧内,PCM等,进行预测及划分。

{

for (int i = compBegin; i < (compBegin + numCom

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值