2012年5月15日 星期二

RTP閱讀心得整理



現今串流媒體在網際網路上的傳輸方式主要有兩種方式,一種是以 HTTP/TCP 為基礎,另一種是以 RTP/UDP 為基礎。此篇整理個人閱讀RFC3350的心得。


基本介紹:

RFC(Request For Comment) 組織定義了RTP協定,其原始編號為RFC 1889,現在則由RFC 3550取代之。

RTP基本上是一個在UDP之上的協定,用來傳送音頻與視頻,RTP 的連線埠號(Port)必須為偶數號碼,而 RTCP 的連線埠號必須為該偶數號碼的下一個數字。
RTP is originated and received on even port numbers and the associated RTCP communication uses the next higher odd port number.

RTP/RTCP 並不提供服務品質或傳輸可靠性的保證,只提供時間戳記(Timestamp,用來達成同步等能力)、序號(Sequence Number,用來決定封包是否遺失等資訊)等一些具有即時特性資料的基本功能。

RFC3551則針對RTP協定所會傳遞的各種音頻與視頻,定義了一套標準的編碼與名稱,提供各式串流應用使用。




RTPRTCP的使用場景如下:


RTP(Real Time Protocol)

RTP Header:

l   V(version):固定為2
l   P(padding):設定是否要在資料的尾端加上padding(某些加密演算法需要固定長度的padding)
l   X(Extension):設定是否要增加擴充的extension header。此extension應加在CSRC list之後,若此封包不存在CSRC list,則加在SSRC 之後。下面為extension header,其中length記錄了header extension共佔據了幾個four-octet

l   CC(CSRC count)CRSC的數量
l   M(Marker):針對不同的 profileMarker會有不同意思,一般用法是用來標註frame boundaries。
l   PT(Payload Type):定義了128種不同的編解碼方式。
l   Sequence number16位元的序號,用來偵測封包遺失,或進行封包重組。
l   timestamp:採樣時的時間,用來作同步和jitter計算。可以使用系統時間或是採樣週期(sampling clock)
l   SSRC:同步來源。在一個RTP會話中,不應該存在相同的SSRC,因此此值需要亂數產生,並且需要偵測是否重複的SSRC產生,並解決此重複的問題。
l   CSRC list(0~15items)
Mixer會重組payload,並將原始payload (SSRC)插入CSRC list。若新的payload由多個payload所組成,CSRC list便會列出所有對此payload作了貢獻的SSRCCRSC list最多只會有15個。
The CSRC list identifies the contributing sources for the payload contained in this packet.


RTCP (RTP Control Protocol): Bandwidth Scaling
RTCP用來在sourcedestination之間交換報告,以了解目前傳送的狀態。報告內容包含各種統計資料,例如:送出的封包數,遺失的封包數,inter-arrival jitter

RTCP有四種功用
l   提供資料傳輸品質的回饋
Provide feedback on the quality of the data distribution.
l   提供CNAME(canonical name),因為SSRC可能因為衝突或程序重起而改變,接收者需要CNAME來追蹤每一個參與者。
l   可以控制傳送速率,讓更多的參與者可以加入RTP會話。作法是藉著觀察參與者的數量,重新計算發包的速率。
l   傳送最小的會談控制資訊,例如顯示使用者身分(CNAME)

RTCP封包格式
有以下五種格式:
l   SR(Sender report):發送端的傳輸與接收到的統計資料。
l   RR(Receiver report):接收端的統計資料,並且結合超過31個來源的SR
Receiver report, for reception statistics from participants that are not active senders and in combination with SR for active senders reporting on more than 31 sources
l   SDES(Source description):對於來源的描述
l   BYE:參與者結束會談
l   APP:提供特殊應用使用

RTCP封包
RTCP封包一定是32位元的倍數(32bits boundary),由於RTCP此種對齊的特性,多個RTCP封包可以直接串接,不需要插入其他欄位,此稱為RTCP ”stackable”特性。

對於RTCP集合封包(compound RTCP packet),定義了以下限制
l   每一個傳送週期所送出的RTCP集合封包必須帶有報告封包(SR or RR)
each periodically transmitted compound RTCP packet MUST include a report packet
l   因為需要使用CNAME儘快辨識來源,所以必須包含SDES欄位。
l   封包種類所佔的個數應該要出現在集合封包的最前面,用來限制第一個字節中constant bits所佔的個數????。(應該也是為了對齊)
l   可以出現在 *集合封包* 的最前面那個封包的種類數要有限制, 這樣可以因為需要分辨的種類少, 而增長前面的常數部分的位元(bit)數. 並且可以使得將其他錯誤封包誤認為是RTCP封包的可能性減少.(感謝徐瑞斌的指正,實際例子請參考下方留言)
The number of packet types that may appear first in the compound packet needs to be limited to increase the number of constant bits in the first word and the probability of successfully validating RTCP packets against misaddressed RTP data packets or other unrelated packets

