rtp h264打包和解包

1、學習思路

         在瞭解rtp對h264數據的打包之前,需要對rtp、h264的一些基本概念有一個初步的瞭解,然後再使用rtp對h264的打包解包做解析

2、rtp認知

實時傳送協議(Real-time Transport Protocol或簡寫RTP,也可以寫成RTTP)是一個網絡傳輸協議,它是由IETF的多媒體傳輸工作小組1996年在RFC 1889中公佈的。
RTP協議詳細說明了在互聯網上傳遞音頻和視頻的標準數據包格式。它一開始被設計爲一個多播協議,但後來被用在很多單播應用中。RTP協議常用於流媒體系統(配合RTCP協議或者RTSP協議)。因爲RTP自身具有Time stamp所以在ffmpeg 中被用做一種formate.
RTP協議格式:
    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |V=2|P|X|  CC      |M|     PT           |       sequence number         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                           timestamp                                                           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           synchronization source (SSRC) identifier                     |
   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
   |            contributing source (CSRC) identifiers                        |
   |                             ....                                                                         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
上圖引自rfc3550,由上圖中可知道RTP報文由兩個部分構成--RTP報頭和RTP的負載:
RTP報文由兩部分組成:報頭和有效載荷。RTP報頭格式如圖6.7所示,其中:
1.V:RTP協議的版本號,佔2位,當前協議版本號爲2。
2. P:填充標誌,佔1位,如果P=1,則在該報文的尾部填充一個或多個額外的八位組,它們不是有效載荷的一部分。
3. X:擴展標誌,佔1位,如果X=1,則在RTP報頭後跟有一個擴展報頭。
4.  CC:CSRC計數器,佔4位,指示CSRC 標識符的個數。
5. M: 標記,佔1位,不同的有效載荷有不同的含義,對於視頻,標記一幀的結束;對於音頻,標記會話的開始。
6. PT: 有效載荷類型,佔7位,用於說明RTP報文中有效載荷的類型,如GSM音頻、JPEM圖像等,在流媒體中大部分是用來區分音頻流和視頻流的,這樣便於客戶端進行解析。
7. 序列號:佔16位,用於標識發送者所發送的RTP報文的序列號,每發送一個報文,序列號增1。這個字段當下層的承載協議用UDP的時候,網絡狀況不好的時候可以用來檢查丟包。同時出現網絡抖動的情況可以用來對數據進行重新排序,在helix服務器中這個字段是從0開始的,同時音頻包和視頻包的sequence是分別記數的。
8. 時戳(Timestamp):佔32位,時戳反映了該RTP報文的第一個八位組的採樣時刻。接收者使用時戳來計算延遲和延遲抖動,並進行同步控制。
9. 同步信源(SSRC)標識符:佔32位,用於標識同步信源。該標識符是隨機選擇的,參加同一視頻會議的兩個同步信源不能有相同的SSRC。
10. 特約信源(CSRC)標識符:每個CSRC標識符佔32位,可以有0~15個。每個CSRC標識了包含在該RTP報文有效載荷中的所有特約信源。
如果擴展標誌被置位則說明緊跟在報頭後面是一個頭擴展,其格式如下:
    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |      defined by profile                  |           length                            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                        header extension                                                   |
   |                             ....                                                                             |




3、h264認知

H264數據2層結構:
一:視頻編碼層(VCL)
二:網絡適配層(NAL)
    在H.264/AVC視頻編碼標準中,整個系統框架被分爲了兩個層面:視頻編碼層面(VCL)和網絡抽象層面(NAL)。其中,前者負責有效表示視頻數據的內容,而後者則負責格式化數據並提供頭信息,以保證數據適合各種信道和存儲介質上的傳輸。NAL佔一個字節。
    NAL單元(NALU):NAL的基本語法結構,它包含一個字節的頭信息和一系列來自VCL的稱爲原始字節序列載荷(RBSP)的字節流。
數據流是儲存在介質上時: 每個NALU 前添加起始碼:0x00000001(或者0x000001),用來指示一個 NALU的起始和終止位置。

NALU頭由一個字節組成, 它的語法如下:
      +---------------+
      |0|1|2|3|4|5|6|7|
      +-+-+-+-+-+-+-+-+
      |F|NRI|  Type   |
      +---------------+
F: 1 個比特.
  forbidden_zero_bit. 在 H.264 規範中規定了這一位必須爲 0.
NRI: 2 個比特.
  nal_ref_idc. 取 00 ~ 11, 似乎指示這個 NALU 的重要性, 如 00 的 NALU 解碼器可以丟棄它而不影響圖像的回放. 不過一般情況下不太關心
這個屬性.
Type: 5 個比特.
 nal_unit_type. 這個 NALU 單元的類型. 簡述如下:
0    沒有定義
1     一個非IDR圖像的編碼條帶 (bp幀)
slice_layer_without_partitioning_rbsp( )     
2     編碼條帶數據分割塊A
slice_data_partition_a_layer_rbsp( )     
3     編碼條帶數據分割塊B
slice_data_partition_b_layer_rbsp( )     
4     編碼條帶數據分割塊C
slice_data_partition_c_layer_rbsp( )     
5     IDR圖像的編碼條帶 (i幀)
slice_layer_without_partitioning_rbsp( )     
6     輔助增強信息 (SEI)
sei_rbsp( )     
7     序列參數集 (sps幀)
seq_parameter_set_rbsp( )     
8     圖像參數集
pic_parameter_set_rbsp( pps幀)     
9     訪問單元分隔符
access_unit_delimiter_rbsp( )     
10     序列結尾
end_of_seq_rbsp( )     
11     流結尾
end_of_stream_rbsp( )     
12     填充數據
filler_data_rbsp( )     
13     序列參數集擴展
seq_parameter_set_extension_rbsp( )     
14...18     保留     
19     未分割的輔助編碼圖像的編碼條帶
slice_layer_without_partitioning_rbsp( )     
20...23     保留     
24    STAP-A   單一時間的組合包
25    STAP-B   單一時間的組合包
26    MTAP16   多個時間的組合包
27    MTAP24   多個時間的組合包
28    FU-A     分片的單元
29    FU-B     分片的單元
30-31 沒有定義

4、rtp 對h264的打包和解包

rtp 打包結構分類:
  1. 單一 NAL 單元模式
     即一個 RTP 包僅由一個完整的 NALU 組成. 這種情況下 RTP NAL 頭類型字段和原始的 H.264的
  NALU 頭類型字段是一樣的.
  2. 組合封包模式
    即可能是由多個 NAL 單元組成一個 RTP 包. 分別有4種組合方式: STAP-A, STAP-B, MTAP16, MTAP24.
  那麼這裏的類型值分別是 24, 25, 26 以及 27.
  3. 分片封包模式
    用於把一個 NALU 單元封裝成多個 RTP 包. 存在兩種類型 FU-A 和 FU-B. 類型值分別是 28 和 29.通用採用FU-A 。
2.1 單一 NAL 單元模式
  對於 NALU 的長度小於 MTU 大小的包, 一般採用單一 NAL 單元模式.
  對於一個原始的 H.264 NALU 單元常由 [Start Code] [NALU Header] [NALU Payload] 三部分組成, 其中 Start Code 用於標示這是一個
NALU 單元的開始, 必須是 "00 00 00 01" 或 "00 00 01", NALU 頭僅一個字節, 其後都是 NALU 單元內容.
  打包時去除 "00 00 01" 或 "00 00 00 01" 的開始碼, 把其他數據封包的 RTP 包即可.
       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |F|NRI|  type   |                                                                                 |
      +-+-+-+-+-+-+-+-+                                                                           |
      |                                                                                                         |
      |               Bytes 2..n of a Single NAL unit                                    |
      |                                                                                                          |
      |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                               :...OPTIONAL RTP padding                          |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

  如有一個 H.264 的 NALU 是這樣的:
  [00 00 00 01 67 42 A0 1E 23 56 0E 2F ... ]
  這是一個序列參數集 NAL 單元. [00 00 00 01] 是四個字節的開始碼, 67 是 NALU 頭, 42 開始的數據是 NALU 內容.
  封裝成 RTP 包將如下:
  [ RTP Header ] [ 67 42 A0 1E 23 56 0E 2F ]
  即只要去掉 4 個字節的開始碼就可以了.

2.2 組合封包模式
  其次, 當 NALU 的長度特別小時, 可以把幾個 NALU 單元封在一個 RTP 包中.
 
       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                          RTP Header                                                         |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |STAP-A NAL HDR |         NALU 1 Size           | NALU 1 HDR    |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                         NALU 1 Data                                                          |
      :                                                               :
      +               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |               | NALU 2 Size                   | NALU 2 HDR    |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                         NALU 2 Data                                                         |
      :                                                               :
      |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                               :...OPTIONAL RTP padding                          |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

2.3 分片打包(FU A).
  而當 NALU 的長度超過 MTU 時, 就必須對 NALU 單元進行分片封包. 也稱爲 Fragmentation Units (FUs).
 
       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      | FU indicator  |   FU header   |                                                      |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                                              |
      |                                                                                                          |
      |                         FU payload                                                            |
      |                                                                                                          |
      |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                               :...OPTIONAL RTP padding                          |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      Figure 14.  RTP payload format for FU-A
   The FU indicator octet has the following format:
      +---------------+
      |0|1|2|3|4|5|6|7|
      +-+-+-+-+-+-+-+-+
      |F|NRI|  Type   |
      +---------------+
      F     NALU頭中的F
      NRI     NALU頭中的NRI
      type    28 表示 FU-A打包
   The FU header has the following format:
      +---------------+
      |0|1|2|3|4|5|6|7|
      +-+-+-+-+-+-+-+-+
      |S|E|R|  Type   |
      +---------------+
      S     bit爲1表示分片的NAL開始,當它爲1時,E不能爲1
      E     bit爲1表示結束,當它爲1,S不能爲1
      R     bit保留位,必須是0
      Type    就是NALU頭中的Type,取1-23的那個值

分片打包解包實例:

80 60 01 0f 00 0e 1000 00 00 00 00 7c 85 8882

00 0a 7f  ca 94 053b 7f  3e 7f  fe14  2b 27 26 f8

89 88 dd85 62 e1 6d fc 33 01 38 1a 10 35 f214 

84 6e 21 24 8f  7262 f0 51 7e 10 5f 0d 42 71 12

17 65 62 a1 f1  44dc df 4b 4a 38 aa 96 b7 dd 24

12字節爲RTP

7c是分片單元指示,01111100  1c-28(FU-A)

85是分片單元頭, 1000 0101 NAl Type=5(關鍵幀)

解包時,取FU-A indicator的前三位和FU Header的後五位,即011001010x65)NAL類型



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章