1. 程式人生 > 實用技巧 >RTP分包解包 ---- H264

RTP分包解包 ---- H264

分包

1、單個NAL包單元

12位元組的RTP頭後面的就是音視訊資料,比較簡單。一個封裝單個NAL單元包到RTP的NAL單元流的RTP序號必須符合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. 組合封包模式

當 NALU 的長度特別小時, 可以把幾個 NALU 單元封在一個 RTP 包中.

3、FU-A的分片格式

資料比較大的H264視訊包,被RTP分片傳送。12位元組的RTP頭後面跟隨的就是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

1) FU indicator有以下格式:

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

FU指示位元組的型別域的28,29表示FU-A和FU-B。NRI域的值必須根據分片NAL單元的NRI域的值設定。(此處Type就是rtp分片型別) 見下表

  .Type   Packet      Type name                       
  ---------------------------------------------------------
  0      undefined                                    -
  1-23   NAL unit    Single NAL unit packet per H.264  
  24     STAP-A     Single-time aggregation packet    
  25     STAP-B     Single-time aggregation packet    
  26     MTAP16    Multi-time aggregation packet     
  27     MTAP24    Multi-time aggregation packet     
  28     FU-A      Fragmentation unit                
  29     FU-B      Fragmentation unit                 
  30-31  undefined  

FU header的格式如下:

  +---------------+
  |0|1|2|3|4|5|6|7|
  +-+-+-+-+-+-+-+-+
  |S|E|R|  Type   |
  +---------------+

S: 1 bit 當設定成1,開始位指示分片NAL單元的開始。當跟隨的FU荷載不是分片NAL單元荷載的開始,開始位設為0。

E: 1 bit 當設定成1, 結束位指示分片NAL單元的結束,即, 荷載的最後位元組也是分片NAL單元的最後一個位元組。
當跟隨的FU荷載不是分片NAL單元的最後分片,結束位設定為0。

R: 1 bit
保留位必須設定為0,接收者必須忽略該位。

Type: 5 bits
此處的Type就是NALU頭中的Type,取1-23的那個值,表示 NAL單元荷載型別定義。

注意:

1. 裝載FU payload部分時候,需要去掉nalu的header(第一個位元組)

2. 一般I幀前面傳送sps和pps,時間戳和I幀相同

3. h264的取樣率固定是9000hz

拆包和解包

拆包:當編碼器在編碼時需要將原有一個NAL按照FU-A進行分片,原有的NAL的單元頭與分片後的FU-A的單元頭有如下關係:

原始的NAL頭的前三位為FU indicator的前三位,原始的NAL頭的後五位為FU header的後五位,

FU indicator與FU header的剩餘位數根據實際情況決定。

解包:當接收端收到FU-A的分片資料,需要將所有的分片包組合還原成原始的NAl包時,FU-A的單元頭與還原後的NAL的關係如下:

還原後的NAL頭的八位是由FU indicator的前三位加FU header的後五位組成,即:

nal_unit_type = (fu_indicator & 0xe0) | (fu_header & 0x1f)