因此RTCP集合封包應該最少包含兩個以下類型的封包
l   Encryption prefix:若是加密的,就需要此欄位。
l   SR or RR集合封包內的第一個封包,必須是報告封包。如果沒有資料需要報告,也可以僅送出一個空的報告。例如結束時,集合封包內容為一個empty RR BYE
l   Additional RRs:如果接收統計的來源個數超過31個,將這些額外的報告加在初始的報告內容之後。
l   SDES:每個集合封包中一定要包含一個具有CNAMESDES封包。
l   BYE or APPBYE是最後一個送出的封包。APP則根據各種應用而定。

每個RTCP參與者在每個發報間隔中,只能發送一個RTCP集合封包。

RTCP的封包格式舉例如下:


RTCP傳送間隔
發送端可以根據報告內容,判斷是否要調整封包傳送的速度。

l   所有的參與者必須使用相同的頻寬,以便於計算RTCP的間隔時間。
l   報告傳送有個基本原則,報告傳送的頻寬最多只占整個會談(session)5%
l   傳送端佔1/4(25%),而接收端佔3/4(75%),因此報告傳送的頻寬計算方式如下:
n   傳送端:0.05*0.25*會談的頻寬
n   接收端:0.05*0.75*會談的頻寬
l   在整個會談啟動時,在送出第一個RTCP集合封包之前,應該加上一段延遲時間,用來接收所有參與者所回的RTCP封包,以便上述的頻寬間隔計算值能夠更快收斂。此延遲值應該設定為最小間隔的一半,建議是5秒。
l   實作上會將延遲值調整為更小的值,調整方式為360/bandwidth,當頻寬>72kbs時,延遲值就會小於5
l   結論整理如下:
傳送端的RTCP封包傳送週期是:
T=(傳送端的數目/0.25*0.05*會談的頻寬) * (平均RTCP封包大小)
接收端的RTCP封包傳送週期是:
T=(接收端的數目/0.75*0.05*會談的頻寬) * (平均RTCP封包大小)

如果在幾個RTCP傳送週期後都沒有收到RTPRTCP資料(建議是5),可以將此參與者設定為inactive或是予以刪除。

RTCP的送收規則
此處將描述實作時的規則。首先要了解以下變數的意義。
l   Tp: the last time an RTCP packet was transmitted;
l   Tc: the current time;
l   Tn: the next scheduled transmission time of an RTCP packet;
l   pmembers: the estimated number of session members at the time tn was last recomputed;
l   members: the most current estimate for the number of session members;
l   senders: the most current estimate for the number of senders in the session; rtcp_bw: The target RTCP bandwidth, i.e., the total bandwidth that will be used for RTCP packets by all members of this session, in octets per second.  This will be a specified fraction of the "session bandwidth" parameter supplied to the application at startup.
l   we_sent: Flag that is true if the application has sent data since the 2nd previous RTCP report was transmitted.
l   avg_rtcp_size: The average compound RTCP packet size, in octets, over all RTCP packets sent and received by this participant.  The size includes lower-layer transport and network protocol headers (e.g., UDP and IP) as explained in Section 6.2.
l   initial: Flag that is true if the application has not yet sent an RTCP packet.

規則如下:
1.    先計算出傳送封包的週期時間 (calculated interval T),基本原則如上,另外有種算法是 Sender=S/S+R, Receiver=R/S+R,詳細的計算方式請直接參考RFC3550

2.    初始化下列變數
Tp=0, Tc=0, senders=0,
pmembers=1, members=1, we_sent=false, initial=false,
rtcp_bw=The target RTCP bandwidth,
avg_rtcp_size = the probable size of the first RTCP packet that the application will later construct
接著設定 Tn=T(cacluated interval),安排第一個封包送出的時間。
  
3.    當收到 RTP 或是 Non-BYE RTCP 封包需要檢查SSRC是否存在,若不存在,則加入SSRC表格中,然後更新avg_rtcp_size
   avg_rtcp_size = (1/16) * packet_size + (15/16) * avg_rtcp_size

