H.264編碼格式分析
H.264的重要性不再提了。本文主要記錄一下H.264的編碼格式。H.264官方文檔:https://github.com/jiayayao/DataSheet/tree/master/encode-decode/h264。
H.264從層次來看分為兩層:視頻編碼層(VCL, Video Coding Layer)和網絡提取層(NAL,Network Abstraction Layer)。VCL輸出的是原始數據比特流(SODB,String of data bits),表示H.264的語法元素編碼完成後的實際的原始二進制碼流。SODB通常不能保證字節對齊,故需要補齊為原始字節序列負荷(RBSP,Raw Byte Sequence Payload)。NAL層實際上就是最終輸出的H.264碼流,它是由一個個NALU組成的,每個NALU包括一組對應於視頻編碼數據的NAL頭信息和一個原始字節序列負荷(RBSP,Raw Byte Sequence Payload)。以上名詞之間的關系如下:
RBSP = SODB + RBSP trailing bits NALU = NAL header(1 byte) + RBSP H.264 = Start Code Prefix(3 bytes) + NALU + Start Code Prefix(3 bytes) + NALU +…
所以H.264碼流的結構如下:
每個NALU之間由起始碼(Start Code Prefix)分隔,起始碼分為兩種:0x000001(3 bytes) or 0x00000001(4 bytes). 如果NALU 對應的Slice 為一幀的開始,則用4 字節表示,即0x00000001;否則用3 字節表示,0x000001.NALU針對起始碼設計了防止沖突機制,如果出現連續的0x000000,0x000001,0x000002,0x000003時,會在兩個0之間插入03,如下:
0x00 00 00 -> 0x00 00 03 00 0x00 00 01 -> 0x00 00 03 01 0x00 00 02 -> 0x00 00 03 02 0x00 00 03 -> 0x00 00 03 03
一個NALU就是編碼後的一幀數據。NAL header是一個字節:
forbidden_zero_bit(1 bit) 禁止位,等於0;
nal_ref_idc(2 bit)指示當前NAL的優先級,取值範圍為0~3,值越高,表示當前NAL越重要。H.264規定,如果當前NAL是序列參數集,或是圖像參數等,該值必須大於0.比如nal_unit_type等於5時,nal_ref_idc大於0;nal_unit_type等於6,9,10,11或12時,nal_ref_idc等於0;
nal_unit_type表示當前NALU的類型,表格如下:
nal_unit_type |
NAL類型 |
C |
0 |
未使用 |
|
1 |
不分區、非IDR圖像的片 |
2,3,4 |
2 |
片分區A |
2 |
3 |
片分區B |
3 |
4 |
片分區C |
4 |
5 |
IDR圖像中的片 |
2,3 |
6 |
補充增強信息單元(SEI) |
5 |
7 |
序列參數集(SPS) |
0 |
8 |
圖像參數集(PPS) |
1 |
9 |
分界符 |
6 |
10 |
序列結束 |
7 |
11 | 碼流結束 | 8 |
12 | 填充 | 9 |
13~23 | 保留 | |
24~31 | 未使用 |
nal_unit_type=5時,表示當前NAL是IDR圖像的一個片,此時,IDR圖像中的每個片的nal_unit_type都應該等於5.
一般H.264原始碼流是以SPS->PPS->SEI->IDR->SCLICE->SCLICE…開頭的。
附:
leixiaohua的H.264分析器,本人在此基礎上做了大量註釋,方便理解H.264:https://github.com/jiayayao/h264_analysis。
H.264編碼格式分析