開發(fā)一個(gè)網(wǎng)站測(cè)試要怎么做的seo平臺(tái)優(yōu)化服務(wù)
H.264視頻流的RTP封裝類型分析:
前言:
1.RTP打包原則:
????????RTP的包長(zhǎng)度必須要小于MTU(最大傳輸單元),IP協(xié)議中MTU的最大長(zhǎng)度為1500字節(jié)。除去IP報(bào)頭(20字節(jié))、UDP報(bào)頭(8字節(jié))、RTP頭(12字節(jié)),所有RTP有效載荷(即NALU內(nèi)容)的長(zhǎng)度不得超過1460字節(jié)。
NULL Hearder簡(jiǎn)介(結(jié)構(gòu)如下):
+---------------+|0|1|2|3|4|5|6|7|+-+-+-+-+-+-+-+-+|F|NRI| Type |+---------------+
- F:forbidden_zero_bit, 占1位,在 H.264 規(guī)范中規(guī)定了這一位必須為 0;
- NRI:nal_ref_idc, 占2位,取值從0到3,指示這個(gè) NALU 的重要性,取值越大約重要;
- Type:nalu是指包含在 NAL 單元中的 RBSP 數(shù)據(jù)結(jié)構(gòu)的類型,其中0未指,1-19在264協(xié)議中有定義,20-23為264協(xié)議指定的保留位。24-29在RFC3984中進(jìn)行了指定。其中STAP-A為24,FU-A為28。
其中Type詳細(xì)介紹前文以敘述:RFC3984: RTP Payload Format for H.264 Video(中英文版)官方文獻(xiàn),RTP協(xié)議頭格式分析詳解;RTP載荷H264碼流;
????????其中我們看到1-11就是NALU的單個(gè)包類型,但是一個(gè)NALU的大小是不一樣的,如果是非視頻數(shù)據(jù)的SPS PPS才十幾個(gè)字節(jié),對(duì)于IDR幀,則有可能幾十KB。這樣把NALU打包到RTP方式就很多:分為一個(gè)RTP包承載一個(gè)NALU,多個(gè)NALU合并到一個(gè)RTP,一個(gè)大的NALU切分成多個(gè)RTP。同時(shí)由于時(shí)間戳的問題,就有了24-29幾種類型。
????????但是對(duì)于發(fā)送端組RTP包的一方來說,盡可能找簡(jiǎn)單的打包方式。對(duì)于接受端則需要適配各種發(fā)送端的打包方式,因?yàn)闊o法決定輸入源的打包方式。這里先分享下我們的打包方式,比較簡(jiǎn)單:
- 我們對(duì)于NALU的長(zhǎng)度<1400的則采用的是單一NALU打包到單一的RTP包中;
- 我們對(duì)于NALU的長(zhǎng)度>=1400的則采用了FU-A的方式進(jìn)行了打包,這種就是把一個(gè)大的NALU進(jìn)行了切分,最后接收方則進(jìn)行了合并,把多個(gè)RTP包合并成一個(gè)完整的NALU即可;
- 至于為什么NALU的長(zhǎng)度大于1400字節(jié)就要進(jìn)行FU-A切片,是因?yàn)榈讓覯TU大小值固定為1500,從傳輸效率講,這里用1400作為切分條件。
2.RTP打包模式:?
主要分為三種模式:單一NALU模式、分片模式、組合模式,實(shí)際中前兩種用的比較多。
一、單一NALU模式分析:
1.單一NALU模式結(jié)構(gòu)如下:
0 1 2 30 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 |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2.抓包對(duì)照分析
二、分片包模式分析
1.FU-A和FU-B的結(jié)構(gòu)如下:
// 5.8. Fragmentation Units (FUs) (p29)
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 | DON |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
| |
| FU payload |
| |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| : ...OPTIONAL RTP padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
?
注意:STAP-A和FU-A的RTP荷載結(jié)構(gòu)不包含DON(解碼順序號(hào)). STAP-B,FU-B結(jié)構(gòu)包含DON。
與單一封包不一樣的是,|F|NRI|type|變成了|FU indicator|FU header|。其實(shí),|FU indicator|就是|F|NRI|type|,但是額外增加了|FU header|用于標(biāo)識(shí)當(dāng)前分片的狀態(tài),如下所示:
// FU header 結(jié)構(gòu)如下:+---------------+|0|1|2|3|4|5|6|7|+-+-+-+-+-+-+-+-+|S|E|R| Type |+---------------+
- S: 1 bit 當(dāng)設(shè)置成1,開始位指示分片NAL單元的開始。當(dāng)跟隨的FU荷載不是分片NAL單元荷載的開始,開始位設(shè)為0;
- E: 1 bit 當(dāng)設(shè)置成1, 結(jié)束位指示分片NAL單元的結(jié)束,即, 荷載的最后字節(jié)也是分片NAL單元的最后一個(gè)字節(jié)。當(dāng)跟隨的FU荷載不是分片NAL單元的最后分片,結(jié)束位設(shè)置為0;
- R: 1 bit 保留位必須設(shè)置為0,接收者必須忽略該位;
- Type: 5 bits NAL單元荷載類型定義在[1]的表7-1(與前文中的type一致,不做展開)。
2.抓包對(duì)照分析,以FU-A為例
三、組合包封裝模式分析
1.STAP-A結(jié)構(gòu)如下(type 24):
當(dāng)NALU的長(zhǎng)度特別小時(shí),可以把幾個(gè)NALU封在一個(gè)RTP包中。下面的是STAP-A模式,如果是STAP-B的話會(huì)多加入一個(gè)DON域。
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 RTP包包含一個(gè)STAP-A. STAP包含兩個(gè)單時(shí)刻聚合單元
?2.STAP-B結(jié)構(gòu)如下(type 25):
0 1 2 30 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-B NAL HDR | DON | NALU 1 Size |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| NALU 1 Size | NALU 1 HDR | NALU 1 Data |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +: :+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| | NALU 2 Size | NALU 2 HDR |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| NALU 2 Data |: :| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| :...OPTIONAL RTP padding |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+圖STAP-B 一個(gè)RTP包包含一個(gè)STAP-B. STAP包含兩個(gè)單時(shí)刻聚合單元例子
- RTP Header(1 byte):RTP協(xié)議頭,前文有敘述,不做展開;
- STAP-(A/B)?NAL HDR():STAP-(A/B)幀頭,與前文的|F|NRI|type|結(jié)構(gòu)一致;
- DON:解碼順序號(hào),STAP-A幀不包含DON,STAP-B幀的話則會(huì)多加入一個(gè)DON域;
例:如有一個(gè) 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個(gè)字節(jié))] [第一個(gè)NALU長(zhǎng)度 (占用兩個(gè)字節(jié))] [ 67 42 A0 1E 23 56 0E 2F ... ] [第二個(gè)NALU長(zhǎng)度 (占用兩個(gè)字節(jié))] [68 42 B0 12 58 6A D4 FF ... ]