目錄
- 1、介紹
- 2、RTP
- 3、格式
- 4、RTP打包H264
- 4.1、H264打包方式之Single NAL Unit
- 4.2、H264打包方式之FU-A
- 4.2.1、FU indication
- 4.2.2、FU header
- 4.2.3、第一個IDR幀的NALU第一個切片
- 4.2.4、第一個IDR幀的NALU第二個切片
- 4.2.5、第一個IDR幀的NALU最后一個切片
- 5、RTP打包AAC
- 5.1、AU-headers-length
- 5.2、AU-header
- 5.3、AU
- 5.4、RTSP/SDP中AAC相關配置
- 5.5、AU-Header數據段的格式
1、介紹
實時流傳輸協議(RTSP:Real Time Streaming Protocol)是一種網絡傳輸協議,旨在發送低延遲流。
該協議由RealNetworks,Netscape和哥倫比亞大學的專家在1996年開發。它定義了應如何打包流中的數
據以進行傳輸。
2、RTP
RTP協議原理,負責對流媒體數據進行封包并實現媒體流的實時傳輸,即它按照RTP數據包格式來封裝流媒體數據,并利用與它綁定的協議進行數據包的傳輸。
RTP可以基于UDP和TCP兩種方式傳輸,兩種方式大致是一樣的,下面主要都是基于UDP的分析:
RTP在端口號1025到65535之間選擇一個未使用的偶數UDP端口號,而在同一次會話中的RTCP則使用下一個基數UDP端口號。
3、格式
RTP報文由兩部分組成:報頭和有效載荷。RTP報頭格式如下圖所示,其中:V:RTP協議的版本號,占2位,當前協議版本號為2。P:填充標志,占1位,如果P=1,則在該報文的尾部填充一個或多個額外的八位組,它們不是有效載荷
的一部分。X:擴展標志,占1位,如果X=1,則在RTP報頭后跟有一個擴展報頭。
CC:CSRC計數器,占4位,指示CSRC 標識符的個數。M: 標記,占1位,不同的有效載荷有不同的含義,對于視頻,標記一幀的結束;對于音頻,標記幀的開
始。PT: 有效載荷類型,占7位,用于說明RTP報文中有效載荷的類型,如GSM音頻、JPEM圖像等。
序列號:占16位,用于標識發送者所發送的RTP報文的序列號,每發送一個報文,序列號增1。接收者
通過序列號來檢測報文丟失情況,重新排序報文,恢復數據。時戳(Timestamp):占32位,時戳反映了該RTP報文的第一個八位組的采樣時刻。接收者使用時戳來
計算延遲和延遲抖動,并進行同步控制。同步信源(SSRC)標識符:占32位,用于標識同步信源。該標識符是隨機選擇的,參加同一視頻會議的
兩個同步信源不能有相同的SSRC。特約信源(CSRC)標識符:每個CSRC標識符占32位,可以有0~15個。每個CSRC標識了包含在該RTP
報文有效載荷中的所有特約信源。
1 typedef struct _rtp_header_t
2 {
3 uint32_t v:2; /* protocol version */
4 uint32_t p:1; /* padding flag */
5 uint32_t x:1; /* header extension flag */
6 uint32_t cc:4; /* CSRC count */
7 uint32_t m:1; /* marker bit */
8 uint32_t pt:7; /* payload type */
9 uint32_t seq:16; /* sequence number */
10 uint32_t timestamp; /* timestamp */
11 uint32_t ssrc; /* synchronization source */
12 } rtp_header_t;
同步信源:是指產生媒體流的信源,例如麥克風、攝像機、RTP混合器等。它通過RTP報頭中的一個32位數
字SSRC標識符來標識,而不依賴于網絡地址,接收者將根據SSRC標識符來區分不同的信源,進行RTP報
文的分組。
特約信源:是指當混合器接收到一個或多個同步信源的RTP報文后,經過混合處理產生一個新的組合RTP報
文,并把混合器作為組合RTP報文的SSRC,而將原來所有的SSRC都作為CSRC傳送給接收者,使接收者
知道組成組合報文的各個SSRC。
例如:
有三個信號源各發出一路rtp流,RTP1攜帶的SSRC是SSRC1,RTP2攜帶的SSRC是SSRC2,
RTP3攜帶SSRC3,這三路RTP流到達混合器時,混合器會將這三路流混合成一路流發出去,它會把這三
路流的SSRC記錄下來,形成一個列表,叫CSRC表,在發送的混合RTP流中,SSRC域填充的字段是混合
器本身的SSRC4,而CSRC字段則會根據該包的負載的源來填入。
如當前的RTP包的負載是來自SSRC1的,那么在當前RTP包的CSRC字段填入SSRC1。
這樣接收者就可以根據CSRC來區分不同的信源。
4、RTP打包H264
RTP的特點不僅僅支持承載在UDP上,這樣利于低延遲音視頻數據的傳輸,另外一個特點是它允許
通過其它協議接收端和發送端協商音視頻數據的封裝和編解碼格式,這樣固定頭的playload type字
段就比較靈活。
H.264標準協議定義了兩種不同的類型:一種是VCL即Video Coding Layer , 一 種 是 NAL 即
Network Abstraction Layer。其中前者就是編碼器吐出來的原始編碼數據,沒有考慮傳輸和存儲
問題。后面這種就是為了展現H.264的網絡親和性,對VCL輸出的slice片數據進行了封裝為
NALUs(NAL Units),然后再封裝為RTP包進行傳輸。
NALU的基本格式是:NALU Header + NALU Data,其中NALU的頭由一個字節組成如下所示:
一、
1-11就是NALU的單個包類型,但是一個NALU的大小是不一樣的,如果是非視頻數據的
SPS PPS才十幾個字節,對于IDR幀,則有可能幾十KB。
這樣把NALU打包到RTP方式就很多,分為:
一個RTP包承載一個NALU;
多個NALU合并到一個RTP;
一個大的NALU切分成多個RTP。
二、
同時由于時間戳的問題,就有了24-29幾種類型。
但是對于發送端組RTP包的一方來說,盡可能找簡單的打包方式。對于接受端則需要適配各種發送
端的打包方式,因為無法決定輸入源的打包方式。
(打包的時候不要搞太復雜的模式)
- 我們對于NALU的長度<=1400(rtp payload size)的則采用的是單一NALU打包到單一的RTP
包中; - 我們對于NALU的長度>1400的則采用了FU-A的方式進行了打包,這種就是把一個大的NALU進
行了切分,最后接收方則進行了合并,把多個RTP包合并成一個完整的NALU即可; - 為什么NALU的長度大于1400字節就要進行FU-A切片,是因為底層MTU大小值一般為1500,從
傳輸效率講,使用1400作為切分條件。
RTP最大數據包(包含RTP頭部) = MTU - UDP首部 - IP 報文首部
4.1、H264打包方式之Single NAL Unit
一個RTP包打包一個單獨的NALU方式,其實最好理解,就是在RTP固定頭后直接填充NLAU
單元數據即可,即:
RTP Header + NALU Header + NALU Data; (不包括startcode)
文件中的SPS:
RTP包中的SPS:
4.2、H264打包方式之FU-A
需要了解兩個數據包頭即FU indicator和Fu header。
4.2.1、FU indication
這里面的的F和NRI就是NALU頭的前面三個bit位,后面的
TYPE就是NALU的FU-A類型28,這樣在RTP固定頭后面第一字節的后面5bit提取出來就確認了該
RTP包承載的不是一個完整的NALU,是其一部分。
那么問題來了,一個NALU切分成多個RTP包傳輸,那么到底從哪里開始哪里結束呢?
可能有人說RTP包固定頭不是有mark標記么,注意區分那個是以幀圖像的結束標記,這里要確定是NALU結束
的標記,其次NALU的類型呢?那么就需要RTP固定12字節后面的Fu Header來進行區分。
4.2.2、FU header
字段解釋:
S: 1 bit 當設置成1,開始位指示分片NAL單元的開始。當跟隨的FU荷載不是分片NAL單元荷載的開
始,開始位設為0。E: 1 bit 當設置成1, 結束位指示分片NAL單元的結束,即, 荷載的最后字節也是分片NAL單元的最后
一個字節,當跟隨的FU荷載不是分片NAL單元的最后分片,結束位設置為0。
也就是說一個NALU切片時,第一個切片的SE是10,然后中間的切片是00,最后一個切片時11。R: 1 bit
保留位必須設置為0,接收者必須忽略該位。Type: 5 bits
此處的Type就是NALU頭中的Type,取1-23的那個值,表示 NAL單元荷載類型定義。
4.2.3、第一個IDR幀的NALU第一個切片
FU indication:
十六機制:0x7C
二進制:0111 1100
FU header:
十六進制:0x85
二進制:1000 0101
這里的SE是10,則說明該RTP包承載的NALU的第一個切片。
4.2.4、第一個IDR幀的NALU第二個切片
FU indication:
十六機制:0x7C
二進制:0111 1100
FU header:
十六進制:0x05
二進制:0000 0101
這里的SE是00,則說明該RTP包承載的NALU的中間切片。
4.2.5、第一個IDR幀的NALU最后一個切片
FU indication:
十六機制:0x7C
二進制:0111 1100
FU header:
十六進制:0x45
二進制:0100 0101
這里的SE是01,則說明該RTP包承載的NALU的最后一個切片。
5、RTP打包AAC
過程:
- 需要將aac的前7個(或9個)字節的ADTS去掉,即是跳過adts header。
- 添加RTP Header。
- 添加AU_HEADER_LENGTH。
- 添加AU_HEADER。
- 添加AU(去掉ADTS的aac數據)數據。
注意:一個RTP包中可以有一個AU-headers-length 和 n個AU-header和 n個AU(AU每包實際音頻數據流)
5.1、AU-headers-length
頭兩個字節表示au-header的長度,單位是bit。 一個AU-header長度是兩個字節(16bit)因為可以有多
個au-header所以AU-headers-length的值是 16的倍數,一般音頻都是單個音頻數據流的發送,所以
AU-headers-length的值是16
//AU_HEADER_LENGTH
bytes[12] = 0x00; //高位
bytes[13] = 0x10; //低位 只有一個AU_HEADER
因為單位是bit, 除以8就是auHeader的字節長度;又因為單個auheader字節長度2字節,所以再除以2就
是auheader的個數。
(注意:AU-header長度并不是固定為2字節,具體要看SDP)
5.2、AU-header
au-header的高13個bits就是一個au 的字節長度:
//AU_HEADER
bytes[14] = (byte)((len & 0x1fe0) >> 5); //高位
bytes[15] = (byte)((len & 0x1f) << 3); //低位
(注意:AU-header長度并不是固定為2字節,具體要看SDP)
5.3、AU
音頻實際數據(去掉ADTS的aac數據)
5.4、RTSP/SDP中AAC相關配置
1 v=0
2 o=- 16128587303007558182 16128587303007558182 IN IP4 WINDOWS-75ID
U9Q
3 s=Unnamed
4 i=N/A
5 c=IN IP4 0.0.0.0
6 t=0 0
7 a=tool:vlc 3.0.5
8 a=recvonly
9 a=type:broadcast
10 a=charset:UTF-8
11 a=control:rtsp://192.168.2.195:8554/
12 m=audio 0 RTP/AVP 96
13 b=AS:128
14 b=RR:0
15 a=rtpmap:96 mpeg4-generic/22050
16 a=fmtp:96 streamtype=5; profile-level-id=15; mode=AAC-hbr; config
=138856e500; sizeLength=13; indexLength=3; indexDeltaLength=3; Pr
ofile=1;
17 a=control:rtsp://192.168.2.195:8554/trackID=4
18 m=video 0 RTP/AVP 96
19 b=AS:800
20 b=RR:0
21 a=rtpmap:96 H264/90000
22 a=fmtp:96 packetization-mode=1;profile-level-id=42c01e;sprop-para
meter-sets=Z0LAHtoCQKeX/8CgAJ/EAAADAZAAAF2qPFi6gA==,aM43IA==;
23 a=control:rtsp://192.168.2.195:8554/trackID=5
streamtype對于AAC, 固定為5。
profile-level-id固定為1。
config, SizeLength, IndexLength, IndexDeltaLength作用:
config是16進制的, 前兩個字節 1388 , 表示采樣率為22050, 1個channel。
前兩個字節的為ios-14996-3中定義的AudioSpecificConfig, 前13個bits的格式為:
samplingFrequencyIndex的取值:
1388 轉換成2進制為 0001 0011 1000 1000
audioObjectType為 00010 , 即 2
samplingFrequencyIndex為 0111 , 即 7 , 對應的采樣頻率為 22050
channelConfiguration為 0001 , 表示channel數量為1。
sizeLength=13; indexLength=3; indexDeltaLength=3涉及到音頻的AU Header。
5.5、AU-Header數據段的格式
其它的值都是可選的, 如果sdp中沒有出現相關的參數(或者為0), 則表示它們不出現。
以最簡單的情況舉例, 假設aac數據長度為200字節, 只有一個au-header。
200 的二進制為 0000011001000。 (補足為13 bits)
AU-headers-length 值為16, 因為只有一個au-header, au-header中
只有AU-size和AU-Index, 共占用16bits。
整個au-header數據段的內容為
0000 0000 0000 1000 0000011001000 000
如果一個rtp中只有一個aac包, 不需要加AU-Header, 那么sdp中的aac參數可以簡化為
a=fmtp:96 streamtype=5; profile-level-id=1; mode=AAC-hbr; config=1
38856e500;