1. 程式人生 > >H264碼流結構分析和rtp打包結構詳解

H264碼流結構分析和rtp打包結構詳解



網路抽象層單元型別 (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-23  NAL單元  單個 NAL 單元包

  24    STAP-A   單一時間的組合包
  25    STAP-B   單一時間的組合包
  26    MTAP16   多個時間的組合包
  27    MTAP24   多個時間的組合包
  28    FU-A     分片的單元
  29    FU-B     分片的單元
  30-31 沒有定義

h264僅用1-23,24以後的用在RTP H264負載型別頭中

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             |
      |                             ....                              |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

      負載型別 Payload type(PT): 7bits
rfc裡面對一些早期的格式定義了這個payload type。但是後來的,如h264並沒有分配,那就用96來代替。因此現在96以上都不表示特定的格式,具體表示什麼要用sdp或者其他協議來協商。

      序列號 Sequence number(SN): 16bits
      時間戳 Timestamp: 32bits

上面介紹了NALU和RTP header的基本結構,下面介紹的全部都是RTP PayLoad的部分

Rtp負載第一個位元組的結構如下,它和H.264的NALU頭結構一致,可以把它認為是RTP h264負載型別

位元組,完全是多增加的一個位元組,不影響後面的NALU結構

      +---------------+
      |0|1|2|3|4|5|6|7|
      +-+-+-+-+-+-+-+-+
      |F|NRI|  Type   |
      +---------------+

這裡的Type型別除1-23外還可取以下值:

  24    STAP-A   單一時間的組合包
  25    STAP-B   單一時間的組合包
  26    MTAP16   多個時間的組合包
  27    MTAP24   多個時間的組合包
  28    FU-A     分片的單元
  29    FU-B     分片的單元

如果使用1-23就是:單一NAL單元模式

封包介紹:

單一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 個位元組的開始碼就可以了.


組合封包模式

  其次, 當 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        |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

這裡只介紹STAP-A模式,如果是STAP-B的話會多加入一個DON域,另外還有MTAP16、MTAP24,具體不介紹,可以看rfc文件,文章尾貼一個連結可以去看。

例:

如有一個 H.264 的 NALU 是這樣的:

  [00 00 00 01 67 42 A0 1E 23 56 0E 2F ... ]

  [00 00 00 01 68 42 B0 12 58 6A D4 FF ... ]

  封裝成 RTP 包將如下:

  [ RTP Header ] [78 (STAP-A頭,佔用1個位元組)] [第一個NALU長度 (佔用兩個位元組)] [ 67 42 A0 1E 23 56 0E 2F ] [第二個NALU長度 (佔用兩個位元組)] [68 42 B0 12 58 6A D4 FF ... ]

分片的單元:

  當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   |
      +---------------+

   別被名字嚇到這個格式就是上面提到的RTP h264負載型別,Type為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保留位

   Type就是NALU頭中的Type,取1-23的那個值

附:

一個翻譯過的rfc3984文件,翻譯的有點亂,湊貨的看看

http://wenku.baidu.com/view/0f612e1ec5da50e2524d7f32.html