1. 程式人生 > >HEVC幀間預測之五——運動估計(二)

HEVC幀間預測之五——運動估計(二)

分析xTZSearch這個函式,xTZSearchHelp是當中最為重要的子函式之一。它實現最基本的功能:根據輸入的搜尋點座標,參考影象首地址,原始影象首地址,以及當前PU大小等相關資訊,計算出SAD,並與之前儲存的最佳值進行比較,更新到目前為止的最佳值相關引數,如uiBestSad,搜尋點座標,搜尋步長等。其他的函式如xTZ8PointSearch等搜尋函式,最終都是呼叫xTZSearchHelp進行誤差匹配的。因此,我們有必要先來了解xTZSearchHelp這個函式:

__inline Void TEncSearch::xTZSearchHelp( TComPattern* pcPatternKey, IntTZSearchStruct& rcStruct, const Int iSearchX, const Int iSearchY, const UChar ucPointNr, const UInt uiDistance )
{
  UInt  uiSad;
  
  Pel*  piRefSrch;
  
  piRefSrch = rcStruct.piRefY + iSearchY * rcStruct.iYStride + iSearchX; //!< 參考影象Y分量的起始地址
  
  //-- jclee for using the SAD function pointer
  m_pcRdCost->setDistParam( pcPatternKey, piRefSrch, rcStruct.iYStride,  m_cDistParam );//!< 該函式主要職能是設定計算SAD的函式指標,下面會更為詳細地分析該函式
  
  // fast encoder decision: use subsampled SAD when rows > 8 for integer ME
  if ( m_pcEncCfg->getUseFastEnc() )
  {
    if ( m_cDistParam.iRows > 8 )
    {
      m_cDistParam.iSubShift = 1;
    }
  }

  setDistParamComp(0);  // Y component

  // distortion
  m_cDistParam.bitDepth = g_bitDepthY; //!< 位深
  uiSad = m_cDistParam.DistFunc( &m_cDistParam ); //!< 計算SAD
  
  // motion cost
  uiSad += m_pcRdCost->getCost( iSearchX, iSearchY ); //!< 考慮上mv本身帶來的開銷
  
  if( uiSad < rcStruct.uiBestSad ) //!< 更新最佳值
  {
    rcStruct.uiBestSad      = uiSad; //!< SAD
    rcStruct.iBestX         = iSearchX; //!< mv_x
    rcStruct.iBestY         = iSearchY; //!< mv_y
    rcStruct.uiBestDistance = uiDistance; //!< 搜尋步長
    rcStruct.uiBestRound    = 0; //!< 搜尋次數
    rcStruct.ucPointNr      = ucPointNr;  //!< 搜尋點序號
  }
}
// Setting the Distortion Parameter for Inter (ME)
Void TComRdCost::setDistParam( TComPattern* pcPatternKey, Pel* piRefY, Int iRefStride, DistParam& rcDistParam )
{
  // set Original & Curr Pointer / Stride
  rcDistParam.pOrg = pcPatternKey->getROIY(); //!< 感興趣區即待搜尋的原始影象首地址
  rcDistParam.pCur = piRefY;	//!< 參考影象首地址
  
  rcDistParam.iStrideOrg = pcPatternKey->getPatternLStride(); //!< 原始影象跨度
  rcDistParam.iStrideCur = iRefStride;	//!< 參考影象跨度
  
  // set Block Width / Height
  rcDistParam.iCols    = pcPatternKey->getROIYWidth();	//!< PU寬度
  rcDistParam.iRows    = pcPatternKey->getROIYHeight();	//!< PU高度
  rcDistParam.DistFunc = m_afpDistortFunc[DF_SAD + g_aucConvertToBit[ rcDistParam.iCols ] + 1 ]; //!< 根據PU的大小選擇相應的失真計算函式
  
#if AMP_SAD //!< 為非對稱分割槽AMP預測模式提供專用的失真函式
  if (rcDistParam.iCols == 12)
  {
	  rcDistParam.DistFunc = m_afpDistortFunc[43 ]; //!< TComRdCost::xGetSAD12
  }
  else if (rcDistParam.iCols == 24)
  {
    rcDistParam.DistFunc = m_afpDistortFunc[44 ]; //!< TComRdCost::xGetSAD24
  }
  else if (rcDistParam.iCols == 48)
  {
    rcDistParam.DistFunc = m_afpDistortFunc[45 ]; //!< TComRdCost::xGetSAD48
  }
#endif

  // initialize
  rcDistParam.iSubShift  = 0; //!< (vertical) subsampling shift (for reducing complexity)
}
/// distortion parameter class
class DistParam
{
public:
  Pel*  pOrg;	//!< 原始影象首地址
  Pel*  pCur;	//!< 參考影象首地址
  Int   iStrideOrg;	 //!< 原始影象跨度
  Int   iStrideCur;	 //!< 參考影象跨度
  Int   iRows;	//!< PU的寬度
  Int   iCols;	//!< PU的高度
  Int   iStep;	
  FpDistFunc DistFunc; //!< 計算失真的函式指標
  Int   bitDepth;	//!< 位深

  Bool            bApplyWeight;     // whether weithed prediction is used or not
  wpScalingParam  *wpCur;           // weithed prediction scaling parameters for current ref
  UInt            uiComp;           // uiComp = 0 (luma Y), 1 (chroma U), 2 (chroma V)

#if NS_HAD
  Bool            bUseNSHAD;
#endif

  // (vertical) subsampling shift (for reducing complexity)
  // - 0 = no subsampling, 1 = even rows, 2 = every 4th, etc.
  Int   iSubShift; //!< 下采樣
  
  DistParam()
  {
    pOrg = NULL;
    pCur = NULL;
    iStrideOrg = 0;
    iStrideCur = 0;
    iRows = 0;
    iCols = 0;
    iStep = 1;
    DistFunc = NULL;
    iSubShift = 0;
    bitDepth = 0;
#if NS_HAD
    bUseNSHAD = false;
#endif
  }
};


具體的SAD計算函式這裡不一一列舉,功能其實很簡單,就是根據PU所包含的總的畫素數計算參考影象與原始影象的畫素差的絕對值的總和。