HTM-16.2代码(6)——xMotionEstimation

基本思想:就是用TZSearch算法先进行整像素搜索,确定一个局部的最佳值,然后以这个最佳点为中心再进行精度更高的分像素搜索。
主要流程:
(1)首先计算搜索范围
(2)获取相邻块像素的访问方式(通过调用getPattern)
(3)计算当前CU(或者说PU)大小
(4)如果是B帧(使用双向预测),还要设置权重?
(5)访问方式的初始化
(6)得到参考帧
(7)根据预先获取的预测MV,设置搜索范围
(8)调用xPatternSearch进行整像素所搜,确定一个局部的最佳位置
(9)调用xPatternSearchFracDIF进行分像素搜索(1/2像素,1/4像素),提高搜索的精度

Void TEncSearch::xMotionEstimation( TComDataCU* pcCU, TComYuv* pcYuvOrg, Int iPartIdx, RefPicList eRefPicList, TComMv* pcMvPred, Int iRefIdxPred, TComMv& rcMv, UInt& ruiBits, Distortion& ruiCost, Bool bBi  )
{
#if NH_MV
  D_PRINT_INC_INDENT(g_traceModeCheck,  "xMotionEstimation");
#endif

  UInt          uiPartAddr;
  Int           iRoiWidth;
  Int           iRoiHeight;

  TComMv        cMvHalf, cMvQter;
  TComMv        cMvSrchRngLT;
  TComMv        cMvSrchRngRB;

  TComYuv*      pcYuv = pcYuvOrg;

  assert(eRefPicList < MAX_NUM_REF_LIST_ADAPT_SR && iRefIdxPred<Int(MAX_IDX_ADAPT_SR));

  // 搜索的范围iSrchRng 
  m_iSearchRange = m_aaiAdaptSR[eRefPicList][iRefIdxPred];
  Int           iSrchRng      = ( bBi ? m_bipredSearchRange : m_iSearchRange );

  // 取得搜索模式(其实是相邻像素的访问方式)  
  TComPattern   tmpPattern;
  TComPattern*  pcPatternKey  = &tmpPattern;

  Double        fWeight       = 1.0;

  pcCU->getPartIndexAndSize( iPartIdx, uiPartAddr, iRoiWidth, iRoiHeight );

#if NH_3D_IC
  Bool bICFlag = pcCU->getICFlag( uiPartAddr ) && ( pcCU->getSlice()->getViewIndex() != pcCU->getSlice()->getRefPic( eRefPicList, iRefIdxPred )->getViewIndex() );
  pcPatternKey->setICFlag( bICFlag );
#endif
#if NH_3D_SDC_INTER
   pcPatternKey->setSDCMRSADFlag( pcCU->getSlice()->getInterSdcFlag() );
#endif

  if ( bBi ) // Bipredictive ME
  {
    TComYuv*  pcYuvOther = &m_acYuvPred[1-(Int)eRefPicList];
    pcYuv                = &m_cYuvPredTemp;

    pcYuvOrg->copyPartToPartYuv( pcYuv, uiPartAddr, iRoiWidth, iRoiHeight );

    pcYuv->removeHighFreq( pcYuvOther, uiPartAddr, iRoiWidth, iRoiHeight, pcCU->getSlice()->getSPS()->getBitDepths().recon, m_pcEncCfg->getClipForBiPredMeEnabled() );

    fWeight = 0.5;
  }
  m_cDistParam.bIsBiPred = bBi;

  //  Search key pattern initialization   //!< 设置待搜索的PU的相关参数,首地址,宽度,高度,跨度等
  pcPatternKey->initPattern( pcYuv->getAddr  ( COMPONENT_Y, uiPartAddr ),
                             iRoiWidth,
                             iRoiHeight,
                             pcYuv->getStride(COMPONENT_Y),
                             pcCU->getSlice()->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA) );
  // 参考帧的像素  
  Pel*        piRefY      = pcCU->getSlice()->getRefPic( eRefPicList, iRefIdxPred )->getPicYuvRec()->getAddr( COMPONENT_Y, pcCU->getCtuRsAddr(), pcCU->getZorderIdxInCtu() + uiPartAddr );
  Int         iRefStride  = pcCU->getSlice()->getRefPic( eRefPicList, iRefIdxPred )->getPicYuvRec()->getStride(COMPONENT_Y);

  TComMv      cMvPred = *pcMvPred;// 预测的MV
