JMVM系列之三_JMVM2.1运动估计相关内容

本文介绍了JMVM2.1中运动矢量搜索类及其参数含义,并概述了运动估计类的功能,包括主要函数estimateBlockWithStart的流程。涵盖不同搜索模式、搜索范围设置及半像素搜索等关键技术。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

主题: JMVM2.1 运动估计相关内容
 
摘要:本文先介绍运动矢量搜索类,解释类中关于运动矢量搜索的参数含义和用法;接着介绍运动估计类,简要解释了其中的主要函数的作用;最后主要函数 MotionEstimation::estimateBlockWithStart 的流程,此函数包含了运动估计的整个流程。
MotionVectorSearchParams类,解释该类中运动矢量搜索的参数含义
class  H264AVCENCODERLIB_API MotionVectorSearchParams
{
public:
MotionVectorSearchParams() :  m_eSearchMode(FAST_SEARCH),  m_eFullPelDFunc(DF_SAD), m_eSubPelDFunc(DF_SAD), m_uiSearchRange(
64), m_uiDirectMode(0{} //具体默认参数的构造函数                
  
  ErrVal check() 
const;
const SearchMode getSearchMode()        const return m_eSearchMode; } 
 
//确定搜索模式Search Mode 0==Block,1==Spiral,2==Log,3==Fast, 4==NewFast
const DFunc getFullPelDFunc()           const return m_eFullPelDFunc; } 
//整像素搜索时的函数  Search Func (Full Pel) 0==SAD,1==SSE,2==Hadamard,3==YUV-SAD"  
const DFunc getSubPelDFunc()           const return m_eSubPelDFunc; }
//半像素搜索时的函数 Search Func (Sub Pel) 0==SAD,1==SSE,2==Hadamard"
    
  
const UInt getSearchRange()             const return m_uiSearchRange; }   //确定搜索范围
  UInt        getNumMaxIter  ()        const return m_uiNumMaxIter; }
  UInt        getIterSearchRange()       
const return m_uiIterSearchRange; }
const UInt getDirectMode()              const return m_uiDirectMode; }  
//Direct模式选择0==Temporal, 1==Spatial

  Void setSearchMode( UInt uiSearchMode )     
{ m_eSearchMode = SearchMode(uiSearchMode); }
  Void setFullPelDFunc( UInt uiFullPelDFunc )      
{ m_eFullPelDFunc = DFunc(uiFullPelDFunc); }
  Void setSubPelDFunc( UInt uiSubPelDFunc )       
{ m_eSubPelDFunc = DFunc(uiSubPelDFunc); }
  Void setSearchRange ( UInt uiSearchRange)       
{ m_uiSearchRange = uiSearchRange; }
  Void setNumMaxIter ( UInt uiNumMaxIter   )    
{ m_uiNumMaxIter      = uiNumMaxIter;     }
  Void setIterSearchRange   ( UInt uiIterSearchRange )  
{ m_uiIterSearchRange = uiIterSearchRange;  }
  Void setDirectMode( UInt uiDirectMode)             
{ m_uiDirectMode = uiDirectMode; }
public:
  SearchMode  m_eSearchMode;   
// 配置文件读取,默认值0==Block
  DFunc       m_eFullPelDFunc;  // 配置文件读取,默认值0==SAD
  DFunc       m_eSubPelDFunc;  // 配置文件读取,默认值0==SAD
  UInt        m_uiSearchRange;   // 配置文件读取,默认值96
  UInt        m_uiNumMaxIter;   // 配置文件读取,默认值4
  UInt        m_uiIterSearchRange; // 配置文件读取,默认值8
  UInt        m_uiDirectMode;    // 0 temporal, 1 spatial
}
;
运动估计类MotionEstimation 
class  MotionEstimation  :  public  MotionCompensation  ,  public  MotionEstimationCost
{
public:
  
class MEBiSearchParameters            //运动估计双向搜索参数
  {
  
public:
    IntYuvMbBuffer
* pcAltRefPelData;    // the prediction signal for the opposite list (not weighted)
    UInt            uiL1Search;         // 1 if current search is L1 search, else false
    const IntFrame* pcAltRefFrame;      // the reference frame of the opposite list
    const PW*       apcWeight[2];       // { list 0 prediction weight, list 1 prediction weight }
  }
;
protected:
  typedef 
struct
  
{
    Void init( Short sLimit, Mv
& rcMvPel, Mv cMin, Mv cMax)
    
{
      cMin 
>>= 2;
      cMax 
>>= 2;
      Short sPosV 
= cMax.getVer() - rcMvPel.getVer();
      Short sNegV 
= rcMvPel.getVer() - cMin.getVer();
      iNegVerLimit 
= min( sLimit, sNegV) - rcMvPel.getVer();
      iPosVerLimit 
= min( sLimit, sPosV) + rcMvPel.getVer();

      Short sPosH 
= cMax.getHor() - rcMvPel.getHor();
      Short sNegH 
= rcMvPel.getHor() - cMin.getHor();
      iNegHorLimit 
= min( sLimit, sNegH) - rcMvPel.getHor();
      iPosHorLimit 
= min( sLimit, sPosH) + rcMvPel.getHor();
    }

