CABAC


 

CABAC(Context-based Adaptive Binary Arithmetic Coding),基於上下文的自適應二進制算術編碼。CABAC是H.264/AVC標准中兩種熵編碼中的一種,它的編碼核心算法就是算術編碼(Arithmetic Coding)。

 

算術編碼

傳統編碼算法

算術編碼與傳統的編碼方法有很大的區別,傳統編碼是通過符號映射實現的。映射包含符號(symbol)與碼字(codeword)兩個要素,如下面的例子

symbol e h l o
codeword 00 01 10 11

通過上述的映射表,我們可以把“hello”編碼成碼流 01 00 10 10 11

而諸如Haffuman,Shannon這些編碼方法也沒脫離這種編碼模式,他們只是通過符號出現的概率對碼字進行調優。

 

算術編碼

算術編碼采用的並非上述這種傳統的單符號映射模式進行編碼,它不是將單個符號映射成一個碼字,而是從全序列出發,將輸入的符號依據它的概率映射到[0,1)內的一個小區間上,如此遞歸地進行區間映射,最后得到一個小區間,從該區間內選取一個代表性的小數作為實際的編碼輸出。

如下面為算術編碼的例子

symbol e h l o
probability 0.1 0.2 0.3 0.4

假設需要編碼的符號只有“e”,“h”,“l”,“o”四個,他們出現的總概率為1,各個符號出現的概率如上述表格所示。現要求“hello”經過算術編碼后的碼字。

 

算術編碼有如下編碼步驟:

1. 首先我們需要根據概率設定各符號在[0,1)上的初始區間,其中區間的起點為表中前面的符號的累計概率
symbol e h l o
sum of probability 0 0.1 0.1+0.2 0.1+0.2+0.3
interval [0,0.1) [0.1,0.3) [0.3,0.6) [0.6,1)

hello”的第一個符號為“h”,那么映射的區間為[0.1,0.3)。

 

2. 接下來我們需要根據符號的概率分割[0.1,0.3)上的區間,得到的結果如下
symbol e h l o
interval [0.1,0.12) [0.12,0.16) [0.16,0.22) [0.22,0.3)

hello”的第二個符號為“e”,那么映射的區間為[0.1,0.12)。

 

3. 按照這種方式繼續進行區間映射,最終“hello”映射到的區間是[0.10888,0.1096)
  映射區間 區間大小
初始值 [0,1) 1
編碼完h后 [0.1,0.3) 0.2
編碼完e后 [0.1,0.12) 0.02
編碼完l后 [0.106,0.112) 0.006
編碼完l后 [0.1078,0.1096) 0.0018
編碼完o后 [0.10888,0.1096) 0.00072

 

4. 從區間[0.10888,0.1096)中任取一個代表性的小數,如“0.109”就是編碼“hello”后的輸出值

 

 

算術編碼的總體的編碼流程可以參考下圖

算術編碼總體上可以按照如下進行描述:

  • 設輸入符號串為$s$,$s$中的符號值取自符號集$S=\{ a_1,a_2,a_3,…,a_m \}$
  • 這些符號出現的概率分別為$p(a_k) = \{ p_1,p_2,p_3,…,p_m \}$
  • 這些符號的累計概率為$P(a_k) = \displaystyle{ \sum_1^{i-1}p_k }$。累計概率可以理解為,如果區間為[0,1)時,該符號的區間起點的位置。
  • 區間大小更新為$R_{i+1} = R_{i}p(a_k)$,初始值為$R_0 = 1$
  • 區間的起點更新為$L_{i+1} = L_{i}+P(a_k)R_i$,初始值為$L_0 = 0$

image

當處理符號$a_k$時,區間$R$寬度根據$a_k$出現概率$p(a_k)$而變窄,符號序列越長,相應的子區間越窄,編碼的位數越多。

 

 

算術解碼就只是需要判斷代表性的小數在哪個區間,相應地就知道輸入的符號了。

 

 

二進制算術編碼

二進制算術編碼的編碼方法跟算術編碼是一樣的,但是輸入只有兩個符號:“0”,“1”,也就是說輸入的是二進制串。

除了是對二進制串進行編碼這個特征外,二進制算術編碼跟普通的算術編碼還有一些區別,總體上可以按照如下進行描述:

  1. 設輸入符號串為$s$,$s$中的符號分為兩種:MPS(Most Probability Symbol),LPS(Low Probality Symbol),分別代表出現概率大小的符號,需要根據實際情況進行調整。如果輸入的二進制串中的“0”較多,“1”較少,那么MPS = “0”,LPS =“1”
  2. LPS出現的概率為$p_{LPS}$,MPS出現的概率為$p_{MPS} = 1- p_{LPS}$
  3. 在編碼中進行區間選擇時,MPS在前,LPS在后,因此
    • LPS的累計概率為$P_{LPS} = p_{MPS} = 1-p_{LPS}$
    • MPS的累計概率為$P_{MPS} = 0$
     
     
  4. 區間大小的更新為
    • 如果當前編碼的是LPS:$R_{i+1} = R_{LPS} = R_{i}\cdot p_{LPS}$
    • 如果當前編碼的是MPS:$R_{i+1} = R_{MPS} = R_{i}-R_{LPS} =  R_i –(R_{i} \cdot p_{LPS})$
  5. 區間的起點更新為
    • 如果當前編碼的是LPS:$L_{i+1} = L_{i} + R_{MPS}$
    • 如果當前編碼的是MPS:$L_{i+1} = L_{i}$

CABAC編碼

CABAC采用的是二進制算術編碼,在編碼過程中需要傳入二進制串,輸出的也是二進制串。

