VTM10.0代码学习18:xCheckRDCostMerge2Nx2N()

此系列是为了记录自己学习VTM10.0的过程,目前正在看编码端。主要的参考文档有JVET-S2001-vH和JVET-S2002-v1。由于本人水平有限,出现的错误恳请大家指正。如果觉得我的文章对您有帮助的话,不妨点赞收藏加关注,谢谢!!本篇博文就是这个系列的最后一篇了,从开始看VTM到现在差不多9个月,之中断断续续地把VTM的主干大致过了一遍,虽然有很多部分都略过未看,但也对VVC有了大致的认识,算得上是实现开始更新这个系列时的初心。之后如果没有找到想跟大家分享的内容,应该就是无期停更了。欢迎大家.
摘要由CSDN通过智能技术生成

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


本篇博文就是这个系列的最后一篇了,从开始看VTM到现在差不多9个月,之中断断续续地把VTM的主干大致过了一遍,虽然有很多部分都略过未看,但也对VVC有了大致的认识,算得上是实现开始更新这个系列时的初心。之后如果没有找到想跟大家分享的内容,应该就是无期停更了。欢迎大家跟我讨论有关VTM的问题,一起加深理解。那么接下来就说说有关merge的内容,即函数xCheckRDCostMerge2Nx2N()


1. 预备阶段

const Slice &slice = *tempCS->slice;
tempCS->initStructData( encTestMode.qp );

MergeCtx mergeCtx;
const SPS &sps = *tempCS->sps;

Mv   refinedMvdL0[MAX_NUM_PARTS_IN_CTU][MRG_MAX_NUM_CANDS];// 用于保存有关DMVR的变量
setMergeBestSATDCost( MAX_DOUBLE );

mergeCtx: 存储有关merge候选的信息

refinedMvdL0: 用于保存有关DMVR的变量

setMergeBestSATDCost: 设置m_mergeBestSATDCost,表示开启merge时的最佳的化简版RDcost


CodingUnit cu( tempCS->area );
cu.cs       = tempCS;
cu.predMode = MODE_INTER;
cu.slice    = tempCS->slice;
cu.tileIdx  = tempCS->pps->getTileIdx( tempCS->area.lumaPos() );

PredictionUnit pu( tempCS->area );
pu.cu = &cu;
pu.cs = tempCS;
PU::getInterMergeCandidates(pu, mergeCtx
                            , 0
                           );// 获取merge候选MVP列表
PU::getInterMMVDMergeCandidates(pu, mergeCtx);// 获取用于MMVD的候选MVP
pu.regularMergeFlag = true;

这段主要是获取merge候选MVP列表和用于MMVD的候选MVP


bool candHasNoResidual[MRG_MAX_NUM_CANDS + MMVD_ADD_NUM];// 为true表示对应merge候选在非skip下不存在有关残差的语法元素
for (uint32_t ui = 0; ui < MRG_MAX_NUM_CANDS + MMVD_ADD_NUM; ui++)
{
   
    candHasNoResidual[ui] = false;
}

bool                                        bestIsSkip = false;// 最佳模式是否是skip
bool                                        bestIsMMVDSkip = true;// 最佳模式是否是MMVD下的skip
// 存储着最终预测值,按merge候选列表排列
PelUnitBuf                                  acMergeBuffer[MRG_MAX_NUM_CANDS];
// 存储着非最终预测值,如果是双向预测值,应当是不经过DMVR、BCW和BDOF处理的,用于CIIP
PelUnitBuf                                  acMergeTmpBuffer[MRG_MAX_NUM_CANDS];
PelUnitBuf                                  acMergeRealBuffer[MMVD_MRG_MAX_RD_BUF_NUM];
// 存储着最终预测值,与RdModeList对应
PelUnitBuf *                                acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM];
PelUnitBuf *                                singleMergeTempBuffer;
int                                         insertPos;// 当前merge候选在RdModeList插入的位置
unsigned                                    uiNumMrgSATDCand = mergeCtx.numValidMergeCand + MMVD_ADD_NUM;// RdModeList的最大长度