#if NH_MV
  m_vertRestriction =  m_pcEncCfg->getUseDisparitySearchRangeRestriction()  && ( pcCU->getSlice()->getRefPic( eRefPicList, iRefIdxPred )->getPOC() == pcCU->getSlice()->getPOC() );
#endif

  // 设置运动估计的搜索范围 
  if ( bBi )
  {
    xSetSearchRange   ( pcCU, rcMv   , iSrchRng, cMvSrchRngLT, cMvSrchRngRB );
  }
  else
  {
    xSetSearchRange   ( pcCU, cMvPred, iSrchRng, cMvSrchRngLT, cMvSrchRngRB );
  }

  m_pcRdCost->selectMotionLambda( true, 0, pcCU->getCUTransquantBypass(uiPartAddr) );// Lambda

  m_pcRdCost->setPredictor  ( *pcMvPred );// 设置预测得到的MV 
#if NH_3D_INTEGER_MV_DEPTH
  if( pcCU->getSlice()->getIsDepth() )
  {
    m_pcRdCost->setCostScale  ( 0 );
  }
  else
  {
#endif
    m_pcRdCost->setCostScale  ( 2 );    
#if NH_3D_INTEGER_MV_DEPTH
  }
#endif


  setWpScalingDistParam( pcCU, iRefIdxPred, eRefPicList );// 设置跟weighted prediction相关的参数

  //  Do integer search   // 先进行整像素搜索,确定一个局部的最佳值  
  if ( (m_motionEstimationSearchMethod==MESEARCH_FULL) || bBi )
  {
    xPatternSearch      ( pcPatternKey, piRefY, iRefStride, &cMvSrchRngLT, &cMvSrchRngRB, rcMv, ruiCost );//进行全局搜索
  }
  else
  {
    rcMv = *pcMvPred;
#if NH_MV_FIX_VERT_MV_REST
    if ( m_vertRestriction )
    {
      if (rcMv.getVer() > cMvSrchRngRB.getVer()<<2)
      {
        rcMv.setVer(cMvSrchRngRB.getVer()<<2);
      }
    }
#endif
    const TComMv *pIntegerMv2Nx2NPred=0;
    if (pcCU->getPartitionSize(0) != SIZE_2Nx2N || pcCU->getDepth(0) != 0)
    {
      pIntegerMv2Nx2NPred = &(m_integerMv2Nx2N[eRefPicList][iRefIdxPred]);
    }
    xPatternSearchFast  ( pcCU, pcPatternKey, piRefY, iRefStride, &cMvSrchRngLT, &cMvSrchRngRB, rcMv, ruiCost, pIntegerMv2Nx2NPred );
    if (pcCU->getPartitionSize(0) == SIZE_2Nx2N)
    {
      m_integerMv2Nx2N[eRefPicList][iRefIdxPred] = rcMv;
    }
  }

  m_pcRdCost->selectMotionLambda( true, 0, pcCU->getCUTransquantBypass(uiPartAddr) );
#if NH_3D_INTEGER_MV_DEPTH
  if( ! pcCU->getSlice()->getIsDepth() )
  {
#endif
  m_pcRdCost->setCostScale ( 1 );

  const Bool bIsLosslessCoded = pcCU->getCUTransquantBypass(uiPartAddr) != 0;
  // 进行分像素搜索,以提高搜索的精度
  xPatternSearchFracDIF( bIsLosslessCoded, pcPatternKey, piRefY, iRefStride, &rcMv, cMvHalf, cMvQter, ruiCost ); 

  m_pcRdCost->setCostScale( 0 );
  rcMv <<= 2;// 整像素 
  rcMv += (cMvHalf <<= 1);// 1/2像素
  rcMv +=  cMvQter;// 1/4像素 
#if NH_3D_INTEGER_MV_DEPTH
  }
#endif

  UInt uiMvBits = m_pcRdCost->getBitsOfVectorWithPredictor( rcMv.getHor(), rcMv.getVer() );
#if NH_3D_INTEGER_MV_DEPTH
  if( pcCU->getSlice()->getIsDepth() )
  {
    ruiCost += m_pcRdCost->getCost( uiMvBits );
  }
#endif
  ruiBits      += uiMvBits;
  ruiCost       = (Distortion)( floor( fWeight * ( (Double)ruiCost - (Double)m_pcRdCost->getCost( uiMvBits ) ) ) + (Double)m_pcRdCost->getCost( ruiBits ) );

#if NH_MV
  D_PRINT_INDENT(g_traceRDCost, "ME Cost:" + n2s(ruiCost)  );
  D_DEC_INDENT  ( g_traceModeCheck ); 
#endif
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值