在h.264標准中,CABAC在語法結構中用ae表示,它只用於編碼slice_data中的語法元素(包括slice_data內部的子模塊的語法元素,請參考h.264語法結構分析

CABAC實現分為四個部分

  • 上下文變量的初始化
  • 待編碼語法元素二值化
  • 上下文建模(確定上下文索引)
  • 算術編碼

 

1. 上下文變量的初始化

初始化執行於slice開始之前,另外如果在編碼過程中某個宏塊是PCM宏塊,那么在PCM宏塊之后,編碼下一個宏塊之前也需要進行初始化。

初始化主要工作就是確定所有上下文的初始MPS以及初始狀態pStateIdx。求解方法如下

preCtxState = Clip3( 1, 126, ( ( m ∗ Clip3( 0, 51, SliceQPY ) ) >> 4 ) + n )

if( preCtxState <= 63 ) {
    pStateIdx = 63 − preCtxState
    valMPS = 0                           ( 9-5)
} else {
    pStateIdx = preCtxState − 64
    valMPS = 1
}

 

上面的計算依賴於SliceQPY,m,n三個變量,其中不同的上下文索引(contex Index)對應不同的m、n,具體的m、n的取值請參考標准9.3.1中的各個表格。上下文索引是基於語法元素以及二值化后的二進制串的索引binIdx,我們將在下一小節進行闡述。

在CABAC的初始化過程的結果會得到所有上下文索引對應的MPS與pStateIdx的初始值。如果確定了MPS為“0”,那么LPS為“1”,反之如果MPS為“1”,那么LPS為“0”。狀態pStateIdx是什么呢?

狀態pStateIdx是LPS出現的概率$p_{LPS}$的索引。算術編碼中最重要的要素就是符號的概率,CABAC是自適應的算術編碼,也就是說符號的概率會隨着符號的輸入而改變,這種變化就是一種狀態機,如果輸入的是LPS的話,狀態(概率)會怎樣變化,如果輸入的是MPS的話,狀態(概率)又會怎么變化。CABAC的狀態機轉換的規則由HOWARD與VITTER的"exponential aging"模型借鑒而來,轉換規則如下

${p^{(t+1)}}_{LPS}= \left\{\begin{matrix}
\alpha \cdot {p^{t}}_{LPS}\qquad\qquad & if\ an\ MPS\ occurs\\
\alpha \cdot {p^{t}}_{LPS} + (1-\alpha) &if\ an\ LPS\ occurs
\end{matrix}\right.$

在CABAC中規定了LPS的概率取值范圍是$p_{LPS}\in [0.01875,0.5]$,由於LPS是小概率符號,因此它的概率肯定是小於0.5的,如果某個小概率符號在狀態轉換的過程中超出了0.5,此時我們就需要把MPS與LPS進行交換。

CABAC的狀態機中共有64個狀態,pStateIdx = 0,1,2,…,63,分別代表64個不同的概率,除了pStateIdx = 63外,其他的63個狀態都滿足上述狀態轉換規則,其中

$\left\{\begin{matrix}
{p^{0}}_{LPS}=0.5 \qquad\\
{p^{62}}_{LPS}=0.01875
\end{matrix}\right.$

結合上述狀態機的轉換規則,我們可以得到狀態轉換參數

$\alpha = \left( \frac{0.01875}{0.5} \right)^{1/63} \approx 0.95$

 

CABAC狀態機的狀態轉換如下圖(黑色實線代表輸入的是MPS,紅色虛線代表輸入的是LPS),具體的pStateIdx變換請參考標准的表9-45

stateMachine2

 

 

2. 待編碼語法元素二值化

CABAC編碼的是slice data中的語法元素,在進行算術編碼前,需要把這些語法元素按照一定的方法轉換成適合進行二進制算術編碼的二進制串,這個轉換的過程被稱為二值化(binarization)。

二值化的方案共有7種

1. 一元碼(Unary)

對於一個非二進制的無符號整數值符號$x \geqslant 0$,在CABAC中的一元碼碼字由$x$個“1”位外加一個結尾的“0”組成,見下表。例如,輸入的語法元素值為3,其二值化結果為1110

value of syntax element Unary
0 0          
1 1 0        
2 1 1 0      
3 1 1 1 0    
4 1 1 1 1 0  
5 1 1 1 1 1 0
           
binIdx 0 1 2 3 4 5

 

2. 截斷一元碼(TU,Truncated Unary)

一元碼的變體,用在已知語法元素的最大值cMax的情況。對於$0\leqslant x < cMax$的范圍內的取值,使用一元碼進行二值化。對於$x = cMax$,其二值化的二進制串全部由“1”組成,長度為cMax。例如,當cMax=5時,語法元素值為4的二進制串為11110,語法元素值為5的二進制串為11111。

 

3. k階指數哥倫布編碼(kth order Exp-Golomb,EGk)

指數哥倫布編碼由前綴和后綴組成。其中前綴部分由$l(x) = \left \lceil log_2(x/2^k+1) \right \rceil$的值所對應的一元碼組成;后綴部分可通過使用長度為$k+l(x)$位的$x+2k(1-2l(x))$的二進制值來計算。詳細的計算過程請參考指數哥倫布編碼,請注意兩者前綴區別。

 

4. 定長編碼(FL,Fixed-Length)

用定長編碼二進制的無符號語法元素, 語法元素的最大值cMax已知,那么定長編碼的長度為$fixlength = \left \lceil log_2(cMax+1) \right \rceil$,其中值就是語法元素的值的二進制。定長編碼用於近似均勻分布的語法元素的二值化。

 

5. mb_type與sub_mb_type特有的查表方式

詳情請查看h.264標准中9.3.2.5小節

 

6. 4位FL與截斷值為2的TU聯合二值化方案

這種方案只用於對語法元素CBP的二值化。4位的FL(cMax=15)的前綴用於編碼亮度CBP,2位的TU用於編碼色度CBP(當色彩格式為4:2:0或4:2:2時才會存在這個后綴)

 

7. TU與EGk的聯合二值化方案(UEGk,Unary/kth order Exp-Golomb)

這種方案的前綴使用一元截斷碼,后綴使用k階哥倫布編碼。但是在取值較小的范圍內,只用一元碼表示(即只有前綴部分)。對於不同的語法元素,有不同的截斷值與階數。如下表為abs_level_minus1的二值化表(cMax=14的TU、0階哥倫布編碼)

* Suffix (EG0)
0 0                                    
1 1 0                                  
2 1 1 0                                
3 1 1 1 0                              
4 1 1 1 1 0                            
                         
             
12 1 1 1 1 1 1 1 1 1 1 1 1 0            
13 1 1 1 1 1 1 1 1 1 1 1 1 1 0          
14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0        
15 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0    
16 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1    
17 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0
18 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1
                                     
binIdx 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

*:abs_level_minus1Prefix (TU)

 

具體哪個語法元素選擇哪種二值化方案,請查看標准9.3.2中d第一個表格。

 

3. 上下文建模(確定上下文索引)

在前面初始化的時候就出現了上下文這個概念,那么上下文所指的是什么?

以JM中的上下文結構體為例

 //! struct for context management
struct bi_context_type   
{ 
   unsigned long  count;  
   byte state; //uint16 state;         // index into state-table CP
   unsigned char  MPS;           // Least Probable Symbol 0/1 CP  
};

上下文包含兩個變量:MPS、pStateIdx(count只是用於計數)。在CABAC編碼的過程中會碰到需要修改這兩個值的情況(如上面的狀態變換),這些修改都是以上下文為單位的。

語法元素在經過二值化后形成二進制串,二進制串中不同binIdx位置上的MPS(出現頻率高的符號)可能會有所不同,並且概率也可能會不同,因此需要用一個概念來表示特定語法元素的二進制串中特定binIdx的MPS與pStateIdx,上下文就是這樣的概念。

 

在h.264標准中,用一個上下文索引ctxIdx來代表上下文,ctxIdx的取值為0~1023,就是說h.264的上下文一共有1024個。

 

ctxIdx的計算方式分為兩種:

如果語法元素為coded_block_flag、significant_coeff_flag、last_significant_coeff_flag、coeff_abs_level_minus1,即殘差系數部分的語法元素,則

ctxIdx = ctxIdxOffset + BlockCatOffset(ctxBlockCat) + ctxIdxInc(ctxBlockCat)

否則

ctxIdx = ctxIdxOffset + ctxIdxInc

 

其中的變量有

  • ctxIdxOffset  每個語法元素都有一個ctxIdxOffset,甚至一些語法元素在二值化后分為前后綴會,這種語法元素可能會有兩個ctxIdxOffset,如下表格部分摘自h.264標准9.3.2的第一個表格
Syntax Element ctxIdxOffset
mb_type
(SI slices only)
prefix: 0
suffix: 3
mb_type (I slices only) 3
mb_skip_flag
(P,SP slices only)
11
mb_type
(P, SP slices only)
prefix: 14
suffix: 17
sub_mb_type[]
(P, SP slices only)
21
  • ctxIdxInc   在特定的語法元素二值化后,會形成以binIdx為索引的二進制串,盡管是同一個二進制串,但是不同的binIdx上的上下文(MPS,pStateIdx)可能會有所不同,ctxIdxInc就是在這種情況下產生的一個值,它用於划分二進制串上不同的上下文。如下面一項表格摘自h.264標准9.3.3.1的第一個表格
    ctxIdxOffset b0 b1 b2 b3 b4 b5 >=b6
    40 0,1,2 3 4 5 6 6 6
    ctxIdxOffset=40代表mvd的橫向分量,上述表格描述了這個語法元素各個binIdx所對應的ctxIdxInc。也就是說mvd橫向分量按照binIdx得到的ctxIdx如下表
    binIdx b0 b1 b2 b3 b4 b5 >=b6
    ctxIdx 40,41,42 43 44 45 46 46 46
    像上面表格的這種binIdx=0中出現三個ctxIdx的情況,意思就是會根據編碼的具體情況選擇0、1或者2作為ctxIdxInc,需要另外分析。ctxIdxInc的確定方法具體請參考標准9.3.3.1小節
  • BlockCatOffset(ctxBlockCat)  其中ctxBlockCat的范圍為0~13,分別代表不同殘差塊類型,如下表
    Block description maxNumCoeff ctxBlockCat
    block of luma DC transform coefficient levels 16 0
    block of luma AC transform coefficient levels 15 1
    block of 16 luma transform coefficient levels 16 2
    block of chroma DC transform coefficient levels when ChromaArrayType is equal to 1 or 2 4*2/4*4 3
    block of chroma AC transform coefficient levels when ChromaArrayType is equal to 1 or 2 15 4
    block of 64 luma transform coefficient levels 64 5
    block of Cb DC transform coefficient levels when ChromaArrayType is equal to 3 16 6
    block of Cb AC transform coefficient levels when ChromaArrayType is equal to 3 15 7
    block of 16 Cb transform coefficient levels when ChromaArrayType is equal to 3 16 8
    block of 64 Cb transform coefficient levels when ChromaArrayType is equal to 3 64 9
    block of Cr DC transform coefficient levels when ChromaArrayType is equal to 3 16 10
    block of Cr AC transform coefficient levels when ChromaArrayType is equal to 3 15 11
    block of 16 Cr transform coefficient levels when ChromaArrayType is equal to 3 16 12
    block of 64 Cr transform coefficient levels when ChromaArrayType is equal to 3 64 13

    在殘差系數部分,上下文是會根據不同的殘差塊類型做出不同選擇的,BlockCatOffset就代表了不同的殘差塊類型的索引偏移,具體偏移值可以查看標准中的相關表格。

 

4. 算術編碼

算術編碼是基於區間划分的,普通的概率划分需要使用到多位乘法。CABAC的算術編碼為了降低計算復雜度,並便於硬件實現,采取了如下一些方法:

  1. 總是估計小概率符號LPS($p_{LPS}<0.5$)的概率,並將其概率離散化成64個不同概率狀態。概率估計轉換成基於表格的概率狀態的轉換(見初始化部分的描述)。
  2. 使用9bit的變量$R$與10bit的$L$表示當前區間,其中$L$為區間的起點,$R$為區間長度
  3. 每當輸入新符號時,會對區間的起點$L$以及區間的長度$R$進行更新,在前面的二進制算術編碼時,我們已經得知兩者的更新方法,其中$R$與$L$的更新包含了浮點數乘法$R_{i}\cdot p$,為了降低運算復雜度,CABAC把乘法換算成了查表的形式。換算方法如下:
    • 離散化的狀態pStateIdx代表了符號的概率$p$
    • 9個bit的區間長度$R$通過$(R>>6) \& 3$被量化成2個bit,即$\{0,1,2,3\}$(因為$R$總是大於等於$2^8$小於$2^9$,在后面的歸一化可以看出來)
    • 有了上述兩個離散的變量,區間更新所需要的乘法就能轉換成查表操作,表格請查看標准9.3.3.2中的第一個表格。
  4. 在算術編碼的過程中,盡管是同一上下文,但是概率並不是固定的,每次輸入一個新符號都會改變相應上下文的概率,也就是會進行狀態轉換(見初始化部分的描述)
  5. 對近似均勻分布的語法元素,在編碼和解碼時選擇盤路(bypass)模式,可以免除上下文建模,提高編解碼的速度。
  6. 由於編碼區間是有限位表示的,因此在輸入一個符號進行區間更新后,需要進行重歸一化以保證編碼精度。

 

算術編碼過程

image

該過程可分為5個步驟

  1. 通過當前編碼器區間范圍$R$得到其量化值$\rho$作為查表索引,然后利用狀態索引$pStateIdx$與$\rho$進行查表得出$R_{LPS}$的概率區間大小。
  2. 根據要編碼的符號是否是MPS來更新算術編碼中的概率區間起點$L$以及區間范圍$R$
  3. $pStateIdx == 0$表明當前LPS在上下文狀態更新之前已經是0.5的概率,那么此時還輸入LPS,表明它已經不是LPS了,因此需要進行LPS、MPS的轉換
  4. 更新上下文模型概率狀態
  5. 重歸一化,輸出編碼比特。

 

重歸一化分析

在區間划分結束后,如果新的區間不在$[2^8,2^9)$之內,即$R<256$,256是最大編碼區間的$\frac{1}{4}$,那么就需要進行重歸一化操作(incremental output and interval expansion),輸出一位或多位編碼比特。重歸一化過程如下圖所示。

image

 

在CABAC編碼過程中,在輸入符號后,進行區間更新,接下來就是重歸一化過程。下面就以$[0,2^{10})$表示區間$[0,1)$為例,分析重歸一化過程

    (請注意,在該過程中,$[0,2^{10})$只起到輔助作用,實際的區間為$R$

  1. $R < 2^8$的情況,如果$L < 2^8$,則可知$R + L < 2^9$,那么可以確定編碼區間$[L, L+R)$在區間$[0, 0.5)$上,用二進制表示這個區間即為$0.0x$,因此輸出$0$(只記錄小數點后面的二進制)。最后用$[0,2^{10})$來表示區間$[0,0.5)$,也就是將原本的$[0,2^9)$線性擴增到$[0,2^{10})$
  2. $R < 2^8$的情況,如果$L \geqslant 2^9$,那么就可以確定編碼區間$[L, L+R)$在區間$[0.5,1)$上,用二進制表示這個區間即為$0.1x$,因此輸出$1$。最后用$[0,2^{10})$來表示區間$[0.5,1)$,也就是將原本的$[2^9,2^{10})$線性擴增到$[0,2^{10})$
  3. $R < 2^8$的情況,如果$2^8 \leqslant L < 2^9$,則$2^8 < R+L < 2^9 + 2^8$,編碼區間$[L, L+R)$可能在$[0,0.5)$區間內,也有可能跨越$[0,0.5)$與$[0.5,1)$兩個區間,即可能是$0.01x$,也可能是$0.10x$。此時可以先暫緩輸出,用$[0,2^{10})$來表示區間$[0.25,0.75)$,也就是將原本的$[2^8,2^8+2^9)$線性擴增到$[0,2^{10})$,然后進入重歸一化的下一個循環繼續判斷。
  4. $R \geqslant 2^8$的情況,無法通過$L < 2^8$來確定編碼區間,需要通過輸入下一個符號來對$R$與$L$進行更新后再繼續進行判斷,因此當前符號的編碼流程結束。由於這個原因,因此在一個符號編碼結束后,另一個符號編碼開始前,總是$2^8 \leqslant R < 2^9$。

cabac_switch

 

輸出

在編碼輸出“0”或者“1”的階段,用PutBit(B)表示

image

關於PutBit(B)的分析,參考上面重歸一化的區間圖,可以看到有三種情況

  1. 情況1,走PutBit(0),直接輸出“0”
  2. 情況2,走PutBit(1),直接輸出“1”
  3. 情況3,輸出可能為“10”或者“01”,因此不能直接輸出,走bitsOutstanding++的步驟。在下一次編碼符號時,符合情況2,走PutBit(1),此時bitsOutstanding = 1,因此輸出“10”

另外,PutBit(B)不會編碼第一個bit。原因是CABAC在初始化的時候,會以$[0,2^{10})$表示區間$[0,1)$,而在初始化區間時$R=510,L=0$,這意味着已經進行了第一次區間選擇,區間為$[0,0.5)$,需要輸出“0”。PutBit(B)在此阻止這個“0”的輸出,這樣就能得到正確的算術編碼結果了。

 

 

旁路(bypass)編碼

有些語法元素在二值化后選擇的可能不是上述的算術編碼,而是旁路編碼,具體情況請查看h.264標准9.3.2的第一個表格。旁路編碼中,假設待編碼的符號符合近似的均勻分布。下圖給出了旁路模式下的編碼過程。

旁路模式有幾個特點:符號均勻分布,無需對$R$進行量化與查表;每編碼完一個符號后,$R$總是會小於$2^8$,因此每次都需要對概率區間進行放大;把對$L$的移位操作提到了前面,因此旁路編碼的重歸一化的區間可以看作由$[0,2^{10})$變成了$[0,2^{11})$。

image

下面是旁路編碼的一個例子

 

 

編碼結束 EncodeTerminate

在編碼語法元素end_of_slice_flag以及I_PCM mb_type時(ctxIdx = 276)會調用EncodeTerminate這個編碼過程。

在EncodeTerminate中,采用的是pStateIdx = 63的狀態,這個狀態表示的是當前宏塊是否為該slice的最后一個宏塊的概率。在該狀態下,對概率區間的划分跟概率區間量化值無關。在編碼end_of_slice_flag以及I_PCM的mb_type時,概率區間固定為$R_{LPS} = 2$。如果當前宏塊為slice的最后一個宏塊(end_of_slice_flag = 1)或者當前編碼為PCM宏塊並且編碼它的mb_type I_PCM時,結束CABAC編碼,調用EncodeTerminate中的EncodeFlush。具體情況請參考標准中的9.3.4.5小節以及CABAC補充討論

image

 

在編碼完成slice的最后一個宏塊后,將會調用字節填充過程。該過程會往NAL單元寫入0個或者更多個字節(cabac_zero_word),目的是完成對NAL單元的封裝(標准9.3.4.6)。這里有計算如下

$k = \left \lceil \left(\left \lceil 3\times \left(\frac{32\times BinCountsInNALunits - RawMbBits\times PicSizeInMbs}{1024}\right) \right \rceil - NumBytesInVclNalunits\right)/3 \right \rceil$

如果$k>0$,則需要將3字節長的0x000003添加到NAL單元$k$次。這里的前兩字節0x0000代表了cabac_zero_word,第三個字節0x03代表一個emulation_prevention_three_byte,這兩個語法元素請參考h.264語法結構分析的相關部分。

如果$k \leqslant 0$,則無需添加字節到NAL單元。

式子中的各個變量所代表的意思請查看標准


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM