RTP被定義為傳輸音頻、視頻渴语、模擬數據等實時數據的傳輸協(xié)議羽资,與傳統(tǒng)的注重的高可靠的數據傳輸的傳輸層協(xié)議相比,它更加側重的數據傳輸的實時性遵班,此協(xié)議提供的服務包括數據順序號屠升、時間標記潮改、傳輸控制等。
RTP一般與傳輸控制協(xié)議RTCP一塊工作腹暖,RTP只負責實時數據的傳輸汇在,RTCP負責對RTP的通訊和會話進行帶外管理(如流量控制、擁塞控制脏答、會話源管理等)糕殉。
RTP使用一個偶數端口號,而相應RTCP流使用下一個(奇數殖告,遞增)端口號阿蝶。
先來看一下rtp和rtcp網絡結構圖:
RTP的數據包由RTP Header + RTP Playload組成,其中RTP固定頭如下圖所示黄绩,字段如下:
- V:當前的協(xié)議的版本號是2羡洁,其中0和1已經在草案規(guī)范中被占用,這里基本就是固定值了爽丹;
- P:填充標記筑煮,包的末尾包含了一個或者多個填充字節(jié),其中填充字節(jié)的第一字節(jié)包括了后面填充字節(jié)的長度粤蝎,該長度字段包含自己真仲,主要是為了一些對齊處理;
- X位初澎,如果為1則說明有擴展頭秸应,一般默認為0,很少有場景會用到碑宴;
- CC位:是為了計算后面有多少個CSRC软啼,四位說明則最大支持15個CSRC,一般默認為0墓懂。
- M位(Marker):特別對于視頻而言就是一幀的結束焰宣,視頻幀比較大,需要通過多個NALU(網絡抽象層單元(Network Abstract Layer Unit))來傳輸捕仔,當看到M位為1時就認為是這個I幀的結束匕积,由于音頻幀比較小,一個RTP包就是一個音頻幀榜跌,所以該位直接置1闪唆。當該值為1時,表示該數據包是一幀數據的最后一個數據包钓葫。
- Sequence number(序列號):16位悄蕾,用于標識發(fā)送者發(fā)送的RTP報文序列號,每發(fā)送一個RTP包,則這里就增加1帆调,當達到最大值后奠骄,則重新從0開始。剛才說了一般RTP協(xié)議是承載協(xié)議是UDP番刊,UDP是不可靠傳輸協(xié)議含鳞。那我們如何保證接收端收的數據是正確的呢,就是通過這個字段進行重新排序芹务,所以接收端一般收到RTP數據第一件事就是排序蝉绷。
特別注意兩點: a. 這個序列號的初始值可以為0但是也可以為其它隨機值,只要符合+1就行; b. 發(fā)送端的音頻和視頻都是通過RTP傳輸的枣抱,但是他們是分別計數的熔吗,所用的序列號 是不同的。
- timestamp(時間戳):占32位四字節(jié)佳晶,這個單位要注意是采樣率倒數桅狠,不是真實的時間,一般要根據采樣率進行換算宵晚。這里反應的RTP報文第一個八位組的采樣時刻垂攘,目的是為了接收端計算延遲维雇、抖動和音視頻同步淤刃。需要說明的是,一個視頻幀的時間戳是相同的吱型,但是一個視頻幀數據量很大可能需要多個RTP包傳輸逸贾,這樣就存在多個RTP包時間戳相同的情況,音頻幀數據小津滞,不存在音頻幀跨RTP的情況铝侵,所以不存在這個問題。
- SSRC(同步源標識符):占32位四字節(jié)触徐,用于標識同步信號源咪鲜,這個值只要保證在一路音視頻會話里面值不相同即可。該標識符是隨機選取的 RFC1889推薦了MD5隨機算法撞鹉。該值的作用就是在會話中標識RTP負載流的身份疟丙,給一個唯一標記值。
- CSRC list(貢獻源列表):同樣是32位鸟雏,四字節(jié)享郊。一個RTP頭最多可以含有0-15個,如果是1對1的流媒體傳輸孝鹊,這個字段就不用處理炊琉,直接忽略該字段。但是混流和混音時又活,則需要把各方的RTP同步信號源列出來苔咪,這樣接收端就能正確指出交談雙方的身份锰悼。用來標志對一個RTP混合器產生的新包有貢獻的所有RTP包的源,由混合器將這些有貢獻的SSRC標識符插入表中团赏。
再看一下RTP完整的報文格式:
- 一部分是RTP Heaeder松捉,RTP
Header占用最少12個字節(jié)(只包含固定頭12個字節(jié)),最多72個字節(jié)(包含固定頭12個字節(jié)+CSRC列表15*4個字節(jié))馆里; -
一部分是RTP Payload隘世,用來封裝實際的數據負載,如封裝h264編碼的視頻數據鸠踪。
RTP完整的報文格式
再來看看RTCP協(xié)議丙者,RTCP協(xié)議將控制包周期發(fā)送給所有連接者,主要功能如下:
- 主要提供數據發(fā)布的質量反饋营密,RTCP是作為RTP傳輸協(xié)議的一部分械媒,與其他傳輸協(xié)議的流和阻塞控制有關,反饋功能由RTCP發(fā)送者和接收者報告執(zhí)行评汰。
RTCP協(xié)議包括五種類型纷捞,這里只討論SR和RR包。
SR包(SenderReport):發(fā)送者報告被去,當前活動發(fā)送者發(fā)送主儡、接收統(tǒng)計;所謂發(fā)送端是指發(fā)出RTP數據報的應用程序或者終端惨缆,發(fā)送端同時也可以是接收端糜值。由三部分組成,也可能還有第四個特定設置擴展部分坯墨。
第一部分為頭:8個字節(jié)寂汇,如下:
- V:2位,標識RTP版本捣染,需要注意的是RTP數據包中的版本號與RTCP數據包的中的版本號是一致的骄瓣。
- 填充P:1位,如設置于此位耍攘,RTCP包結尾包含一些附加填充八位組榕栏,它們不屬于控制信息。最后一個字節(jié)填充表示應忽略多少個填充少漆。有些加密算法需要填充臼膏,塊大小固定。在組合RTCP包內示损,填充僅在最后一個包中需要渗磅,因為組合包加密成一個整體。
- 接收報告計數(RC):5位,包含在包內的接收報告塊數目始鱼,該字段0值為有效的仔掸,但沒有實際意義。
- 包類型(PT):8位医清,包含常數200標識此包為RTCP的SR包起暮。
- 長度length:16位,其中存放的是該SR包以32比特為單位的總長度減一(減去一個header)会烙。使用4個字節(jié)為1組负懦,長度共有幾個4個字節(jié)的組,然后用該長度減去1柏腻,即為RTCP包中的長度纸厉。舉個栗子:假設RTCP數據包的長度為32個字節(jié),32/4=8五嫂,總共有8組4個字節(jié)颗品,8-1=7,此時RTCP數據包中l(wèi)ength的值為7沃缘。
- SSRC:32位躯枢,同步源標識,與對應rtp包中的ssrc一樣槐臀。
第二部分為發(fā)送者信息:20個字節(jié)锄蹂,如下:
- NTP(Network time protocol)時標:64位,表示報告發(fā)送時的時鐘時間峰档,這樣它就可用于合并從其他發(fā)送者到那些接收者的接收報告返回的時標败匹。SR包發(fā)送時的絕對時間值寨昙,NTP的作用是同步不同的RTP媒體流讥巡。
Ntp把當前時間(自1970.1.1以來的秒數)分為整數部分N和小數部分X Ntp高位=整數部分N + 2208988800UL (其中2208988800UL表示自1900.1.1到1970.1.1的秒數,70年) Ntp低位=小數部分 X 4294967296 (其中4294967296為2^32舔哪,相當于左移32位)
- RTP時標:32位欢顷,與上述NTP時標同一時間有關,與RTP數據包中的RTP時間戳具有相同的單位和隨機初始值捉蚤。
以sample為單位抬驴,如音頻8000HZ,一個packet為20ms缆巧,則兩個rtp時間戳的間隔為160. 從rtp時間戳換算成ms的公式為: rtp時間戳 x 1000/samplerate布持。
- 發(fā)送者包計數:32位,自開始發(fā)送起陕悬,直到SR包產生時刻题暖,發(fā)送者發(fā)送RTP數據包總數。如改變SSRC標識符,此計數重置胧卤。
- 發(fā)送者八位組計數:32位唯绍,發(fā)送者在RTP數據包中發(fā)送的載荷八位組總數(不包括頭部和填充)。從發(fā)送開始枝誊,直到產生SR包况芒,如發(fā)送者改變SSRC標識,重置此計數叶撒。這部分可用于估計載荷數據平均速率绝骚。
第三部分包含接收報告快,大小不固定祠够。每個接收報告塊傳送單個同步源接收RTP包的統(tǒng)計皮壁。發(fā)生沖突,當源改變SSRC標識時哪审,接收者并不繼續(xù)統(tǒng)計蛾魄。這些統(tǒng)計包括:
- SSRC_n(源標識):32位,接收報告塊中信息所屬源的SSRC標識湿滓。
- 丟失部分:8位滴须,前一個SR或RR包發(fā)送以來所丟失的源SSRC_n的RTP數據包中一部分,定義成所丟失包的數目叽奥。
- 丟失包累積數:24位扔水,自接收以來所丟失的源SSRC_n的RTP數據包總數,定義成小于實際所接收包的數量朝氓,該數量包括遲到或復制的包魔市。因此,遲到的包不計為丟失赵哲,如有復制待德,此數量可能為負數。
- 收到已擴展的最高系列號:32位枫夺,低16位包含從SSRC_n源RTP數據包中收到的最高系列號将宪,最重要的16位以系列號循環(huán)相應計數擴展系列號。如開始時間明顯不同橡庞,同一連接內不同接收者將對系列號產生不同擴展较坛。
- 間隔抖動:32位,RTP數據包接受時間的統(tǒng)計方差估計扒最,以時標為單位丑勤,是一個無符號整數。
- 上次SR時標(LSR):32位吧趣,取最近從SSRC_n收到的SR包中的NTP時間戳的中間32比特法竞,如還沒有收到SR除呵,此段設為零。
- 上次SR以來的延時(DLSR):32位爪喘,延遲以1/65536秒為單位颜曾,上次從SSRC_n收到SR包到發(fā)送本報告的延時,如還沒有收到SR秉剑,此段設為零泛豪。
RR包(ReceiverReport):接收者報告,非活動發(fā)送者接收統(tǒng)計侦鹏,僅作為接收者(只接收rtp包)發(fā)送出去的包诡曙;所謂接收者是指僅接收但不發(fā)送RTP數據報的應用程序或者終端。包類型包含常數201略水,并刪除發(fā)送者信息的20個字節(jié)价卤。
各個字段解釋如下:
- SSRC_n(32bit) : 發(fā)送端的信源標識符,與發(fā)送端的SSRC一致渊涝。
- 丟包數8(8bit) :前一個SR或RR包發(fā)送后慎璧,到當前的SR包或RR包的間隔內,來自源(共享源SSRC標識)發(fā)送的數據包的丟失個數跨释。
丟包率胸私,它是定義一個rr發(fā)送間隔中rtp報文的丟失率。 它是一個8bits的數據段鳖谈,計算方法為岁疼,loss fraction=lost rate x 256. 舉例,丟包率為25%缆娃,該字段為25%*256=64
- 累積丟包數(24bit) : 自開始接受源(共享源SSRC標識)發(fā)送的數據開始捷绒,累積丟失的數據包的個數。
理論計算方式, packet lost = 期待得到報文數量 - 實際收到報文的數量 實際計算方式, packet lost = 期待收到最新sequence - 第一次收到報文的sequence #需要注意: 1. sequence為16位贯要,容易翻轉 可以通過計算extend_sequence來區(qū)分翻轉的sequence暖侨。 2. packet lost可能為負數 因為有rtp報文的重傳,如果重傳次數多郭毕,可能造成負數 3. 該值的測量周期是整個會話 測量周期是整個會話它碎,而不是RR的發(fā)送間隔
- 擴展包序號(32bit) :低16位為當前接收到的來自源的(共享源SSRC標識)數據包的最大序列號;高16位表示RT包序列號的循環(huán)計數显押!我們都知道RTP數據包中,表示序列號的長度為2個字節(jié)傻挂,即最大的RTP序列號為65536(2的16次方)乘碑,如果序列號超了65536,假設為65537金拒,這個時候RTCP在擴展包序號中對其說明兽肤,如果沒有超過65536套腹,則高16位為0,如果超過65536资铡,則為1电禀,如果再來一圈,則為3笤休。做個不恰當的比喻尖飞,我們跑步一圈為65536,高16位表示我們當前正在跑第幾圈店雅,從0開始計數政基。
計算方法,extended_seq_num = seq_num + (65536 * wrap_around_count) 例如:100 + 65536*2 (即2左移到高16位) 其中: seq_num為當前接收到的來自源的數據包的最大序列號闹啦; wrap_around_count為sequence翻轉的次數沮明。
- 間隔抖動(32bit) :RTP數據包間隔時間的統(tǒng)計估計,以時間戳為單位窍奋,用無符號整數表示荐健。
這里的延時抖動指的是rtp報文發(fā)送方的網絡傳輸時間的變量估計值。 計算單位 是基于時間戳的基礎單位琳袄,也是32位無符號整形摧扇。 因為rtp的發(fā)送和接收方沒有時 間同步系統(tǒng),所以不大可能能準確的測量網絡傳送時間挚歧。 #相反扛稽,傳輸時間= |rtp的時間戳-rtp接受者本地時間| 因為沒有發(fā)送和接收方的時間同步機制,所以這里關心的不是傳輸時間滑负,是兩次接收到rtp報文傳輸時間的對比在张,計算公式如下: D(i,j)=(Rj-Ri)-(Sj-Si)=(Rj-Sj)-(Ri-Si) R是接收到的時間戳,Rj是packet j接收到的時間戳矮慕,Ri是packet i接收到的時間戳, S是rtp報文的時間戳帮匾,Sj是packet j的rtp時間戳,Si是packet i的rtp時間戳 而Jitter的計算公式如下: # J(i) = J(i-1) + (|D(i-1,i)| - J(i-1))/16
- LSR(32bit) :last SR timestamp痴鳄,表示上一個SR數據包的NTP時間戳瘟斜,由于NTP時間戳為64bit,LSR為32bit痪寻,LSR取上一個SR的NTP時間戳的中間32位:如上一個SR數據包的NTP時間戳為0x 00 01 7d 6e 3b 64 5a 1c螺句,則LSR為0x 7d 6e 3b 64。
- DLSR(32bit) :發(fā)送當前RR包的時間與上一個SR之間的時間間隔橡类,以1/65536為單位蛇尚,如,本次RR包與上一次SR的時間間隔為264ms顾画,則本字段的值為0.264*65536=17301.54取劫。
最后通過LSR,DLSR可以計算RTT:
RTT: Round-Trip Time匆笤,發(fā)送者計算的發(fā)送來回時間。
發(fā)送者可以通過RR報文中的LSR和DLSR來計算RTT谱邪。
計算方法: 發(fā)送者用接收到RR報文的當前時間-RR報文的LSR炮捧,得到發(fā)送SR和接收到RR所花費的網絡延時。
再進行: (接收到RR報文的當前時間-RR報文的LSR) - RR中的DLSR惦银,也就是去除了在RTP接收者方本地的SR接收和RR發(fā)送的延時咆课,這樣就得到了RTT。
RTT = 接收到RR報文的當前時間-RR報文的LSR - RR中的DLSR
經驗表明璧函,如果RTT大于300ms傀蚌,這樣的質量網絡通話無法完成。
只能通過降低比特率蘸吓,降低打包延時或應用好的錯誤修復機制來完成善炫。