[置顶] HEVC帧间预测之三——TEncCu::xCheckRDCostMerge2Nx2N函数分析

本文将对实现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 ) } 

你可能感兴趣的:(merge,HEVC)