VTM10.0代码学习17:xCheckRDCostInter()&xCheckRDCostInterIMV()

此系列是为了记录自己学习VTM10.0的过程,目前正在看编码端。主要的参考文档有JVET-S2001-vH和JVET-S2002-v1。由于本人水平有限,出现的错误恳请大家指正。如果觉得我的文章对您有帮助的话,不妨点赞收藏加关注,谢谢!!


上次更新博客已是两个月前了,这两个月被internship反复折磨,但收获也是不少。现在终于结束了!!想到的第一件事就是赶快更博客,大家千万别取关/(ㄒoㄒ)/~。从这篇博客就开始讲有关帧间的内容了,不知道大家还记不记得之前的博客(VTM10.0代码学习11),末尾就是对当前CU进行各种模式的测试。看标题就知道这次要说的是xCheckRDCostInter()和CheckRDCostInterIMV()。这是有关AMVP的函数,大家也都知道帧间主要内容可以分成merge和AMVP。这两个函数还同时包括affine的AMVP,唯一的区别就是开不开启AMVR。帧内剩余的三个函数是:xCheckRDCostMerge2Nx2N(非affine的merge)、xCheckRDCostAffineMerge2Nx2N(affine的merge)、xCheckRDCostMergeGeo2Nx2N(GPM,是特殊的merge模式,比较复杂就用独立函数处理)。目前的打算是下一篇就开始讲xCheckRDCostMerge2Nx2N,同时也是本系列的终点了!!废话不多说,这就开始本篇内容


1. xCheckRDCostInter

由于无论是RA和LD的CTC都是不开启WP,所以帧间中有关WP的代码之后都会自动略去。

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();
int 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;
}

double curBestCost = bestCS->cost;//当前CU目前的最佳RDcost
double equBcwCost = MAX_DOUBLE;//不开启BCW时的RDcost

m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;

initStructData():重置tempCS

setAffineModeSelected():重置m_affineModeSelected,为true表示affine被选为最佳模式

第一个if分支:当前帧为low-delay时会用到m_bestBcwCost和m_bestBcwIdx,所以需要先重置

bcwLoopNum:表示需要测试的BCW权重的次数

curBestCost:当前CU之前的最佳RDcost

equBcwCost:不开启BCW时的RDcost


for( int bcwLoopIdx = 0; bcwLoopIdx < bcwLoopNum; bcwLoopIdx++ )
{
   
}

for循环:遍历BCW的5种权重,具体参考1.1小节


1.1 循环遍历BCW

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分支:CTC一般默认开启BCW的快速算法,这里表示当CU目前的最佳模式为帧间时,不测试均等权重和最佳BCW权重之外的权重

第二个if分支:如果当前帧不为low-delay时,只测试BCW的三种全权重,跳过其余两种


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.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);//为true表示开启BCW

这段主要用来设置CU

bcwIdx:当前测试的BCW权重

testBcw:为true表示开启BCW


m_pcInterSearch->predInterSearch( cu, partitioner );//进行AMVP的帧间预测

bcwIdx = CU::getValidBcwIdx(cu);
if( testBcw && bcwIdx == BCW_DEFAULT ) // Enabled Bcw but the search results is uni.
{
   
    tempCS->initStructData(encTestMode.qp);
    continue;
}

bool isEqualUni = false;
if( m_pcEncCfg->getUseBcwFast() )
{
   
    if( cu.firstPU->interDir != 3 && testBcw == 0 )
    {
   
        isEqualUni = true;
    }
}

predInterSearch():进行AMVP的帧间预测,具体参考第3大节,里面的RDcost都是化简的

isEqualUni:为true表示不开启BCW时最佳模式为单向预测


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;
}

xEncodeInterResidual():进行RDcost计算,抉择出最佳帧间模式,还包含对SBT的RD决策过程,实际RDcost计算是通过调用encodeResAndCalcRdInterCU。encodeResAndCalcRdInterCU包含对MTS的RD决策过程

第一个if分支:设置m_affineModeSelected

第二个if分支:不开启BCW时的RDcost如果超过之前的最佳RDcost的1.05倍,就跳过之后BCW的权重测试

第三个if分支:当序列中只有第一帧是I帧时,如果不开启BCW时最佳模式为单向预测,就跳过之后BCW的权重测试

第四个if分支:满足一定条件,就跳过之后BCW的权重测试


2. xCheckRDCostInterIMV

与xCheckRDCostInter差别不大,就只讲不同点

int iIMV = int( ( encTestMode.opts & ETO_IMV ) >> ETO_IMV_SHIFT );
const bool testAltHpelFilter = iIMV == 4;//是否在测试半像素精度

testAltHpelFilter:是否在测试半像素精度


2.1 循环遍历BCW

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;
}

如果当前帧是low-delay,只能测试不开启AMVR时最好的两次RDcost下的BCW权重还有默认权重


if (testAltHpelFilter)
{
   
    cu.imv = IMV_HPEL;
}
else
{
   
    cu.imv = iIMV == 1 ? IMV_FPEL : IMV_4PEL;
}

非affine下imv可以为0,1,2,3,分别为1/4,1,4,1/2像素精度;affine下imv可以为0,1,2,分别为1/4,1/16,1像素精度


bool affineAmvrEanbledFlag = !testAltHpelFilter && cu.slice->getSPS()->getAffineAmvrEnabledFlag();
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 coding
        m_CurrCtx->best = m_CABACEstimator->getCtx();
    }
    if ( affineAmvrEanbledFlag )
    {
   
        tempCS->initStructData( encTestMode.qp );
        continue;
    }
    else
    {
   
        return false;
    }
}

这段有点不明白就先不说了


3. predInterSearch

3.1 预备变量

CodingStructure& cs = *cu.cs;

//AMVP列表的暂时变量
AMVPInfo     amvp[2];
Mv           cMvSrchRngLT;
Mv           cMvSrchRngRB;

Mv           cMvZero;

// RPL0/1各自单向预测时的最佳情况下的MV
Mv           cMv[2];
// 双向预测时的最佳情况下的MV
Mv           cMvBi[2];
Mv           cMvTemp[
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值