關於RTP負載類型及時間戳介紹


轉自:http://www.360doc.com/content/11/1018/13/1016783_157133781.shtml

 

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

前12個字節在每一個RTP packet中都存在,而一系列的CSRC標記只有存在Mixer時才有。

   version (V): 2 bits
      標明RTP版本號。協議初始版本為0,RFC3550中規定的版本號為2。

   padding (P): 1 bit
      如果該位被設置,則在該packet末尾包含了額外的附加信息,附加信息的最后一個字節表示額外附加信息的長度(包含該字節本身)。該字段之所以存在是因 為一些加密機制需要固定長度的數據塊,或者為了在一個底層協議數據單元中傳輸多個RTP packets。

   extension (X): 1 bit
      如果該位被設置,則在固定的頭部后存在一個擴展頭部,格式定義在RFC3550 5.3.1節。

   CSRC count (CC): 4 bits
      在固定頭部后存在多少個CSRC標記。

   marker (M): 1 bit
      該位的功能依賴於profile的定義。profile可以改變該位的長度,但是要保持marker和payload type總長度不變(一共是8 bit)。

   payload type (PT): 7 bits
      標記着RTP packet所攜帶信息的類型,標准類型列出在RFC3551中。如果接收方不能識別該類型,必須忽略該packet。

   sequence number: 16 bits
      序列號,每個RTP packet發送后該序列號加1,接收方可以根據該序列號重新排列數據包順序。

   timestamp: 32 bits
      時間戳。反映RTP packet所攜帶信息包中第一個字節的采樣時間。

   SSRC: 32 bits
      標識數據源。在一個RTP Session其間每個數據流都應該有一個不同的SSRC。

   CSRC list: 0 to 15 items, 32 bits each

 

      標識貢獻的數據源。只有存在Mixer的時候才有效。如一個將多聲道的語音流合並成一個單聲道的語音流,在這里就列出原來每個聲道的SSRC。

        10~16 Bit為PT域,指的就是負載類型(PayLoad),負載類型定義了RTP負載的格式,協議原文說該域由具體應用決定其解釋。
        目前,負載類型主要用來告訴接收端(或者播放器)傳輸的是哪種類型的媒體(例如G.729,H.264,MPEG-4等),這樣接收端(或者播放器)才知 道了數據流的格式,才會調用適當的編解碼器去解碼或者播放,這就是負載類型的主要作用。
        就ORTP庫而言,負載類型定義如下:
        

    每一種 負載類型都有着其獨特的參數,這里基本上涵蓋了當前主流的一些媒體類型,例如pcmu 、g.729、h.263(很奇怪,竟然沒有定義h.264)、mpeg-4等等。Jrtplib庫應該也有相類似的定義,你可以去找找源碼,在此我就不 再贅述了。

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

    好了,再說說RTP 的時間戳吧。

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

    時間戳單位:時間戳計算的單位不是秒之類的單位,而是由采樣頻率所代替的單位,這樣做的目的就是 為了是時間戳單位更為精准。比如說一個音頻的采樣頻率為8000Hz,那么我們可以把時間戳單位設為1 / 8000。
    時間戳增量:相鄰兩個RTP包之間的時間差(以時間 戳單位為基准)。
    采樣頻率:  每秒鍾抽取樣本的次數,例如音頻的采樣率一般為8000Hz
    幀率:      每秒傳輸或者顯示幀數,例如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。
    在Jrtplib中好像不需要自己管理時間戳的遞增,由庫內部管理。但在ORTP中每次數據的發送都需要自己傳入時間戳的值,即自己 需要每次發完一個RTP包后,累加時間戳增量,不是很方便,這就需要自己對RTP的時間戳有比較深刻地理解,我剛開始就是因為沒搞清楚,隨時設置時間戳增 量導致傳輸一直有問題,困擾我好久。

RTCP的bit圖:(http://www.cnblogs.com/Jimmly/archive/2009/08/03/1537468.html)
 //        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
 //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 //byte=0 |V=2|P|    RC   |   PT=SR=200   |             length            |
 //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 //     4 |                         SSRC of sender                        |
 //       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
 //     8 |              NTP timestamp, most significant word             |
 //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 //    12 |             NTP timestamp, least significant word             |
 //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 //    16 |                         RTP timestamp                         |
 //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 //    20 |                     sender's packet count                     |
 //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 //    24 |                      sender's octet count                     |
 //       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
 //    28 |V=2|P|    SC   |  PT=SDES=202  |             length            |
 //       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
 //    32 |                          SSRC/CSRC_1                          |
 //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 //    36 |    CNAME=1    |     length    | user and domain name        ...
 //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

 

多媒體通信同步方法,主要有時間戳同步法、同步標記法、多路復用同步法三種。下面主要討論時間戳同步法,特別是RTP時間戳同步。內容包括RTP媒 體間同步的實現,為什么需要RTCP的NTP時間來實現媒體間同步?沒有RTCP,能實現RTP媒體間的同步嗎?DirectShow時間戳和RTP時間 戳的區別,MPEG2-TS流的時間戳等。本文只簡單討論時間戳同步的原理,不涉及具體的實現方法,如音頻幀和視頻幀時間戳的計算方法,怎樣根據時間戳去 做音視頻的呈現等。

 根據RTP規范,不同的RTP媒體流是分開傳輸的,且使用各自獨立的時間戳進行同步。假設在一次視頻點播中,傳輸兩路RTP媒體流,一路視頻,一 路音頻。根據視頻幀時間戳,可以實現視頻流內同步,這很好理解,通過視頻幀時間戳可以計算出相鄰視頻幀的時間間隔,也就是視頻幀之間的相對時間關系很容易 通過時間戳來確定,按照這個間隔去呈現視頻,就可以獲得較好的效果。同理,音頻流也可以實現自身的同步。 

那么音頻和視頻這兩路媒體間如何實現同步呢?我們只使用音視頻的RTP時間戳,看能否實現媒體間的同步。音視頻的RTP時間戳的增長速率一般是不同的,但沒關系,知道了具體的單位后,兩者是可以通過單位換算聯系起來的。如下圖:

現在來看,這種方法好像可以實現同步,因為音視頻被映射到同一個時間軸上了,音頻和視頻幀間的相對關系很清楚。慢着,RTP規范要求時間戳的初 始值應該是一個隨機值,那么假設音頻幀時間戳的初始值是隨機值1234,視頻幀時間戳的初始值是隨機值5678,看起來應該是下面這樣:
這么做合適嗎?我們把音頻幀時間戳1234和視頻幀時間戳5678對應到絕對時間軸的0上,我們這么做的理由是什么?你可能會說,因為那是第一 個音頻幀和第一個視頻幀,所以可以對應到同一個點上,在第一幅圖中我們就是這么做的,把音頻幀時間戳0和視頻幀時間戳0對應到絕對時間軸的0上。但是 RTP規范並沒有規定第一個視頻幀的時間戳和第一個音頻幀的時間戳必須或者應該對應到絕對時間軸的同一個點上,從整個RTP規范中不能直接得出這樣的結 論,也推導不出這樣的結論。 

我們上面兩幅圖所做的轉換是不正確的,為什么呢?因為在做轉換時,隱含了一個假設,我們想當然地認為這個假設是成立的,實際上它並不總是成立。這個假設就是第一個視頻幀和第一個音頻幀的時間戳應該對應到同一個點上,即無論它們時間戳是多少,都應該在同一時間播放。

僅僅使用RTP時間戳是無法實現媒體間同步的,根本的原因是音頻時間軸和視頻時間軸是完全獨立的,通過音頻幀和視頻幀的時間戳,無法確定一個視頻幀和一個音頻幀的相對時間關系,也就是無法把它們都准確定位在絕對時間軸上,只能准確定位一個。

要實現RTP媒體間同步,需要借助於RTCP,在RTCP的SR包中,包含有<NTP時間,RTP時間戳>對,音頻幀RTP時間戳和視 頻幀RTP時間戳通過<NTP時間,RTP時間戳>對,都可以准確定位到絕對時間軸NTP上,音頻幀和視頻幀的相對時間關系就可以確定下來 了。

上面提到,我們的那個隱含的假設並不總是成立,那就是說它有成立的時候。那是不是說當它成立時,我們就可以不用RTCP來做媒體間同步了?答案是,基本上可以這么認為。

例如,對於RTP實時流,在發送端媒體間就同步的很好,在接收端只需做少許處理,不需要RTCP,就可以實現媒體間同步。當然,這只是少數例外。因為RTP規范並不包括這個假設,所以我們還是按照RTP規范來做吧。

下面說一下DirectShow和MPEG2-TS的時間戳。DirectShow中的時間戳和RTP中的時間戳,除了單位不一樣,計算方法不一樣 外,本質的區別就是DirectShow中的音頻幀和視頻幀時間戳使用的是同一個時間軸,所以不需要借助其他的東西,僅僅使用音頻幀時間戳和視頻幀時間戳 就可以實現媒體間同步。MPEG2-TS流中也有時間戳,它的時間戳和RTP及DirectShow的時間戳都不同,TS流中的音頻幀和視頻幀時間戳使用 的也是同一個時間軸,TS流中的音頻和視頻是復用的,這在一定程度上就起到了同步的作用,所以它並不是在每個幀上都打時間戳,比如它的PTS時間戳就是每 隔0.1秒一個,缺失的時間戳是通過其他時間戳插值計算出來的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM