【同其他模块一样,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); } } }