转载

HEVC sad计算函数 – FindSpace

Introduction

HEVC学习笔记目录

本文主要简单追一下sad的计算函数,是如何调用,以及做简单注释。

TZSearch

tzsearch函数是帧间预测中一个很重要的函数,以后再重新梳理这个函数。

在tzsearch中,可以看到start search部分,根据不同的配置,进行调用不同的search函数, xTZ8PointDiamondSearchxTZ8PointSquareSearchxTZSearchHelp 等,这些函数又都是最后调用了 xTZSearchHelp 函数,

xTZSearchHelp是当中最为重要的子函数之一。它实现最基本的功能:根据输入的搜索点坐标,参考图像首地址,原始图像首地址,以及当前PU大小等相关信息,计算出SAD,并与之前保存的最佳值进行比较,更新到目前为止的最佳值相关参数,如uiBestSad,搜索点坐标,搜索步长等。其他的函数如xTZ8PointSearch等搜索函数,最终都是调用xTZSearchHelp进行误差匹配的。

setDistParam 设置sad函数

在tzsearchhelp里,

m_pcRdCost->setDistParam( pcPatternKey, piRefSrch, rcStruct.iYStride,  m_cDistParam );//!< 该函数主要职能是设置计算SAD的函数指针, 

然后在下面的

      Distortion uiTempSad = m_cDistParam.DistFunc( &m_cDistParam );  

这里调用函数进行计算。这里用的是函数指针。

而在setDistParam里,主要是 rcDistParam.DistFunc = m_afpDistortFunc[DF_SAD12]; 类似这样的语句,在根据不同PU的大小进行设置函数。

找到 DF_SAD12 的定义的地方,在TypeDef.h里,集合DFunc的定义。

enum DFunc {   DF_DEFAULT         = 0, ...    DF_SAD             = 8,      ///< general size SAD   DF_SAD4            = 9,      ///<   4xM SAD   DF_SAD8            = 10,     ///<   8xM SAD   DF_SAD16           = 11,     ///<  16xM SAD   DF_SAD32           = 12,     ///<  32xM SAD   DF_SAD64           = 13,     ///<  64xM SAD   DF_SAD16N          = 14,     ///< 16NxM SAD ...   DF_TOTAL_FUNCTIONS = 64 }; 

m_afpDistortFunc 则是定义在这里的:

//TComRdCost.h about line 111 /// RD cost computation class class TComRdCost { private:   // for distortion   FpDistFunc              m_afpDistortFunc[DF_TOTAL_FUNCTIONS]; // [eDFunc] 

对于这个数组的初始化则是在这里,进行了函数和函数指针数组的绑定:

//TComRdCost.cpp line 120 // Initalize Function Pointer by [eDFunc] Void TComRdCost::init() {   m_afpDistortFunc[DF_DEFAULT] = NULL;                  // for DF_DEFAULT  。。。   m_afpDistortFunc[DF_SAD    ] = TComRdCost::xGetSAD;   m_afpDistortFunc[DF_SAD4   ] = TComRdCost::xGetSAD4;   m_afpDistortFunc[DF_SAD8   ] = TComRdCost::xGetSAD8;   m_afpDistortFunc[DF_SAD16  ] = TComRdCost::xGetSAD16; 。。。 

xGetSAD函数

xGetSAD和函数xGetSAD4等的区别就是一次计算一行的几个元素,比如8×4的PU,宽8高4,那么应该设置为SAD8函数,每次计算一行的8个元素。对于sad函数,大概的注释

Distortion TComRdCost::xGetSAD4( DistParam* pcDtParam ) {   if ( pcDtParam->bApplyWeight )   {     return TComRdCostWeightPrediction::xGetSADw( pcDtParam );   }   const Pel* piOrg   = pcDtParam->pOrg;//原图像的首地址   const Pel* piCur   = pcDtParam->pCur;//当前参考帧PU块的首地址   Int  iRows   = pcDtParam->iRows;//不知道为什么用rows,从代码来看应该是宽度   Int  iSubShift  = pcDtParam->iSubShift;   Int  iSubStep   = ( 1 << iSubShift );//每次计算一行的几个元素   Int  iStrideCur = pcDtParam->iStrideCur*iSubStep;//原图像的跨度   Int  iStrideOrg = pcDtParam->iStrideOrg*iSubStep;//当前参考帧图像的跨度    Distortion uiSum = 0;    for( ; iRows != 0; iRows-=iSubStep )   {     uiSum += abs( piOrg[0] - piCur[0] );     uiSum += abs( piOrg[1] - piCur[1] );     uiSum += abs( piOrg[2] - piCur[2] );     uiSum += abs( piOrg[3] - piCur[3] ); //都是在整个帧中的地址,所以需要加上跨度     piOrg += iStrideOrg;     piCur += iStrideCur;   }    uiSum <<= iSubShift;   return ( uiSum >> DISTORTION_PRECISION_ADJUSTMENT(pcDtParam->bitDepth-8) ); } 

声明:

文章若无说明转载,均为FindSpace博客原创,如需转载,请注明出处FindSpace博客!

原文  http://www.findspace.name/easycoding/1544
正文到此结束
Loading...