HEVC代码学习17:m_filteredBlockTmp[]和m_filteredBlock[][]

在之前的运动估计的亚像素搜索中,提到了插值之后的数据存放在m_filteredBlock[][]中,最近在学习中,发现其中涉及很多问题,不容易研究明白一些,记录一下。

基本结构

m_filteredBlockTmp[]大小为4,m_filteredBlock[][]大小为4x4,类型为TComYuv。

//LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS = 4
  TComYuv m_filteredBlock[LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS][LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS];
  TComYuv m_filteredBlockTmp[LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS];

看下TComYuv类的基本成员,其中m_apiBuf[MAX_NUM_COMPONENT]用来存储像素信息,还存储有YUV的长、宽、格式参数。

/// general YUV buffer class
class TComYuv
{
private:
  Pel*    m_apiBuf[MAX_NUM_COMPONENT];//存储像素
  UInt     m_iWidth;
  UInt     m_iHeight;
  ChromaFormat m_chromaFormatIDC; ////< Chroma Format
}

两者的用途分析

1.m_filteredBlockTmp[]

由名字可以看出,是个临时的中间量。实际用于存储水平插值得到的各像素位置的YUV信息。[]中的数字指示水平插值的像素位置。
在1/2像素插值xExtDIFUpSamplingH中,有这样的操作:

  Pel *srcPtr = pattern->getROIY() - halfFilterSize*srcStride - 1;      

  m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, m_filteredBlockTmp[0].getAddr(COMPONENT_Y), intStride, width+1, height+filterSize, 0, false, chFmt, pattern->getBitDepthY());
  m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, m_filteredBlockTmp[2].getAddr(COMPONENT_Y), intStride, width+1, height+filterSize, 2, false, chFmt, pattern->getBitDepthY());

对参考图像进行水平插值,整像素位置直接复制给了m_filteredBlockTmp[0],1/2像素位置插值后给了m_filteredBlockTmp[2]。
在1/4像素插值xExtDIFUpSamplingQ中类似,1/4和3/4像素位置水平插值后给了m_filteredBlockTmp[1]和m_filteredBlockTmp[3]。

2.m_filteredBlock[][]
在做完水平插值之后,会进行垂直插值,得到最终的数据,存储与m_filteredBlock[][]中。第一个[]中的数字指示垂直插值位置,第二个指示水平插值位置。
例如下面的代码,将1/4像素水平插值后的m_filteredBlockTmp[1],进行1/4像素垂直插值,最终数据存储在m_filteredBlock[1][1]中。

  // Generate @ 1,1
  intPtr = m_filteredBlockTmp[1].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride;
  dstPtr = m_filteredBlock[1][1].getAddr(COMPONENT_Y);
  if (halfPelRef.getVer() == 0)
  {
    intPtr += intStride;
  }
  m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 1, false, true, chFmt, pattern->getBitDepthY());

处理中的问题

这些问题是我在具体学习中遇到的,搞了好久才弄明白点,不清楚具体是否正确,记录下,如果有错误望指正。

1.m_filteredBlockTmp[]的大小
水平插值时,生成的m_filteredBlockTmp大小都是width+1, height+filterSize,是为了包含插值滤波器插值时需要使用到的所有数据。垂直方向上为上下留出halfFilterSize行数据,插值时要用。

2.m_filteredBlock[][]的大小
垂直插值中,不同位置的m_filteredBlock[][]大小不同,会看到m_filteredBlock[2][0]和m_filteredBlock[2][2]的大小为width+1, height+1,m_filteredBlock[0][2]的大小为width+1, height。
这样做是为了在之后的xPatternRefinement操作中便于对正负位置进行操作,因此多保留了一行或一列,为负位置。

你可能感兴趣的:(HEVC,HM,HEVC代码学习)