參考
《新一代視頻壓縮編碼標準 畢厚杰 第7章 H.264的句法和語義》
【H.264/AVC視頻編解碼技術(shù)詳解】 九、序列參數(shù)集Sequence Paramater Set(SPS)解析
在H.264標準協(xié)議中規(guī)定了多種不同的NAL Unit類型,其中類型7表示該NAL Unit內(nèi)保存的數(shù)據(jù)為Sequence Paramater Set。在H.264的各種語法元素中,SPS中的信息至關(guān)重要。如果其中的數(shù)據(jù)丟失或出現(xiàn)錯誤,那么解碼過程很可能會失敗。SPS及后續(xù)將要講述的圖像參數(shù)集PPS在某些平臺的視頻處理框架(比如iOS的VideoToolBox等)還通常作為解碼器實例的初始化信息使用。
SPS即Sequence Paramater Set,又稱作序列參數(shù)集。SPS中保存了一組編碼視頻序列(Coded video sequence)的全局參數(shù)。所謂的編碼視頻序列即原始視頻的一幀一幀的像素數(shù)據(jù)經(jīng)過編碼之后的結(jié)構(gòu)組成的序列。而每一幀的編碼后數(shù)據(jù)所依賴的參數(shù)保存于圖像參數(shù)集中。
一、SPS的結(jié)構(gòu)
為了讓后續(xù)的解碼過程可以使用SPS中包含的參數(shù),必須對其中的數(shù)據(jù)進行解析。其中H.264標準協(xié)議中規(guī)定的SPS格式位于文檔的7.3.2.1.1部分,如下圖所示:



