1. 程式人生 > >H.264---CAVLC---實戰篇

H.264---CAVLC---實戰篇

轉自:https://blog.csdn.net/jubincn/article/details/6948334

再次宣告:文中用的標準是BS的正式標準,如果大家發現序號不對,參考著改過來就是了!

編碼過程:
假設有一個4*4資料塊
{
   0,   3,   -1,   0,
   0,   -1,   1,   0,
   1,   0,   0,   0,
   0,   0,    0,   0
}
資料重排列:0,3,0,1,-1,-1,0,1,0……

1)初始值設定:
非零係數的數目(TotalCoeffs) = 5;
拖尾係數的數目(TrailingOnes)= 3;
最後一個非零係數前零的數目(Total_zeros) = 3;
變數NC=1;
(說明:NC值的確定:色度的直流係數NC=-1;其他係數型別NC值是根據當前塊左邊4*4塊的非零係數數目(NA)當前塊上面4*4塊的非零係數數目(NB)求得的,見畢厚傑書P120表6.10)
suffixLength = 0;
i = TotalCoeffs = 5;
2)編碼coeff_token:
查標準(BS ISO/IEC 14496-10:2003)Table 9-5,可得:
If (TotalCoeffs == 5 && TrailingOnes == 3 && 0 <= NC < 2

)
      coeff_token = 0000 100;
      Code = 0000 100;
3)編碼所有TrailingOnes的符號:
逆序編碼,三個拖尾係數的符號依次是+(0),-(1),-(1);
即:
TrailingOne sign[i--] = 0;
TrailingOne sign[i--] = 1;
TrailingOne sign[i--] = 1;
Code = 0000 1000 11
;
4)編碼除了拖尾係數以外非零係數幅值Levels:
過程如下:
(1)將有符號的Level[i]轉換成無符號的levelCode;
如果Level[i]是正的,levelCode = (Level[i]<<1) – 2; 
如果Level[i]是負的,levelCode = - (Level[i]<<1) – 1;
(2)計算level_prefix(字首):level_prefix = levelCode / (1<<suffixLength);
       查表9-6可得所對應的bit string;
(3)計算level_suffix(字尾):level_suffix = levelCode % (1<<suffixLength);
(4)根據suffixLength的值來確定字尾的長度;
(5)suffixLength updata:
If ( suffixLength == 0 )
suffixLength++;
         else if ( levelCode > (3<<suffixLength-1) && suffixLength <6)
            suffixLength++;

回到例子中,依然按照逆序,Level[i--] = 1;(此時i = 1)
levelCode = 0;level_prefix = 0;
查表9-6,可得level_prefix = 0時對應的bit string = 1;
因為suffixLength初始化為0,故該Level沒有後綴;
因為suffixLength = 0,故suffixLength++;
Code = 0000 1000 111
編碼下一個Level:Level[0] = 3;
levelCode = 4;level_prefix = 2;查表得bit string = 001
level_suffix = 0;suffixLength = 1;故碼流為0010;
Code = 0000 1000 1110 010;
i = 0,編碼Level結束。
5)編碼最後一個非零係數前零的數目(TotalZeros):
   查表9-7,當TotalCoeffs = 5,total_zero = 3時,bit string = 111;
   Code = 0000 1000 1110 0101 11;
6)對每個非零係數前零的個數(RunBefore)進行編碼:
i = TotalCoeffs = 5;ZerosLeft = Total_zeros = 3;查表9-10:
依然按照逆序編碼
ZerosLeft =3, run_before = 1         run_before[4]=10;
ZerosLeft =2, run_before = 0         run_before[3]=1;
ZerosLeft =2, run_before = 0         run_before[2]=1;
ZerosLeft =2, run_before = 1         run_before[1]=01;
ZerosLeft =1, run_before = 1         run_before[0]不需要碼流來表示
Code = 0000 1000 1110 0101 1110 1101;
編碼完畢。