HEVC代码学习8:xMotionEstimation函数

来源:互联网 发布:客单价方面的优化 编辑:程序博客网 时间:2024/05/21 04:24

之前学习了xPatternSearchFracDIF函数,今天来学习其上层的xMotionEstimation函数,从字面就可以理解,功能是进行运动估计。

xMotionEstimation是运动估计的入口函数,通过调用xPatternSearch、xPatternSearchFast、xPatternSearchFracDIF进行运动搜索。主要工作流程是:进行一些初始化,设置搜索范围,然后通过整像素搜索得到一个最优点,将这个最优点作为起点进行亚像素搜索,最终得到以1/4精度为单位的MV。

Void TEncSearch::xMotionEstimation( TComDataCU* pcCU, TComYuv* pcYuvOrg, Int iPartIdx, RefPicList eRefPicList, TComMv* pcMvPred, Int iRefIdxPred, TComMv& rcMv, UInt& ruiBits, Distortion& ruiCost, Bool bBi  ){  UInt          uiPartAddr;  Int           iRoiWidth;  Int           iRoiHeight;  TComMv        cMvHalf, cMvQter;   //定义1/21/4精度MV  TComMv        cMvSrchRngLT;  TComMv        cMvSrchRngRB;  TComYuv*      pcYuv = pcYuvOrg;   //图像首地址  assert(eRefPicList < MAX_NUM_REF_LIST_ADAPT_SR && iRefIdxPred<Int(MAX_IDX_ADAPT_SR));  m_iSearchRange = m_aaiAdaptSR[eRefPicList][iRefIdxPred];  //根据参考帧列表类型、参考帧序号自适应设置搜索范围   Int           iSrchRng      = ( bBi ? m_bipredSearchRange : m_iSearchRange );  //根据是否是双向预测设置搜索范围  TComPattern   tmpPattern;  TComPattern*  pcPatternKey  = &tmpPattern;    // TComPattern是用于访问相邻块/像素的一个工具类,用于获取neighbor的信息  Double        fWeight       = 1.0;  pcCU->getPartIndexAndSize( iPartIdx, uiPartAddr, iRoiWidth, iRoiHeight );   //获取PU的地址,宽度和高度   if ( bBi )    //B帧  {    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;  }  //  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;   //设置运动估计的搜索范围,LeftTop & RightBottom  if ( bBi )  {    xSetSearchRange   ( pcCU, rcMv   , iSrchRng, cMvSrchRngLT, cMvSrchRngRB );  }  else  {    xSetSearchRange   ( pcCU, cMvPred, iSrchRng, cMvSrchRngLT, cMvSrchRngRB );  }  m_pcRdCost->getMotionCost( true, 0, pcCU->getCUTransquantBypass(uiPartAddr) );   //计算率失真代价  m_pcRdCost->setPredictor  ( *pcMvPred );    //设置预测得到的MV  m_pcRdCost->setCostScale  ( 2 );  setWpScalingDistParam( pcCU, iRefIdxPred, eRefPicList );   //设置跟weighted prediction相关的参数    //  Do integer search 整像素搜索  if ( !m_iFastSearch || bBi )  {    // 如果是B帧或者不是快速搜索模式,进行常规搜索      xPatternSearch      ( pcPatternKey, piRefY, iRefStride, &cMvSrchRngLT, &cMvSrchRngRB, rcMv, ruiCost );  }  else  {    // 进行快速搜索    rcMv = *pcMvPred;    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->getMotionCost( true, 0, pcCU->getCUTransquantBypass(uiPartAddr) );  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像素,最终MV单位为1/4精度  UInt uiMvBits = m_pcRdCost->getBits( rcMv.getHor(), rcMv.getVer() );  ruiBits      += uiMvBits;  ruiCost       = (Distortion)( floor( fWeight * ( (Double)ruiCost - (Double)m_pcRdCost->getCost( uiMvBits ) ) ) + (Double)m_pcRdCost->getCost( ruiBits ) );}
1 0
原创粉丝点击