上一篇我們講到了ZigZag掃描,經過這一掃描之後,發現原本是4*4的像素矩陣,就變成了一連串的數字,可以說是二維到一維的一個轉換吧,而且經過ZigZag掃描後,一連串的數字的最後大部分爲0,以及一些+1,-1。針對這一系列的數字,從概率的角度,再進行一次編碼,這個過程稱之爲熵編碼,熵編碼主要分爲CAVLC,和CABAC,分別代表基於上下文的自適應可變長編碼和基於上下文的自適應二進制算術編碼,本節介紹CAVLC。
一、簡介
CAVLC(Context-Adaptive Variable Length Coding), 基於上下文的自適應可變長編碼,主要通過對ZigZag掃描後的序列中的非零值的個數,+1, -1的個數等進行編碼。
二、名詞解釋:
TotalCoffes: 代表ZigZag掃描後序列中非0值的個數;
TrailingOnes: 又稱做拖尾係數,代表ZigZag掃描後序列中+1,和-1的總個數,如果超過3,則爲3,在ZigZag掃描序列中從右到左選取三個,作爲拖尾係數;
TotalZeros: 最後一個非零係數前零的數目;
NC:用來決策coeff如何編碼的變量;
ZerosLeft: 當前係數之前所有的0的個數;
RunBefore: 緊鄰當前係數的0的個數;
三、編碼分析準備
上述矩陣來自H264白皮書的示例,權且以該矩陣作爲經過變換量化後表示的示例,演示編碼過程,首先對其進行ZigZag掃描,得到序列
0, 3,0,1,-1,-1,0,1,0,0,0,0,0,0,0,0
很顯然:TotalCoffes = 5,即掃描後序列中有5個非零值;
TraillingOnes = 3,即+1,-1的個數,從右到左分別是1, -1,-1,由於TrailingOnes最大值爲3,因此爲3.
TotalZeros = 3,即最後一個非零元素之前零的個數爲3.
四、編碼詳細過程
1. 編碼coeff_token:
coeff_token根據TotalCoffes,TrailiingOnes以及NC而確定,NC如何去確定這裏不贅述,此處先假設NC = 1, 然後去查表 (標準Table 9-5),可以看到:
從表中可以看出,coeff_token部分編碼爲: 0000 100,整個編碼的序列同樣也是0000 100。
2. 編碼Traillingones:
對於拖尾部分的編碼,用0表示+1,1表示-1,從右到左依次編碼爲011,此時編![](
3.編碼除拖尾以外的非零係數的level(ZigZag逆序,從右到左):
非零係數的level編碼首先將非零係數從有符號變成無符號,算法如下:
如果level > 0: level = level << 1 - 2
如果level < 0: level = -(level << 1) - 1
然後根據level_prefix去查表如何編碼,而level_prefix的計算公式是:
level_prefix = levelcode / (1 << suffix_length)
得到level_prefix之後通過查表即可以獲得對應該如何編碼。
Suffix_length表示的是level編碼後綴的長度,後綴用0填充,長度爲多少就填充多少個0。初始值爲0,如果非零係數 > 10且 拖尾數目 < 1的時候,suffix_length初始值爲1,suffix_length變化更新的算法爲:
if(suffix_length == 0)
suffix_length++;
else if(level > 3 << (suffix_length - 1) && suffix_length < 6)
suffix_length++;
來來來:
除拖尾外非零係數從左到右分別爲1, 3.
編碼“1”:
level = 1 << 1 - 2 = 0;
level_prefix = 0 / (1 << 0) = 0;
此時suffix_length == 0,沒有後綴,同時suffix_lengt++,suffix_length = 1.
查表,level_prefix = 0時,編碼爲“1”,且suffix_length = 0,無後綴,此時編碼的序列爲:
0000 100 || 011 | 1。
編碼“3”:
level = 3 << 1 - 2 = 4;
level_prefix = level / (1 << suffix_length) = 4 / (1 << 1) = 2 ;
level_prefix = 2, 編碼爲“001”,且suffix_length = 1, 填充1位“0”,此時的編碼序列爲:
0000 100 || 011 | 1 | 0010
此時,非零係數的level編碼結束。
4.編碼最後一個非零係數前的0的個數:
TotalZeros = 3, TotalCoeffs = 5, 接着查表嘍:
![](http://i2.51cto.com/images/blog/201802/05/9346dbf09b36718c34641d1eacd1d870.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
根據表9-7,得知,此部分編碼爲“111”,此時的編碼序列爲:
0000 100 || 011 | 1 | 0010 | 111
5. 對每個非零係數前零的個數進行編碼,依舊採用ZigZag逆序:
整個序列中非零的係數按照ZigZag逆序分別爲 1, -1, -1, 1, 3。分別編碼。
![](http://i2.51cto.com/images/blog/201802/05/db6685956ab284313b82a3aa169eaee7.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
對1編碼: zerosLeft = 3, run_before = 1, 編碼爲“10”;
對-1編碼: zerosLeft = 2, run_before = 0, 編碼爲“1”;
對-1編碼: zerosLeft = 2, run_before = 0, 編碼爲“1”
對1編碼: zerosLeft = 2, rub_before = 1, 編碼爲“01”
對3編碼: zerosLeft = 1, run_before = 1, 最後一個元素不需要編碼。
此時編碼的序列爲:
0000 100 | 011 | 1 | 0010 | 111 | 101101。
此時整個熵編碼的過程也就結束了,有沒有很暈,有沒有很累,木有事,慢慢來,一小步一小步的慢慢研究,這是一個循序漸進的過程,稍事休息,接下來咱們研究熵編碼之CABAC.