談談RTP傳輸中的負載類型和時間戳

  最近被RTP的負載類型和時間戳搞鬱悶了,一個問題調試了近一週,終於圓滿解決,回頭看看,發現其實主要緣由仍是本身沒有真正地搞清楚RTP協議中負載類型和時間戳的含義。雖然作RTP傳輸,有着JrtplibOrtp這兩個強大的庫支持,一個是c++接口,一個是c語言接口,各有各的特色,各有各的應用環境,可是僅僅有庫就能解決一切問題嗎?可能仿照着一些例子程序,你可以完成主要的功能,但一旦問題發生了,不清楚原理你是很難定位和解決問題的,因此在此,用個人經驗勸勸你們,磨刀不誤砍柴工,作應用仍是先把原理搞清楚再動手吧……
  
php

  看這篇文章以前,首先你應該知道什麼是RTP協議,能夠去看RTP協議原文(RFC3550協議),也能夠看一些網友對RTP協議的講解的文章,不少,這裏我提供一篇我我的以爲寫得還不錯的:http://blog.csdn.net/bripengandre/archive/2008/04/01/2238818.aspxc++

  

  下面言歸正傳,首先談談RTP傳輸中的負載類型吧。網絡

  

  首先,看RTP協議包頭的格式:
       ide

  10~16 Bit爲PT域,指的就是負載類型(PayLoad),負載類型定義了RTP負載的格式,協議原文說該域由具體應用決定其解釋。函數

  

  目前,負載類型主要用來告訴接收端(或者播放器)傳輸的是哪一種類型的媒體(例如G.729,H.264,MPEG-4等),這樣接收端(或者播放器)才知道了數據流的格式,纔會調用適當的編×××去解碼或者播放,這就是負載類型的主要做用。編碼

 

  就ORTP庫(本文用的是ortp-0.9.1)而言,負載類型定義以下:
       spa

  每一種負載類型都有着其獨特的參數,這裏基本上涵蓋了當前主流的一些媒體類型,例如pcmu 、g.72九、h.263(很奇怪,居然沒有定義h.264,注:新版本已經添加了對h.264的支持)、mpeg-4等等。Jrtplib庫應該也有相相似的定義,你能夠去找找源碼,在此我就再也不贅述了。.net

  

  在ORTP庫和JRTplib庫中,都提供了設置RTP負載類型的函數,千萬要記得根據實際的應用進行設置,我就是當時沒有注意,使用ORTP默認的pcmu音頻的負載類型,傳輸H.264編碼的視頻數據,結果傳輸中一直有問題,困擾我很久很久設計


  再說說RTP的時間戳吧。3d

  

  首先,瞭解幾個基本概念:


  時間戳單位:時間戳計算的單位不是秒之類的單位,而是由採樣頻率所代替的單位,這樣作的目的就是爲了是時間戳單位更爲精準。好比說一個音頻的採樣頻率爲8000Hz,那麼咱們能夠把時間戳單位設爲1 / 8000。

  

  時間戳增量:相鄰兩個RTP包之間的時間差(以時間戳單位爲基準)。

  

  採樣頻率:每秒鐘抽取樣本的次數,例如音頻的採樣率:8000Hz、44100Hz、48000Hz等


  幀率:每秒傳輸或者顯示幀數,例如25f/s

   
  再看看RTP時間戳課本中的定義:


  RTP包頭的第2個32Bit即爲RTP包的時間戳,Time Stamp ,佔32位。
  

  時間戳反映了RTP分組中的數據的第一個字節的採樣時刻。在一次會話開始時的時間戳初值也是隨機選擇的。即便是沒有信號發送時,時間戳的數值也要隨時間不斷的增長。接收端使用時間戳可準確知道應當在什麼時間還原哪個數據塊,從而消除傳輸中的抖動。時間戳還可用來使視頻應用中聲音和圖像同步。
 

  在RTP協議中並無規定時間戳的粒度,這取決於有效載荷的類型。所以RTP的時間戳又稱爲媒體時間戳,以強調這種時間戳的粒度取決於信號的類型。例如,對於8kHz採樣的話音信號,若每隔20ms構成一個數據塊,則一個數據塊中包含有160個樣本(0.02×8000=160)。所以每發送一個RTP分組,其時間戳的值就增長160。

    

  官方的解釋看懂沒?沒看懂?不要緊,我剛開始也沒看懂,那就聽個人解釋吧。

  

  首先,時間戳就是一個值,用來反映某個數據塊的產生(採集)時間點的,後採集的數據塊的時間戳確定是大於先採集的數據塊的。有了這樣一個時間戳,就能夠標記數據塊的前後順序。


  第二,在實時流傳輸中,數據採集後馬上傳遞到RTP模塊進行發送,那麼,其實,數據塊的採集時間戳就直接做爲RTP包的時間戳。

  

  第三,若是用RTP來傳輸固定的文件,則這個時間戳就是讀文件的時間點,依次遞增。這個再也不咱們當前的討論範圍內,暫時不考慮。

  

  第四,時間戳的單位採用的是採樣頻率的倒數,例如採樣頻率爲8000Hz時,時間戳的單位爲1 / 8000 ,在Jrtplib庫中,有設置時間戳單位的函數接口,而ORTP庫中根據負載類型直接給定了時間戳的單位(音頻負載1/8000,視頻負載1/90000)

  

  第五,時間戳增量是指兩個RTP包之間的時間間隔,詳細點說,就是發送第二個RTP包相距發送第一個RTP包時的時間間隔(單位是時間戳單位)。

  

  若是採樣頻率爲90000Hz,則由上面討論可知,時間戳單位爲1/90000,咱們就假設1s鐘被劃分了90000個時間塊,那麼,若是每秒發送25幀,那麼,每個幀的發送佔多少個時間塊呢?固然是 90000/25 = 3600。所以,咱們根據定義“時間戳增量是發送第二個RTP包相距發送第一個RTP包時的時間間隔”,故時間戳增量應該爲3600。

 

 【補充】:最近思考了一下,又有了新的體會和解釋,可能對你們更容易地去理解這個時間戳增量會有所幫助,補充在下面吧:

 

  其實,網絡發送重點關注的是流量的平衡,即均勻地利用網絡帶寬,爲了實現這一點,須要知足:數據採集的速率與數據網絡傳輸的速率儘可能保持一致。時間戳增量的設置影響的是RTP包的網絡傳輸的速率,時間戳增量越小,發送速度越快。

 

  下面再進一步解釋一下時間戳增量是怎麼計算出來的:


  對於PAL制式的視頻而言,每秒攝像頭會採集 25 幀 數據,那麼,每採集到 1幀 耗時 1/25 s ,若是咱們設計爲1個RTP包只包含1幀數據,而且一次發送1幀,那麼,要想網絡流量均勻,則時間戳增量應該設計爲 1/25 s .  而在通常的RTP協議的實現中,時間戳單位不是 秒(s),而約定爲採樣頻率的倒數,因爲通常視頻的採樣頻率是 90000,故時間戳單位爲 1/90000 s,所以,實際的時間戳增量 = 時間戳增量 ( 1/25 s ) / 時間戳單位(1/90000 s) = 3600  


  在Jrtplib中好像不須要本身管理時間戳的遞增,由庫內部管理。但在ORTP中每次數據的發送都須要本身傳入時間戳的值,即本身須要每次發完一個RTP包後,累加時間戳增量,不是很方便,這就須要本身對RTP的時間戳有比較深入地理解,我剛開始就是由於沒搞清楚,隨時設置時間戳增量致使傳輸一直有問題,困擾我很久。


  好了,關於RTP的負載類型和時間戳的介紹就到這裏了,此次經過解決RTP傳輸中的問題學到了很多知識,在此分享但願對你們有用。有疑問或者建議和留言或者來信交流:lujun.hust@gmail.com,也能夠關注個人新浪微博(@盧_俊)獲取最新的文章和資訊。

相關文章
相關標籤/搜索