banner
fwrite

fwrite

好好生活
twitter
github
email

RTP

RTP 協議介紹#

即時傳輸協議 RTP(Real-time Transport Protocol)是一個網路傳輸協議,它是由 IETF 的多媒體傳輸工作小組 1996 年在 RFC 1889 中公布的,後在 RFC3550 中進行更新。

它作為互聯網標準在 RFC 3550 有詳細說明。
RTP 協議詳細說明了在互聯網上傳遞音頻和視頻的標準數據包格式。它一開始被設計為一個多播協議,但後來被用在很多單播應用中。RTP 協議常用於串流媒體系統(配合 RTSP 協議)、視頻會議和一鍵通(Push to Talk)系統(配合 H.323 或 SIP),使它成為 IP 電話產業的技術基礎。RTP 協議和 RTP 控制協議 RTCP 一起使用,而且它是建立在用戶數據報協議上的(UDP)。

RTP 和 RTCP#

  • 數據傳輸協議 RTP 用於即時傳輸數據。該協議提供的信息包括:時間戳(用於同步)、序列號(用於丟包和重排序檢測)、以及負載格式(用於說明數據的編碼格式)。

  • 控制協議 RTCP,用於 QoS 反饋和同步媒體流。相對於 RTP 來說,RTCP 所佔的帶寬非常小,通常只有 5%。

RTP 的優勢#

提到串流媒體傳輸、視頻監控、視頻會議、語音電話(VOIP),都離不開 RTP 協議的應用,但是為什麼要使用 RTP 來進行串流媒體的傳輸呢?為什麼一定要用 RTP?

像 TCP 這樣的可靠傳輸協議,通過超時和重傳機制來保證傳輸數據流中的每一個 bit 的正確性,但這樣會使得無論從協議的實現還是傳輸的過程都變得非常的複雜。而且,當傳輸過程中有數據丟失的時候,由於對數據丟失的檢測(超時檢測)和重傳,會使數據流的傳輸被迫暫停和延遲。

RTP 協議是一種基於 UDP 的傳輸協議,RTP 本身並不能為按順序傳送數據包提供可靠的傳送機制,也不提供流量控制或擁塞控制,它依靠 RTCP 提供這些服務。這樣,對於那些丟失的數據包,不存在由於超時檢測而帶來的延遲,同時,對於那些被丟棄的包,也可以由上層根據其重要性來選擇性地重傳。

RTP 的協議層次#

串流媒體體系結構

串流媒體應用中典型的協議體系結構。

2022-06-29-22-46-30

從圖中可以看出,RTP 被劃分在傳輸層,它建立在 UDP 上。同 UDP 協議一樣,為了實現其即時傳輸功能,RTP 也有固定的封裝形式。RTP 用來為端到端的即時傳輸提供時間信息和流同步,但並不保證服務質量。服務質量由 RTCP 來提供。

RTP 工作機制#

當應用程序建立一個 RTP 會話時,應用程序將確定一對目的傳輸地址。目的傳輸地址由一個網路地址和一對端口組成,有兩個端口:一個給 RTP 包,一個給 RTCP 包,使得 RTP/RTCP 數據能夠正確發送。RTP 數據發向偶數的 UDP 端口,而對應的控制信號 RTCP 數據發向相鄰的奇數 UDP 端口(偶數的 UDP 端口 + 1),這樣就構成一個 UDP 端口對。RTP 的發送過程如下,接收過程則相反。

  1. RTP 協議從上層接收串流媒體信息碼流(如 H.263),封裝成 RTP 數據包;RTCP 從上層接收控制信息,封裝成 RTCP 控制包。
  2. RTP 將 RTP 數據包發往 UDP 端口對中偶數端口;RTCP 將 RTCP 控制包發往 UDP 端口對中的奇數端口。

RTP 分組只包含 RTP 數據,而控制是由 RTCP 協議提供。RTP 在 1025 到 65535 之間選擇一個未使用的偶數 UDP 端口號,而在同一次會話中的 RTCP 則使用下一個奇數 UDP 端口號。端口號 5004 和 5005 分別用作 RTP 和 RTCP 的默認端口號。RTP 分組的首部格式如圖 2 所示,其中前 12 個字節是必須的。

2022-06-29-22-46-40

應用層#

