[置顶] HEVC学习(十三) —— SAO函数解析之一

关于SAO的原理和流程的解析,已经在我转载的一篇博客HEVC中SAO--自适应样点补偿 详细分析解读有了比较清楚的介绍了,本文就不再重复这个过程,而把主要精力放在具体函数实现的解析上。在我自己的一篇博客HEVC学习(八) —— 以SAO为例浅析跟踪代码方法里其实也作了相关的铺垫了,当中重点放在跟踪代码的方法上,本文在此基础上对重要的函数进行解析,它们的调用位置这里就不提了,有关这部分的内容请参考前述的两篇博客。

本文首先介绍

m_cEncSAO.create( getSourceWidth(), getSourceHeight(), g_uiMaxCUWidth, g_uiMaxCUHeight, _uiMaxCUDepth );

该函数为SAO的相关参数分配内存和初始化。

/** create SampleAdaptiveOffset memory.
 * \param 
 */
Void TComSampleAdaptiveOffset::create( UInt uiSourceWidth, UInt uiSourceHeight, UInt uiMaxCUWidth, UInt uiMaxCUHeight, UInt uiMaxCUDepth)
{
  m_iPicWidth  = uiSourceWidth;
  m_iPicHeight = uiSourceHeight;

  m_uiMaxCUWidth  = uiMaxCUWidth;
  m_uiMaxCUHeight = uiMaxCUHeight;

  m_iNumCuInWidth  = m_iPicWidth / m_uiMaxCUWidth;
  m_iNumCuInWidth += ( m_iPicWidth % m_uiMaxCUWidth ) ? 1 : 0;

  m_iNumCuInHeight  = m_iPicHeight / m_uiMaxCUHeight;
  m_iNumCuInHeight += ( m_iPicHeight % m_uiMaxCUHeight ) ? 1 : 0;
  //! 以下四句根据CU的实际尺寸计算可划分的最大深度
  Int iMaxSplitLevelHeight = (Int)(logf((Float)m_iNumCuInHeight)/logf(2.0));
  Int iMaxSplitLevelWidth  = (Int)(logf((Float)m_iNumCuInWidth )/logf(2.0));

  m_uiMaxSplitLevel = (iMaxSplitLevelHeight < iMaxSplitLevelWidth)?(iMaxSplitLevelHeight):(iMaxSplitLevelWidth);
  m_uiMaxSplitLevel = (m_uiMaxSplitLevel< m_uiMaxDepth)?(m_uiMaxSplitLevel):(m_uiMaxDepth);
  /* various structures are overloaded to store per component data.
   * m_iNumTotalParts must allow for sufficient storage in any allocated arrays */
  /*
  const Int TComSampleAdaptiveOffset::m_aiNumCulPartsLevel[5] =
  {
  1,   //level 0
  5,   //level 1
  21,  //level 2
  85,  //level 3
  341, //level 4
  };
  */
  m_iNumTotalParts  = max(3,m_aiNumCulPartsLevel[m_uiMaxSplitLevel]);

  UInt uiPixelRangeY = 1 << g_bitDepthY; //!< Y分量的像素范围(256 for 8it-depth)
  UInt uiBoRangeShiftY = g_bitDepthY - SAO_BO_BITS; //!< Band Offset (BO)中每个band的宽度(3 for 8bit-depth,即1<<3 = 8)(Y分量)

  m_lumaTableBo = new Pel [uiPixelRangeY]; //!< Y分量在BO模式下的索引表,根据像素值可以索引到对应的band序号
  for (Int k2=0; k2<uiPixelRangeY; k2++)
  {
    m_lumaTableBo[k2] = 1 + (k2>>uiBoRangeShiftY); //!< 总共分了32个band(1~32)
  }

  UInt uiPixelRangeC = 1 << g_bitDepthC; //!< CbCr分量的像素范围(256 for 8it-depth)
  UInt uiBoRangeShiftC = g_bitDepthC - SAO_BO_BITS; //!< Band Offset (BO)中每个band的宽度(3 for 8bit-depth,即1<<3 = 8)(CbCr分量)

  m_chromaTableBo = new Pel [uiPixelRangeC]; //!< CbCr分量在BO模式下的索引表,根据像素值可以索引到对应的band序号
  for (Int k2=0; k2<uiPixelRangeC; k2++)
  {
    m_chromaTableBo[k2] = 1 + (k2>>uiBoRangeShiftC); //!< 总共分了32个band(1~32)
  }

  m_iUpBuff1 = new Int[m_iPicWidth+2];
  m_iUpBuff2 = new Int[m_iPicWidth+2];
  m_iUpBufft = new Int[m_iPicWidth+2];

  m_iUpBuff1++;
  m_iUpBuff2++;
  m_iUpBufft++;
  Pel i;

  UInt uiMaxY  = (1 << g_bitDepthY) - 1; //!< Y分量像素最大值(255 for 8bit-depth)
  UInt uiMinY  = 0;

  Int iCRangeExt = uiMaxY>>1; //!< 对范围进行扩展

  m_pClipTableBase = new Pel[uiMaxY+2*iCRangeExt];
  m_iOffsetBo      = new Int[uiMaxY+2*iCRangeExt];

  for(i=0;i<(uiMinY+iCRangeExt);i++)
  {
    m_pClipTableBase[i] = uiMinY;
  }

  for(i=uiMinY+iCRangeExt;i<(uiMaxY+  iCRangeExt);i++)
  {
    m_pClipTableBase[i] = i-iCRangeExt;
  }

  for(i=uiMaxY+iCRangeExt;i<(uiMaxY+2*iCRangeExt);i++)
  {
    m_pClipTableBase[i] = uiMaxY;
  }
  //! 0 0 0 ... 0 1 2 3 4 ... 255 255 ... 255//!
  m_pClipTable = &(m_pClipTableBase[iCRangeExt]); //!< 查找表

  UInt uiMaxC  = (1 << g_bitDepthC) - 1; //!< CbCr分量像素最大值(255 for 8bit-depth)
  UInt uiMinC  = 0;

  Int iCRangeExtC = uiMaxC>>1; //!< 对范围进行扩展

  m_pChromaClipTableBase = new Pel[uiMaxC+2*iCRangeExtC];
  m_iChromaOffsetBo      = new Int[uiMaxC+2*iCRangeExtC];

  for(i=0;i<(uiMinC+iCRangeExtC);i++)
  {
    m_pChromaClipTableBase[i] = uiMinC;
  }

  for(i=uiMinC+iCRangeExtC;i<(uiMaxC+  iCRangeExtC);i++)
  {
    m_pChromaClipTableBase[i] = i-iCRangeExtC;
  }

  for(i=uiMaxC+iCRangeExtC;i<(uiMaxC+2*iCRangeExtC);i++)
  {
    m_pChromaClipTableBase[i] = uiMaxC;
  }
  //! 0 0 0 ... 0 ! 1 2 3 4 ... 255 255 ... 255 //!
  m_pChromaClipTable = &(m_pChromaClipTableBase[iCRangeExtC]); //!< 查找表,实际上与Y分量是相同的

  m_iLcuPartIdx = new Int [m_iNumCuInHeight*m_iNumCuInWidth];
  m_pTmpL1 = new Pel [m_uiMaxCUHeight+1];
  m_pTmpL2 = new Pel [m_uiMaxCUHeight+1];
  m_pTmpU1 = new Pel [m_iPicWidth];
  m_pTmpU2 = new Pel [m_iPicWidth];
}

