轉自:http://blog.csdn.net/wudebao5220150/article/details/13816225
RTP協議是real-time transport protocol的縮寫,被設計來傳輸流媒體數據,有着廣泛的應用,其它相關介紹自己去看RFC,我不打算討論這些無聊的概念性的東西。
(1)了解RTP
可以說,RTP協議不依賴於底層協議,也就是說,它是獨立的協議。而一般的,由於UDP包的快速、時實性高的特點,它通常和UDP結合在一起,作為UDP的上層載體數據的形式傳播。
typedef struct {
IN OUT UINT32 timestamp;
IN OUT BOOL marker;
IN OUT BYTE payload;
OUT UINT32 sSrc;
OUT UINT16 sequenceNumber;
OUT int sByte;
OUT int len;
} rtpParam;
這是一個RTP頭,很簡單,並沒有你想象的那么復雜,對不對?我們來看幾個主要的參數,他們也是RTP的靈魂:
(1)payload。payload表示了此RTP包的數據是那種類型的數據,不同的數值表示不同的類型。如0是PCMU,8是723,24是視頻263等等。
(2)SSRC,這個東西並不常用,實際上它是一個隨即生成的ID,表示了一個RTP連接。在應用的時候,確保這個ID唯一就可以了。
(3)sequence number。也就是序列號,它表示了當前包是第幾個包。發送方每發送一個包,就把這個數值加一。接受放可以根據這個數值來重新組合包順序,判斷包是否丟失等操作。注意:它只是表示了包的先后順序,它不能表示時間上的任何其它信息。這個請和后面的時間戳比較。
(4)timestamp。時間戳,它的概念稍微有點復雜,我用稍微通俗點的理解去解釋它,雖然這樣有點不太正確。時間戳顧名思義,它表示了一個數據產生的時間,和我們郵遞的郵戳一樣,它是個時間標記(至於這個時間干什么用,我后面會詳細的說),通常表示RTP數據包中,第一個字節數據產生的時間(至於你是不是這么用就是你寫程序的問題了)。
如果你上面理解了,那么我們更進一步:實際上,時間戳增加一並不是我們通常意義上的過了一個微秒,而是增加了一個采樣間隔那么長的時間。舉個例子來說。不同的采集有不同的采樣頻率,比如一般的音頻是8K的采樣頻率,也就是一毫秒采集8次數據,也就是每次采樣間隔是1/8MS,而timestamp增加1也就意味着增加了一個采樣間隔。也就是過了1/8MS。換個例子,如果令一種編碼的采樣頻率是16K,那么timestamp增加1也就意味着系統過了1/16MS。也就是說,再同一個系統中,對不同編碼,雖然使用同一個時鍾,但timestamp的增長速度是不同的,在這個例子中,采樣頻率是16K的編碼要比8K的快兩倍,請記住這個區別。
(2)了解RTCP
RTCP協議是real-time transport control protocol的縮寫,被設計來做RTP的控制,這個相對來說大家不怎么關心,我只介紹下它基本的東西。
RTCP實際上是RTP傳輸情況的反饋,通俗的說,它告訴另外一方,在一端時間內(5秒),它發送多少數據包給對方,接收到了多少對方的包。
另外,在RTCP中,還有兩個比較重要的東西,一個64位的絕對時間戳和一個32位的相對時間戳。64 位時間戳也叫NTP時間戳,它的前32位是從1900 年1 月1 日0 時開始到現在的以秒為單位的整數部分,后32 位是此時間的小數部,因此,它可以肯定的表示了數據發送出去的絕對時間。32位的時間戳和RTP中的時間戳是一樣的,沒有任何區別。
(3)大家感興趣的時間戳的使用和同步的一些話題。
1、SSRC的作用。
SSRC相當於一個RTP傳輸session的ID,就象每個人都有一個名字一樣,每一個RTP傳輸也都有一個名字。這個數字是隨機產生,並且要保證唯一。當RTP session改變(如IP等)時,這個ID也要改變。
2、序列號字段是否可以作為流內的同步標時?
我在上面已經說過,序列號只表示了包發出的先后順序,它表示不了任何時間上的其它概念,所有嚴格的說,序列號並不能作為流內的同步標志。但是,由於一般來說,包的發送時間都會有嚴格限制,比如音頻包是每秒種發送30個數據包,也就是說,每個包間隔1000/30MS,而這個時間就可以作為一個同步時間來播放。也就是說,按照序列號,每1000/30MS間隔播放一個數據包,這樣也能保證同步,但是這時候請考慮丟包問題。
3、絕對時間戳和相對時間戳在進行同步處理時有什么不同
當我們取得絕對時間后,我們就可以根據這個絕對時間來播放這些數據包。這個絕對時間,加上我們需要的延時(用於數據傳輸,解碼等等的時間)就是我們的播放時間,這樣我們可以保證時間的嚴格同步(相當於把對方的動作延時一段時間后原原本本的再現出來)。目前,在RTP中,能得到這個絕對時間的辦法只有RTCP。
對於相對時間戳,我們更關心的是兩個時間戳之間的時間間隔,依靠這個時間間隔,來確定兩個包的播放時間間隔。
4、單個媒體內的同步和不同媒體流之間的同步在處理方式上有什么不同
應該說,不同媒體之間同步比單媒體同步要復雜得多,除了要保證本身的播放要和時間同步外,還要保證兩個或多個媒體間同步(比如音視頻的同步)。這種不同更關心的兩個時間戳時間的換算統一,前面我已經說過,不同編碼有不同的采樣頻率,那么時間戳的增長速度就不同。另外,兩個時間戳也需要有一個標准時間來表示時間戳的同步。最簡單的方法是兩個媒體的第一個時間戳相同,表示兩個流的采集開始時間統一。另外還可以通過RTCP來做不同流之間的同步,這在下個問題中會提到。
5、時間戳字段如何用於作為流間同步標識
在RTP協議中,我們取得時間戳的方法有兩個:一個是RTP包中的時間戳,另外一個是RTCP包中的絕對時間戳和相對時間戳。絕對時間戳的概念上面我已經說了,它可以表示系統的絕對時間。而RTCP包中的相對時間就是RTP包中的時間。根據這兩個時間,不同流都可以糾正自己播放時間和真正時間的偏差以達到和絕對時間同步的目的。反過來說,如果我們沒有辦法拿到這個絕對時間,只有RTP包中的相對時間,那怎我們需要確定兩個流在某一時間點的時間戳的數值。通俗的說,就是在某個時間點,流A的timestamp是多少,B是多少,然后根據這個時間兩個流播放的延時時間,以達到同步的目的。實現這個目的最簡單的辦法是在兩個流開始的時候,使用相同的stamp,拿音視頻來說,在某一絕對時刻,采集相應的數據,並打上相同的時間戳,以后的播放,都以這個時間做基准時間,以保證同步。