在我們這個實例中,SPS NAL Unit中的二進制內(nèi)容為:
42 00 1e e8 58 58 98 80
(1). profile_idc:
標識當前H.264碼流的profile。我們知道,H.264中定義了三種常用的檔次profile:
- 基準檔次:baseline profile;
- 主要檔次:main profile;
- 擴展檔次:extended profile;
在H.264的SPS中,第一個字節(jié)表示profile_idc,根據(jù)profile_idc的值可以確定碼流符合哪一種檔次。判斷規(guī)律為:
- profile_idc = 66 → baseline profile;
- profile_idc = 77 → main profile;
- profile_idc = 88 → extended profile;
在新版的標準中,還包括了High、High 10、High 4:2:2、High 4:4:4、High 10 Intra、High 4:2:2 Intra、High 4:4:4 Intra、CAVLC 4:4:4 Intra等,每一種都由不同的profile_idc表示。
另外,constraint_set0_flag ~ constraint_set5_flag是在編碼的檔次方面對碼流增加的其他一些額外限制性條件。
在我們實驗碼流中,profile_idc = 0x42 = 66,因此碼流的檔次為baseline profile。
(2). level_idc
標識當前碼流的Level。編碼的Level定義了某種條件下的最大視頻分辨率、最大視頻幀率等參數(shù),碼流所遵從的level由level_idc指定。
當前碼流中,level_idc = 0x1e = 30,因此碼流的級別為3。
(3). seq_parameter_set_id
表示當前的序列參數(shù)集的id。通過該id值,圖像參數(shù)集pps可以引用其代表的sps中的參數(shù)。本句法元素的值應該在[0,31]。
注意:當編碼器需要產(chǎn)生新的序列參數(shù)集時,應該使用新的 seq_parameter_set_id,即使用新的序列參數(shù)集,而不是去改變原來的參數(shù)集中的內(nèi)容
(4). log2_max_frame_num_minus4
這個句法元素主要是為讀取另一個句法元素 frame_num 服務的,frame_num 是最重要的句法元素之一,它標識所屬圖像的解碼順序??梢栽诰浞ū砜吹?,fram-num的解碼函數(shù)是 ue(v),函數(shù)中的 v 在這里指定:
v = log2_max_frame_num_minus4 + 4
從另一個角度看,這個句法元素同時也指明了 frame_num 的所能達到的最大值:
MaxFrameNum = 2( log2_max_frame_num_minus4 + 4 )
變量 MaxFrameNum 表示 frame_num 的最大值,在后文中可以看到,在解碼過程中它也是一個非常重要的變量。
值得注意的是 frame_num 是循環(huán)計數(shù)的,即當它到達 MaxFrameNum 后又從 0 重新開始新一輪的計數(shù)。解碼器必須要有機制檢測這種循環(huán),不然會引起類似千年蟲的問題,在圖像的順序上造成混亂。在第八章會詳細講述 H.264 檢測這種循環(huán)的機制。
(5). pic_order_cnt_type
指明了 poc (picture order count) 的編碼方法,poc 標識圖像的播放順序。由于H.264 使用了 B 幀預測,使得圖像的解碼順序并不一定等于播放順序,但它們之間存在一定的映射關(guān)系。poc 可以由 frame-num 通過映射關(guān)系計算得來,也可以索性由編碼器顯式地傳送。H.264 中一共定義了三種 poc 的編碼方法,這個句法元素就是用來通知解碼器該用哪種方法來計算 poc。而以下的幾個句法元素是分別在各種方法中用到的數(shù)據(jù)。
在如下的視頻序列中本句法元素不應該等于 2:
- 一個非參考幀的接入單元后面緊跟著一個非參考圖像(指參考幀或參考場)的接入單元
- 兩個分別包含互補非參考場對的接入單元后面緊跟著一個非參考圖像的接入單元.
- 一個非參考場的接入單元后面緊跟著另外一個非參考場,并且這兩個場不能構(gòu)成一個互補場對
(6). log2_max_pic_order_cnt_lsb_minus4
用于計算MaxPicOrderCntLsb的值,該值表示POC的上限。計算方法為MaxPicOrderCntLsb = 2^(log2_max_pic_order_cnt_lsb_minus4 + 4)。該變量在 pic_order_cnt_type = 0 時使用。
(7). max_num_ref_frames
用于表示參考幀的最大數(shù)目。解碼器依照這個句法元素的值開辟存儲區(qū),這個存儲區(qū)用于存放已解碼的參考幀,H.264 規(guī)定最多可用 16 個參考幀,本句法元素的值最大為 16。值得注意的是這個長度以幀為單位,如果在場模式下,應該相應地擴展一倍。
(8). gaps_in_frame_num_value_allowed_flag
這個句法元素等于 1 時,表示允許句法元素 frame_num 可以不連續(xù)。當傳輸信道堵塞嚴重時,編碼器來不及將編碼后的圖像全部發(fā)出,這時允許丟棄若干幀圖像。在正常情況下每一幀圖像都有依次連續(xù)的frame_num 值,解碼器檢查到如果 frame_num 不連續(xù),便能確定有圖像被編碼器丟棄。這時,解碼器必須啟動錯誤掩藏的機制來近似地恢復這些圖像,因為這些圖像有可能被后續(xù)圖像用作參考幀。
當這個句法元素等于 0 時,表不允許 frame_num 不連續(xù),即編碼器在任何情況下都不能丟棄圖像。這時,H.264 允許解碼器可以不去檢查 frame_num 的連續(xù)性以減少計算量。這種情況下如果依然發(fā)生 frame_num 不連續(xù),表示在傳輸中發(fā)生丟包,解碼器會通過其他機制檢測到丟包的發(fā)生,然后啟動錯誤掩藏的恢復圖像。
(9). pic_width_in_mbs_minus1
本句法元素加 1 后指明圖像寬度,以宏塊為單位:
PicWidthInMbs = pic_width_in_mbs_minus1 + 1
通過這個句法元素解碼器可以計算得到亮度分量以像素為單位的圖像寬度:
PicWidthInSamplesL = PicWidthInMbs * 16
從而也可以得到色度分量以像素為單位的圖像寬度:
PicWidthInSamplesC = PicWidthInMbs * 8
以上變量 PicWidthInSamplesL、PicWidthInSamplesC 分別表示圖像的亮度、色度分量以像素為單位的寬。
H.264 將圖像的大小在序列參數(shù)集中定義,意味著可以在通信過程中隨著序列參數(shù)集動態(tài)地改變圖像的大小,在后文中可以看到,甚至可以將傳送的圖像剪裁后輸出。
(10). pic_height_in_map_units_minus1
本句法元素加 1 后指明圖像高度:
PicHeightInMapUnits = pic_height_in_map_units_minus1 + 1
PicSizeInMapUnits = PicWidthInMbs * PicHeightInMapUnits
圖像的高度的計算要比寬度的計算復雜,因為一個圖像可以是幀也可以是場,從這個句法元素可以在幀模式和場模式下分別計算出出亮度、色度的高。值得注意的是,這里以 map_unit 為單位,map_unit的含義由后文敘述。
(11). frame_mbs_only_flag
本句法元素等于 0 時表示本序列中所有圖像的編碼模式都是幀,沒有其他編碼模式存在;本句法元素等于 1 時 ,表示本序列中圖像的編碼模式可能是幀,也可能是場或幀場自適應,某個圖像具體是哪一種要由其他句法元素決定。
結(jié)合 map_unit 的含義,這里給出上一個句法元素 pic_height_in_map_units_minus1的進一步解析步驟:
當 frame_mbs_only_flag 等于1,pic_height_in_map_units_minus1 指的是一個 picture 中幀的高度;
當frame_mbs_only_flag 等于0,pic_heght_in_map_units_minus1 指的是一個 picture 中場的高度,所以可以得到如下以宏塊為單位的圖像高度:
FrameHeightInMbs = ( 2 – frame_mbs_only_flag ) * PicHeightInMapUnits
PictureHeightInMbs= ( 2 – frame_mbs_only_flag ) * PicHeightInMapUnits
(12). mb_adaptive_frame_field_flag
指明本序列是否屬于幀場自適應模式。mb_adaptive_frame_field_flag等于1時表明在本序列中的圖像如果不是場模式就是幀場自適應模式,等于0時表示本序列中的圖像如果不是場模式就是幀模式。。表 列舉了一個序列中可能出現(xiàn)的編碼模式:
- a. 全部是幀,對應于 frame_mbs_only_flag =1 的情況。
- b. 幀和場共存。frame_mbs_only_flag =0, mb_adaptive_frame_field_flag =0
- c. 幀場自適應和場共存。frame_mbs_only_flag =0, mb_adaptive_frame_field_flag =1
值得注意的是,幀和幀場自適應不能共存在一個序列中。
(13). direct_8x8_inference_flag
用于指明 B 片的直接和 skip 模式下運動矢量的預測方法。
(14). frame_cropping_flag
用于指明解碼器是否要將圖像裁剪后輸出,如果是的話,后面緊跟著的四個句法元素分別指出左右、上下裁剪的寬度。
(15). vui_parameters_present_flag
指明 vui 子結(jié)構(gòu)是否出現(xiàn)在碼流中,vui 的碼流結(jié)構(gòu)在附錄中指明,用以表征視頻格式等額外信息。