音視頻開發-RTP協議

基於WebRTC的音視頻直播框架,使用RTP/RTCP,這裏記錄下。

RTP/RTCP

一般情況下,在實時互動直播系統傳輸音視頻數據流時,我們並不直接將音視頻數據流交給 UDP 傳輸,而是先給音視頻數據加個RTP 頭,然後再交給 UDP 進行傳輸。爲什麼要這樣做呢?

以太網的 MTU 最大傳輸單元1500字節 約爲1.5K,意味着傳輸一個I幀就需要幾十個包。意味着就需要拆包,然後重新組裝。

RTP協議

在這裏插入圖片描述

  • 版本號(V):2比特,用來標誌使用的RTP版本。

  • 填充位(P):1比特,如果該位置位,則該RTP包的尾部就包含附加的填充字節。

  • 擴展位(X):1比特,如果該位置位的話,RTP固定頭部後面就跟有一個擴展頭部。

  • CSRC計數器(CC):4比特,含有固定頭部後面跟着的CSRC的數目。

  • 標記位(M):1比特,該位的解釋由配置文檔(Profile)來承擔.

  • 載荷類型(PT)- Payload Type:7比特,標識了RTP載荷的類型。音頻流的 PT 值與視頻的 PT 值是不同的,通過它就可以知道這個包存放的是什麼類型的數據。

  • sequence number:序號,用於記錄包的順序。這與上面我們自己實現拆包、組包是同樣的道理。

  • timestamp:時間戳,同一個幀的不同分片的時間戳是相同的。這樣就省去了前面所講的起始標記和結束標記。一定要記住,不同幀的時間戳肯定是不一樣的。

假設你從網上接收一組音視頻數據

...
 
{V=2,P=0,X=0,CC=0,M=0,PT:98,seq:13,ts:1122334455,ssrc=2345},
{V=2,P=0,X=0,CC=0,M=0,PT:111,seq:14,ts:1122334455,ssrc=888},
{V=2,P=0,X=0,CC=0,M=0,PT:98,seq:14,ts:1122334455,ssrc=2345},
{V=2,P=0,X=0,CC=0,M=0,PT:111,seq:15,ts:1122334455,ssrc=888},
{V=2,P=0,X=0,CC=0,M=0,PT:98,seq:15,ts:1122334455,ssrc=2345},
{V=2,P=0,X=0,CC=0,M=0,PT:111,seq:16,ts:1122334455,ssrc=888},
{V=2,P=0,X=0,CC=0,M=0,PT:98,seq:16,ts:1122334455,ssrc=2345},
{V=2,P=0,X=0,CC=0,M=0,PT:111,seq:17,ts:1122334455,ssrc=888},
{V=2,P=0,X=0,CC=0,M=0,PT:98,seq:17,ts:1122334455,ssrc=2345},
{V=2,P=0,X=0,CC=0,M=0,PT:111,seq:18,ts:1122334455,ssrc=888},
{V=2,P=0,X=0,CC=0,M=0,PT:98,seq:18,ts:1122334455,ssrc=2345},
{V=2,P=0,X=0,CC=0,M=0,PT:111,seq:19,ts:1122334455,ssrc=888},
{V=2,P=0,X=0,CC=0,M=0,PT:98,seq:19,ts:1122334455,ssrc=2345},
{V=2,P=0,X=0,CC=0,M=0,PT:111,seq:20,ts:1122334455,ssrc=888},
{V=2,P=0,X=0,CC=0,M=1,PT:98,seq:20,ts:1122334455,ssrc=2345},
...

PT=98 是視頻數據,PT=111 是音頻數據,那麼按照上面的規則很容易就能將視頻幀組裝起來。

RTCP 協議

在使用 RTP 包傳輸數據時,難免會發生丟包、亂序、抖動等問題,下面我們來看一下使用的網絡一般都會在什麼情況下出現問題:

  • 網絡線路質量問題引起丟包率高;
  • 傳輸的數據超過了帶寬的負載引起的丟包問題;
  • 信號干擾(信號弱)引起的丟包問題;
  • 跨運營商引入的丟包問題 ;
  • ……

WebRTC對這些問題在底層都有相應的處理策略,但在處理這些問題之前,它首先要讓各端都知道它們自己的網絡質量到底是怎樣的,這就是 RTCP 的作用。

RTCP 有兩個最重要的報文:RR(Reciever Report)和 SR(Sender Report)。通過這兩個報文的交換,各端就知道自己的網絡質量到底如何了。

這裏我們以SR 報文爲例,看看 SR 報文中都包括哪些信息。

在這裏插入圖片描述

下面我就簡要說明一下該報文中字段的含義:

  • V=2,指報文的版本。
  • P,表示填充位,如果該位置 1,則在 RTCP 報文的最後會有填充字節(內容是按字節對齊的)。
  • RC,全稱 Report Count,指 RTCP 報文中接收報告的報文塊個數。
  • PT=200,Payload Type,也就是說 SR 的值爲 200。
    ……

從上圖中我們可以瞭解到,SR 報文分成三部分:Header、Sender info和Report block。在 NTP 時間戳之上的部分爲 SR 報文的 Header 部分,SSRC_1 字段之上到 Header 之間的部分爲 Sender info 部分,剩下的就是一個一個的 Report Block 了。那這每一部分是用於幹什麼的呢?

  • Header 部分用於標識該報文的類型,比如是 SR 還是 RR。
  • Sender info 部分用於指明作爲發送方,到底發了多少包。
  • Report block 部分指明發送方作爲接收方時,它從各個 SSRC 接收包的情況。
    通過以上的分析,你可以發現SR 報文並不僅是指發送方發了多少數據,它還報告了作爲接收方,它接收到的數據的情況。當發送端收到對端的接收報告時,它就可以根據接收報告來評估它與對端之間的網絡質量了,隨後再根據網絡質量做傳輸策略的調整。

SR 報文RR 報文無疑是RTCP協議中最重要的兩個報文,不過 RTCP 中的其他報文也都非常重要的,如果你想學好 WebRTC ,那麼 RTCP 中的每個報文你都必須掌握。

比如,RTCP 類型206、子類型爲 4 的 FIR 報文,其含義是 Full Intra Request (FIR) Command,即完整幀請求命令。會緊接發送一幀I幀

該報文也是一個特別關鍵的報文,我爲什麼這麼說呢?試想一下,在一個房間裏有 3 個人進行音視頻聊天,然後又有一個人加入到房間裏,這時如果不做任何處理的話,那麼第四個人進入到房間後,在一段時間內很難直接看到其他三個人的視頻畫面了,這是爲什麼呢?
原因就在於解碼器在解碼時有一個上下文。在該上下文中,必須先拿到一個 IDR 幀之後才能將其後面的 P 幀、B 幀進行解碼。也就是說,在沒有 IDR 幀的情況下,對於收到的 P 幀、B 幀解碼器只能乾瞪眼了。
如何解決這個問題呢?這就引出了 FIR 報文。當第四個人加入到房間後,它首先發送 FIR 報文,當其他端收到該報文後,便立即產生各自的 IDR 幀發送給新加入的人,這樣當新加入的人拿到房間中其他的 IDR 幀後,它的解碼器就會解碼成功,於是其他人的畫面也就一下子全部展示出來了。


附圖

RTP協議頭
在這裏插入圖片描述

RTCP 協議頭:

在這裏插入圖片描述

RTCP PT 類型:
在這裏插入圖片描述

對於 205 和 206 兩種不同的反饋消息,又在 RFC5104 中做了更詳細的定義:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章