直观起见,不妨把m_lumaTableBo和m_pClipTable的内容打印出来,

/* m_lumaTableBo */

1 	1 	1 	1 	1 	1 	1 	1 	
2 	2 	2 	2 	2 	2 	2 	2 	
3 	3 	3 	3 	3 	3 	3 	3 	
4 	4 	4 	4 	4 	4 	4 	4 	
5 	5 	5 	5 	5 	5 	5 	5 	
6 	6 	6 	6 	6 	6 	6 	6 	
7 	7 	7 	7 	7 	7 	7 	7 	
8 	8 	8 	8 	8 	8 	8 	8 	
9 	9 	9 	9 	9 	9 	9 	9 	
10	10	10	10	10	10	10	10	
11	11	11	11	11	11	11	11	
12	12	12	12	12	12	12	12	
13	13	13	13	13	13	13	13	
14	14	14	14	14	14	14	14	
15	15	15	15	15	15	15	15	
16	16	16	16	16	16	16	16	
17	17	17	17	17	17	17	17	
18	18	18	18	18	18	18	18	
19	19	19	19	19	19	19	19	
20	20	20	20	20	20	20	20	
21	21	21	21	21	21	21	21	
22	22	22	22	22	22	22	22	
23	23	23	23	23	23	23	23	
24	24	24	24	24	24	24	24	
25	25	25	25	25	25	25	25	
26	26	26	26	26	26	26	26	
27	27	27	27	27	27	27	27	
28	28	28	28	28	28	28	28	
29	29	29	29	29	29	29	29	
30	30	30	30	30	30	30	30	
31	31	31	31	31	31	31	31	
32	32	32	32	32	32	32	32	

/* m_pClipTable */

0   	1   	2   	3   	4   	5   	6   	7   	8   	9   	10  	11  	12  	13  	14  	15  	16  	17  	18  	19  	20  	21  	22  	23  	24  	25  	26  	27  	28  	29  	30  	31  	32  	33  	34  	35  	36  	37  	38  	39  	40  	41  	42  	43  	44  	45  	46  	47  	48  	49  	50  	51  	52  	53  	54  	55  	56  	57  	58  	59  	60  	61  	62  	63  	64  	65  	66  	67  	68  	69  	70  	71  	72  	73  	74  	75  	76  	77  	78  	79  	80  	81  	82  	83  	84  	85  	86  	87  	88  	89  	90  	91  	92  	93  	94  	95  	96  	97  	98  	99  	100 	101 	102 	103 	104 	105 	106 	107 	108 	109 	110 	111 	112 	113 	114 	115 	116 	117 	118 	119 	120 	121 	122 	123 	124 	125 	126 	127 	128 	129 	130 	131 	132 	133 	134 	135 	136 	137 	138 	139 	140 	141 	142 	143 	144 	145 	146 	147 	148 	149 	150 	151 	152 	153 	154 	155 	156 	157 	158 	159 	160 	161 	162 	163 	164 	165 	166 	167 	168 	169 	170 	171 	172 	173 	174 	175 	176 	177 	178 	179 	180 	181 	182 	183 	184 	185 	186 	187 	188 	189 	190 	191 	192 	193 	194 	195 	196 	197 	198 	199 	200 	201 	202 	203 	204 	205 	206 	207 	208 	209 	210 	211 	212 	213 	214 	215 	216 	217 	218 	219 	220 	221 	222 	223 	224 	225 	226 	227 	228 	229 	230 	231 	232 	233 	234 	235 	236 	237 	238 	239 	240 	241 	242 	243 	244 	245 	246 	247 	248 	249 	250 	251 	252 	253 	254 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	255 	

更直观的做法就是绘制出像素值vs索引值的曲线图来,不过根据这些数据,相信大家很容易就能想象出这两条曲线是何种形状的了,这里就不必要画出图来了。


 

你可能感兴趣的:(Sao,hm,HEVC,样点自适应偏移)