H.266/VVC代码学习:xCheckRDCostInter函数

编程入门 行业动态 更新时间:2024-10-14 10:45:23

H.266/VVC代码学习:xCheckRDCostInter<a href=https://www.elefans.com/category/jswz/34/1771370.html style=函数"/>

H.266/VVC代码学习:xCheckRDCostInter函数

xCheckRDCostInter函数主要是用来检查inter模式的,包括常规AMVP模式和Affine AMVP模式。该函数主要是通过调用predInterSearch实现对常规AMVP模式和Affine AMVP模式检查的,其调用关系如下所示:

在xCheckRDCostInter函数,遍历所有的BCW权重,对于每个BCW权重,调用predInterSearch找到最优的运动信息,并通过xEncodeInterResidual对预测残差进行变换量化。最后,通过xCalDebCost函数计算去块滤波后最终的Cost。

代码及注释如下:(基于VTM10.0)

void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
{tempCS->initStructData( encTestMode.qp );m_pcInterSearch->setAffineModeSelected(false);if( tempCS->slice->getCheckLDC() ){m_bestBcwCost[0] = m_bestBcwCost[1] = std::numeric_limits<double>::max();m_bestBcwIdx[0] = m_bestBcwIdx[1] = -1;}m_pcInterSearch->resetBufferedUniMotions();// 判断你是否使用BCW,如果是B帧且开启BCW,则BCW待测数目为5,否则为1int bcwLoopNum = (tempCS->slice->isInterB() ? BCW_NUM : 1); bcwLoopNum = (tempCS->sps->getUseBcw() ? bcwLoopNum : 1);if( tempCS->area.lwidth() * tempCS->area.lheight() < BCW_SIZE_CONSTRAINT ){bcwLoopNum = 1; //BCW用于宽度*高度大于等于256的CU}double curBestCost = bestCS->cost; //当前最佳的Costdouble equBcwCost = MAX_DOUBLE;m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;// 遍历BCW所有权重for( int bcwLoopIdx = 0; bcwLoopIdx < bcwLoopNum; bcwLoopIdx++ ){if( m_pcEncCfg->getUseBcwFast() ) //BCW快速算法{auto blkCache = dynamic_cast< CacheBlkInfoCtrl* >(m_modeCtrl);if( blkCache ){bool isBestInter = blkCache->getInter(bestCS->area);uint8_t bestBcwIdx = blkCache->getBcwIdx(bestCS->area);if( isBestInter && g_BcwSearchOrder[bcwLoopIdx] != BCW_DEFAULT && g_BcwSearchOrder[bcwLoopIdx] != bestBcwIdx ){continue;}}}if( !tempCS->slice->getCheckLDC() ){if( bcwLoopIdx != 0 && bcwLoopIdx != 3 && bcwLoopIdx != 4 ){continue;}}CodingUnit &cu      = tempCS->addCU( tempCS->area, partitioner.chType );partitioner.setCUData( cu );cu.slice            = tempCS->slice;cu.tileIdx          = tempCS->pps->getTileIdx( tempCS->area.lumaPos() );cu.skip             = false;cu.mmvdSkip = false;
//cu.affinecu.predMode         = MODE_INTER;cu.chromaQpAdj      = m_cuChromaQpOffsetIdxPlus1;cu.qp               = encTestMode.qp;CU::addPUs( cu );cu.BcwIdx = g_BcwSearchOrder[bcwLoopIdx];uint8_t bcwIdx = cu.BcwIdx;bool  testBcw = (bcwIdx != BCW_DEFAULT);m_pcInterSearch->predInterSearch( cu, partitioner ); //搜索最佳的帧间预测bcwIdx = CU::getValidBcwIdx(cu);if( testBcw && bcwIdx == BCW_DEFAULT ) // Enabled Bcw but the search results is uni. 已启用Bcw,但搜索结果为uni。{tempCS->initStructData(encTestMode.qp);continue;}CHECK(!(testBcw || (!testBcw && bcwIdx == BCW_DEFAULT)), " !( bTestBcw || (!bTestBcw && bcwIdx == BCW_DEFAULT ) )");bool isEqualUni = false;if( m_pcEncCfg->getUseBcwFast() ){if( cu.firstPU->interDir != 3 && testBcw == 0 ){isEqualUni = true;}}xEncodeInterResidual( tempCS, bestCS, partitioner, encTestMode, 0, 0, &equBcwCost); //编码残差if( g_BcwSearchOrder[bcwLoopIdx] == BCW_DEFAULT )m_pcInterSearch->setAffineModeSelected((bestCS->cus.front()->affine && !(bestCS->cus.front()->firstPU->mergeFlag)));tempCS->initStructData(encTestMode.qp);double skipTH = MAX_DOUBLE;skipTH = (m_pcEncCfg->getUseBcwFast() ? 1.05 : MAX_DOUBLE);if( equBcwCost > curBestCost * skipTH ){// 快速算法break;}if( m_pcEncCfg->getUseBcwFast() ){if( isEqualUni == true && m_pcEncCfg->getIntraPeriod() == -1 ){break;}}if( g_BcwSearchOrder[bcwLoopIdx] == BCW_DEFAULT && xIsBcwSkip(cu) && m_pcEncCfg->getUseBcwFast() ){break;}}  // for( UChar bcwLoopIdx = 0; bcwLoopIdx < bcwLoopNum; bcwLoopIdx++ )if ( m_bestModeUpdated && bestCS->cost != MAX_DOUBLE ){xCalDebCost( *bestCS, partitioner );}
}

