量化矩陣的原理是對應不同位置的係數使用不同的量化系步長進行量化,人眼對高頻不敏感,對低頻分量進行小步長量化,對高頻分量進行大步長量化,在保證主觀質量的情況下,提高壓縮效率。HEVC支持量化矩陣,但是默認不啓用。HEVC的量化矩陣與TU大小相同,分爲4x4,8x8,16x16,32x32 4種尺寸。
HEVC可以使用兩種形式的量化矩陣:默認量化矩陣、自定義量化矩陣。下面來學習默認量化矩陣。
默認量化矩陣的定義
HEVC定義了4x4,8x8,16x16,32x32 4種尺寸的默認量化矩陣,其中8x8及以上 幀內、幀間使用不同矩陣。4x4、8x8幀內、8x8幀間的量化矩陣如下圖,16x16、32x32的矩陣由8x8矩陣插值得到,後邊會詳細說明計算過程。在TComRom
中定義,解碼端可以直接拿到,不需要傳輸。量化矩陣中的元素可以看作放縮係數,量化係數除以對應位置的元素得到最終的量化係數。
默認量化矩陣詳細推導過程推薦閱讀論文Adaptive Quantization Matrices for HD and UHD Display Resolutions in Scalable HEVC。
量化矩陣的作用
量化的公式如下:
abs(x)=(abs(d) * MF + f_temp) >> (qbits + T_Shift)
qbits = + floor(QP/6)
MF = 2^qbits / Qstep
f_temp = f << (qbits + T_Shift)
一般情況下,對於I幀,f=1/3,對於P、B幀,f=1/6,x是量化後的係數,d是量化之前的係數,MF
即量化係數,量化矩陣即根據位置改變MF
值。
編碼端量化係數矩陣的計算
編碼端,會在xInitScalingLists
中初始化量化矩陣,當ScalingListId
爲SCALING_LIST_DEFAULT
,即使用默認量化矩陣,會調用setScalingList
初始化默認量化矩陣。這裏也可以看到,默認量化矩陣是不需要在SPS和PPS裏傳的。
setScalingList
是設置量化係數矩陣的入口函數,遍歷4種尺寸、6種模式(Y/Cb/Cr、幀內/幀間)、6種qp(qp%6)設置量化矩陣。其中xSetScalingListEnc
計算量化矩陣,xSetScalingListDec
計算反量化矩陣,setErrScaleCoeff
這個沒具體看,應該是在反量化時用到。
xSetScalingListEnc
計算編碼端量化係數矩陣的入口函數,調用processScalingListEnc
計算量化矩陣。其中quantScales
即與QP%6對應的量化係數,quantScales[6]={26214,23302,20560,18396,16384,14564}
,爲保持精度,在傳給processScalingListEnc
時quantScales
根據TU尺寸放大4倍。
processScalingListEnc
中計算最終的量化係數矩陣。因爲之前quantScales
已經放大了4倍,這裏quantcoeff
實際等於quantScales*4
除以對應位置量化矩陣元素得到最終的量化係數,即量化矩陣元素16對應位置的量化係數不進行調整,大於16位置的係數會相應的縮小,使量化係數MF
變小。量化公式如下,MF
變小從而量化後的值會變小。
以8x8 intra爲例,量化矩陣各位置係數對MF
的改變情況如下,左上角16對應1.0000,即MF
不變;係數越大,會給MF
乘以更小的數,使MF
變小。
在HM中只存了4x4和8x8的矩陣,這裏通過對8x8插值計算16x16和32x32,插值過程很簡單,如下圖,對於16x16的矩陣,即使用8x8矩陣的一個係數填充2x2的區域,32x32的矩陣,即1個係數填充4x4的區域。
xSetScalingListDec
反量化矩陣與量化矩陣處理類似,不做具體介紹了。