• HM16.0之帧间Merge模式——xCheckRDCostMerge2Nx2N


    参考:https://blog.csdn.net/nb_vol_1/article/details/51163625

    1、源代码:

    /** check RD costs for a CU block encoded with merge
     * param rpcBestCU
     * param rpcTempCU
     * 
    eturns Void
     */
    Void TEncCu::xCheckRDCostMerge2Nx2N( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU DEBUG_STRING_FN_DECLARE(sDebug), Bool *earlyDetectionSkipMode )
    {
      assert( rpcTempCU->getSlice()->getSliceType() != I_SLICE ); // 确定该片是P Slice或者B Slice
      TComMvField  cMvFieldNeighbours[2 * MRG_MAX_NUM_CANDS]; // double length for mv of both lists
      UChar uhInterDirNeighbours[MRG_MAX_NUM_CANDS];
      Int numValidMergeCand = 0;
      const Bool bTransquantBypassFlag = rpcTempCU->getCUTransquantBypass(0);
    
      for( UInt ui = 0; ui < rpcTempCU->getSlice()->getMaxNumMergeCand(); ++ui )
      {
        uhInterDirNeighbours[ui] = 0;
      }
      UChar uhDepth = rpcTempCU->getDepth( 0 ); // 获取当前深度
      // 给PU中相应的partition写入分割模式
    rpcTempCU
    ->setPartSizeSubParts( SIZE_2Nx2N, 0, uhDepth ); // interprets depth relative to LCU level // 取出Merge候选列表
    rpcTempCU->getInterMergeCandidates( 0, 0, cMvFieldNeighbours,uhInterDirNeighbours, numValidMergeCand );
    // 构造候选列表 Int mergeCandBuffer[MRG_MAX_NUM_CANDS];
    for( UInt ui = 0; ui < numValidMergeCand; ++ui ) { mergeCandBuffer[ui] = 0; } Bool bestIsSkip = false; UInt iteration;
    // 默认为false,iteration = 2
    if ( rpcTempCU->isLosslessCoded(0)) { iteration = 1; } else { iteration = 2; } DEBUG_STRING_NEW(bestStr)

        //代码结构分析

        //第一次不理skip模式,bestIsSkip的初始值为false;

        //第二次不处理mergeCandBuffer[uiMergeCand]为1的情况.


    // 遍历两次:第一次无残差编码,第二次对残差编码
    for( UInt uiNoResidual = 0; uiNoResidual < iteration; ++uiNoResidual ) {
    // 遍历所有Merge候选成员
    for( UInt uiMergeCand = 0; uiMergeCand < numValidMergeCand; ++uiMergeCand ) { if(!(uiNoResidual==1 && mergeCandBuffer[uiMergeCand]==1)) { if( !(bestIsSkip && uiNoResidual == 0) ) { DEBUG_STRING_NEW(tmpStr) // set MC parameters 设置运动补偿参数 rpcTempCU->setPredModeSubParts( MODE_INTER, 0, uhDepth ); // interprets depth relative to LCU level rpcTempCU->setCUTransquantBypassSubParts( bTransquantBypassFlag, 0, uhDepth ); rpcTempCU->setChromaQpAdjSubParts( bTransquantBypassFlag ? 0 : m_ChromaQpAdjIdc, 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 计算残差和RDCost,并进行编码 m_pcPredSearch->encodeResAndCalcRdInterCU( rpcTempCU, m_ppcOrigYuv [uhDepth], m_ppcPredYuvTemp[uhDepth], m_ppcResiYuvTemp[uhDepth], m_ppcResiYuvBest[uhDepth], m_ppcRecoYuvTemp[uhDepth], (uiNoResidual != 0) DEBUG_STRING_PASS_INTO(tmpStr) ); #ifdef DEBUG_STRING DebugInterPredResiReco(tmpStr, *(m_ppcPredYuvTemp[uhDepth]), *(m_ppcResiYuvBest[uhDepth]), *(m_ppcRecoYuvTemp[uhDepth]), DebugStringGetPredModeMask(rpcTempCU->getPredictionMode(0))); #endif // 第一次迭代时进行 if ((uiNoResidual == 0) && (rpcTempCU->getQtRootCbf(0) == 0)) { // If no residual when allowing for one, then set mark to not try case where residual is forced to 0 mergeCandBuffer[uiMergeCand] = 1; } rpcTempCU->setSkipFlagSubParts( rpcTempCU->getQtRootCbf(0) == 0, 0, uhDepth ); Int orgQP = rpcTempCU->getQP( 0 ); xCheckDQP( rpcTempCU );
    // 更新最优模式 xCheckBestMode(rpcBestCU, rpcTempCU, uhDepth DEBUG_STRING_PASS_INTO(bestStr) DEBUG_STRING_PASS_INTO(tmpStr)); // 重新初始化预测参数,为下一次预测做准备 rpcTempCU
    ->initEstData( uhDepth, orgQP, bTransquantBypassFlag ); if( m_pcEncCfg->getUseFastDecisionForMerge() && !bestIsSkip ) { bestIsSkip = rpcBestCU->getQtRootCbf(0) == 0; } } } }
    // 如果开启earlyDetectionSkip时,第一次迭代执行
    if(uiNoResidual == 0 && m_pcEncCfg->getUseEarlySkipDetection()) { if(rpcBestCU->getQtRootCbf( 0 ) == 0) { if( rpcBestCU->getMergeFlag( 0 )) { *earlyDetectionSkipMode = true; } else if(m_pcEncCfg->getFastSearch() != SELECTIVE) { 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; } } } } } DEBUG_STRING_APPEND(sDebug, bestStr) }
  • 相关阅读:
    C++每次读取一行字符串输入(学习笔记) (转)
    Ubuntu使用Windows下的conio.h
    容斥原理、欧拉函数、phi
    UVa1635
    转:用STL中的vector动态开辟二维数组
    [转载]Vector用法(C++ Primer中文版)
    c++中vector的pair与make_pair的使用,双关键字排序
    uva12716 GCD XOR
    在 Ubuntu 14.04 中安装 Pepper Flash Player For Chromium
    Careercup
  • 原文地址:https://www.cnblogs.com/lucifer1997/p/10996665.html
Copyright © 2020-2023  润新知