xCheckRDCostInterIMV和xCheckRDCostInter函数类似,不同的是,xCheckRDCostInterIMV函数会提前设置cu.imv(具体细节没看懂),cu.imv的作用如下:

  • 对于常规AMVP模式,imv的值为0 1 2 3分别代表1/4像素精度、整像素精度、4像素精度和1/2像素精度
  • 对于Affine AMVP模式,imv的值为0 1 2分别代表1/4像素精度、1/16像素精度和整像素精度
 const MvPrecision Mv::m_amvrPrecision[4] = { MV_PRECISION_QUARTER, MV_PRECISION_INT, MV_PRECISION_4PEL, MV_PRECISION_HALF }; // for cu.imv=0, 1, 2 and 3const MvPrecision Mv::m_amvrPrecAffine[3] = { MV_PRECISION_QUARTER, MV_PRECISION_SIXTEENTH, MV_PRECISION_INT }; // for cu.imv=0, 1 and 2
bool EncCu::xCheckRDCostInterIMV(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode, double &bestIntPelCost)
{int iIMV = int( ( encTestMode.opts & ETO_IMV ) >> ETO_IMV_SHIFT ); //设置IMVm_pcInterSearch->setAffineModeSelected(false);// Only Half-Pel, int-Pel, 4-Pel and fast 4-Pel allowedCHECK(iIMV < 1 || iIMV > 4, "Unsupported IMV Mode");const bool testAltHpelFilter = iIMV == 4;// Fast 4-Pel Modem_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;EncTestMode encTestModeBase = encTestMode;                                        // copy for clearing non-IMV optionsencTestModeBase.opts        = EncTestModeOpts( encTestModeBase.opts & ETO_IMV );  // clear non-IMV options (is that intended?)tempCS->initStructData( encTestMode.qp );m_pcInterSearch->resetBufferedUniMotions();int bcwLoopNum = (tempCS->slice->isInterB() ? BCW_NUM : 1);bcwLoopNum = (tempCS->slice->getSPS()->getUseBcw() ? bcwLoopNum : 1);if( tempCS->area.lwidth() * tempCS->area.lheight() < BCW_SIZE_CONSTRAINT ){bcwLoopNum = 1;}bool validMode = false;double curBestCost = bestCS->cost;double equBcwCost = MAX_DOUBLE;for( int bcwLoopIdx = 0; bcwLoopIdx < bcwLoopNum; bcwLoopIdx++ ){if( m_pcEncCfg->getUseBcwFast() ){auto blkCache = dynamic_cast< CacheBlkInfoCtrl* >(m_modeCtrl);if( blkCache ){bool isBestInter = blkCache->getInter(bestCS->area);uint8_t bestBcwIdx = blkCache->getBcwIdx(bestCS->area);if( isBestInter && g_BcwSearchOrder[bcwLoopIdx] != BCW_DEFAULT && g_BcwSearchOrder[bcwLoopIdx] != bestBcwIdx ){continue;}}}if( !tempCS->slice->getCheckLDC() ){if( bcwLoopIdx != 0 && bcwLoopIdx != 3 && bcwLoopIdx != 4 ){continue;}}if( m_pcEncCfg->getUseBcwFast() && tempCS->slice->getCheckLDC() && g_BcwSearchOrder[bcwLoopIdx] != BCW_DEFAULT&& (m_bestBcwIdx[0] >= 0 && g_BcwSearchOrder[bcwLoopIdx] != m_bestBcwIdx[0])&& (m_bestBcwIdx[1] >= 0 && g_BcwSearchOrder[bcwLoopIdx] != m_bestBcwIdx[1])){continue;}CodingUnit &cu = tempCS->addCU( tempCS->area, partitioner.chType );partitioner.setCUData( cu );cu.slice            = tempCS->slice;cu.tileIdx          = tempCS->pps->getTileIdx( tempCS->area.lumaPos() );cu.skip             = false;cu.mmvdSkip = false;
//cu.affinecu.predMode         = MODE_INTER;cu.chromaQpAdj      = m_cuChromaQpOffsetIdxPlus1;cu.qp               = encTestMode.qp;CU::addPUs( cu );if (testAltHpelFilter){cu.imv = IMV_HPEL;}else{cu.imv = iIMV == 1 ? IMV_FPEL : IMV_4PEL;}// const MvPrecision Mv::m_amvrPrecision[4] = { MV_PRECISION_QUARTER, MV_PRECISION_INT, MV_PRECISION_4PEL, MV_PRECISION_HALF }; // for cu.imv=0, 1, 2 and 3// const MvPrecision Mv::m_amvrPrecAffine[3] = { MV_PRECISION_QUARTER, MV_PRECISION_SIXTEENTH, MV_PRECISION_INT }; // for cu.imv=0, 1 and 2bool testBcw;uint8_t bcwIdx;bool affineAmvrEanbledFlag = !testAltHpelFilter && cu.slice->getSPS()->getAffineAmvrEnabledFlag();cu.BcwIdx = g_BcwSearchOrder[bcwLoopIdx];bcwIdx = cu.BcwIdx;testBcw = (bcwIdx != BCW_DEFAULT);cu.firstPU->interDir = 10;m_pcInterSearch->predInterSearch( cu, partitioner );if ( cu.firstPU->interDir <= 3 ){bcwIdx = CU::getValidBcwIdx(cu);}else{return false;}if( m_pcEncCfg->getMCTSEncConstraint() && ( ( cu.firstPU->refIdx[L0] < 0 && cu.firstPU->refIdx[L1] < 0 ) || ( !( MCTSHelper::checkMvBufferForMCTSConstraint( *cu.firstPU ) ) ) ) ){// Do not use this modetempCS->initStructData( encTestMode.qp );continue;}if( testBcw && bcwIdx == BCW_DEFAULT ) // Enabled Bcw but the search results is uni.{tempCS->initStructData(encTestMode.qp);continue;}CHECK(!(testBcw || (!testBcw && bcwIdx == BCW_DEFAULT)), " !( bTestBcw || (!bTestBcw && bcwIdx == BCW_DEFAULT ) )");bool isEqualUni = false;if( m_pcEncCfg->getUseBcwFast() ){if( cu.firstPU->interDir != 3 && testBcw == 0 ){isEqualUni = true;}}if ( !CU::hasSubCUNonZeroMVd( cu ) && !CU::hasSubCUNonZeroAffineMVd( cu ) ){if (m_modeCtrl->useModeResult(encTestModeBase, tempCS, partitioner)){std::swap(tempCS, bestCS);// store temp best CI for next CU codingm_CurrCtx->best = m_CABACEstimator->getCtx();}if ( affineAmvrEanbledFlag ){tempCS->initStructData( encTestMode.qp );continue;}else{return false;}}xEncodeInterResidual( tempCS, bestCS, partitioner, encTestModeBase, 0, 0, &equBcwCost);if( cu.imv == IMV_FPEL && tempCS->cost < bestIntPelCost ){bestIntPelCost = tempCS->cost;}tempCS->initStructData(encTestMode.qp);double skipTH = MAX_DOUBLE;skipTH = (m_pcEncCfg->getUseBcwFast() ? 1.05 : MAX_DOUBLE);if( equBcwCost > curBestCost * skipTH ){break;}if( m_pcEncCfg->getUseBcwFast() ){if( isEqualUni == true && m_pcEncCfg->getIntraPeriod() == -1 ){break;}}if( g_BcwSearchOrder[bcwLoopIdx] == BCW_DEFAULT && xIsBcwSkip(cu) && m_pcEncCfg->getUseBcwFast() ){break;}validMode = true;} // for( UChar bcwLoopIdx = 0; bcwLoopIdx < bcwLoopNum; bcwLoopIdx++ )if ( m_bestModeUpdated && bestCS->cost != MAX_DOUBLE ){xCalDebCost( *bestCS, partitioner );}return tempCS->slice->getSPS()->getAffineAmvrEnabledFlag() ? validMode : true;
}

更多推荐

H.266/VVC代码学习:xCheckRDCostInter函数

本文发布于:2024-02-06 10:08:49,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1748086.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:函数   代码   VVC   xCheckRDCostInter

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!