一些变量,含义参考注释


struct ModeInfo
{
   //这里的regular merge和MMVD是区分开来的
    uint32_t mergeCand;
    bool     isRegularMerge;
    bool     isMMVD;
    bool     isCIIP;
    ModeInfo() : mergeCand(0), isRegularMerge(false), isMMVD(false), isCIIP(false) {
   }
    ModeInfo(const uint32_t mergeCand, const bool isRegularMerge, const bool isMMVD, const bool isCIIP) :
    mergeCand(mergeCand), isRegularMerge(isRegularMerge), isMMVD(isMMVD), isCIIP(isCIIP) {
   }
};

static_vector<ModeInfo, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM>  RdModeList;// merge候选的Index列表,以化简版RDcost从小到大排列
bool                                        mrgTempBufSet = false;// acMergeTmpBuffer和acMergeTempBuffer是否存在有效值
const int candNum = mergeCtx.numValidMergeCand + (tempCS->sps->getUseMMVD() ? std::min<int>(MMVD_BASE_MV_NUM, mergeCtx.numValidMergeCand) * MMVD_MAX_REFINE_NUM : 0);

for (int i = 0; i < candNum; i++)
{
   
    if (i < mergeCtx.numValidMergeCand)
    {
   
        RdModeList.push_back(ModeInfo(i, true, false, false));
    }
    else
    {
   
        RdModeList.push_back(ModeInfo(std::min(MMVD_ADD_NUM, i - mergeCtx.numValidMergeCand), false, true, false));
    }
}

这段主要用来设置RdModeList,是merge候选的Index列表,以化简版RDcost从小到大排列,用于存储merge模式粗选的结果


const UnitArea localUnitArea(tempCS->area.chromaFormat, Area(0, 0, tempCS->area.Y().width, tempCS->area.Y().height));
for (unsigned i = 0; i < MMVD_MRG_MAX_RD_BUF_NUM; i++)
{
   
    acMergeRealBuffer[i] = m_acMergeBuffer[i].getBuf(localUnitArea);
    if (i < MMVD_MRG_MAX_RD_NUM)
    {
   
        acMergeTempBuffer[i] = acMergeRealBuffer + i;
    }
    else
    {
   
        singleMergeTempBuffer = acMergeRealBuffer + i;
    }
}

获取缓存


bool isIntrainterEnabled = sps.getUseCiip();// 是否允许测试CIIP
if (bestCS->area.lwidth() * bestCS->area.lheight() < 64 || bestCS->area.lwidth() >= MAX_CU_SIZE || bestCS->area.lheight() >= MAX_CU_SIZE)
{
   
    isIntrainterEnabled = false;
}
// 对应merge候选是否测试过开启skip
bool isTestSkipMerge[MRG_MAX_NUM_CANDS]; // record if the merge candidate has tried skip mode
for (uint32_t idx = 0; idx < MRG_MAX_NUM_CANDS; idx++)
{
   
    isTestSkipMerge[idx] = false;
}

isIntrainterEnabled: 是否允许测试CIIP

isTestSkipMerge: 对应merge候选是否测试过开启skip


2. 用化简版RDcost对merge候选进行筛选

uiNumMrgSATDCand = NUM_MRG_SATD_CAND;
if (isIntrainterEnabled)
{
   
    uiNumMrgSATDCand += 1;
}
bestIsSkip       = false;

if( auto blkCache = dynamic_cast< CacheBlkInfoCtrl* >( m_modeCtrl ) )
{
   
    if (slice.getSPS()->getIBCFlag())
    {
   
        ComprCUCtx cuECtx = m_modeCtrl->getComprCUCtx();
        bestIsSkip = blkCache->isSkip(tempCS->area) && cuECtx.bestCU;
    }
    else
        bestIsSkip = blkCache-
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值