当前位置:编程学习 > C/C++ >>

HEVC帧间预测之三——TEncCu::xCheckRDCostMerge2Nx2N函数分析

本文将对实现merge模式的主函数xCheckRDCostMerge2Nx2N进行分析,方便理清merge模式的整个过程。之前的一篇分析了getInterMergeCandidates的具体实现,还有两个比较重要的函数motionCompensation和encodeResAndCalcRdInterCU,将留在后面陆续进行分析,但是根据它们的命名就不难猜出它们的作用,而且事实也是这样,因此对理解merge模式的整个过程没有影响,可以暂时不用去细究具体实现。下面仍然以贴代码及注释的方式来进行分析:
[cpp]  

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  
      {  <
补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,