RTP 應當是應用層的一部分。在應用的發送端,開發者必須編寫用 RTP 封裝分組的程序代碼,然後把 RTP 分組交給 UDP。在接收端,RTP 分組通過 UDP 接口進入應用層後,還要利用開發者編寫的程序代碼從 RTP 分組中把應用數據塊提取出來。

RTP 報文#

首先,我們看看 RTP 的包頭。RTP 報文頭格式(見 RFC3550 Page12):

2022-06-29-22-47-13

  • 版本號(V):2 比特,用來標誌使用的 RTP 版本。
  • 填充位(P):1 比特,如果該位置位,則該 RTP 包的尾部就包含附加的填充字節。
  • 擴展位(X):1 比特,如果該位置位的話,RTP 固定頭部後面就跟有一個擴展頭部。
  • CSRC 計數器(CC):4 比特,含有固定頭部後面跟著的 CSRC 的數目。
  • 標記位(M):1 比特,該位的解釋由配置文檔(Profile)來承擔。對於在 RTP 以最小的控制配置文件下在音頻和視頻會議下運行的音頻流,標記位設置為 1,表示在一段靜默期後發送的第一個數據包,否則設置為 0。
  • 載荷類型(PayloadType):7 比特,標識了 RTP 載荷的類型。
  • 序列號(SN):16 比特,每發送一個 RTP 數據包,序列號增加 1。接收端可以據此檢測丟包和重建包序列。
  • 時間戳(Timestamp):2 比特,記錄了該包中數據的第一個字節的採樣時刻。
  • 同步源標識符(SSRC):32 比特,同步源就是指 RTP 包流的來源。在同一個 RTP 會話中不能有兩個相同的 SSRC 值。該標識符是隨機選取的 RFC1889 推薦了 MD5 隨機算法。
  • 贡献源列表(CSRC List):0~15 項,每項 32 比特,用來標誌對一個 RTP 混合器產生的新包有貢獻的所有 RTP 包的源。由混合器將這些有貢獻的 SSRC 標識符插入表中。SSRC 標識符都被列出來,以便接收端能正確指出交談雙方的身份。

RTP 擴展頭結構#

2022-06-29-22-47-30

若 RTP 固定頭中的擴展比特位置 1(注意:如果有 CSRC 列表,則在 CSRC 列表之後),則一個長度可變的頭擴展部分被加到 RTP 固定頭之後。頭擴展包含 16 比特的長度域,指示擴展項中 32 比特字的個數,不包括 4 個字節擴展頭(因此零是有效值)。

RTP 固定頭之後只允許有一個頭擴展。為允許多個互操作實現獨立生成不同的頭擴展,或某種特定實現有多種不同的頭擴展,擴展項的前 16 比特用以識別標識符或參數。這 16 比特的格式由具體實現的上層協議定義。基本的 RTP 說明並不定義任何頭擴展本身。

RTP 會話#

當應用程序建立一個 RTP 會話時,應用程序將確定一對目的傳輸地址。目的傳輸地址由一個網路地址和一對端口組成,有兩個端口:一個給 RTP 包,一個給 RTCP 包,使得 RTP/RTCP 數據能夠正確發送。RTP 數據發向偶數的 UDP 端口,而對應的控制信號 RTCP 數據發向相鄰的奇數 UDP 端口(偶數的 UDP 端口 + 1),這樣就構成一個 UDP 端口對。

RTP 發送過程#

  1. RTP 協議從上層接收串流媒體信息碼流(如 H.263),封裝成 RTP 數據包;RTCP 從上層接收控制信息,封裝成 RTCP 控制包。
  2. RTP 數據包發往 UDP 端口對中偶數端口;RTCP 將 RTCP 控制包發往 UDP 端口對中的接收端口。

RTP profile 機制#

RTP 為具體的應用提供了非常大的靈活性,它將傳輸協議與具體的應用環境、具體的控制策略分開,傳輸協議本身只提供完成即時傳輸的機制,開發者可以根據不同的應用環境,自主選擇合適的配置環境、以及合適的控制策略。

這裡所說的控制策略指的是你可以根據自己特定的應用需求,來實現特定的一些 RTCP 控制算法,比如前面提到的丟包的檢測算法、丟包的重傳策略、一些視頻會議應用中的控制方案等等(這些策略我可能將在後續的文章中進行描述)。