    Int iNegVerLimit;
    Int iPosVerLimit;
    Int iNegHorLimit;
    Int iPosHorLimit;
  }

SearchRect;                   
//结构体SearchRect,用于根据搜索范围确定搜索矩阵

  typedef 
struct
  
{
    XPel
* pucYRef;
    XPel
* pucURef;
    XPel
* pucVRef;
    Int   iYStride;
    Int   iCStride;
    Int   iBestX;
    Int   iBestY;
    UInt  uiBestRound;
    UInt  uiBestDistance;
    UInt  uiBestSad;
    UChar ucPointNr;

#if TMS_SE_MVC_IC
    IcpInMs sBestIcpInMs;
#endif

  }

  IntTZSearchStrukt;                  
//快速搜索TZ方法的一些参数

protected:
    MotionEstimation();              
//构造函数
    virtual ~MotionEstimation();       //析构函数

public:
  ErrVal destroy();
  
virtual ErrVal uninit();

  SampleWeighting
* getSW() return m_pcSampleWeighting; }

  ErrVal initMb( UInt uiMbPosY, UInt uiMbPosX, MbDataAccess
& rcMbDataAccess );  //宏块初始化

  
virtual ErrVal init(  XDistortion*  pcXDistortion,
                        CodingParameter
* pcCodingParameter,
                        RateDistortionIf
* pcRateDistortionIf,
                        QuarterPelFilter
* pcQuarterPelFilter,
                        Transform
*        pcTransform,
                        SampleWeighting
* pcSampleWeighting);
  UInt getRateCost ( UInt  uiBits,  Bool  bSad)  
{ xGetMotionCost( bSad, 0 ); return xGetCost( uiBits ); }
  ErrVal  estimateBlockWithStart( 
const MbDataAccess&   rcMbDataAccess,  // estimateBlockWithStart
                                  const IntFrame&       rcRefFrame,
                                  Mv
&         rcMv,         // <-- MVSTART / --> MV
                                  Mv&                   rcMvPred,
                                  UInt
&                 ruiBits,
                                  UInt
&                 ruiCost,
                                  UInt                  uiBlk,
                                  UInt                  uiMode,
                                  Bool                  bQPelRefinementOnly,
                                  UInt                  uiSearchRange,
                                  
const PW*             pcPW,
                                  MEBiSearchParameters
* pcBSP = 0 );
#if TMS_SE_MVC_IC
  ErrVal  estimateBlockWithStart( Icp
&                  rcIcp,
 
// ….   此函数与上面estimateBlockWithStart功能相同。
#endif
  
virtual ErrVal compensateBlock( IntYuvMbBuffer *pcRecPelData, UInt uiBlk, UInt uiMode, IntYuvMbBuffer *pcRefPelData2 = NULL ) = 0
DFunc getDistortionFunction() 
return m_cParams.getSubPelDFunc(); }  //块补偿函数

//TMM_WP
  Void setLstIdx( ListIdx eLstIdx) {m_eLstIdx = eLstIdx;}
  ListIdx getLstIdx() 
{return m_eLstIdx;}
//TMM_WP

