分包
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)