對於上面說的合適的配置環境,主要是指 RTP 的相關配置和負載格式的定義。RTP 協議為了廣泛地支持各種多媒體格式(如 H.264, MPEG-4, MJPEG, MPEG),沒有在協議中體現出具體的應用配置,而是通過 profile 配置文件以及負載類型格式說明文件的形式來提供。對於任何一種特定的應用,RTP 定義了一個 profile 文件以及相關的負載格式說明。

RTCP#

服務質量的監視與反饋、媒體間的同步,以及多播組中成員的標識。在 RTP 會話期間,各參與者周期性地傳送 RTCP 包。RTCP 包中含有已發送的數據包的數量、丟失的數據包的數量等統計資料,因此,各參與者可以利用這些信息動態地改變傳輸速率,甚至改變有效載荷類型。RTP 和 RTCP 配合使用,它們能以有效的反饋和最小的開銷使傳輸效率最佳化,因而特別適合傳送網上的即時數據。

 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
+---------------+---------------+-------------------------------+
|V=2|P|   IC    |       PT      |             Length            |
+---------------+---------------+-------------------------------+
|                                                               |
|                  Format-specific information                  |
|                                                               |
|                                       +-----------------------+
|                                       |    Padding if P = 1   |
+---------------------------------------+-----------------------+

各個字段的含義為:

  • 版本號,固定為 2;
  • 填充(Padding)標誌位,1 表示有填充;
  • 條目數量(Item Count,簡稱 IC),在 RTCP 包的內容是條目列表時,用來表明條目數量;其他情況可作為別的含義;
  • 包類型(Packet Type,也簡稱 PT),rfc3550 定義了五種標準包類型,分別是 sender report (SR), receiver report (RR), source description (SDES), goodbye (BYE), application-specific message (APP);
  • 長度,包頭之後的內容總長度,單位是四字節,允許為 0;

RTCP 包不會單獨的被傳輸,它需要打包在一起形成複合包(compound packets)進行傳輸。每一個複合包都會被一個底層的包封裝(通常是 UDP/IP 包)用來傳輸。如果要對複合包進行加密,那麼 RTCP 的包組的前綴通常是一個 32 位的隨機數。複合包的結構如下圖所示:

+---------------------------------------------------------------+
|                                                               |
|                          IP header                            |
|                                                               |
+---------------------------------------------------------------+
|                                                               |
|                          UDP header                           |
|                                                               |
+---------------------------------------------------------------+
|                  Random prefix (if encrypted)                 |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|V=2|P|   IC    |       PT      |             Length            |
+---------------+---------------+-------------------------------+
|                                                               | first
|                                                               | RTCP
|                  Format-specific information                  | packet
|                                                               |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|V=2|P|   IC    |       PT      |             Length            |
+---------------+---------------+-------------------------------+
|                                                               | second
|                                                               | RTCP
|                  Format-specific information                  | packet
|                                                               |
+---------------------------------------------------------------+

RTCP 也是用 UDP 來傳送的,但 RTCP 封裝的僅僅是一些控制信息,因而分組很短,所以可以將多個 RTCP 分組封裝在一個 UDP 包中。RTCP 有如下五種分組類型。

類型縮寫表示用途
200SR(Sender Report)發送端報告
201RR(Receiver Report)接收端報告
202SDES(Source Description Items)源點描述
203BYE結束傳輸
204.APP特定應用

上述五種分組的封裝大同小異,下面只講述 SR 類型,而其它類型請參考 RFC3550。

發送端報告分組 SR(Sender Report)用來使發送端以多播方式向所有接收端報告發送情況。SR 分組的主要內容有:相應的 RTP 流的 SSRC,RTP 流中最新產生的 RTP 分組的時間戳和 NTP,RTP 流包含的分組數,RTP 流包含的字節數。SR 包的封裝如圖所示:

 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|    RC   |   PT=SR=200   |             Length            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                     SSRC of packet sender                     |