protected:
//TZ快速搜索系列函数
  Void  xTZSearch   ( IntYuvPicBuffer *pcPelData, Mv& rcMv, UInt& ruiSAD, UInt uiSearchRange = 0 );
  __inline Void xTZSearchHelp         ( IntTZSearchStrukt
& rcStrukt, const Int iSearchX, const Int iSearchY, const UChar ucPointNr, const UInt uiDistance );
  __inline Void xTZ2PointSearch       ( IntTZSearchStrukt
& rcStrukt, SearchRect rcSearchRect );
  __inline Void xTZ8PointSquareSearch ( IntTZSearchStrukt
& rcStrukt, SearchRect rcSearchRect, const Int iStartX, const Int iStartY, const Int iDist );
  __inline Void xTZ8PointDiamondSearch( IntTZSearchStrukt
& rcStrukt, SearchRect rcSearchRect, const Int iStartX, const Int iStartY, const Int iDist );

  Void          xPelBlockSearch ( IntYuvPicBuffer 
*pcPelData, Mv& rcMv, UInt& ruiSAD,                              UInt uiSearchRange = 0 );    //块搜索函数Search Mode 0调用此函数
  Void          xPelSpiralSearch( IntYuvPicBuffer *pcPelData, Mv& rcMv, UInt& ruiSAD,                              UInt uiSearchRange = 0 );    //螺旋搜索函数Search Mode 1调用此函数
  Void          xPelLogSearch   ( IntYuvPicBuffer *pcPelData, Mv& rcMv, UInt& ruiSAD, Bool bFme,  UInt uiStep = 4, UInt uiSearchRange = 0 );   //对数搜索Search Mode 2调用此函数
  virtual Void  xSubPelSearch   ( IntYuvPicBuffer *pcPelData, Mv& rcMv, UInt& ruiSAD, UInt uiBlk, UInt uiMode,     Bool bQPelOnly ) = 0;    //半像素搜索函数

//TMM_WP
   Int getDistScaleFactor(Int iCurrPoc, Int iL0Poc, Int iL1Poc ) const;
//TMM_WP

#if TMS_SE_MVC_IC
// ….该模式下搜索模式比较少
#endif
protected:
  QuarterPelFilter
* m_pcQuarterPelFilter;
  MotionVectorSearchParams m_cParams;
  Int m_iMaxLogStep;
  Mv 
*m_pcMvSpiralSearch;
  UInt m_uiSpiralSearchEntries;
  Mv m_cLastPelMv;
  Mv  m_acMvPredictors[
3];

  XDistortion
*      m_pcXDistortion;
  XDistSearchStruct m_cXDSS;

//TMM_WP
  ListIdx m_eLstIdx;
//TMM_WP
}
;

