【HEVC学习与研究】44、HEVC量化系数的解析——反量化过程

来源:互联网 发布:手机水印软件下载 编辑:程序博客网 时间:2024/05/06 09:14

【同其他模块一样,HEVC标准文档中只实现了反量化过程,量化过程交由编码器实现。这样可使得编码器采用如自适应量化AQ、率失真优化量化RDOQ等更优的量化方法。这里首先简要记录标准文档的实现,然后再在参考代码中寻找对应的实现。具体可参见标准文档8.6.3】

1、输入与输出数据

反量化过程的输入数据主要有:
①(xTbY,yTbY):当前亮度TB的左上顶点相对于整帧左上顶点的相对位置坐标;
②nTbS:以边长表示当前TB的大小;
③cIdx:表示当前TB所属的颜色分量;
④qP:表示所选量化参数。
该过程的输出数据主要有:
反量化之后的变换系数矩阵d[x][y],大小为(nTbS)×(nTbS)。


2、数据推导过程

(1)变量bdShift

如果cIdx ==0 (为亮度分量),则bdShift = BitDepthY + log2(nTbS) - 5;

如果cIdx !=0 (为色度分量),则bdShift = BitDepthC + log2(nTbS) - 5;

(2)量化系数level列表levelScale

该列表指定为levelScale[i] = {40, 45, 51, 57, 64, 72}, i∈[0,5]。

(3)量化矩阵m[x][y]

①如果标志位scaling_list_enabled_flag为0,则m[x][y]=16;

②若scaling_list_enabled_flag为1,则m[x][y]=ScalingFactor[sizeId][matrixId][x][y];其中,sizeId表示TB大小的索引值,对于4×4、8×8、16×16、32×32分别为0、1、2、3;matrixId表示矩阵的索引,依据是sizeId、CuPredMode和cIdx(也就是块尺寸、预测模式和颜色分量)。

(4)量化系数d[x][y]

d[x][y] = Clip3( −32768, 32767, ( ( TransCoeffLevel[ xTbY ][ yTbY ][ cIdx ][ x ][ y ] * m[ x ][ y ] * levelScale[ qP%6 ] << (qP / 6 ) ) + ( 1 << ( bdShift − 1 ) ) ) >> bdShift )。
即变换系数由量化后的变换系数与变换矩阵、量化系数列表、qp和偏移值等数据计算得到,并且取值范围限制于[-32768,32767]之间。

实现方法:

Void TComTrQuant::xDeQuant(Int bitDepth, const TCoeff* pSrc, Int* pDes, Int iWidth, Int iHeight, Int scalingListType ){    const TCoeff* piQCoef   = pSrc;  Int*   piCoef    = pDes;    if ( iWidth > (Int)m_uiMaxTrSize )  {    iWidth  = m_uiMaxTrSize;    iHeight = m_uiMaxTrSize;  }    Int iShift,iAdd,iCoeffQ;  UInt uiLog2TrSize = g_aucConvertToBit[ iWidth ] + 2;  Int iTransformShift = MAX_TR_DYNAMIC_RANGE - bitDepth - uiLog2TrSize;  iShift = QUANT_IQUANT_SHIFT - QUANT_SHIFT - iTransformShift;  /*  因此iShift的实际取值为  iShift = bitDepth + uiLog2TrSize + (QUANT_IQUANT_SHIFT(20) - QUANT_SHIFT(14) -MAX_TR_DYNAMIC_RANGE(15)) = bitDepth + uiLog2TrSize - 9 = bdShift - 4;  */  TCoeff clipQCoef;  if(getUseScalingList())//默认为false  {    //......      }  else  {    iAdd = 1 << (iShift-1);    Int scale = g_invQuantScales/*levelScale[]数组*/[m_cQP.m_iRem/*qp%6*/] << m_cQP.m_iPer/*qp/6*/;    for( Int n = 0; n < iWidth*iHeight; n++ )    {      clipQCoef = Clip3( -32768, 32767, piQCoef[n] );      iCoeffQ = ( clipQCoef * scale + iAdd ) >> iShift;  /*  实际取值iCoeffQ = ( clipQCoef * scale + 1 << (iShift-1) ) >> iShift; = ( clipQCoef * g_invQuantScales[m_cQP.m_iRem] << m_cQP.m_iPer + 1 << (iShift-1) ) >> iShift; = ( clipQCoef * g_invQuantScales[m_cQP.m_iRem] << m_cQP.m_iPer + 1 << (bdShift - 4 - 1) ) >> (bdShift - 4); = ( clipQCoef * 2^4 *g_invQuantScales[m_cQP.m_iRem] << m_cQP.m_iPer + 1 << (bdShift - 1) ) >> bdShift;  由于scaling_list_enabled_flag默认为false,因此m[x][y]默认为16,即公式中的2^4。  */      piCoef[n] = Clip3(-32768,32767,iCoeffQ);    }  }}


0 0