+---------------------------------------------------------------+
|                        NTP timestamp                          |
|                                                               |
+---------------------------------------------------------------+
|                        RTP timestamp                          |
+---------------------------------------------------------------+
|                    Sender's packet count                      |
+---------------------------------------------------------------+
|                    Sender's octet count                       |
+---------------------------------------------------------------+
|                   Receiver report block(s)                    |
|                                                               |
  • 版本(V):同 RTP 包頭域。
  • 填充(P):同 RTP 包頭域。
  • 接收報告計數器(RC):5 比特,該 SR 包中的接收報告塊的數目,可以為零。
  • 包類型(PT):8 比特,SR 包是 200。
  • 長度域(Length):16 比特,其中存放的是該 SR 包以 32 比特為單位的總長度減一。
  • 同步源(SSRC):SR 包發送者的同步源標識符。與對應 RTP 包中的 SSRC 一樣。
  • NTP Timestamp(Network time protocol):SR 包發送時的絕對時間值。NTP 的作用是同步不同的 RTP 媒體流。
  • RTP Timestamp:與 NTP 時間戳對應,與 RTP 數據包中的 RTP 時間戳具有相同的單位和隨機初始值。
  • Sender's packet count:從開始發送包到產生這個 SR 包這段時間裡,發送者發送的 RTP 數據包的總數。SSRC 改變時,這個域清零。
  • Sender's octet count:從開始發送包到產生這個 SR 包這段時間裡,發送者發送的淨荷數據的總字節數(不包括頭部和填充)。發送者改變其 SSRC 時,這個域要清零。
  • 同步源 n 的 SSRC 標識符:該報告塊中包含的是從該源接收到的包的統計信息。
  • 丟失率 (Fraction Lost):表明從上個 SR 或 RR 包發出以來從同步源 n (SSRC_n) 來的 RTP 數據包的丟失率。
  • 累計的包丟失數目:從開始接收到 SSRC_n 的包到發送 SR, 從 SSRC_n 傳過來的 RTP 數據包的丟失總數。
  • 收到的擴展最大序列號:從 SSRC_n 收到的 RTP 數據包中最大的序列號,
  • 接收抖動 (Interarrival jitter):RTP 數據包接受時間的統計方差估計
  • 上次 SR 時間戳 (Last SR,LSR):取最近從 SSRC_n 收到的 SR 包中的 NTP 時間戳的中間 32 比特。如果目前還沒收到 SR 包,則該域清零。
  • 上次 SR 以來的延時 (Delay since last SR,DLSR):上次從 SSRC_n 收到 SR 包到發送本報告的延時。

RTP 時間戳#

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

在 RTP 協議中並沒有規定時間戳的粒度,這取決於有效載荷的類型,如採樣頻率為 90000 HZ,那麼時間戳單位為 1/90000, 如果每秒發送 30 幀,那麼時間戳增量就是 90000/30 = 3000。

時間戳增量是發送第二個 RTP 包相距發送第一個 RTP 包時的時間間隔,如果是視頻應該是發送每幀的間隔時間。

代碼#

RTP header

/*
 * RTP header
 */
typedef struct 
{
#if 0   //BIG_ENDIA
    unsigned int version:2;   /* protocol version */
    unsigned int p:1;         /* padding flag */
    unsigned int x:1;         /* header extension flag */
    unsigned int cc:4;        /* CSRC count */
    unsigned int m:1;         /* marker bit */
    unsigned int pt:7;        /* payload type */
    unsigned int seq:16;      /* sequence number */

#else
    unsigned int cc:4;        /* CSRC count */
    unsigned int x:1;         /* header extension flag */
    unsigned int p:1;         /* padding flag */
    unsigned int version:2;   /* protocol version */
    unsigned int pt:7;        /* payload type */
    unsigned int m:1;         /* marker bit */
    unsigned int seq:16;      /* sequence number */
#endif
    u_int32 ts;               /* timestamp */
    u_int32 ssrc;             /* synchronization source */
    u_int32 csrc[1];          /* optional CSRC list */
} rtp_hdr_t;

RTCP Common header

/*
 * RTCP common header word
 */
typedef struct {
#if 0   //BIG_ENDIA
    unsigned int version:2;   /* protocol version */
    unsigned int p:1;         /* padding flag */
    unsigned int count:5;     /* varies by packet type */
#else
    unsigned int count:5;     /* varies by packet type */
    unsigned int p:1;         /* padding flag */
    unsigned int version:2;   /* protocol version */
#endif
    unsigned int pt:8;        /* RTCP packet type */
    unsigned short length;           /* pkt len in words, w/o this word */

} rtcp_common_t;
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。