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

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

GitHub程式碼地址:點選這裡

H.264中的條帶(Slice)

1. Slice的概念

我們已經知道,整個H.264的碼流結構可以分為兩層:網路抽象層NAL和視訊編碼層VCL。在NAL層,H.264的碼流表示為一系列的NAL Units,不同的NAL Units中包含不同型別的語法元素。前面兩篇中所解析的序列引數集SPS和影象引數集PPS就是其中重要的兩個部分,其中包含了控制解碼過程的一些通用的引數。

實際儲存原始視訊的影象資料的部分儲存在其他的VCL層的NAL Units中。這部分資料在碼流中稱作是條帶(Slice)。一個Slice包含一幀影象的部分或全部資料,換言之,一幀視訊影象可以編碼為一個或若干個Slice。一個Slice最少包含一個巨集塊,最多包含整幀影象的資料。在不同的編碼實現中,同一幀影象中所構成的Slice數目不一定相同。

在H.264中設計Slice的目的主要在於防止誤碼的擴散。因為不同的slice之間,其解碼操作是獨立的。某一個slice的解碼過程所參考的資料(例如預測編碼)不能越過slice的邊界。

2. Slice的型別

根據碼流中不同的資料型別,H.264標準中共定義了5總Slice型別:

  • I slice: 幀內編碼的條帶;
  • P slice: 單向幀間編碼的條帶;
  • B slice: 雙向幀間編碼的條帶;
  • SI slice: 切換I條帶,用於擴充套件檔次中碼流切換使用;
  • SP slice: 切換P條帶,用於擴充套件檔次中碼流切換使用;

在I slice中只包含I巨集塊,不能包含P或B巨集塊;在P和B slice中,除了相應的P和B型別巨集塊之外,還可以包含I型別巨集塊。

3. Slice的組成

每一個Slice總體來看都由兩部分組成,一部分作為Slice header,用於儲存Slice的總體資訊(如當前Slice的型別等),另一部分為Slice body,通常是一組連續的巨集塊結構(或者巨集塊跳過資訊),如下圖所示:

4. Slice Header結構

Slice header中主要儲存了當前slice的一些全域性的資訊,slice body中的巨集塊在進行解碼時需依賴這些資訊。其中比較常見的一些語法元素有:

  1. first_mb_in_slice: 當前slice中包含的第一個巨集塊在整幀中的位置;
  2. slice_type:當前slice的型別;
  3. pic_parameter_set_id:當前slice所依賴的pps的id;
  4. colour_plane_id:當標識位separate_colour_plane_flag為true時,colour_plane_id表示當前的顏色分量,0、1、2分別表示Y、U、V分量。
  5. frame_num:表示當前幀序號的一種計量方式。
  6. field_pic_flag:場編碼標識位。當該標識位為1時表示當前slice按照場進行編碼;該標識位為0時表示當前slice按照幀進行編碼。
  7. bottom_field_flag:底場標識位。該標誌位為1表示當前slice是某一幀的底場;為0表示當前slice為某一幀的頂場。
  8. idr_pic_id:表示IDR幀的序號。某一個IDR幀所屬的所有slice,其idr_pic_id應保持一致。該值的取值範圍為[0,65535]。
  9. pic_order_cnt_lsb:表示當前幀序號的另一種計量方式。
  10. delta_pic_order_cnt_bottom:表示頂場與底場POC差值的計算方法,不存在則預設為0;
  11. slice_qp_delta:用於計算當前slice內所使用的初始qp值。

整個slice header的結構如下表所示: