本文将对实现merge模式的主函数xCheckRDCostMerge2Nx2N进行分析,方便理清merge模式的整个过程。之前的一篇分析了getInterMergeCandidates的具体实现,还有两个比较重要的函数motionCompensation和encodeResAndCalcRdInterCU,将留在后面陆续进行分析,但是根据它们的命名就不难猜出它们的作用,而且事实也是这样,因此对理解merge模式的整个过程没有影响,可以暂时不用去细究具体实现。下面仍然以贴代码及注释的方式来进行分析:

Void TEncCu::xCheckRDCostMerge2Nx2N( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, Bool *earlyDetectionSkipMode )
{
assert( rpcTempCU->getSlice()->getSliceType() != I_SLICE );
TComMvField  cMvFieldNeighbours[MRG_MAX_NUM_CANDS << 1]; // double length for mv of both lists
UChar uhInterDirNeighbours[MRG_MAX_NUM_CANDS];
Int numValidMergeCand = 0;

  for( UInt ui = 0; ui < rpcTempCU->getSlice()->getMaxNumMergeCand(); ++ui )
{
uhInterDirNeighbours[ui] = 0;
}
UChar uhDepth = rpcTempCU->getDepth( 0 );
rpcTempCU->setPartSizeSubParts( SIZE_2Nx2N, 0, uhDepth ); // interprets depth relative to LCU level
rpcTempCU->setCUTransquantBypassSubParts( m_pcEncCfg->getCUTransquantBypassFlagValue(), 0, uhDepth );
rpcTempCU->getInterMergeCandidates( 0, 0, cMvFieldNeighbours,uhInterDirNeighbours, numValidMergeCand );
//! 创建一个merging candidates的列表
Int mergeCandBuffer[MRG_MAX_NUM_CANDS];
for( UInt ui = 0; ui < rpcTempCU->getSlice()->getMaxNumMergeCand(); ++ui )
{
mergeCandBuffer[ui] = 0;
}

  Bool bestIsSkip = false;

  UInt iteration;
if ( rpcTempCU->isLosslessCoded(0)) //!< 默认为false
{
iteration = 1;
}
else
{
iteration = 2;
}

  for( UInt uiNoResidual = 0; uiNoResidual < iteration; ++uiNoResidual )
{
for( UInt uiMergeCand = 0; uiMergeCand < numValidMergeCand; ++uiMergeCand ) //!< 遍历所有merging candidates
{
{
if(!(uiNoResidual==1 && mergeCandBuffer[uiMergeCand]==1)) //!< uiNoResidual等于0或者mergeCandBuffer[uiMergeCand]等于0时条件成立
{

        if( !(bestIsSkip && uiNoResidual == 0) ) //!< bestIsSkip等于false或者uiNoResidual等于1时条件成立
{
// set MC parameters
rpcTempCU->setPredModeSubParts( MODE_INTER, 0, uhDepth ); // interprets depth relative to LCU level
rpcTempCU->setCUTransquantBypassSubParts( m_pcEncCfg->getCUTransquantBypassFlagValue(),     0, uhDepth );
rpcTempCU->setPartSizeSubParts( SIZE_2Nx2N, 0, uhDepth ); // interprets depth relative to LCU level
rpcTempCU->setMergeFlagSubParts( true, 0, 0, uhDepth ); // interprets depth relative to LCU level
rpcTempCU->setMergeIndexSubParts( uiMergeCand, 0, 0, uhDepth ); // interprets depth relative to LCU level
rpcTempCU->setInterDirSubParts( uhInterDirNeighbours[uiMergeCand], 0, 0, uhDepth ); // interprets depth relative to LCU level
rpcTempCU->getCUMvField( REF_PIC_LIST_0 )->setAllMvField( cMvFieldNeighbours[0 + 2*uiMergeCand], SIZE_2Nx2N, 0, 0 ); // interprets depth relative to rpcTempCU level
rpcTempCU->getCUMvField( REF_PIC_LIST_1 )->setAllMvField( cMvFieldNeighbours[1 + 2*uiMergeCand], SIZE_2Nx2N, 0, 0 ); // interprets depth relative to rpcTempCU level

       // do MC
m_pcPredSearch->motionCompensation ( rpcTempCU, m_ppcPredYuvTemp[uhDepth] ); //!< 运动补偿
// estimate residual and encode everything
m_pcPredSearch->encodeResAndCalcRdInterCU( rpcTempCU,
m_ppcOrigYuv    [uhDepth],
m_ppcPredYuvTemp[uhDepth],
m_ppcResiYuvTemp[uhDepth],
m_ppcResiYuvBest[uhDepth],
m_ppcRecoYuvTemp[uhDepth],
(uiNoResidual? true:false)); //!< 对残差进行编码并计算RDCost

if(uiNoResidual==0)
{
if(rpcTempCU->getQtRootCbf(0) == 0) //!< CBF为0,说明变换系数全为0
{
mergeCandBuffer[uiMergeCand] = 1;
}
}

       rpcTempCU->setSkipFlagSubParts( rpcTempCU->getQtRootCbf(0) == 0, 0, uhDepth );
Int orgQP = rpcTempCU->getQP( 0 );
xCheckDQP( rpcTempCU );
xCheckBestMode(rpcBestCU, rpcTempCU, uhDepth); //!< 更新最佳模式
rpcTempCU->initEstData( uhDepth, orgQP ); //!< 重新初始化预测参数,为下一次预测做准备

if( m_pcEncCfg->getUseFastDecisionForMerge() && !bestIsSkip ) //!< m_useFastDecisionForMerge默认为true
{
bestIsSkip = rpcBestCU->getQtRootCbf(0) == 0;
}

    }//!< if( !(bestIsSkip && uiNoResidual == 0) )
}//!< if(!(uiNoResidual==1 && mergeCandBuffer[uiMergeCand]==1))
}//!<
}//!< for( UInt uiMergeCand = 0; uiMergeCand < numValidMergeCand; ++uiMergeCand )

  if(uiNoResidual == 0 && m_pcEncCfg->getUseEarlySkipDetection()) //!< 第一次对merging candidates迭代后
{
if(rpcBestCU->getQtRootCbf( 0 ) == 0) //!< earlyDetectionSkip 算法
{
if( rpcBestCU->getMergeFlag( 0 ))
{
*earlyDetectionSkipMode = true;
}
else
{
Int absoulte_MV=0;
for ( UInt uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ )
{
if ( rpcBestCU->getSlice()->getNumRefIdx( RefPicList( uiRefListIdx ) ) > 0 )
{
TComCUMvField* pcCUMvField = rpcBestCU->getCUMvField(RefPicList( uiRefListIdx ));
Int iHor = pcCUMvField->getMvd( 0 ).getAbsHor();
Int iVer = pcCUMvField->getMvd( 0 ).getAbsVer();
absoulte_MV+=iHor+iVer;
}
}

        if(absoulte_MV == 0)
{
*earlyDetectionSkipMode = true;
}
}//!< else
}//!< if(rpcBestCU->getQtRootCbf( 0 ) == 0)
}//!< if(uiNoResidual == 0 && m_pcEncCfg->getUseEarlySkipDetection())
}//!< for( UInt uiNoResidual = 0; uiNoResidual < iteration; ++uiNoResidual )
} 

HEVC帧间预测之三——TEncCu::xCheckRDCostMerge2Nx2N函数分析相关推荐

  1. 【HEVC帧间预测论文】P1.2 An Efficient Inter Mode Decision Approach for H.264 Video Codin

    参考:An Efficient Inter Mode Decision Approach for H.264 Video Coding <HEVC标准介绍.HEVC帧间预测论文笔记>系列博 ...

  2. HEVC帧间预测原理

    一.帧间预测基本原理 主要原理是为当前图像的每个像素块在之前已编码图像中寻找一个最佳匹配块,该过程称为运动估计( Motion Estimation,ME).其中用于预测的图像称为参考图(Refere ...

  3. HEVC帧间预测流程梳理

    HEVC帧间预测流程 前言:最近在琢磨hevc理论知识,看着那本书绕过去绕过来咋也没把流程想通,去找了师兄说耽误他一分钟,结果叭叭叭了六小时哈哈哈哈. 最后还是感谢师兄给我解答问题,我写这篇文章主要是 ...

  4. 【Codecs系列】HEVC标准(五):帧间预测技术及x265实现分析

    DATE: 2021.12.27 文章目录 1.帧间关键技术 1.1.Merge/Skip 1.2.AMVP 1.2.1 Inter模式下的AMVP技术 1.2.2 Merge模式下的AMVP技术 1 ...

  5. HEVC代码学习:帧间预测——MVP过程中MV的获取、传递及存储

    作为一个视频编码小白,最近开始着手啃HEVC帧间预测的代码,想用博客记录一下自己的学习过程,也想与大家分享.交流一下. HEVC代码的学习主要是参考两位大神岳麓吹雪.NB_vol_1的博客以及HM参考 ...

  6. HEVC代码学习——帧间预测:预测MV获取(xEstimateMvPredAMVP、fillMVPCand)

    HEVC帧间预测在AMVP模式下是依靠xEstimateMvPredAMVP函数获取预测MV(MVP)的. 这部分内容的学习还可以参考这两篇博客: HEVC代码学习15:AMVP相关函数 HM编码器代 ...

  7. HEVC参考软件HM源码分析--帧间预测(1)--xCompressCU

    本文首先对HM中帧间预测的基本流程作简要介绍,接着对代码中关键变量的用途作出说明,最后以源代码+注释的形式进行具体分析. 备注:这位大神的博客对楼主帮助很大,解决了我的不少疑惑,最后才能顺利写下这篇博 ...

  8. HM16.0之帧间预测——xCheckRDCostInter()函数

    参考:https://blog.csdn.net/nb_vol_1/article/category/6179825/1? 1.源代码: #if AMP_MRG Void TEncCu::xCheck ...

  9. Overview of HEVC之5 帧间预测

    预测块(PB)的划分:与帧内预测的CB相比, HEVC为帧间预测的CB提供了更多的PB划分形状: PART_2N×2N的划分模式表示CB不划分:PART_2N×N的划分模式表示CB水平划分成两个相等尺 ...

  10. HM编码器代码阅读(32)——帧间预测之AMVP/Merge模式(七)encodeResAndCalcRdInterCU函数:残差计算、变换量化

    encodeResAndCalcRdInterCU 原理和细节 经过运动估计.运动补偿,我们得到了MV以及参考块,那么接下来是计算残差.计算MVD,然后对系数进行变换.量化. encodeResAnd ...

最新文章

  1. ACL 2020 亮点摘要
  2. 玲珑杯 1157 - 造物主的戒律 主席树+离散化
  3. Val编程-特殊函数使用
  4. matlab绘制烟花,[原创]利用MATLAB燃放烟花(礼花)
  5. 机器学习高级篇:解密微信视频号推荐机制
  6. Matlab - VideoReader Error: Unable to initialize the video properties
  7. apache FilesMatch
  8. 【机器学习】因子分解机(Factorization Machine)原理与java实现
  9. 集成Slice2Java插件
  10. 软考 系统架构设计师考试大纲
  11. 明尼苏达大学Transportation Research Data Lab (TDRL)交通数据读取
  12. 手机显示服务器维护是啥意思,手机系统维护怎么解除_手机显示系统维护是什么意思_游戏吧...
  13. Java包装类 学习
  14. 25~30K的国外企业招聘面试考题,10分钟就能写出来了?
  15. linux查看文件打开限制,Linux最大文件打开数使用经验详解
  16. IDEA创建applicationContext.xml文件图标不是xml文件图标
  17. 【数据库系统原理】数据库课内实验
  18. tcp连接失败触发的异常
  19. 借鉴FCoin商业模式,写了一份白皮书去参赛
  20. 单品销量破百万+,登顶天猫类目第一!摇滚动物园的爆品打造攻略你学会了吗?

热门文章

  1. swc反编译工具_JPEXS Free Flash Decompiler(Flash反编译工具)v11.3.0 中文免费版-ucbug软件站...
  2. R语言大作业(全国2000-2019年人口各项数据分析)
  3. 分享一套jquery视频教程
  4. 数字温度传感器DS18B20的数据手册理解
  5. window核心编程 22.3 DIPS.exe的踩坑逻辑梳理
  6. 解决:Failed to create 'build\outputs\apk\watch-debug-unaligned.apks': 拒绝访问。
  7. 基于matlab的信号与系统课程设计,信号与系统课程设计基于 MATLAB 完成信号与系统综合设计实验...
  8. 浅谈数学在c语言编程中的,试论C语言程序设计中算法设计的作用
  9. AIDE2.6.1安装及配置C/C++开发数据
  10. 启动startUML的时候报错“Exception EOleSysError in module StarUML.exe at 000AD559.