由于宏JVET_L0632_AFFINE_MERGE默认开启,因此删减了函数中一些无用代码。
xCheckRDCostAffineMerge2Nx2N函数的流程和普通Merge模式的函数流程基本完全一样。都是先获取候模式选列表,然后SATD,再RDO选最优。
Affine_Merge模式要求,块的大小长宽必须都大于8.
其中调用getAffineMergeCand函数获取AffineMerge候选列表,长度为5,存储在AffineMergeCtx中。

void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
{if( m_modeCtrl->getFastDeltaQp() ){return;}//Affine merge模式块长宽均要大于等于8if ( bestCS->area.lumaSize().width < 8 || bestCS->area.lumaSize().height < 8 ){return;}const Slice &slice = *tempCS->slice;CHECK( slice.getSliceType() == I_SLICE, "Affine Merge modes not available for I-slices" );tempCS->initStructData( encTestMode.qp, encTestMode.lossless );    //tempCS清空初始化AffineMergeCtx affineMergeCtx;     //AffineMerge模式的候选列表,长度为5,最大存储5组3控制点的MVconst SPS &sps = *tempCS->sps;#if JVET_L0369_SUBBLOCK_MERGEMergeCtx mrgCtx;                if ( sps.getSpsNext().getUseSubPuMvp() ){Size bufSize = g_miScaling.scale( tempCS->area.lumaSize() );mrgCtx.subPuMvpMiBuf = MotionBuf( m_SubPuMiBuf, bufSize );affineMergeCtx.mrgCtx = &mrgCtx;   //merge候选列表,主要记录ATMVP模式的一些信息,包含在AffineMerge候选列表中}
#endif{// first get merge candidatesCodingUnit cu( tempCS->area );cu.cs = tempCS;cu.partSize = SIZE_2Nx2N;         //tempCS添加cu、pucu.predMode = MODE_INTER;cu.slice = tempCS->slice;
#if HEVC_TILES_WPPcu.tileIdx = tempCS->picture->tileMap->getTileIdxMap( tempCS->area.lumaPos() );
#endif
#if JVET_L0054_MMVDcu.mmvdSkip = false;
#endifPredictionUnit pu( tempCS->area );pu.cu = &cu;pu.cs = tempCS;PU::getAffineMergeCand( pu, affineMergeCtx );       //构造Affine_Merge候选列表if ( affineMergeCtx.numValidMergeCand <= 0 ){return;}}bool candHasNoResidual[AFFINE_MRG_MAX_NUM_CANDS];for ( uint32_t ui = 0; ui < affineMergeCtx.numValidMergeCand; ui++ ){candHasNoResidual[ui] = false;}bool                                        bestIsSkip = false;uint32_t                                    uiNumMrgSATDCand = affineMergeCtx.numValidMergeCand;PelUnitBuf                                  acMergeBuffer[AFFINE_MRG_MAX_NUM_CANDS]; //记录5组AffineMerge候选分别经MC得到的pred像素static_vector<uint32_t, AFFINE_MRG_MAX_NUM_CANDS>  RdModeList;bool                                        mrgTempBufSet = false;for ( uint32_t i = 0; i < AFFINE_MRG_MAX_NUM_CANDS; i++ ){RdModeList.push_back( i );      //5个AffineMerge候选的idx压栈}if ( m_pcEncCfg->getUseFastMerge() )     //FastMerge,是否SATD{uiNumMrgSATDCand = std::min( NUM_AFF_MRG_SATD_CAND, affineMergeCtx.numValidMergeCand );bestIsSkip = false;if ( auto blkCache = dynamic_cast<CacheBlkInfoCtrl*>(m_modeCtrl) ){bestIsSkip = blkCache->isSkip( tempCS->area );}static_vector<double, AFFINE_MRG_MAX_NUM_CANDS> candCostList;// 1. Pass: get SATD-cost for selected candidates and reduce their countif ( !bestIsSkip )             //非skip{RdModeList.clear();         //之前有idx压栈过程,此时清空mrgTempBufSet = true;const double sqrtLambdaForFirstPass = m_pcRdCost->getMotionLambda( encTestMode.lossless );CodingUnit &cu = tempCS->addCU( tempCS->area, partitioner.chType );//tempCS添加cu、pupartitioner.setCUData( cu );cu.slice = tempCS->slice;
#if HEVC_TILES_WPPcu.tileIdx = tempCS->picture->tileMap->getTileIdxMap( tempCS->area.lumaPos() );
#endifcu.skip = false;cu.partSize = SIZE_2Nx2N;cu.affine = true;cu.predMode = MODE_INTER;cu.transQuantBypass = encTestMode.lossless;cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;cu.qp = encTestMode.qp;PredictionUnit &pu = tempCS->addPU( cu, partitioner.chType );DistParam distParam;const bool bUseHadamard = !encTestMode.lossless;      //设置计算失真的类distParamm_pcRdCost->setDistParam( distParam, tempCS->getOrgBuf().Y(), m_acMergeBuffer[0].Y(), sps.getBitDepth( CHANNEL_TYPE_LUMA ), COMPONENT_Y, bUseHadamard );const UnitArea localUnitArea( tempCS->area.chromaFormat, Area( 0, 0, tempCS->area.Y().width, tempCS->area.Y().height ) );for ( uint32_t uiMergeCand = 0; uiMergeCand < affineMergeCtx.numValidMergeCand; uiMergeCand++ )    //loop{                                                                 //5组AffineMerge候选,分别SATDacMergeBuffer[uiMergeCand] = m_acMergeBuffer[uiMergeCand].getBuf( localUnitArea );// set merge informationpu.interDir = affineMergeCtx.interDirNeighbours[uiMergeCand];    //用Affine候选的运动信息赋给pu,然后MC得Affine预测像素pu.mergeFlag = true;pu.mergeIdx = uiMergeCand;         //pu.mergeIdx为Affine候选在AffineMerge列表中的idxcu.affineType = affineMergeCtx.affineType[uiMergeCand];       //4参数/6参数
#if JVET_L0646_GBIcu.GBiIdx = affineMergeCtx.GBiIdx[uiMergeCand];
#endif#if JVET_L0369_SUBBLOCK_MERGEpu.mergeType = affineMergeCtx.mergeType[uiMergeCand];if ( pu.mergeType == MRG_TYPE_SUBPU_ATMVP )          //如果mergeType为ATMVP{pu.refIdx[0] = affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][0].refIdx;pu.refIdx[1] = affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][0].refIdx;PU::spanMotionInfo( pu, mrgCtx );           //构造AffineMerge候选列表时,ATMVP提供的候选,就记录在mrgCtx中}else{#endifPU::setAllAffineMvField( pu, affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0], REF_PIC_LIST_0 );PU::setAllAffineMvField( pu, affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1], REF_PIC_LIST_1 );PU::spanMotionInfo( pu );
#if JVET_L0369_SUBBLOCK_MERGE}
#endifdistParam.cur = acMergeBuffer[uiMergeCand].Y();//Affine模式的MC过程不同于merge模式和inter_MEm_pcInterSearch->motionCompensation( pu, acMergeBuffer[uiMergeCand] );       //MC  由控制点运动信息获得当前块的预测像素predDistortion uiSad = distParam.distFunc( distParam );        //失真uint32_t   uiBitsCand = uiMergeCand + 1;if ( uiMergeCand == tempCS->slice->getMaxNumAffineMergeCand() - 1 ){uiBitsCand--;}double cost = (double)uiSad + (double)uiBitsCand * sqrtLambdaForFirstPass;    //cost
#if JVET_L0283_MULTI_REF_LINEstatic_vector<int, AFFINE_MRG_MAX_NUM_CANDS> * nullList = nullptr;
#endifupdateCandList( uiMergeCand, cost, RdModeList, candCostList       //由cost给AffineMerge候选排序
#if JVET_L0283_MULTI_REF_LINE, *nullList, -1
#endif, uiNumMrgSATDCand );CHECK( std::min( uiMergeCand + 1, uiNumMrgSATDCand ) != RdModeList.size(), "" );}// Try to limit number of candidates using SATD-costs   裁剪for ( uint32_t i = 1; i < uiNumMrgSATDCand; i++ ){if ( candCostList[i] > MRG_FAST_RATIO * candCostList[0] ){uiNumMrgSATDCand = i;break;}}tempCS->initStructData( encTestMode.qp, encTestMode.lossless );}else    //skip时{uiNumMrgSATDCand = affineMergeCtx.numValidMergeCand;}}const uint32_t iteration = encTestMode.lossless ? 1 : 2;// 2. Pass: check candidates using full RD test                 //RDOfor ( uint32_t uiNoResidualPass = 0; uiNoResidualPass < iteration; uiNoResidualPass++ ){for ( uint32_t uiMrgHADIdx = 0; uiMrgHADIdx < uiNumMrgSATDCand; uiMrgHADIdx++ ){uint32_t uiMergeCand = RdModeList[uiMrgHADIdx];       //AffineMerge候选列表中的候选idxif ( ((uiNoResidualPass != 0) && candHasNoResidual[uiMergeCand])|| ((uiNoResidualPass == 0) && bestIsSkip) ){continue;}// first get merge candidatesCodingUnit &cu = tempCS->addCU( tempCS->area, partitioner.chType );   //tempCS添加cu、pupartitioner.setCUData( cu );cu.slice = tempCS->slice;
#if HEVC_TILES_WPPcu.tileIdx = tempCS->picture->tileMap->getTileIdxMap( tempCS->area.lumaPos() );
#endifcu.skip = false;cu.partSize = SIZE_2Nx2N;cu.affine = true;cu.predMode = MODE_INTER;cu.transQuantBypass = encTestMode.lossless;cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;cu.qp = encTestMode.qp;PredictionUnit &pu = tempCS->addPU( cu, partitioner.chType );// set merge informationpu.mergeFlag = true;                      //pu中赋值RDO的AffineMerge候选运动信息pu.mergeIdx = uiMergeCand;pu.interDir = affineMergeCtx.interDirNeighbours[uiMergeCand];cu.affineType = affineMergeCtx.affineType[uiMergeCand];
#if JVET_L0646_GBIcu.GBiIdx = affineMergeCtx.GBiIdx[uiMergeCand];
#endif#if JVET_L0369_SUBBLOCK_MERGEpu.mergeType = affineMergeCtx.mergeType[uiMergeCand];if ( pu.mergeType == MRG_TYPE_SUBPU_ATMVP ){pu.refIdx[0] = affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][0].refIdx;pu.refIdx[1] = affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][0].refIdx;PU::spanMotionInfo( pu, mrgCtx );}else{#endifPU::setAllAffineMvField( pu, affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0], REF_PIC_LIST_0 );PU::setAllAffineMvField( pu, affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1], REF_PIC_LIST_1 );PU::spanMotionInfo( pu );
#if JVET_L0369_SUBBLOCK_MERGE}
#endifif ( mrgTempBufSet )      //非skip时为true。因为非skip模式已经处理过并得到pred像素,无需MC{tempCS->getPredBuf().copyFrom( acMergeBuffer[uiMergeCand] );}else{m_pcInterSearch->motionCompensation( pu );        //MC   由控制点运动信息获得当前块的预测像素pred}//由pred像素计算失真和cost,将最优信息存入bestCSxEncodeInterResidual( tempCS, bestCS, partitioner, encTestMode, uiNoResidualPass, NULL, true, ((uiNoResidualPass == 0) ? &candHasNoResidual[uiMergeCand] : NULL) );if ( m_pcEncCfg->getUseFastDecisionForMerge() && !bestIsSkip ){bestIsSkip = bestCS->getCU( partitioner.chType )->rootCbf == 0;}tempCS->initStructData( encTestMode.qp, encTestMode.lossless );}// end loop uiMrgHADIdxif ( uiNoResidualPass == 0 && m_pcEncCfg->getUseEarlySkipDetection() ){const CodingUnit     &bestCU = *bestCS->getCU( partitioner.chType );const PredictionUnit &bestPU = *bestCS->getPU( partitioner.chType );if ( bestCU.rootCbf == 0 ){if ( bestPU.mergeFlag ){m_modeCtrl->setEarlySkipDetected();}else if ( m_pcEncCfg->getMotionEstimationSearchMethod() != MESEARCH_SELECTIVE ){int absolute_MV = 0;for ( uint32_t uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ ){if ( slice.getNumRefIdx( RefPicList( uiRefListIdx ) ) > 0 ){absolute_MV += bestPU.mvd[uiRefListIdx].getAbsHor() + bestPU.mvd[uiRefListIdx].getAbsVer();}}if ( absolute_MV == 0 ){m_modeCtrl->setEarlySkipDetected();}}}}}}

VTM3.0代码阅读:xCheckRDCostAffineMerge2Nx2N函数相关推荐

  1. VTM3.0代码阅读:xEstimateMvPredAMVP函数

    AMVP运用于inter_ME模式的时候. xEstimateMvPredAMVP进行AMVP,获得当前pu的相邻运动信息,构建AMVP列表,最终选择出最优的MVP.AMVP最终获得的MVP作为ME的 ...

  2. VTM3.0代码阅读:xDeriveCUMV函数

    xDeriveCUMV函数根据解码得到的预测参数数据,计算得到mv. 函数内根据解码得到的各个模式的数据,获取到MMVD.三角预测.AffineMerge.普通merge.AffineME.普通int ...

  3. VVC 代码阅读 compressCtu()函数

    void EncCu::compressCtu( CodingStructure& cs, const UnitArea& area, const unsigned ctuRsAddr ...

  4. VTM1.0代码阅读:CodingStructure类主要函数

    CodingStructure类中的各个函数对于cu.pu和tu的函数处理,其实大致流程都是差不多一样的,所以这里只对cu的相应函数进行分析. 对于下面CodingStructure类中的各个函数的阅 ...

  5. yii 2.0 代码阅读 小记

    1.\yii\base\object 设置了get/set属性...使用getName()获取属性名..构造函数中使用config初始化属性 2.\yii\base\Component 继承自Obje ...

  6. VVC代码阅读 xCheckModeSplit()函数 (中间CABAC还没看)最后代码还没看完

    //当前测试qpconst int qp = encTestMode.qp;//当前sliceconst Slice &slice = *tempCS->slice;// 之前的QPco ...

  7. VTM1.0代码阅读:CU、PU、TU

    VTM中的cu.pu和tu在使用时都是作为CodingStructure类的成员变量来使用的,即作为CS中cus.pus和tus数组中的一个变量来使用的,毕竟VTM中的操作都是以CS作为最基本的类来执 ...

  8. Apollo 3.0代码浅析(一)

    0.写在前面 因为工作中的项目使用到ros,因此本次对于apollo的分析是基于apollo 3.0 代码阅读工具为understand 1.目录结构 1.1 根目录 docker:容器相关 docs ...

  9. HM代码阅读0:Win10下安装HM16.23,编码一个视频,main函数阅读

    HEVC理论知识的学习告了一段落了,说实话脑子里还是嗡嗡的,剩下的部分就一边阅读代码一边掌握吧. 1. HM16.23安装 首先需要安装Cmake,参考以下博客,照步骤安装即可 https://blo ...

  10. ORB-SLAM2代码阅读笔记(五):Tracking线程3——Track函数中单目相机初始化

    Table of Contents 1.特征点匹配相关理论简介 2.ORB-SLAM2中特征匹配代码分析 (1)Tracking线程中的状态机 (2)单目相机初始化函数MonocularInitial ...

最新文章

  1. 【直播】王茂霖:二手车交易价格预测 Baseline 提高(河北高校数据挖掘邀请赛)
  2. java一般会写javadoc吗_怎么写javadoc
  3. vue 2.x项目 vue-qriously 生成二维码并下载、cliploard复制粘贴
  4. 关于PHP中Session文件过多的问题
  5. php表格 单元格,如何更改PHPWord表格单元格高度?
  6. 基于 Ubuntu 搭建微信小程序服务
  7. java异常判断_Java异常退出条件的判断示例代码
  8. vue获取当前月最后一天_只争朝夕,不负韶华——站在2020年第一天,回望2019最后的两个月...
  9. linux系统下文件查找
  10. Android 多媒体【转】
  11. 【软件工程】数据库设计说明书
  12. android webview 透明背景,在android中的半透明webview背景
  13. Appium自动化测试基础--补充:C/S架构和B/S架构说明
  14. dmz区域和虚拟服务器的区别,dmz主机 虚拟服务器
  15. Spectre V1理论与实践
  16. 51单片机控制双步进电机的魔法师思想
  17. 美DARPA支持研发用于救灾与高风险环境的微型机器人
  18. Markdown (CSDN) MD编辑器(一)- 实现页内跳转
  19. 51单片机定时器的查询和进入中断处理
  20. SCI科研工具推荐合集!

热门文章

  1. 《土豆荣耀》重构笔记(七)控制角色移动并添加音效
  2. 高质量C编程00-汇总
  3. 比较器与滞回比较器的原理及应用
  4. ipad文献管理软件_【MAC上写论文有哪些好的文献管理软件可以推荐?】-看准网
  5. Matlab - Matlab 2016a 安装破解教程
  6. 华为4g显示无服务器,华为nova5 插卡无4G
  7. 7.13 Python循环语句(2)、number、字符串
  8. Java程序设计基础------Java基础
  9. 洛谷OJ_P1009涉及的高精度算法
  10. python并行编程手册 pdf_Python并行编程手册