天天看點

【H.264/AVC視訊編解碼技術詳解】 九、序列參數集Sequence Paramater Set(SPS)解析

《H.264/AVC視訊編解碼技術詳解》視訊教程已經在“CSDN學院”上線,視訊中詳述了H.264的背景、标準協定和實作,并通過一個實戰工程的形式對H.264的标準進行解析和實作,歡迎觀看!

“紙上得來終覺淺,絕知此事要躬行”,隻有自己按照标準文檔以代碼的形式操作一遍,才能對視訊壓縮編碼标準的思想和方法有足夠深刻的了解和體會!

連結位址:H.264/AVC視訊編解碼技術詳解

GitHub代碼位址:點選這裡

在H.264标準協定中規定了多種不同的NAL Unit類型,其中類型7表示該NAL Unit内儲存的資料為Sequence Paramater Set。在H.264的各種文法元素中,SPS中的資訊至關重要。如果其中的資料丢失或出現錯誤,那麼解碼過程很可能會失敗。SPS及後續将要講述的圖像參數集PPS在某些平台的視訊處理架構(比如iOS的VideoToolBox等)還通常作為解碼器執行個體的初始化資訊使用。

1. 什麼是SPS

如上文所述,SPS即Sequence Paramater Set,又稱作序列參數集。SPS中儲存了一組編碼視訊序列(Coded video sequence)的全局參數。所謂的編碼視訊序列即原始視訊的一幀一幀的像素資料經過編碼之後的結構組成的序列。而每一幀的編碼後資料所依賴的參數儲存于圖像參數集中。

在簡單的H.264編解碼的Demo(例如本系列博文、課程所做的SimpleH264Analyzer工程)中,一個SPS和PPS的NAL Unit通常位于整個碼流的起始位置。但在某些特殊情況下,在碼流中間也可能出現這兩種結構,主要原因可能為:

  1. 解碼器需要在碼流中間開始解碼;
  2. 編碼器在編碼的過程中改變了碼流的參數(如圖像分辨率等);

2. SPS的結構

在我們這個執行個體中,SPS NAL Unit中的二進制内容為:

42 00 1e e8 58 58 98 80
           

為了讓後續的解碼過程可以使用SPS中包含的參數,必須對其中的資料進行解析。其中H.264标準協定中規定的SPS格式位于文檔的7.3.2.1.1部分,如下圖所示:

【H.264/AVC視訊編解碼技術詳解】 九、序列參數集Sequence Paramater Set(SPS)解析
【H.264/AVC視訊編解碼技術詳解】 九、序列參數集Sequence Paramater Set(SPS)解析

其中的每一個文法元素及其含義如下:

(1). profile_idc:

辨別目前H.264碼流的profile。我們知道,H.264中定義了三種常用的檔次profile:

  • 基準檔次:baseline profile;
  • 主要檔次:main profile;
  • 擴充檔次:extended profile;

在H.264的SPS中,第一個位元組表示profile_idc,根據profile_idc的值可以确定碼流符合哪一種檔次。判斷規律為:

  • 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定義了某種條件下的最大視訊分辨率、最大視訊幀率等參數,碼流所遵從的level由level_idc指定。

目前碼流中,level_idc = 0x1e = 30,是以碼流的級别為3。

(3). seq_parameter_set_id

表示目前的序列參數集的id。通過該id值,圖像參數集pps可以引用其代表的sps中的參數。

(4). log2_max_frame_num_minus4

用于計算MaxFrameNum的值。計算公式為MaxFrameNum = 2^(log2_max_frame_num_minus4 + 4)。MaxFrameNum是frame_num的上限值,frame_num是圖像序号的一種表示方法,在幀間編碼中常用作一種參考幀标記的手段。

(5). pic_order_cnt_type

表示解碼picture order count(POC)的方法。POC是另一種計量圖像序号的方式,與frame_num有着不同的計算方法。該文法元素的取值為0、1或2。

(6). log2_max_pic_order_cnt_lsb_minus4

用于計算MaxPicOrderCntLsb的值,該值表示POC的上限。計算方法為MaxPicOrderCntLsb = 2^(log2_max_pic_order_cnt_lsb_minus4 + 4)。

(7). max_num_ref_frames

用于表示參考幀的最大數目。

(8). gaps_in_frame_num_value_allowed_flag

辨別位,說明frame_num中是否允許不連續的值。

(9). pic_width_in_mbs_minus1

用于計算圖像的寬度。機關為宏塊個數,是以圖像的實際寬度為:

frame_width = 16 × (pic\_width\_in\_mbs_minus1 + 1);
           

(10). pic_height_in_map_units_minus1

使用PicHeightInMapUnits來度量視訊中一幀圖像的高度。PicHeightInMapUnits并非圖像明确的以像素或宏塊為機關的高度,而需要考慮該宏塊是幀編碼或場編碼。PicHeightInMapUnits的計算方式為:

PicHeightInMapUnits = pic\_height\_in\_map\_units\_minus1 + 1;
           

(11). frame_mbs_only_flag

辨別位,說明宏塊的編碼方式。當該辨別位為0時,宏塊可能為幀編碼或場編碼;該辨別位為1時,所有宏塊都采用幀編碼。根據該辨別位取值不同,PicHeightInMapUnits的含義也不同,為0時表示一場資料按宏塊計算的高度,為1時表示一幀資料按宏塊計算的高度。

按照宏塊計算的圖像實際高度FrameHeightInMbs的計算方法為:

FrameHeightInMbs = ( 2 − frame_mbs_only_flag ) * PicHeightInMapUnits
           

(12). mb_adaptive_frame_field_flag

辨別位,說明是否采用了宏塊級的幀場自适應編碼。當該辨別位為0時,不存在幀編碼和場編碼之間的切換;當辨別位為1時,宏塊可能在幀編碼和場編碼模式之間進行選擇。

(13). direct_8x8_inference_flag

辨別位,用于B_Skip、B_Direct模式運動矢量的推導計算。

(14). frame_cropping_flag

辨別位,說明是否需要對輸出的圖像幀進行裁剪。

(15). vui_parameters_present_flag

辨別位,說明SPS中是否存在VUI資訊。