H.264(層次結構,NAL,SPS) 詳細重要引數
一 H.264句法
1.1元素分層結構
H.264編碼器輸出的Bit流中,每個Bit都隸屬於某個句法元素。句法元素被組織成有層次的結構,分別描述各個層次的資訊。
圖1
H.264分層結構由五層組成,分別是序列引數集、影象引數集、片(Slice)、和巨集塊和子塊。引數集是一個獨立的資料單位,不依賴於引數集外的其它句法元素。圖2描述了引數集與引數集外的句法元素之間的關係。
圖2
一個引數集不對應某一個特定的影象或序列,同一序列引數集可以被多個影象引數集引用,同理,同一個影象引數集也可以被多個影象引用。只在編碼器認為需要更新引數集的內容時,才會發出新的引數集。
在H.264中,影象以序列為單位進行組織。一個序列的第一個影象叫做IDR影象,IDR影象都是I幀,
IDR是I幀,但I幀不一定是IDR。I幀之後的影象有可能會使用I幀之前的影象做運動參考。
1.2描述子
描述子描述從Bit流中取出句法元素的方法。
編號 |
語法 |
說明 |
1 |
ae(e) |
CABAC |
2 |
b(8) |
讀進連續的8個Bit |
3 |
ce(v) |
CAVLC |
4 |
f(n) |
讀進連續的n個Bit |
5 |
i(n)/i(v) |
讀進連續的若干Bit,並把它們解釋為有符號整數 |
6 |
me(v) |
對映指數Golomb熵編碼 |
7 |
se(v) |
有符號指數Golomb熵編碼 |
8 |
te(v) |
截斷指數Golomb熵編碼 |
9 |
u(n)/u(v) |
讀進連續的若干Bit,並把它們解釋為無符號整數 |
10 |
ue(v) |
無符號指數Golomb熵編碼 |
表1
1.3句法的表示方法
句法元素的名稱由小寫字母和一系列下劃線組成,變數名稱是大小寫字母組成,中間沒有下劃線。
二 句法表
定義了H.264的句法,指明在碼流中依次出現的句法元素及它們出現的條件、提取描述子等。句法表是分層巢狀的。
句法表中的C欄位表示該句法元素的分類,這是為片區服務,分類的具體含義如下表描述。
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 |
序列引數集 |
0 |
8 |
影象引數集 |
1 |
9 |
分界符 |
6 |
10 |
序列結束 |
7 |
11 |
碼流結束 |
8 |
12 |
填充 |
9 |
13..23 |
保留 |
|
24..31 |
不保留 |
表2
2.1 NAL語法
編碼器將每個NAL各自獨立、完整地放入一個分組,因為分組都有頭部,解碼器可以方便地檢測出NAL的分界,並依次取出NAL進行解碼。
每個NAL前有一個起始碼 0x000001,解碼器檢測每個起始碼,作為一個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的長度,然後再開始解碼。
句法 |
C |
Desc |
nal_nuit(NumBytesInNALunit){/* NumBytesInNALunit為統計出來的資料長度 */ |
||
forbidden_zero_bit /* 等於0 */ |
All |
f(1) |
nal_ref_idc/* 當前NAL的優先順序,取值範圍0-3 */ |
All |
u(2) |
nal_unit_type /* NAL型別,見表2描述 */ |
All |
u(5) |
NumBytesInRBSP=0 |
||
for(i=1;i<NumBytesInNALunit;i++){ |
||
if(i+2<NumBytesInNALunit && next_bits(24)==0x000003{ |
||
/* 0x000003偽起始碼,需要刪除0x03這個位元組 */ |
||
rbsp_byte[NumBytesInRBSP++] |
All |
b(8) |
rbsp_byte[NumBytesInRBSP++] |
All |
b(8) |
i+=2/* 取出前兩個0x00後,跳過0x03 */ |
||
emulation_prevention_three_byte/* equal to 0x03 */ |
All |
f(8) |
}else{ |
||
rbsp_byte[NumBytesInRBSP++] /* 繼續讀取後面的位元組 */ |
All |
b(8) |
} |
||
} |
表3
2.2序列引數集(SPS)
句法 |
C |
Desc |
seq_parameter_set_rbsp(){ |
||
profile_idc/* 指明所用的Profile */ |
0 |
u(8) |
constraint_set0_flag |
0 |
u(1) |
constraint_set1_flag |
0 |
u(1) |
constraint_set1_flag |
0 |
u(1) |
reserved_zero_5bits /* equal to 0 */ |
0 |
u(5) |
level_idc /* 指明所用的Level */ |
0 |
u(8) |
seq_parameter_set_id /* 指明本序列引數集的id號,0-31,被影象集引用,編碼需要產生新的序列集時,使用新的id,而不是改變原來引數集的內容 */ |
0 |
ue(v) |
log2_max_frame_num_minus4/* 為讀取元素frame_num服務,frame_num標識影象的解碼順序,frame_num的解碼函式是ue(v),其中v=log2_max_frame_num_minus4+4,該元素同時指明frame_num的最大值MaxFrameNum=2( log2_max_frame_num_minus4+4)*/ |
0 |
ue(v) |
pic_order_cnt_type /* 指明poc的編碼方法,poc標識影象的播放順序,poc可以由frame_num計算,也可以顯示傳送。poc共三種計算方式 */ |
0 |
ue(v) |
if(pic_order_cnt_type==0) |
||
log2_max_pic_order_cnt_lsb_minus4 /* 指明變數MaxPicOrderCntLsb的值, MaxPicOrderCntLsb=2(log2_max_pic_order_cnt_lsb_minus4+4) */ |
0 |
ue(v) |
else if(pic_order_cnt_type==1){ |
||
delta_pic_order_always_zero_flag /* 等於1時,元素delta_pic_order_cnt[0]和delta_pic_order_cnt[1]不在片頭中出現,並且它們的預設值是0,等於0時,上述兩元素出現的片頭中 */ |
0 |
u(1) |
offset_for_non_ref_pic /* 用來計算非參考幀或場的poc,[-231,231-1] */ |
0 |
se(v) |
offset_for_top_to_bottom_field/* 計算幀的底場的poc */ |
0 |
se(v) |
num_ref_frames_inpic_order_cnt_cycle /* 用來解碼poc,[0.255] */ |
0 |
ue(v) |
for(i=0;i<num_ref_frames_inpic_order_cnt_cycle;i++) |
||
offset_for_ref_frame[i]/* 用來解碼poc,對於迴圈中的每個元素指定一個偏移 */ |
0 |
se(v) |
} |
||
num_ref_frames /* 參考幀佇列可達到的最大長度,[0,16] */ |
0 |
ue(v) |
gaps_in_frame_num_value_allowed_flag /* 為1,允許slice header中的frame_num不連續 */ |
0 |
u(1) |
pic_width_inmbs_minus1 /* 本元素加1,指明以巨集塊為單位的影象寬度PicWidthInMbs=pic_width_in_mbs_minus1+1 */ |
0 |
ue(v) |
pic_height_in_map_units_minus1 /* 本元素加1,指明以巨集塊為單位的影象高寬度PicHeightInMapUnitsMbs=pic_height_in_map_units_minus1+1 */ |
0 |
ue(v) |
frame_mbs_only_flag /* 等於0表示本序列中所有影象均為幀編碼;等於1,表示可能是幀,也可能場或幀場自適應,具體編碼方式由其它元素決定。結合前一元素:FrameHeightInMbs=(2-frame_mbs_only_flag)*PicHeightInMapUnits */ |
0 |
ue(v) |
if(frame_mbs_only_flag) |
||
mb_adaptiv_frame_field_flag /* 指明本序列是否是幀場自適應模式: frame_mbs_only_flag=1,全部是幀 frame_mbs_only_flag=0, mb_adaptiv_frame_field_flag=0,幀場共存 frame_mbs_only_flag=0, mb_adaptiv_frame_field_flag=1,幀場自適應和場共存*/ |
0 |
u(1) |
direct_8x8_inference_flag /* 用於指明B片的直接和skip模式下的運動向量的計算方式 */ |
0 |
u(1) |
frame_cropping_flag /* 解碼器是否要將影象裁剪後輸出,如果是,後面為裁剪的左右上下的寬度 */ |
0 |
u(1) |
if(frame_cropping_flag){ |
||
frame_crop_left_offset |
0 |
ue(1) |
frame_crop_right_offset |
0 |
ue(1) |
frame_crop_top_offset |
0 |
ue(1) |
frame_crop_bottom_offset |
0 |
ue(1) |
} |
||
vui_parameters_present_flag /* 指明vui子結構是否出現在碼流中,vui子結構在附錄中指明,用於表徵視訊格式的資訊 */ |
0 |
u(1) |
if(vui_parameters_present_flag) |
||
vui_parameters() |
0 |
|
rbsp_trailing_bits() |
0 |
|
} |
表4