VTM3.0代码阅读:xCheckRDCostAffineMerge2Nx2N函数
由于宏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函数相关推荐
- VTM3.0代码阅读:xEstimateMvPredAMVP函数
AMVP运用于inter_ME模式的时候. xEstimateMvPredAMVP进行AMVP,获得当前pu的相邻运动信息,构建AMVP列表,最终选择出最优的MVP.AMVP最终获得的MVP作为ME的 ...
- VTM3.0代码阅读:xDeriveCUMV函数
xDeriveCUMV函数根据解码得到的预测参数数据,计算得到mv. 函数内根据解码得到的各个模式的数据,获取到MMVD.三角预测.AffineMerge.普通merge.AffineME.普通int ...
- VVC 代码阅读 compressCtu()函数
void EncCu::compressCtu( CodingStructure& cs, const UnitArea& area, const unsigned ctuRsAddr ...
- VTM1.0代码阅读:CodingStructure类主要函数
CodingStructure类中的各个函数对于cu.pu和tu的函数处理,其实大致流程都是差不多一样的,所以这里只对cu的相应函数进行分析. 对于下面CodingStructure类中的各个函数的阅 ...
- yii 2.0 代码阅读 小记
1.\yii\base\object 设置了get/set属性...使用getName()获取属性名..构造函数中使用config初始化属性 2.\yii\base\Component 继承自Obje ...
- VVC代码阅读 xCheckModeSplit()函数 (中间CABAC还没看)最后代码还没看完
//当前测试qpconst int qp = encTestMode.qp;//当前sliceconst Slice &slice = *tempCS->slice;// 之前的QPco ...
- VTM1.0代码阅读:CU、PU、TU
VTM中的cu.pu和tu在使用时都是作为CodingStructure类的成员变量来使用的,即作为CS中cus.pus和tus数组中的一个变量来使用的,毕竟VTM中的操作都是以CS作为最基本的类来执 ...
- Apollo 3.0代码浅析(一)
0.写在前面 因为工作中的项目使用到ros,因此本次对于apollo的分析是基于apollo 3.0 代码阅读工具为understand 1.目录结构 1.1 根目录 docker:容器相关 docs ...
- HM代码阅读0:Win10下安装HM16.23,编码一个视频,main函数阅读
HEVC理论知识的学习告了一段落了,说实话脑子里还是嗡嗡的,剩下的部分就一边阅读代码一边掌握吧. 1. HM16.23安装 首先需要安装Cmake,参考以下博客,照步骤安装即可 https://blo ...
- ORB-SLAM2代码阅读笔记(五):Tracking线程3——Track函数中单目相机初始化
Table of Contents 1.特征点匹配相关理论简介 2.ORB-SLAM2中特征匹配代码分析 (1)Tracking线程中的状态机 (2)单目相机初始化函数MonocularInitial ...
最新文章
- 【直播】王茂霖:二手车交易价格预测 Baseline 提高(河北高校数据挖掘邀请赛)
- java一般会写javadoc吗_怎么写javadoc
- vue 2.x项目 vue-qriously 生成二维码并下载、cliploard复制粘贴
- 关于PHP中Session文件过多的问题
- php表格 单元格,如何更改PHPWord表格单元格高度?
- 基于 Ubuntu 搭建微信小程序服务
- java异常判断_Java异常退出条件的判断示例代码
- vue获取当前月最后一天_只争朝夕,不负韶华——站在2020年第一天,回望2019最后的两个月...
- linux系统下文件查找
- Android 多媒体【转】
- 【软件工程】数据库设计说明书
- android webview 透明背景,在android中的半透明webview背景
- Appium自动化测试基础--补充:C/S架构和B/S架构说明
- dmz区域和虚拟服务器的区别,dmz主机 虚拟服务器
- Spectre V1理论与实践
- 51单片机控制双步进电机的魔法师思想
- 美DARPA支持研发用于救灾与高风险环境的微型机器人
- Markdown (CSDN) MD编辑器(一)- 实现页内跳转
- 51单片机定时器的查询和进入中断处理
- SCI科研工具推荐合集!