JMVC中的运动估计

由于后面要在运动估计方面做些优化,所以这几天看了下JMVC的motionEstimation.cpp即运动估计。

大家都知道运动估计只是在inter prediction即帧间预测才用到的

所以在宏块预测MbEncoder中有如下函数

xEstimateMb16x16

xEstimateMb16x8

xEstimateMb8x16

xEstimateSubMb8x8

xEstimateSubMb8x4

xEstimateSubMb4x8

xEstimateSubMb4x4

通过调用运动估计的入口函数m_pcMotionEstimation->estimateBlockWithStart()来实现运动估计。

xEstimateMb8x8eEstimateMb8x8Frext也间接通过调用xEstimateSubMb8x8,8x4,4x8,4x4来进行运动估计。

下面进入正题运动估计的入口函数estimateBlockWithStart()

首先是很多的预处理和初始化工作(这个还没有看太明白,希望有大牛懂的话讲解下吧)

然后就是调用一些搜索策略进行运动估计,主要有

xPelBlockSearch()全搜索

xPelSpiralSearch()螺旋搜索

xPelLogSearch()对数搜索

xTZSearch()这个就不知到叫什么名字了(to be continued)

至于搜索算法的具体实现,目前只看了全搜索的,下面就讲一下对xPelBlockSearch()的理解与疑问吧,希望大家能指出我理解不透的地方或解答我没有解决的问题,谢谢

全搜索顾名思义,就是在搜索范围内把所有的宏块都扫描一遍,然后取最优的结果(搜索范围内最优,基本上是全局最优)。

JMVC运动估计motionEstimation全搜索xPelBlockSearch()代码详解

Void MotionEstimation::xPelBlockSearch( IntYuvPicBuffer *pcPelData, Mv& rcMv, UInt& ruiSAD, UInt uiSearchRange )

{

  if( ! uiSearchRange )              //对为0SearchRange进行赋值,值为配置文件中给定的值

  {

    uiSearchRange = m_cParams.getSearchRange();

  }

 

  Int     iYStride   = pcPelData->getLStride();    //获取Y的行跨度

  XPel*   pucYRef    = pcPelData->getLumBlk ();    //获取当前块的Y地址

  XPel*   pucYSearch;                             

  Int     iCStride   = pcPelData->getCStride();    //获取C的行跨度

  XPel*   pucURef    = pcPelData->getCbBlk  ();    //获取当前块的U地址

  XPel*   pucVRef    = pcPelData->getCrBlk  ();    //获取当前块的V地址

  UInt    uiSad;

 

  Int y = 0;

  Int x = 0;

 

  m_cXDSS.iYStride = iYStride;

  m_cXDSS.iCStride = iCStride;

 

  ruiSAD = MSYS_UINT_MAX;                      //初始化绝对误差和,置为最大

  rcMv.limitComponents( m_cMin, m_cMax );     

  rcMv >>= 2;

 

  SearchRect cSearchRect;

  cSearchRect.init( uiSearchRange, rcMv, m_cMin, m_cMax );

 

  pucYSearch  = pucYRef - iYStride * (cSearchRect.iNegVerLimit); //计算Y的初始搜索地址

 

  for(  y = -cSearchRect.iNegVerLimit; y <= cSearchRect.iPosVerLimit; y++ )

  {

    for( x = -cSearchRect.iNegHorLimit; x <= cSearchRect.iPosHorLimit; x++ )

    {

     //JVT-W080 BUG_FIX

     if( OmitPDISearch( x, y+rcMv.getVer(),false ) )

         continue;

     //~JVT-W080 BUG_FIX

      m_cXDSS.pYSearch  = pucYSearch + x;                    //分别计算搜索块的YUV地址

      m_cXDSS.pUSearch  = pucURef + (y>>1)*iCStride + (x>>1);

      m_cXDSS.pVSearch  = pucVRef + (y>>1)*iCStride + (x>>1);

 

      uiSad  = m_cXDSS.Func( &m_cXDSS );                 //计算当前块和搜索块的绝对误差和

      uiSad += xGetCost( x, y);                         //这个是干什么的?先加上,后面又减了?

 

      if( ruiSAD > uiSad )                         //更新绝对误差最小的块和块的地址

      {

        ruiSAD = uiSad;

        rcMv.setVer( y );

        rcMv.setHor( x );

      }

    }

    pucYSearch += iYStride;                        //Y的宽度,即切换到下一行

  }

 

 

  y = rcMv.getVer();

  x = rcMv.getHor();

 

  ruiSAD -= xGetCost( x, y);                   //减了?到底是什么情况?

 

  DO_DBG( m_cXDSS.pYSearch = pucYRef +  y     * iYStride +  x     );

  DO_DBG( m_cXDSS.pUSearch = pucURef + (y>>1) * iCStride + (x>>1) );

  DO_DBG( m_cXDSS.pVSearch = pucVRef + (y>>1) * iCStride + (x>>1) );

  uiSad  = m_cXDSS.Func( &m_cXDSS );

  AOF_DBG( ruiSAD == ( uiSad  = m_cXDSS.Func( &m_cXDSS ) ) );

}

 

上段代码有三个地方我还是不是很清楚:

1:  rcMv.limitComponents( m_cMin, m_cMax );     

   rcMv >>= 2;

2:   SearchRect cSearchRect;

 

 

 

 

 

 

 

 

   cSearchRect.init( uiSearchRange, rcMv, m_cMin, m_cMax );

3:  y = rcMv.getVer();

   x = rcMv.getHor();

希望看到并了解其中含义的大牛们解释下

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值