4.    當參與者收到 BYE RTCP 封包,第一件要做的事便是移除SSRC,然後執行"reverse reconsideration"
members = members - 1
tn = tc + (members/pmembers) * (tn - tc)
tp = tc - (members/pmembers) * (tc - tp).
pmembers = members
經過上述計算後,Tn應該會變小,所以下一個封包的發送時間會提早。

5.    處理時的SSRC
接收端的檢查:
對於那些沒有在 Tc-MTd (Mtimeout的乘積,預設為5) 期間內送出 RTP/RTCPSSRC,我們將其視為過期(timeout)SSRC
發送端的檢查:
對於那些沒有在 Tc-2T(最近兩次RTCP報告間隔時間) 期間內送出 RTP/RTCPSSRC,我們將其視為過期(timeout)SSRC
一旦SSRC發生逾時,則需要進行"reverse reconsideration",移除此SSRC,所有參與會談的參與者在每個RTCP周期都應該進行此檢查。

6.    傳輸計時器過期(transmission timer expires)
當傳輸超過指定的傳輸時間,參與者應該執行下列運算 Tp+T<=Tc,便看成RTCP封包已經發送。          Tp=Tc,重新計算TTn=Tc+T,將新的Transmission timer設定為tnTp+T>Tc,表示RTCP封包沒有送達目的地。           Tn=Tp+T,將新的Transmission timer設定為tnpmembers = member
更新avg_rtcp_size
             avg_rtcp_size = (1/16) * packet_size + (15/16) * avg_rtcp_size

7.   當參與者要離開一個會談時,如果此會談參加者超過50,為了避免同時有多個參與者送出BYE封包造成flood,應該執行下列程序。
  • 針對此參與者,重設相關變數
Tp=Tc,the current time = members = pmembers=1,initial=1,we_sent=false,senders=0,avgrtcp_size=the size of compound BYE packet,並且重算T。
  • 接著會安排在 Tn=Tc+T時間送出 BYE封包。
  • 若準備送出BYE封包時,收到別的參與者所送來的BYE封包,為了避免flood,要令 members=members+1,重新計算T。
  • l送出BYE封包。
參與者也可以不送出BYE封包,直接離開會談,藉由上述的過期機制,其他與會者可以發現此參與者已經離開會談。

若是某個參與者從未發送RTP/RTCP封包,則其離開會談時,也不需要發送BYE封包。

8.   如果一個參與者最近有送出封包,則將we_sent設定為TRUE。若經過某段時間都沒有送出封包(Tc-2T),則將we_sent設為FALSE

9.   SDES頻寬配置
對於一個參與者,其傳送額外的資訊量應該有所限制,基本原則是不要超過20%RTCP頻寬。此外,送出SDES封包時不應該送出所有的SDES itemsRFC 3550建議不要動態估算送出的資料量,而是根據item的長度,決定其被送出的週期時間。 
例如:假設一個應用需要CNAME, NAME, EMAIL三個欄位,此會談的平均間隔週期為5秒,則每個RTCP週期都會送出CNAME欄位,每三個周期(15)才會在SDES封包中加上一個額外的欄位,以兩分鐘為例,共可送出8個額外資訊,其中7次是NAME欄位,1次是EMAIL欄位,


RTP的Marker bit補充說明

RFC3550 定義如何將 H.264 使用 RTP 傳送
Marker bit (M): 1 bit
Set for the very last packet of the access unit indicated by the
RTP timestamp, in line with the normal use of the M bit in video
formats, to allow an efficient playout buffer handling.  For
aggregation packets (STAP and MTAP), the marker bit in the RTP
header MUST be set to the value that the marker bit of the last
NAL unit of the aggregation packet would have been if it were
transported in its own RTP packet.  Decoders MAY use this bit as
an early indication of the last packet of an access unit, but MUST
NOT rely on this property.
以下列封包為例,在每個 H.264 Frame 的最後一個封包會設定 marker bit(圖中顯示Mark處),而且由圖中可以看到兩個 Frame之間差異的值為 3000,由於預設 RTP clock = 90000HZ, 因此可以得知此串流的傳輸速度為 3000/90000 = 1/30 FPS。


參考資料
  1. RFC 3550
  2. RFC 3550
  3. 多媒體串流應用:產品比較與實例分析
  4. 原始 VLC
  5. http://www.iana.org/assignments/rtp-parameters/rtp-parameters.xml