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