最近被RTP的負(fù)載類型和時(shí)間戳搞郁悶了,一個(gè)問(wèn)題調(diào)試了近一周,終于圓滿解決,回頭看看,發(fā)現(xiàn)其實(shí)主要原因還是自己沒有真正地搞清楚RTP協(xié)議中負(fù)載類型和時(shí)間戳的含義。雖然做RTP傳輸,有著Jrtplib和Ortp這兩個(gè)強(qiáng)大的庫(kù)支持,一個(gè)是c++接口,一個(gè)是c語(yǔ)言接口,各有各的特點(diǎn),各有各的應(yīng)用環(huán)境,但是僅僅有庫(kù)就能解決一切問(wèn)題嗎?可能仿照著一些例子程序,你能夠完成主要的功能,但一旦問(wèn)題發(fā)生了,不清楚原理你是很難定位和解決問(wèn)題的,所以在此,用我的經(jīng)驗(yàn)勸勸大家,磨刀不誤砍柴工,做應(yīng)用還是先把原理搞清楚再動(dòng)手吧……
看這篇文章之前,首先你應(yīng)該知道什么是RTP協(xié)議,可以去看RTP協(xié)議原文(RFC3550協(xié)議),也可以看一些網(wǎng)友對(duì)RTP協(xié)議的講解的文章,很多,這里我提供一篇我個(gè)人覺得寫得還不錯(cuò)的:http://blog.csdn.net/bripengandre/archive/2008/04/01/2238818.aspx 。
好,下面言歸正傳,首先談?wù)凴TP傳輸中的負(fù)載類型吧。
首先,看RTP協(xié)議包頭的格式:
 10~16 Bit為PT域,指的就是負(fù)載類型(PayLoad),負(fù)載類型定義了RTP負(fù)載的格式,協(xié)議原文說(shuō)該域由具體應(yīng)用決定其解釋。
目前,負(fù)載類型主要用來(lái)告訴接收端(或者播放器)傳輸?shù)氖悄姆N類型的媒體(例如G.729,H.264,MPEG-4等),這樣接收端(或者播放器)才知道了數(shù)據(jù)流的格式,才會(huì)調(diào)用適當(dāng)?shù)木幗獯a器去解碼或者播放,這就是負(fù)載類型的主要作用。
就ORTP庫(kù)(本文用的是ortp-0.9.1)而言,負(fù)載類型定義如下:
 每一種負(fù)載類型都有著其獨(dú)特的參數(shù),這里基本上涵蓋了當(dāng)前主流的一些媒體類型,例如pcmu 、g.729、h.263(很奇怪,竟然沒有定義h.264,注:新版本已經(jīng)添加了對(duì)h.264的支持)、mpeg-4等等。Jrtplib庫(kù)應(yīng)該也有相類似的定義,你可以去找找源碼,在此我就不再贅述了。 在ORTP庫(kù)和JRTplib庫(kù)中,都提供了設(shè)置RTP負(fù)載類型的函數(shù),千萬(wàn)要記得根據(jù)實(shí)際的應(yīng)用進(jìn)行設(shè)置,我就是當(dāng)時(shí)沒有注意,使用ORTP默認(rèn)的pcmu音頻的負(fù)載類型,傳輸H.264編碼的視頻數(shù)據(jù),結(jié)果傳輸中一直有問(wèn)題,困擾我好久好久。 好了,再說(shuō)說(shuō)RTP的時(shí)間戳吧。 首先,了解幾個(gè)基本概念:
時(shí)間戳單位:時(shí)間戳計(jì)算的單位不是秒之類的單位,而是由采樣頻率所代替的單位,這樣做的目的就是為了是時(shí)間戳單位更為精準(zhǔn)。比如說(shuō)一個(gè)音頻的采樣頻率為8000Hz,那么我們可以把時(shí)間戳單位設(shè)為1 / 8000。
時(shí)間戳增量:相鄰兩個(gè)RTP包之間的時(shí)間差(以時(shí)間戳單位為基準(zhǔn))。
采樣頻率: 每秒鐘抽取樣本的次數(shù),例如音頻的采樣率一般為8000Hz
幀率: 每秒傳輸或者顯示幀數(shù),例如25f/s
再看看RTP時(shí)間戳課本中的定義: RTP包頭的第2個(gè)32Bit即為RTP包的時(shí)間戳,Time Stamp ,占32位。
時(shí)間戳反映了RTP分組中的數(shù)據(jù)的第一個(gè)字節(jié)的采樣時(shí)刻。在一次會(huì)話開始時(shí)的時(shí)間戳初值也是隨機(jī)選擇的。即使是沒有信號(hào)發(fā)送時(shí),時(shí)間戳的數(shù)值也要隨時(shí)間不斷的增加。接收端使用時(shí)間戳可準(zhǔn)確知道應(yīng)當(dāng)在什么時(shí)間還原哪一個(gè)數(shù)據(jù)塊,從而消除傳輸中的抖動(dòng)。時(shí)間戳還可用來(lái)使視頻應(yīng)用中聲音和圖像同步。
在RTP協(xié)議中并沒有規(guī)定時(shí)間戳的粒度,這取決于有效載荷的類型。因此RTP的時(shí)間戳又稱為媒體時(shí)間戳,以強(qiáng)調(diào)這種時(shí)間戳的粒度取決于信號(hào)的類型。例如,對(duì)于8kHz采樣的話音信號(hào),若每隔20ms構(gòu)成一個(gè)數(shù)據(jù)塊,則一個(gè)數(shù)據(jù)塊中包含有160個(gè)樣本(0.02×8000=160)。因此每發(fā)送一個(gè)RTP分組,其時(shí)間戳的值就增加160。 官方的解釋看懂沒?沒看懂?沒關(guān)系,我剛開始也沒看懂,那就聽我的解釋吧。 首先,時(shí)間戳就是一個(gè)值,用來(lái)反映某個(gè)數(shù)據(jù)塊的產(chǎn)生(采集)時(shí)間點(diǎn)的,后采集的數(shù)據(jù)塊的時(shí)間戳肯定是大于先采集的數(shù)據(jù)塊的。有了這樣一個(gè)時(shí)間戳,就可以標(biāo)記數(shù)據(jù)塊的先后順序。
第二,在實(shí)時(shí)流傳輸中,數(shù)據(jù)采集后立刻傳遞到RTP模塊進(jìn)行發(fā)送,那么,其實(shí),數(shù)據(jù)塊的采集時(shí)間戳就直接作為RTP包的時(shí)間戳。
第三,如果用RTP來(lái)傳輸固定的文件,則這個(gè)時(shí)間戳就是讀文件的時(shí)間點(diǎn),依次遞增。這個(gè)不再我們當(dāng)前的討論范圍內(nèi),暫時(shí)不考慮。
第四,時(shí)間戳的單位采用的是采樣頻率的倒數(shù),例如采樣頻率為8000Hz時(shí),時(shí)間戳的單位為1 / 8000 ,在Jrtplib庫(kù)中,有設(shè)置時(shí)間戳單位的函數(shù)接口,而ORTP庫(kù)中根據(jù)負(fù)載類型直接給定了時(shí)間戳的單位(音頻負(fù)載1/8000,視頻負(fù)載1/90000)
第五,時(shí)間戳增量是指兩個(gè)RTP包之間的時(shí)間間隔,詳細(xì)點(diǎn)說(shuō),就是發(fā)送第二個(gè)RTP包相距發(fā)送第一個(gè)RTP包時(shí)的時(shí)間間隔(單位是時(shí)間戳單位)。
如果采樣頻率為90000Hz,則由上面討論可知,時(shí)間戳單位為1/90000,我們就假設(shè)1s鐘被劃分了90000個(gè)時(shí)間塊,那么,如果每秒發(fā)送25幀,那么,每一個(gè)幀的發(fā)送占多少個(gè)時(shí)間塊呢?當(dāng)然是 90000/25 = 3600。因此,我們根據(jù)定義“時(shí)間戳增量是發(fā)送第二個(gè)RTP包相距發(fā)送第一個(gè)RTP包時(shí)的時(shí)間間隔”,故時(shí)間戳增量應(yīng)該為3600。
【補(bǔ)充】:最近思考了一下,又有了新的體會(huì)和解釋,可能對(duì)大家更容易地去理解這個(gè)時(shí)間戳增量會(huì)有所幫助,補(bǔ)充在下面吧:
其實(shí),網(wǎng)絡(luò)發(fā)送重點(diǎn)關(guān)注的是流量的平衡,即均勻地利用網(wǎng)絡(luò)帶寬,為了實(shí)現(xiàn)這一點(diǎn),需要滿足:數(shù)據(jù)采集的速率與數(shù)據(jù)網(wǎng)絡(luò)傳輸?shù)乃俾时M量保持一致。時(shí)間戳增量的設(shè)置影響的是RTP包的網(wǎng)絡(luò)傳輸?shù)乃俾剩瑫r(shí)間戳增量越小,發(fā)送速度越快。
下面再進(jìn)一步解釋一下時(shí)間戳增量是怎么計(jì)算出來(lái)的:
對(duì)于PAL制式的視頻而言,每秒攝像頭會(huì)采集 25 幀 數(shù)據(jù),那么,每采集到 1幀 耗時(shí) 1/25 s ,如果我們?cè)O(shè)計(jì)為1個(gè)RTP包只包含1幀數(shù)據(jù),并且一次發(fā)送1幀,那么,要想網(wǎng)絡(luò)流量均勻,則時(shí)間戳增量應(yīng)該設(shè)計(jì)為 1/25 s . 而在一般的RTP協(xié)議的實(shí)現(xiàn)中,時(shí)間戳單位不是 秒(s),而約定為采樣頻率的倒數(shù),由于一般視頻的采樣頻率是 90000,故時(shí)間戳單位為 1/90000 s,因此,實(shí)際的時(shí)間戳增量 = 時(shí)間戳增量 ( 1/25 s ) / 時(shí)間戳單位(1/90000 s) = 3600
在Jrtplib中好像不需要自己管理時(shí)間戳的遞增,由庫(kù)內(nèi)部管理。但在ORTP中每次數(shù)據(jù)的發(fā)送都需要自己傳入時(shí)間戳的值,即自己需要每次發(fā)完一個(gè)RTP包后,累加時(shí)間戳增量,不是很方便,這就需要自己對(duì)RTP的時(shí)間戳有比較深刻地理解,我剛開始就是因?yàn)闆]搞清楚,隨時(shí)設(shè)置時(shí)間戳增量導(dǎo)致傳輸一直有問(wèn)題,困擾我好久。
好了,關(guān)于RTP的負(fù)載類型和時(shí)間戳的介紹就到這里了,這次通過(guò)解決RTP傳輸中的問(wèn)題學(xué)到了不少知識(shí),在此分享希望對(duì)大家有用。有說(shuō)得不正確的地方歡迎高手指教,也可以來(lái)信交流: lujun.hust@gmail.com
|