[置顶] 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所包含的总的像素数计算参考图像与原始图像的像素差的绝对值的总和。

 

你可能感兴趣的:(hm,HEVC,DistParam,xTZSearchHelp,setDistParam)