// 主要函数MotionEstimation::estimateBlockWithStart的流程图
ErrVal
MotionEstimation::estimateBlockWithStart( 
const  MbDataAccess &   rcMbDataAccess,
                                    
const  IntFrame &       rcRefFrame,   // 参考帧
                                    Mv &              rcMv,          //  <-- MVSTART / --> MV
                                    Mv &                   rcMvPred,  // Pred Mv
                                    UInt &                 ruiBits,      // bits
                                    UInt &                 ruiCost,      // cost
                                    UInt                 uiBlk,
                                    UInt                 uiMode,      
// searchmode
                                    Bool                 bQPelRefinementOnly,
                                    UInt                 uiSearchRange, 
// searchrange
                                     const  PW *              pcPW,
                                    MEBiSearchParameters
*  pcBSP )
{
const LumaIdx    cIdx                 = B4x4Idx(uiBlk);
  IntYuvMbBuffer
*  pcWeightedYuvBuffer  = NULL;
  IntYuvPicBuffer
* pcRefPelData[2];
  IntYuvMbBuffer   cWeightedYuvBuffer;

  pcRefPelData[
0= const_cast<IntFrame&>(rcRefFrame).getFullPelYuvBuffer();
  pcRefPelData[
1= const_cast<IntFrame&>(rcRefFrame).getHalfPelYuvBuffer();

  m_pcXDistortion
->set4x4Block( cIdx );
  pcRefPelData[
0]->set4x4Block( cIdx );
  pcRefPelData[
1]->set4x4Block( cIdx );

  
if( bQPelRefinementOnly )rcMv = rcMvPred;

  UInt   uiMinSAD  
= MSYS_UINT_MAX;
  Mv     cMv       
= rcMv;
  Double fWeight   
= 1.0;
  Double afCW[
2]   = 1.01.0 };

  Bool      bOriginalSearchModeIsYUVSAD  
= ( m_cParams.getFullPelDFunc() == DF_YUV_SAD );
  
const Int iXSize                       = m_pcXDistortion->getBlockWidth  ( uiMode ); 
const Int iYSize                       = m_pcXDistortion->getBlockHeight ( uiMode );

if( pcBSP ) // bi prediction
  {
//…….双向预测
 }

  
else // unidirectional prediction 单向预测
  {

}

//===== FULL-PEL ESTIMATION ======
  if( bOriginalSearchModeIsYUVSAD && ( pcBSP /* bi-prediction */ || fWeight != afCW[0|| fWeight != afCW[1/* different component weights */ ) )
  
{
    m_cParams.setFullPelDFunc( DF_SAD ); 
// set to normal SAD
  }

  
// <<< heiko.schwarz@hhi.fhg.de (fix for uninitialized memory with YUV_SAD and bi-directional search)
  xGetMotionCost( ( 1 != m_cParams.getFullPelDFunc() ), 0 );
  m_pcXDistortion
->getDistStruct( uiMode, m_cParams.getFullPelDFunc(), false, m_cXDSS );
  m_cXDSS.pYOrg 
= pcWeightedYuvBuffer->getLumBlk();
  m_cXDSS.pUOrg 
= pcWeightedYuvBuffer->getCbBlk ();
  m_cXDSS.pVOrg 
= pcWeightedYuvBuffer->getCrBlk ();
  xSetPredictor( rcMvPred );
  xSetCostScale( 
2 );

if! bQPelRefinementOnly )  //这个参数不清楚
  {
    
if( uiSearchRange )
    
{
      xPelBlockSearch     ( pcRefPelData[
0], cMv, uiMinSAD, uiSearchRange );
    }

    
else
    
{
      
switch( m_cParams.getSearchMode() )
      
{
      
case 0:
        
{
          xPelBlockSearch ( pcRefPelData[
0], cMv, uiMinSAD );
        }

        
break;
      
case 1:
        
{
          xPelSpiralSearch( pcRefPelData[
0], cMv, uiMinSAD );
        }

        
break;
      
case 2:
   
{  xPelLogSearch   ( pcRefPelData[0], cMv, uiMinSAD, false, m_iMaxLogStep << ((NULL == pcBSP) ? 1 : 0) );
        }

        
break;
      
case 3:
        
{
          rcMbDataAccess.getMvPredictors( m_acMvPredictors );
          xPelLogSearch   ( pcRefPelData[
0], cMv, uiMinSAD, true, (NULL == pcBSP) ? 2 : 1 );
        }

        
break;
      
case 4:
        
{
          rcMbDataAccess.getMvPredictors( m_acMvPredictors );
          xTZSearch( pcRefPelData[
0], cMv, uiMinSAD );
        }

        
break;
      
default:
        RERR();
        
break;
      }

    }

    cMv 
<<= 2;
  }

  
else
  
{
    Mv cMvBase 
= cMv;
    cMv.limitComponents( m_cMin, m_cMax );
    
if! ( cMvBase == cMv ) )
    
{
      
// don't refine in that case
      rcMv     = cMvBase;
      ruiBits 
+= 2;
      ruiCost  
= MSYS_UINT_MAX / 2;
      
// >>>> bug fix by H.Schwarz 19/9/05
      if( bOriginalSearchModeIsYUVSAD )
      
{
        m_cParams.setFullPelDFunc( DF_YUV_SAD );
      }

      
// <<<< bug fix by H.Schwarz 19/9/05
      return Err::m_nOK;
    }

  }


//===== SUB-PEL ESTIMATION =====
  xGetMotionCost( 1 != ( 1 & m_cParams.getSubPelDFunc() ), 0 );
  m_pcXDistortion
->getDistStruct( uiMode, m_cParams.getSubPelDFunc(), false, m_cXDSS );
  m_cXDSS.pYOrg 
= pcWeightedYuvBuffer->getLumBlk();
  xSetCostScale( 
0 );

  xSubPelSearch( pcRefPelData[
1], cMv, uiMinSAD, uiBlk, uiMode, bQPelRefinementOnly );

  Short sHor      
= cMv.getHor();
  Short sVer      
= cMv.getVer();
  UInt  uiMvBits  
= xGetBits( sHor, sVer );
  ruiBits        
+= uiMvBits;
  ruiCost   
= (UInt)floor( fWeight * (Double)( uiMinSAD - xGetCost( uiMvBits ) ) ) + xGetCost( ruiBits );
  rcMv            
= cMv;

  
return Err::m_nOK;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值