1、學習路線
step1、初步瞭解h264,瞭解h264數據幀分類和識別
step2、h264語法相關算法解析,這裏對理解h264的視頻幀很重要。通俗的說h264數據定義是由一組Bit組成,但是某個字段不是固定專有幾個bit,它是根據其值通過算法轉義保存。
step3、sps、pps幀語法定義
2、h264簡介
在H.264/AVC視頻編碼標準中,整個系統框架被分爲了兩個層面:視頻編碼層面(VCL)和網絡抽象層面(NAL)。其中,前者負責有效表示視頻數據的內容,而後者則負責格式化數據並提供頭信息,以保證數據適合各種信道和存儲介質上的傳輸。NAL佔一個字節。
NAL單元(NALU):NAL的基本語法結構,它包含一個字節的頭信息和一系列來自VCL的稱爲原始字節序列載荷(RBSP)的字節流。 數據流是儲存在介質上時: 每個NALU 前添加起始碼:0x00000001(或者0x000001),用來指示一個 NALU的起始和終止位置。我們平時的每幀數據就是一個NAL單元(SPS與PPS除外)。
編碼器將每個NAL各自獨立、完整地放入一個分組,因爲分組都有頭部,解碼器可以方便地檢測出NAL的分界,並依次取出NAL進行解碼。每個NAL前有一個起始碼 0x00 00 01(或者0x00 00 00 01),解碼器檢測每個起始碼,作爲一個NAL的起始標識,當檢測到下一個起始碼時,當前NAL結束。同時H.264規定,當檢測到0x000000時,也可以表徵當前NAL的結束。那麼NAL中數據出現0x000001或0x000000時怎麼辦?H.264引入了防止競爭機制,如果編碼器檢測到NAL數據存在0x000001或0x000000時,編碼器會在最後個字節前插入一個新的字節0x03,這樣:
0x000000->0x00000300
0x000001->0x00000301
0x000002->0x00000302
0x000003->0x00000303
解碼器檢測到0x000003時,把03拋棄,恢復原始數據(脫殼操作)。解碼器在解碼時,首先逐個字節讀取NAL的數據,統計NAL的長度,然後再開始解碼。
NALU頭由一個字節組成, 它的語法如下:
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
+---------------+
F: 1 個比特.
forbidden_zero_bit. 在 H.264 規範中規定了這一位必須爲 0.
NRI: 2 個比特.
nal_ref_idc. 取 00 ~ 11, 似乎指示這個 NALU 的重要性, 如 00 的 NALU 解碼器可以丟棄它而不影響圖像的回放. 不過一般情況下不太關心
這個屬性.
Type: 5 個比特.
nal_unit_type. 這個 NALU 單元的類型. 簡述如下:
0 沒有定義
1 一個非IDR圖像的編碼條帶 (bp幀)
slice_layer_without_partitioning_rbsp( )
2 編碼條帶數據分割塊A
slice_data_partition_a_layer_rbsp( )
3 編碼條帶數據分割塊B
slice_data_partition_b_layer_rbsp( )
4 編碼條帶數據分割塊C
slice_data_partition_c_layer_rbsp( )
5 IDR圖像的編碼條帶 (i幀)
slice_layer_without_partitioning_rbsp( )
6 輔助增強信息 (SEI)
sei_rbsp( )
7 序列參數集 (sps幀)
seq_parameter_set_rbsp( )
8 圖像參數集
pic_parameter_set_rbsp( pps幀)
9 訪問單元分隔符
access_unit_delimiter_rbsp( )
10 序列結尾
end_of_seq_rbsp( )
11 流結尾
end_of_stream_rbsp( )
12 填充數據
filler_data_rbsp( )
13 序列參數集擴展
seq_parameter_set_extension_rbsp( )
14...18 保留
19 未分割的輔助編碼圖像的編碼條帶
slice_layer_without_partitioning_rbsp( )
20...23 保留
24 STAP-A 單一時間的組合包
25 STAP-B 單一時間的組合包
26 MTAP16 多個時間的組合包
27 MTAP24 多個時間的組合包
28 FU-A 分片的單元
29 FU-B 分片的單元
30-31 沒有定義
當遇到 00 00 00 01 67表示sps幀
當遇到 00 00 00 01 68 表示pps幀
3、h264語法相關算法解析
1、無符號指數哥倫布熵編碼
1.1 編碼過程
1、將待編碼的數加1轉換爲最小的二進制序列(假設一共M位);
2、此二進制序列前面補充M-1個0;
3、enjoy!
1.1.1 示例
對 4 進行無符號指數哥倫布熵編碼
1、將4加1(爲5)轉換爲最小的二進制序列即 101 (此是M=3)
2、此二進制序列前面補充M-1即兩個0
3、得出的4的無符號指數哥倫布熵編碼的序列爲 00101
1.2 解碼過程
1、獲取二進制序列開頭連續的N個0
2、讀取之後的N+1位的值,假設爲X
3、X-1獲取解碼後的值
1.2.1 示例
如對 00101進行無符號指數哥倫布熵解碼
1、獲取開頭連續的N個0, 此時N = 2
2、再向後讀取N+1位的值,即 101,爲5
3、 5 - 1 =4 獲取其解碼後碼值,enjoy!
1.3 其他
注意0的無符號指數哥倫布熵編碼的二進制序列爲 1
2 有符號指數哥倫布熵編碼
2.1 編碼過程
1、將待編碼的數的絕對值轉換爲最小的二進制序列(假設一共M位)
2、在此二進制序列後補充一位符號位0表示正,1表示負
3、在此二進制序列前補充M個0
4、enjoy
2.1.1 示例1
如對4進行有符號指數哥倫布熵編碼
1、4的絕對值轉爲最小二進制序列,即 100 (此時M = 3)
2、後面補充符號位,0 即 1000
3、前面補充M個0, 即 0001000
4、enjoy
2.1.2 示例2
如對-15進行有符號指數哥倫布熵編碼
1、-7的絕對值轉爲最小二進制序列,即 1111 (此時M = 4)
2、後面補充符號位,1,即 11111
3、前面補充M個0,即 000011111
4、enjoy
2.2 解碼過程
1、獲取二進制序列開頭連續的N個0
2、讀取之後的N位的值,假設爲X
3、獲取最後1位符號位
4、獲取解碼後碼值
2.2.1 示例1
如對二進制序列 0001000 進行有符號指數哥倫布熵解碼
1、獲取開頭連續的N個0, 此時N = 3
2、再獲取N爲數值,即 100 即爲4
3、獲取最後的符號位,0,即爲正值
4、故此序列解碼後的碼值爲4
2.2.2 示例2
如對二進制序列 000011111 進行有符號指數哥倫布熵解碼
1、獲取開頭連續的N個0, 此時N = 4
2、再獲取N爲數值,即 1111 即爲15
3、獲取最後的符號位,1,即爲負值
4、故此序列解碼後的碼值爲-15
4、sps語法
5、pps語法