xCheckRDCostAffineMerge2Nx2N函数和xCheckRDCostMerge2Nx2N函数类似,但是过程要比其简单很多。xCheckRDCostAffineMerge2Nx2N函数是用来选出Affine Merge模式中的最佳候选MV。

主要过程如下:

  1. 获取Affine Merge候选列表,Affine Merge候选列表的推导参考:仿射运动补偿预测
  2. 若开启快速Merge模式,根据当前CU的编码信息缩减进行细选的Merge模式数目
    1. 若当前CU最佳模式不是Skip模式,则先遍历可用候选Merge模式,进行运动补偿计算预测值,然后根据SAD和Merge模式比特数更新RD代价列表,如果第i个模式代价 > 第一个模式的代价*MRG_FAST_RATIO(1.25),则将细选模式数设置为i
    2. 否则,进行细选的模式数为可用的Merge模式数
  3. 进行细选,细选过程和xCheckRDCostMerge2Nx2N的细选过程类似

代码及注释如下:

void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
{if( m_modeCtrl->getFastDeltaQp() ){return;}if ( bestCS->area.lumaSize().width < 8 || bestCS->area.lumaSize().height < 8 ){return;}m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;const Slice &slice = *tempCS->slice;CHECK( slice.getSliceType() == I_SLICE, "Affine Merge modes not available for I-slices" );tempCS->initStructData( encTestMode.qp );AffineMergeCtx affineMergeCtx; //Affine Merge上下文const SPS &sps = *tempCS->sps;if (sps.getMaxNumAffineMergeCand() == 0){return;}setAFFBestSATDCost(MAX_DOUBLE);MergeCtx mrgCtx;if (sps.getSbTMVPEnabledFlag()){Size bufSize = g_miScaling.scale( tempCS->area.lumaSize() );mrgCtx.subPuMvpMiBuf = MotionBuf( m_SubPuMiBuf, bufSize );affineMergeCtx.mrgCtx = &mrgCtx;}{// first get merge candidates 首先获得Merge候选模式CodingUnit cu( tempCS->area );cu.cs = tempCS;cu.predMode = MODE_INTER;cu.slice = tempCS->slice;cu.tileIdx          = tempCS->pps->getTileIdx( tempCS->area.lumaPos() );cu.mmvdSkip = false;PredictionUnit pu( tempCS->area );pu.cu = &cu;pu.cs = tempCS;pu.regularMergeFlag = false;PU::getAffineMergeCand( pu, affineMergeCtx ); //获得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];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 );}if ( m_pcEncCfg->getUseFastMerge() ) //快速Merge模式{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 count 获得所选候选人的SATD费用,并减少其数量if ( !bestIsSkip ){RdModeList.clear();mrgTempBufSet = true;const double sqrtLambdaForFirstPass = m_pcRdCost->getMotionLambda( );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.affine = true;cu.predMode = MODE_INTER;cu.chromaQpAdj = m_cuChromaQpOffsetIdxPlus1;cu.qp = encTestMode.qp;PredictionUnit &pu = tempCS->addPU( cu, partitioner.chType );DistParam distParam;const bool bUseHadamard = !tempCS->slice->getDisableSATDForRD();m_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 ) );// 遍历可用候选Merge模式for ( uint32_t uiMergeCand = 0; uiMergeCand < affineMergeCtx.numValidMergeCand; uiMergeCand++ ){acMergeBuffer[uiMergeCand] = m_acMergeBuffer[uiMergeCand].getBuf( localUnitArea );// set merge informationpu.interDir = affineMergeCtx.interDirNeighbours[uiMergeCand];pu.mergeFlag = true;pu.regularMergeFlag = false;pu.mergeIdx = uiMergeCand;cu.affineType = affineMergeCtx.affineType[uiMergeCand];cu.BcwIdx = affineMergeCtx.BcwIdx[uiMergeCand];pu.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{PU::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 );}distParam.cur = acMergeBuffer[uiMergeCand].Y();// 运动补偿m_pcInterSearch->motionCompensation( pu, acMergeBuffer[uiMergeCand], REF_PIC_LIST_X, true, false );Distortion uiSad = distParam.distFunc( distParam );uint32_t   uiBitsCand = uiMergeCand + 1;if ( uiMergeCand == tempCS->picHeader->getMaxNumAffineMergeCand() - 1 ){uiBitsCand--;}double cost = (double)uiSad + (double)uiBitsCand * sqrtLambdaForFirstPass;updateCandList( uiMergeCand, cost, RdModeList, candCostList, uiNumMrgSATDCand );CHECK( std::min( uiMergeCand + 1, uiNumMrgSATDCand ) != RdModeList.size(), "" );}// Try to limit number of candidates using SATD-costs 尽量限制使用SATD Cost的模式数for ( uint32_t i = 1; i < uiNumMrgSATDCand; i++ ){if ( candCostList[i] > MRG_FAST_RATIO * candCostList[0] ){uiNumMrgSATDCand = i;break;}}tempCS->initStructData( encTestMode.qp );setAFFBestSATDCost(candCostList[0]);}else{uiNumMrgSATDCand = affineMergeCtx.numValidMergeCand;}}uint32_t iteration;uint32_t iterationBegin = 0;iteration = 2;for (uint32_t uiNoResidualPass = iterationBegin; uiNoResidualPass < iteration; ++uiNoResidualPass){for ( uint32_t uiMrgHADIdx = 0; uiMrgHADIdx < uiNumMrgSATDCand; uiMrgHADIdx++ ){uint32_t uiMergeCand = RdModeList[uiMrgHADIdx];if ( ((uiNoResidualPass != 0) && candHasNoResidual[uiMergeCand])|| ((uiNoResidualPass == 0) && bestIsSkip) ){continue;}// first get merge candidatesCodingUnit &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.affine = true;cu.predMode = MODE_INTER;cu.chromaQpAdj = m_cuChromaQpOffsetIdxPlus1;cu.qp = encTestMode.qp;PredictionUnit &pu = tempCS->addPU( cu, partitioner.chType );// set merge informationpu.mergeFlag = true;pu.mergeIdx = uiMergeCand;pu.interDir = affineMergeCtx.interDirNeighbours[uiMergeCand];cu.affineType = affineMergeCtx.affineType[uiMergeCand];cu.BcwIdx = affineMergeCtx.BcwIdx[uiMergeCand];pu.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{PU::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( m_pcEncCfg->getMCTSEncConstraint() && ( !( MCTSHelper::checkMvBufferForMCTSConstraint( *cu.firstPU ) ) ) ){// Do not use this modetempCS->initStructData( encTestMode.qp );return;}if ( mrgTempBufSet ){tempCS->getPredBuf().copyFrom(acMergeBuffer[uiMergeCand], true, false);   // Copy Luma Onlym_pcInterSearch->motionCompensation(pu, REF_PIC_LIST_X, false, true);}else{m_pcInterSearch->motionCompensation( pu );}xEncodeInterResidual( tempCS, bestCS, partitioner, encTestMode, uiNoResidualPass, ( uiNoResidualPass == 0 ? &candHasNoResidual[uiMergeCand] : NULL ) );if ( m_pcEncCfg->getUseFastDecisionForMerge() && !bestIsSkip ){bestIsSkip = bestCS->getCU( partitioner.chType )->rootCbf == 0;}tempCS->initStructData( encTestMode.qp );}// 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();}}}}}if ( m_bestModeUpdated && bestCS->cost != MAX_DOUBLE ){xCalDebCost( *bestCS, partitioner );}
}

H.266/VVC代码学习:xCheckRDCostAffineMerge2Nx2N函数相关推荐

  1. H.266/VVC代码学习20:角度预测入口 / 特殊模式的PDPC技术(predIntraAng)

    1.predIntraAng函数 predIntraAng是帧内0~66这67种预测的入口.其中可细分为: 模式0:PLANAR模式 模式1:DC模式 模式2~66:角度模式 此函数在亮度预测和色度预 ...

  2. H.266/VVC代码学习21:帧内角度预测的实现 / 近对角模式的PDPC(xPredIntraAng)

    xPredIntraAng函数的作用是对任意大小的块和任意模式,如何将参考像素的值根据其模式的角度填充进每一个像素. 下图是basketball drill的一个16*16的块,其预测模式为10(偏斜 ...

  3. H.266/VVC代码学习17:帧内亮度预测的编解码(intra_luma_pred_modes)

    引--亮度预测:H.266/VVC代码学习5:VTM4.0帧内亮度预测代码(estIntraPredLumaQT) 一.结论: 亮度编解码根据MPM列表的值分为两个阶段: 1 亮度模式在MPM列表中: ...

  4. H.266/VVC代码学习:帧内预测之角度预测函数(predIntraAng、xPredIntraAng)

    predIntraAng函数 VTM中,帧内预测的角度预测的入口函数为predIntraAng函数,该函数主要是用于进行传统的帧内预测(Planar.DC.角度预测),然后对Planar和DC模式使用 ...

  5. H.266/VVC代码学习:xCompressCU函数

    xCompressCU函数是用来进行CU划分(递归调用自身)以及模式选择. 首先调用m_modeCtrl->initCULevel函数初始化模式选择列表,由堆栈控制,将当前CU可以划分的模式(四 ...

  6. H.266/VVC代码学习:MIP技术相关代码之initIntraMip函数

    initIntraMip函数主要是对参考像素进行下采样并为MIP矩阵乘法准备输入数据,函数结构如下: MIP根据块尺寸可以分为以下三种情况:   块尺寸 下采样后的边界长度 m_reducedBdry ...

  7. H.266/VVC代码学习32:VTM5.0解码端最上层函数

    解码部分的研究不像编码端那样需要精雕细琢,但如果想研究一个内容划分或选择模式等的最终结果是怎样,那么应该从解码端入手.下面让我们来学习解码端的框架及最上层的三个函数. 文章目录 1 main() 2 ...

  8. H.266/VVC代码学习:DC模式和Planar模式

    Planar模式和DC模式时两种特殊的角度模式,分别对应于模式号0和1. 一.DC模式 DC模式适用于大面积平坦区域,其预测值是通过计算左边和(或)上边参考像素的平均值获得的. 1.1.计算 DC模式 ...

  9. H.266/VVC技术学习之帧内模式编码

    在HEVC中,支持33种角度模式.DC模式和Planar模式,为了减少编码比特,使用长度为3的最可能模式列表.在VVC中,引入了ISP模式.MRL模式.MIP模式等,帧内模式编码时需要先对这些模式的f ...

  10. H.266/VVC-VTM代码学习27-VTM中编码器主函数逻辑

    H.266/VVC专栏传送 上一篇:H.266/VVC-VTM代码学习26-VTM中RDcost的计算与λ的设定(二) 下一篇:持续创作中- 目录 H.266/VVC专栏传送 前言 一.简介 二.代码 ...

最新文章

  1. IDC行业前景,机遇与挑战并存
  2. 利用CodeBERT,这个VS Code扩展可以自动生成Python文档字符串
  3. USB数据线内阻对充电电流的影响
  4. java barrier_Java - Latch和Barrier的区别
  5. java 多态实现的jvm调用过程_多态:JVM是如何进行方法调用的
  6. java 错误页_《javaweb学习笔记2-jsp错误页设置》
  7. 拓端tecdat|ARIMA模型预测CO2浓度时间序列-python实现
  8. 网付快讯:华为拿下支付牌照!移动支付行业迎来三足鼎立盛况
  9. 详谈软件工程之系统设计模式
  10. 我要彻底搞懂SSD网络结构(2)特征提取网络
  11. 文档自动同步云服务器,​文件自动同步网盘能实现吗?
  12. 关于手机号不能登录微信解决办法
  13. 套件端口 群晖_群晖NAS的各种端口
  14. echarts 饼状图渐变色
  15. directx安装后找不到_如何下载,安装,更新到最新的DirectX
  16. el-input 正则,非负数且只有一个小数点
  17. 王者荣耀我的服务器没显示哪个区,王者荣耀怎么看自己在哪个区
  18. 纷享销客产品副总裁李杰:连接型CRM如何支撑快消品牌企业新增长
  19. 计算机c盘是内存还是外存,rom是内存还是外存?
  20. 程设大作业之魔兽世界

热门文章

  1. WebView交互架构项目实战(三)(1),老罗android开发视频教程
  2. Android学习路线图
  3. 系统集成项目管理工程师计算题(成本管理计算)
  4. Centos7 设置静态IP地址
  5. SQL语句执行顺序【全】
  6. 【网络覆盖优化】基于matlab的网络覆盖遗传优化问题仿真
  7. 安装genymotion模拟器
  8. 基于java电子病历管理系统设计与实现
  9. 物业费管理java_java毕业设计_springboot框架的物业收费管理系统
  10. 怎么配置FlyMcu(stm32串口下载软件)有图 超详细