天天看點

音視訊 RED 與 FEC 的 RTP 格式封裝背景RTP格式 (RFC 3550)RED資料(RFC 2198)一般FEC的RTP載荷格式 (RFC 2733)ULP FEC的RTP載荷格式(RFC 5109)

音視訊 RED 與 FEC 的 RTP 格式封裝

  • 背景
  • RTP格式 (RFC 3550)
  • RED資料(RFC 2198)
    • 背景知識
    • RED RTP 格式
    • RED SDP 協商
  • 一般FEC的RTP載荷格式 (RFC 2733)
    • 基本原理
    • Generic FEC 方案
    • Generic FEC RTP 格式
    • FEC 生成與恢複
    • FEC 生成示例
    • FEC 作為備援編碼使用
    • FEC SDP 協商
      • FEC 作為獨立流傳輸
      • FEC 作為備援編碼傳輸
  • ULP FEC的RTP載荷格式(RFC 5109)
    • RTP 格式
    • 資料包保護與等級示例
    • ULP FEC 保護操作
    • ULP FEC 恢複操作
      • RTP Header 重建
      • RTP payload 重建
    • 示例
      • RFC 2733 相似示例
      • 兩個保護等級的示例
      • FEC 作為備援編碼的示例

背景

對于語音通信來說,語音的碼率較低,添加适當的備援是對抗網絡丢包常見的方式。備援方式分為多種,包括資料備援,或者編碼備援等,RED,FEC等都是備援的一種。如果備援分數較多,可以采取交織的方式實作。RFC 2198 是備援資料 RTP 封裝的标準協定,RFC 3550 為RTP的基礎标準協定,RFC 5109 為FEC資料的 RTP 封裝标準協定。webrtc中有RED和FEC相關的實作與處理,這也是在看代碼時才決定重新整理協定并記錄下來。

RTP格式 (RFC 3550)

RTP(Real- time Transport Protocol,實時傳輸協定)是在網際網路上常見的一種處理媒體資料流的網絡協定,包括單點傳播或者多點傳播等多種場景下的網絡環境中媒體資料的傳輸。RTP是一種應用層協定,一般使用 UDP作為底層協定實作資料傳輸,但并不強制底層協定的選擇,比如利用 RTSP進行流媒體傳輸時使用 TCP也非常常見。

RTP本身沒有提供任何的機制來確定實時的傳輸或其他的服務品質保證,而是由低層的服務來完成。它不保證傳輸或防止亂序傳輸,它不假定下層網絡是否可靠,是否按順序傳送資料包。

RTP 一般與 RTCP 同時出現,端口号相鄰。RTCP 主要用來提供資料傳輸品質的回報,通過發送接收資訊估算目前網絡狀态,調整資料流。RTCP 為每個RTP源傳輸一個固定的識别符,CNAME。當 SSRC 因重新開機或者沖突發生改變時,可以根據 CNAME 跟蹤參與者,或者用CNAME來關聯一系列相關RTP會話中來自同一個成員的多個資料流,例如同步語音和圖像。當會議時,參與方過多時,需要控制 RTCP流的快速增長,一般以不超過總占用帶寬的 5%。

本文主要是 RTP 的封裝,是以僅僅讨論 RTP,協定格式如下:

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|X|  CC   |M|     PT      |       sequence number         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                           timestamp                           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           synchronization source (SSRC) identifier            |
   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
   |            contributing source (CSRC) identifiers             |
   |                             ....                              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
           

其中,主要的協定字段說明如下:

  1. V:version,2 bits, RTP協定版本号,預設版本号為2, 值 0,1 已經被使用,如 1 用于第一個草案版本,。
  2. P:padding,1 bit, 填充标志。如果 P=1,則在該封包的尾部填充一個或多個額外的填充資料,它們不算作負載的一部分。填充的最後一個位元組指明可以忽略多少個填充比特。填充可能用于某些具有固定長度的加密算法,或者用于在底層資料單元中傳輸多個RTP包。
  3. X:extension,1 bit,擴充标志。如果 X=1,則在 RTP 報頭後将有且僅有一個擴充報頭。
  4. CC:CSRC count,4 bits,CSRC 計數器,辨別 CSRC 辨別符的數量。
  5. M:marker,1 bit,由具體協定解釋其意義。它用來允許在比特流中标記重要的事件,如音視訊幀邊界。
  6. PT:payload type,7 bits,載荷格式,可以用來區分多路音視訊流。接收方必須忽略不了解的 PT 值的資料包。
  7. sequence number:16 bits,序列号,每發送一個 RTP 資料包,序列号加 1,接收端可以據此檢測丢包和重建包序列。
  8. timestamp:32 bits,時間戳。反映了 RTP 資料包中第一個位元組的采樣時間。時間戳的初始值應當是随機的,類似序号。時鐘頻率依賴于負載資料格式,是以時間戳增量依據目前資料格式與政策。如果RTP包是周期性産生的,那麼将使用由采樣時鐘決定的名義上的采樣時刻,而不是讀取系統時間。
  9. SSRC:Synchronization source,32 bits,同步源。RTP 包流的源,使其不依賴于網絡位址。一個同步源的所有包構成了相同計時和序列号空間的一部分,這樣接收方就可以把一個同步源的包放在一起,來進行重放。SSRC 辨別符是一個随機值,它在特定的RTP會話中是全局唯一。一個同步源可能随着時間變化而改變其資料格式,如音頻編碼。
  10. CSRC:Contributing source,0~15 項,每個 32 bits,作用源。若一個 RTP 流的源,對由 RTP 混頻器生成的組合流起了作用,則它就是一個作用源。對特定包的生成起作用的源,其SSRC辨別符組成的清單,被混頻器插入到包的RTP報頭中,這個清單叫做CSRC表。相關應用的例子如,在音頻會議中,混頻器向所有的說話人(talker)指出,誰的話語(speech)将被組合到即将發出的包中,即便所有的包都包含在同一個(混頻器的)SSRC辨別符中,也可讓聽者(接收者)可以清楚誰是目前說話人。

RED資料(RFC 2198)

背景知識

RTP 本身并不提供任何品質保證措施,是以面對網絡擾動時,常常表現的不如人意。是以考慮在通信過程中添加備援資料,即使存在丢包,也可以在一定程度上進行恢複。RFC 2198 主要針對音頻資料,在常見的實作中,如 webrtc 中,也是對于音頻資料采用該标準協定。

對協定産生需求來說,主要存在以下幾個方面:

  1. 每個包必須攜帶一個主編碼資料,以及一個或多個備援編碼資料。
  2. 備援資訊可以存在多種方式,但是每一個備援塊必須有一個編碼類型辨別。
  3. 可能存在變長編碼,是以每個編碼塊都存在長度辨別。
  4. 每個編碼塊都有自己的時間戳,對于備援塊,可以參考與主編碼塊的時間戳內插補點。

RED RTP 格式

處理方式有增加 RTP header 擴充或者采用新的一個或多個負載類型,即 PT來辨別。鑒于使用擴充頭會帶來更多的限制,是以建議采取新增負載類型的方式,靜态配置設定或動态配置設定都可以。在RTP 中,備援頭格式如下:

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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |F|   block PT  |  timestamp offset         |   block length    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
           

相關字段說明如下:

  1. F:1 bit,辨別後面是否還存在其他的頭塊。設定為 1 辨別存在,0 辨別不存在,此為最後一個頭塊。
  2. block PT:7 bits,此資料塊的 RTP payload type。
  3. timestamp offset:14 bits,相對于 RTP header中時間戳的偏移量。使用 unsigned 表示主資料以發送。
  4. block length:10 bits,對應資料塊的有效負載長度,不包含頭長度。

主編碼塊頭位于整個標頭的最後,PT 與 timestamp 參考RTP頭中的值,是以格式如下:

0 1 2 3 4 5 6 7
                     +-+-+-+-+-+-+-+-+
                     |0|   Block PT  |
                     +-+-+-+-+-+-+-+-+

               The primary encoding block header
           

最後一個頭之後就是資料塊,存儲順序和頭的排列順序相同。資料塊之間不需要填充或者使用其它分隔,一般不需要32位對齊。如此選擇仍是為了在損失一定額外解碼時間的情況下降低帶寬負擔。舉例如下,一個音頻資料包包含 DVI4 (8KHz) 主編碼,和一個 8KHz LPC (both 20ms) 的備援編碼包:

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|X| CC=0  |M|      PT     |   sequence number of primary  |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              timestamp  of primary encoding                   |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           synchronization source (SSRC) identifier            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |1| block PT=7  |  timestamp offset         |   block length    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |0| block PT=5  |                                               |
   +-+-+-+-+-+-+-+-+                                               +
   |                                                               |
   +                LPC encoded redundant data (PT=7)              +
   |                (14 bytes)                                     |
   +                                               +---------------+
   |                                               |               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+               +
   |                                                               |
   +                                                               +
   |                                                               |
   +                                                               +
   |                                                               |
   +                                                               +
   |                DVI4 encoded primary data (PT=5)               |
   +                (84 bytes,not to scale)                       +
   /                                                               /
   +                                                               +
   |                                                               |
   +                                                               +
   |                                                               |
   +                                               +---------------+
   |                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
           

RED SDP 協商

在收發雙方進行通信協商時,需要通知雙方的 SDP 協商完成資訊互動,協定中建議的SDP 形式如下:

m=audio 12345 RTP/AVP 121 0 5
       a=rtpmap:121 red/8000/1
       a=fmtp:121 0/5
           

其中,121 為備援編碼的 PT值,0 為PCM,主編碼,5 為 DVI4,第二編碼。a=fmtp 行隻有在指定編碼有效時才可使用,否則,不出現這一行。一般情況下,可以與主編碼保持一緻。

一般FEC的RTP載荷格式 (RFC 2733)

在 Internet 中,語音品質表現不佳的主要原因在于高丢包率,在廣域網中尤其突出。更不幸的是,實時多媒體通信過程中對時延的嚴格要求導緻通過重傳來解決這個問題難以實作。也正是基于此,FEC 才被考慮解決丢包的問題,特别時傳統糾錯碼如校驗碼、RS碼、漢明碼等的使用引起了很多人的注意。為了能夠更好地應用這些糾錯碼,必須有相關的協定來支援。

RFC 2733 定義了一種傳輸實時媒體資料的一般性的 RTP 的載荷格式。一般性意味着,

  1. FEC 協定獨立于它保護的媒體資料,可以是音頻,視訊或者其他;
  2. 具有足夠的靈活性以支援不同的 FEC 機制;
  3. 自适應的設計,使得 FEC 技術修改但不影響帶外傳輸的信令;
  4. 支援許多不同的傳輸FEC 包的機制.

基本原理

RFC 2733 載荷格式支援基于異或校驗算法的 FEC 機制。發送端在媒體流中取出一些包,并對其負荷,以及 RTP 頭中的元件進行異或操作,得到包含 FEC 資訊的 RTP 包。産生的FEC 包可以在接收端恢複關聯到這個 FEC 包的任何一個包。實際中使用時,其實是overhead,時延以及恢複能力之間的一種平衡。

為了能正常恢複,發送方還需要在載荷格式中攜帶資訊,包括哪些媒體包用來生成 FEC 包。每個 FEC 中包含一個24 位的掩碼 mask,如果第 i 位被設定為 1,表示序号 N + 1 的媒體包被用來生成這個FEC 包,其中,N 為 base SN,也将被包含在 FEC 載荷格式中。接收端也可以在不了解具體就糾錯碼的細節使用 FEC,允許發送端具有較大的靈活性,可以根據網絡環境進行自适應的編碼,而接收端仍能正常恢複。

媒體流從發送端發送到接收端,不管是否存在FEC 包,FEC 包在生成後也立即發出,接收端即使不支援 FEC,也不影響媒體流的正常接收。但是也存在一些FEC 糾錯碼,不傳輸原始媒體流,隻使用 FEC 流就可以恢複,缺點是要求所有接收者必須支援 FEC。

FEC 包不與媒體包在同一個RTP 流中發送,以一個單獨的流進行發送,或者作為作為一種備援編碼中次編碼發送(參見RFC 2198)。當作為單獨流發送時,FEC 包具有獨立的序列号空間,但時間戳從對應媒體包得來,單調遞增。FEC 包流支援任何固定內插補點的標頭壓縮機制。對接收端來說,如果沒有丢包,則忽略FEC 包,如果丢包出現,則FEC 将聯合接收到的關聯生成的媒體包組,完全恢複丢失的媒體包。

Generic FEC 方案

定義函數 f(x,y,…) 為對包x,y,…等的異或操作,被叫做奇偶校驗包,也被稱作監督包。為簡單起見,假設監督包就是輸入的各個包的按位異或得到。而使用校驗包對資料包進行恢複是通過産生這些校驗包的這一組資料包完成,這一組資料包必須是線性無關的。這個特定的組合就被稱為一個奇偶校驗碼。一組 k 個資料包,生成 n-k 個校驗包。對于給定的 n 和 k,可能存在大量可能的校驗包,荷載格式并未要求使用某個特定的校驗包。

舉例來說,比如兩個資料包,産生一個校驗包,原始資料包 a,b,c,d,發送端産生包如下所示,時間從左到右。如果 b 丢失,可以通過a 和 f(a,b) 恢複。

a        b        c        d               <-- media stream
              f(a,b)            f(c,d)        <-- FEC stream
           

其他的校驗碼産生方式如下所示:

方案1:
a        b        c        d        e        <-- media stream
    f(a,b)   f(b,c)   f(c,d)   f(d,e)          <-- FEC stream
           

方案 1 可以恢複連續兩個丢包。

方案2:
f(a,b)  f(a,c)  f(a,b,c)  f(c,d)  f(c,e)  f(c,d,e)  <-- FEC stream
           

方案2不發送媒體流,直接發送 FEC 流,通過 FEC 流就可以恢複所有的資料包。好處是占用帶寬小一些,能對付單個丢包和部分連續丢包。

方案3:
a         b          c                    d     <-- 媒體流
             f(a,b,c)    f(a,c,d) f(a,b,d)       <-- FEC流
           

方案 3 恢複包時需要等待4個發包時間間隔。好處是可以恢複單個丢包和連續丢包。

Generic FEC RTP 格式

如果FEC 作為獨立流發送,媒體資料包格式與傳輸不受影響,如果作為備援編碼發送,則參考RFC 2198中主編碼傳輸媒體資料包,次編碼傳輸FEC 包。

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         RTP Header                            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         FEC Header                            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         FEC Payload                           |
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                       FEC Packet Structure
           

FEC 的 RTP 頭中,padding bit、extension bit、CC、marker bit 通過計算得到,SSRC的值一般情況下應當與它所保護的

媒體資料包的SSRC值相同,除非 FEC 流通過 SSRC 值來進行解複用操作。CSRC list 不存在,extension 不存在,這兩個值不受 CC 與 X 影響。序号 sequence number 單調遞增,timestamp 須與當時發送的媒體包時間戳一緻,單調遞增,與 FEC 方案無關。FEC 包的 PT 值動态确定,通過帶外協商完成。不認識的 PT 值包需要抛棄,即提供靈活的處理機制。

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |      SN base                  |        length recovery        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |E| PT recovery |                 mask                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                          TS recovery                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                      Parity Header Format
           

FEC 頭 12 個位元組,如上所示,包含字段 SN base,length recovery,E,PT recovery,mask and TS recovery。

字段 length recovery 将被用來恢複任意關聯資料包,通過多個資料包長度按位異或計算得到,為一個網絡位元組序的無符号的16位整數。資料包長度包含媒體負載,CSRC list,extension 和 padding。如果每個資料包長度不等,仍可以進行異或操作。如兩個媒體包長度分别為 3 (0b011) 和 5 (0b101),則 length recovery 計算方式: 0b011 xor 0b101 = 0b110。

字段 mask 長度 24 bit,如果第 i 位設定為 1,表示序号 N + i 的媒體包被關聯到這個 FEC 包,其中 N 為 SN base,表示這一組媒體包中最小的 RTP 序号。是以,一個 FEC 包最多可以通過一組 24 個包計算得到,最低為 i = 0,最高為 i = 23。

FEC 生成與恢複

保護操作,或者說計算,實際上就是将媒體包中 RTP 頭中對應字段級聯計算,以及負荷中。對于每一個要保護的媒體包,按照下面的次序将各個字段級聯起來生成一個比特序列:

  • Padding Bit (1 bit) 最重要比特位
  • Extension Bit (1 bit)
  • CC bits (4 bits)
  • Marker bit (1 bit)
  • Payload Type (7 bits)
  • Timestamp (32 bits)
  • Unsigned network-ordered 16 bit representation of the sum ofthe lengths (in bytes) of the CSRC List length of the padding,length of the extension,and length of the media payload (16 bits)
  • if CC is nonzero,the CSRC List (variable length)
  • if X is 1,the Header Extension (variable length)
  • the payload (variable length)

如果比特字元串的長度不等,那些短的比特串需要填充到最長的串等長。填充值可以任意,但必須在比特串末尾。然後對這些bit 串進行異或操作,結果便适用于構造 FEC 包的比特串,成為 FEC 比特串。構造包時,按照上述順序逐一按照比特大小填入。

使用FEC 包恢複丢包過程包含兩步,第一步确定丢包所在的媒體包組,包括媒體包和 FEC 包,第二步進行恢複。設 T 為用來恢複一些媒體包 xi 的包組,包括接收到的媒體包和 FEC 包,RTP 頭以及整個負荷的恢複方法如下:

  1. 對于 T 中的媒體包,如上節所述保護操作計算比特串;
  2. 對于 T 中的 FEC 包,以相同的方式計算比特串,除了使用 PT Recovery 代替 PT,使用 TS Recovery 代替 Timestamp,設定 CSRC list Extension,Padding 為空;
  3. 如果某個媒體包生成的比特串小于 FEC 包的比特串長度,則在後面填充到一樣長,填充值随意;
  4. 對這些字元串執行異或操作,得到一個恢複比特串;
  5. 建立一個空的12位元組的 RTP 頭,負載為空;
  6. 設定新的 RTP 包版本号為 2;
  7. 設定新包 Padding 字段為恢複比特串的第 1 bit;
  8. 設定新包 Extension 字段為恢複比特串的第 2 bit;
  9. 設定新包 CC 字段為恢複比特串的接下來的 4 bits;
  10. 設定新包 marker 字段為恢複比特串的接下來的 1 bit;
  11. 設定新包 PT 字段為恢複比特串的接下來的 7 bits;
  12. 設定新包 SN 字段為 xi;
  13. 設定新包 TS 字段為恢複比特串的接下來的 32 bits;
  14. 從恢複出的比特序列中取出接下來的16 bits,将其作為一個網絡序的無符号整數,然後從恢複出的比特序列中取出這個整數那麼多的位元組,添加在新包之後,表示新包的CSRC清單、擴充、荷載和填充;
  15. 設定新包 SSRC 字段為所保護媒體包的 SSRC。

FEC 生成示例

示例如下。兩個媒體包 X, Y,其 RTP header 如下所示,根據這兩個媒體包生成一個 FEC 包。負載長度分别為 10,11。

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        Version:   2
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      Padding:   0
   |1 0|0|0|0 0 0 0|0|0 0 0 1 0 1 1|0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0|      Extension: 0
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      Marker:    0
   |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1|      PTI:       11
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      SN:        8
   |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0|      TS:        3
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      SSRC:      2

                  RTP Header for Media Packet X

   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        Version:   2
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      Padding:   0
   |1 0|0|0|0 0 0 0|1|0 0 1 0 0 1 0|0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1|      Extension: 0
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      Marker:    1
   |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1|      PTI:       18
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      SN:        9
   |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0|      TS:        5
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      SSRC:      2

                  RTP Header for Media Packet Y
           

FEC 包的 PT 值設定為 127, 對于 RTP Header 來說,Version 固定設定為 2,PTI 設定為 127,TS 與 Y 保持一緻,設定為 5, SSRC 保持相同。對于 FEC Header,SN base 設定為組中最小序号,length recovery,PTI recovery,TS recovery 設定為異或計算結果。mask 表示連續的第 0,1 兩個包。長度為最長值。

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        Version:   2
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      Padding:   0
   |1 0|0|0|0 0 0 0|1|1 1 1 1 1 1 1|0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1|      Extension: 0
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      Marker:    1
   |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1|      PTI:       127
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      SN:        1
   |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0|      TS:        5
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      SSRC:      2

                  RTP Header of FEC for Packets X and Y

 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      SN base:   8    [min(8,9)]
   |0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0|0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1|      len. rec.: 1    [8 xor 9]
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      E:         0
   |0|0 0 1 1 0 0 1|0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1|      PTI rec.:  25   [11 xor 18]
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      mask:      3
   |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0|      TS rec.:   6    [3 xor 5]
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      The payload length is 11 bytes.

                  FEC Header of Result
           

FEC 作為備援編碼使用

如果将 FEC 作為 RFC 2198 中的備援編碼發送,被保護的媒體流被封裝到标準 RTP 媒體包中,産生的 FEC 包流需要稍有改變:如果媒體包包含 RTP extension,padding,或者 a CSRC list,必須先從包中移除,然後設定the CC field,Padding Bit,and Extension 被設定為 0,然後再對這些包應用 FEC 保護操作。原始媒體包作為主編碼資料,僅僅在生成 FEC 包時才去掉上述字段。

一旦 FEC 包生成,将媒體包中的負荷提取出來,作為主編碼資料。FEC header 和 FEC 包中的 payload 提取出來,作為備援編碼。FEC 包外其他包也可以增加在備援編碼發送,但是不受 FEC 保護。 主編碼的備援編碼頭按照 RFC 2198 中的定義進行設定。

FEC 資料的備援編碼頭的設定:

  • 塊荷載類型域(block PT)設定為與 FEC 相關聯的動态 PT 值;
  • 塊長度(block length)設定為 FEC 頭和 FEC 荷載的長度之和;
  • 時間戳偏移(timestamp offset)應當設定為 0;
  • 次編碼(secondary codec)的荷載包括 FEC 頭和 FEC 荷載。

在接收端,主編碼與所有次編碼作為獨立的 RTP 包提取出來,複制備援編碼包的 RTP 頭中的 sequence number,SSRC,marker bit,CC field,RTP version,和 extension bit 到每一個提取出來包的 RTP 頭。如果次編碼包含 FEC,那麼FEC 包的 RTP 頭中 CC,Extension Bit,和 Padding Bit 必須設定為 0, 提取出的包的 PT 從備援編碼頭中 block PT 複制過來, 提取出的包的時間戳是 RTP 頭中 timestamp 與 block header 中的 offset 之差。

為了使用 FEC 和媒體包進行恢複,CSRC list,extension,和 padding 如果存在則需要先去掉,并把 CC,Extension Bit,和 Padding Bit 設定為 0,修改後的媒體包與 FEC 包一起進行恢複丢失包。恢複出的包将總是沒有 extension,padding,或者 CSRC list。在具體實作中,如果其它包中存在這些部分,可以從其它包中将這些部分拷貝過來。

使用備援編碼的荷載格式,有可能不能正确恢複出 marker bit。在使用 RFC 2198 來進行 FEC 封裝的應用程式中,必須把恢複出的媒體資料包的 marker bit 設定為零。相對于發送完整的FEC包,這種方法的優點在于它能夠減少 overhead。

FEC SDP 協商

SDP 協商将必要資訊帶外傳輸給對端,包括 RTP PT,多點傳播組或端口,是否使用備援編碼載荷格式等。本節主要分為 FEC 流獨立流傳輸,和使用備援編碼中傳輸兩種方式。

FEC 作為獨立流傳輸

FEC包是作為一個獨立的流來進行傳輸的。這可能意味着它們被發往與媒體包不同的端口或不同的多點傳播組。必須攜帶資訊:

  • FEC包被發往的位址和端口
  • FEC包的 PT 值
  • 所保護的流辨別

FEC 的 rtpmap 行表明 FEC 的 PT 值,以及名稱 “parityfec”, FEC 的 fmtp 行傳遞端口和位址資訊,格式如下所示:

a=fmtp:<荷載類型号> <端口> <網絡類型> <位址類型> <連接配接位址>

SDP 示例如下,媒體格式為 0 的 PCM 編碼的音頻,它被 PT 值為 78 的 FEC 流保護,視訊流被 PT 值為 79 的 FEC 流保護,這個FEC流的端口号是一樣的,但是多點傳播位址不一樣:

v=0
   o=hamming 2890844526 2890842807 IN IP4 126.16.64.4
   s=FEC Seminar
   c=IN IP4 224.2.17.12/127
   t=0 0
   m=audio 49170 RTP/AVP 0 78
   a=rtpmap:78 parityfec/8000
   a=fmtp:78 49172 IN IP4 224.2.17.12/127
   m=video 51372 RTP/AVP 31 79
   a=rtpmap:79 parityfec/8000
   a=fmtp:79 51372 IN IP4 224.2.17.13/127
           

FEC 作為備援編碼傳輸

當 FEC 流以備援編碼格式作為次編碼來發送的時候,必須使用 RFC2198中定義的步驟通過 SDP 通知對方。FEC的荷載類型就象其它任意一個次編碼那樣表示,用 rtpmap 屬性行來訓示出 FEC 包的動态 PT 值。FEC必須隻保護主編碼。這時,FEC 的 fmtp 屬性必須不出現。

SDP 示例如下,有一個單一的音頻流,由 PCM 格式(PT 值為 0)和 DVI 格式(PT 值為 5)組成,一個備援編碼(用 PT 值 121 表示,在 rtpmap 屬性中綁定為 red),以及一個FEC(PT 值 100,在 rtpmap 屬性中綁定為 parityfec)。盡管 FEC 格式是作為媒體流的一個可能編碼來描述的,但它不能單獨傳送。它出現在 m 行中隻是因為按照 RFC 2198,非主編碼(non-primary codec)都必須在這裡列出來。fmtp 屬性指出備援編碼格式可以這樣使用:DVI 作為一個次編碼(secondary coding),而 FEC 作為第三編碼(tertiary encoding)。

m=audio 12345 RTP/AVP 121 0 5 100
   a=rtpmap:121 red/8000/1
   a=rtpmap:100 parityfec/8000
   a=fmtp:121 0/5/100
           

ULP FEC的RTP載荷格式(RFC 5109)

RTP 格式

ULP (uneven level protection) 為不均等保護,即對被保護的資料重要性進行分級保護,保證重要的資料擁有更大的可恢複性,同時也會占用更多的帶寬。這一點,在音視訊資料上表現較明顯,攜帶多個 level 的 ULP FEC 包結構如下所示。RTP Header 格式遵循 RFC 3550。

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                RTP Header (12 octets or more)                 |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    FEC Header (10 octets)                     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                      FEC Level 0 Header                       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                     FEC Level 0 Payload                       |
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                      FEC Level 1 Header                       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                     FEC Level 1 Payload                       |
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                            Cont.                              |
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                  FEC Packet Structure
           

FEC 包的 RTP Header 僅僅針對資料流與 FEC 分離的方式。FEC Header 如下所示,與 RFC 2733 比較,需要注意差別。

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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |E|L|P|X|  CC   |M| PT recovery |            SN base            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                          TS recovery                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |        length recovery        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                  FEC Header Format 
           

其中:

  1. E 為擴充位,被設定為0,接收方應當忽略此字段;
  2. L 辨別長掩碼是否被使用,預設不設定,16 位,如果設定,則 48 位。
  3. FEC Header 中五個恢複相關字段 P,X,CC,M,PT recovery 的值都是通過被保護資料的 RTP 頭中對應字段通過 FEC 算法計算而出。
  4. SN base 字段中填入被 FEC 保護的媒體包的最小 RTP 序号(注意序号環繞),辨別起始序号。如果 L 字段被設定為 0,最多16個包,如果 L 字段被設定為 1,則可最多 48 個包。
  5. TS recovery 通過關聯的媒體包的時間戳計算而來,可以對時間戳進行恢複。
  6. length recovery 根據長度字段計算得到,用于得到恢複包的長度。長度包括media payload,CSRC list,extension 和 padding,是以被保護的媒體包長度可以不相同。

FEC level header 長度與 L 字段有關,4 位元組或 8 位元組,Protection Length 占 16 位, mask 占 16 位或者48 位,結構格式如下所示。

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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |       Protection Length       |             mask              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              mask cont. (present only when L = 1)             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                  ULP Level Header Format
           

其中,mask 字段辨別哪些包在目前的保護層級(level)上被保護。如果 mask 第 i 位被設定為 1, 表示序号為 SN base + i 的媒體包被保護。對邊界情形 i = 0 和 i = 15 的情況需要特别注意一些。mask 字段設定需要遵循的規則如下:

  • a. 一個媒體資料包在高于保護等級 0 的級别中隻能被保護一次,但可能被多個包在等級 0 上保護,且在等級 0 上保護長度相等;
  • b. 如果一個包在等級 p 上被保護,它也必須在等級 p-1 上被一些 FEC 包保護。注意,對相同媒體包,在等級 p 上的 FEC 包和 p-1 上的 FEC 包可以不同;
  • c. 如果一個 ULP FEC 包在等級 p 上對媒體包提供保護,那麼也将在 p-1 上提供。注意,在等級 p 上保護的包組可能不同于 p -1 上保護的包組。

資料包保護與等級示例

Packet A          #####################
                                  :        :
         Packet B          ############### :
                                  :        :
         ULP FEC Packet #1 @@@@@@@@        :
                                  :        :
         Packet C          ###########     :
                                  :        :
         Packet D          ###################################
                                  :        :
         ULP FEC Packet #2 @@@@@@@@@@@@@@@@@
                           :      :        :
                           :<-L0->:<--L1-->:

         Payload packet #  |  ULP FEC packet that protects at level
                           |          L0             L1
      ---------------------+---------------------------------------
                A          |          #1             #2
                B          |          #1             #2
                C          |          #2             #2
                D          |          #2             #2

           An Example of Protection Combination
           

在上例中可以看出,ULP FEC packet #1 僅保護等級 0, ULP FEC packet #2 同時保護等級 0 和等級 1。資料包 A 在保護等級 0 被 ULP FEC packet #1 保護,在保護等級 1 被 ULP FEC packet #2 保護。ULP FEC packet #2 在 等級 0上保護資料包 C 和 D,在等級 1 上保護 A,B,C,D。

ULP FEC 保護操作

在ULP FEC 包的每一層負荷資料都是通過 FEC 保護算法(如 XOR) 對關聯到這一保護層級的媒體資料包中的負荷以及填充資料進行計算而得到,ULP FEC 包的長度由所保護的長度決定。

FEC Header 占 80 bits,其中前 64 bits 是 RTP Header 中對應字段進行奇偶校驗操作得到(XOR),剩餘 16 bits 為網絡位元組序的無符号整數,表示計算得到的保護長度值。

将資料包看成由 bit 組成的 字元串,那麼 FEC bit string 的生成實際上是需要被保護的 payload bit string 按位異或操作得到。如果有包的長度較短,需要先用 0 做補齊操作。

對于每個保護級别 n (n = 0,1,…),第 n 級 ULP Header 後跟随第 n 級保護資料。是以 Ln 資料開始于FEC 字元串的 第(Sn + 13)位元組,其中 Sn = sum(Li : 0 <= i < n),前12個位元組為 FEC Header。

ULP FEC 恢複操作

FEC 主要用來恢複丢失媒體包,恢複操作分為兩部分,首先需要找到包括丢失包的這一組生成 FEC 包的媒體包,然後再重建,包括頭部與負載。丢失的負荷包可能被完全或部分恢複,取決于丢包程度以及保護等級。

RTP Header 重建

設 T 表示 在等級 0 上,用于恢複一些媒體包 xi 的包組,包括 FEC 包和媒體包。過程如下:

  1. 對 T 中的每個媒體包,計算被保護的序列最前面的 80 位;
  2. 對 T 中的 FEC 包,FEC 比特序列是 80 位的 FEC 頭;
  3. 計算恢複字串,通過對 T 中所有的媒體包和FEC 的比特序列按位異或;
  4. 建立一個無負荷的 RTP 標頭;
  5. version 為 2, recovery bit string 後移 2 位;
  6. Padding 為 recovery bit string 下一位;
  7. Extension 為 recovery bit string 下一位;
  8. CC 為 recovery bit string 下 4 位;
  9. marker 為 recovery bit string 下一位;
  10. PT 為 recovery bit string 下 7 位;
  11. SN 為 xi,跳過 recovery bit string 16位;
  12. TS 為 recovery bit string 下 32 位;
  13. 在新包後添加 recovery bit string 下 16 位,表示 CSRC list,extension,payload,padding;
  14. SSRC 與關聯媒體流中相同。

RTP payload 重建

T 與 xi 同上,重建過程如下:

  1. 假定我們需要重建的是等級 n 上的資料,首先需要從等級 n 的 ULP header 中擷取保護長度 Ln;
  2. 對 T 中的 FEC 包,FEC 在 等級 n 上的負載為等級 n 上的 FEC 比特序列;
  3. 對 T 中的 媒體包,在等級 n 上被保護的比特序列為包從第 (Sn + 13) 個位元組開始的 Ln 個位元組;
  4. 如果從媒體包中産生的在等級 n 上被保護的比特序列長度小于目前等級的保護長度,則在後面補 0 到對應長度;
  5. 對 T 中所有媒體包在等級 n 産生的被保護的比特串,以及 T 中所有 FEC 包在等級 n 産生的比特串進行異或操作計算,得到恢複的比特序列;
  6. 聯合其他等級生成的恢複字元串,生成恢複的媒體包;
  7. 被恢複媒體包的總長度從等級 0 的恢複操作中得到,也可以用這個長度來檢查是否恢複完全。

示例

RFC 2733 相似示例

4 個媒體包,生成一個 FEC 包,如下所示:

+-------------------+             :
         Packet A   |                   |             :
                    +-------------+-----+             :
         Packet B   |             |                   :
                    +---------+---+                   :
         Packet C   |         |                       :
                    +---------+-----------------------+
         Packet D   |                                 |
                    +---------------------------------+
                                                      :
                    +---------------------------------+
         Packet FEC |                                 |
                    +---------------------------------+
                    :                                 :
                    :<------------- L0 -------------->:

            FEC Scheme with Single-Level Protection
           

假設 FEC 包 PT 值為 127,生成包中 RTP Header 如下所示:

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       Version:   2
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      Padding:   0
   |1 0|0|0|0 0 0 0|0|1 1 1 1 1 1 1|0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1|      Extension: 0
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      Marker:    0
   |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1|      PT:        127
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      SN:        1
   |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0|      TS:        9
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      SSRC:      2

                  RTP Header of FEC Packet
           

FEC 包 FEC header 如下所示:

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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |0|0|0|0|0 0 0 0|0|0 0 0 0 0 0 0|0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |0 0 0 0 0 0 0 1 0 1 1 1 0 1 0 0|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

      E:         0     [this specification]
      L:         0     [short 16-bit mask]
      P rec.:    0     [0 XOR 0 XOR 0 XOR 0]
      X rec.:    0     [0 XOR 0 XOR 0 XOR 0]
      CC rec.:   0     [0 XOR 0 XOR 0 XOR 0]
      M rec.:    0     [1 XOR 0 XOR 1 XOR 0]
      PT rec.:   0     [11 XOR 18 XOR 11 XOR 18]
      SN base:   8     [min(8,9,10,11)]
      TS rec.:   8     [3 XOR 5 XOR 7 XOR 9]
      len. rec.: 372   [200 XOR 140 XOR 100 XOR 340]

               FEC Header of FEC Packet
           

在等級 0 上的 FEC level header 如下所示:

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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |0 0 0 0 0 0 0 1 0 1 0 1 0 1 0 0|1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

      L0:        340   [the longest of 200,140,100,and 340]
      mask:      61440 [with Bits 1,2,3,and 4 marked accordingly for
                        Packets 8,9,10,and 11]
      The payload length for level 0 is 340 bytes.

               FEC Level Header (Level 0)
           

兩個保護等級的示例

兩個保護等級将會更複雜,等級 0 的 FEC 将對包的前部分提供更重要的保護,因為一般情況下,前部分的資料最重要。等級 1 将對其餘包提供額外的保護,如下所示,其中 L0 = 70 ,L1 = 90。

+------:--------:---+
   Packet A   |      :        :   |
              +------:------+-:---+
   Packet B   |      :      | :
              +------:--+---+ :
                     :        :
              +------+        :
   ULP #1     |      |        :
              +------+        :
                     :        :
              +------:--+     :
   Packet C   |      :  |     :
              +------:--+-----:-----------------+
   Packet D   |      :        :                 |
              +------:--------:-----------------+
                     :        :
              +------:--------+
   ULP #2     |      :        |
              +------:--------+
              :      :        :
              :<-L0->:<--L1-->:

    ULP FEC Scheme with Protection Level 0 and Level 1
           

如上所示,将産生兩個 FEC 包,#1 和 #2。ULP FEC packet #1 中的 RTP header 如下圖所示:

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       Version:   2
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      Padding:   0
   |1 0|0|0|0 0 0 0|1|1 1 1 1 1 1 1|0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1|      Extension: 0
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      Marker:    1
   |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1|      PT:        127
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      SN:        1
   |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0|      TS:        5
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      SSRC:      2

               RTP Header of FEC Packet #1
           

ULP FEC packet #1 中的 level 0 ULP header 如下所示:

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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |0|0|0|0|0 0 0 0|0|0 0 1 1 0 0 1|0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

      E:         0     [this specification]
      L:         0     [short 16-bit mask]
      P rec.:    0     [0 XOR 0 XOR 0 XOR 0]
      X rec.:    0     [0 XOR 0 XOR 0 XOR 0]
      CC rec.:   0     [0 XOR 0 XOR 0 XOR 0]
      M rec.:    0     [1 XOR 0 XOR 1 XOR 0]
      PT rec.:   25    [11 XOR 18]
      SN base:   8     [min(8,9)]
      TS rec.:   6     [3 XOR 5]
      len. rec.: 68    [200 XOR 140]

               FEC Header of ULP FEC Packet #1
           

FEC Packet #1 的 FEC Level Header (Level 0)如下所示:

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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0|1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

      L0:        70
      mask:      49152 [with Bits 1 and 2 marked accordingly for
                        Packets 8 and 9]

      The payload length for level 0 is 70 bytes.

      FEC Level Header (Level 0) for FEC Packet #1
           

FEC packet #2 的 RTP header 如下所示:

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       Version:   2
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      Padding:   0
   |1 0|0|0|0 0 0 0|1|1 1 1 1 1 1 1|0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0|      Extension: 0
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      Marker:    1
   |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1|      PT:        127
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      SN:        2
   |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0|      TS:        9
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+      SSRC:      2

                RTP Header of FEC Packet #2
           

FEC packet #2 的 FEC header 如下所示:

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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |0|0|0|0|0 0 0 0|0|0 0 1 1 0 0 1|0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |0 0 0 0 0 0 0 1 0 0 1 1 0 0 0 0|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

      E:         0     [this specification]
      L:         0     [short 16-bit mask]
      P rec.:    0     [0 XOR 0 XOR 0 XOR 0]
      X rec.:    0     [0 XOR 0 XOR 0 XOR 0]
      CC rec.:   0     [0 XOR 0 XOR 0 XOR 0]
      M rec.:    0     [1 XOR 0 XOR 1 XOR 0]
      PT rec.:   25    [11 XOR 18]
      SN base:   8     [min(8,9,10,11)]
      TS rec.:   14    [7 XOR 9]
      len. rec.: 304   [100 XOR 340]

               FEC Header of FEC Packet #2
           

FEC Packet #2 在等級 0 上的 ULP header 如下圖所示:

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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0|0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

      L0:        70
      mask:      12288 [with Bits 3 and 4 marked accordingly for
                        Packets 10 and 11]

      The payload length for level 0 is 70 bytes.

      FEC Level Header (Level 0) for FEC Packet #2
           

FEC Packet #2 在等級 1 上的 ULP header 如下圖所示:

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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |0 0 0 0 0 0 0 0 0 1 0 1 1 0 1 0|1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

      L1:        90
      mask:      61440 [with Bits 1,2,3,and 4 marked accordingly for
                        Packets 8,9,10,and 11]

      The payload length for level 1 is 90 bytes.

       FEC Level Header (Level 1) for FEC Packet #2
           

FEC 作為備援編碼的示例

FEC 作為備援編碼在同一個流中傳輸,設定 5 個媒體包 A,B,C,D,and E,均來自 SSRC 2。序号分别為 8,9,10,11,和 12,時間戳分别是 3,5,7,9,和 11。所有媒體包作為主編碼,FEC 作為次編碼,媒體流 PT 設定為 11。負荷長度分别是 200 bytes,140 bytes,100 bytes,340 bytes,160 bytes。包 A 和 包 C 的 marker bit 被設定。FEC 結構如上所示,保護長度 L0 為 340 位元組。

備援編碼打包時,PT 值被設定為 100,FEC PT 值設定為 127。開始是從 RED #1 到 RED #4 的四個 RED 包,均包含一個獨立的媒體包A,B,C,D。然後開始生成對前四個媒體包的 FEC 包。接下來是第五個備援包 RED #5,包含媒體包 E 和備援編碼的 FEC 資料。

RED Packet #1:    Media Packet A
   RED Packet #2:    Media Packet B
   RED Packet #3:    Media Packet C
   RED Packet #4:    Media Packet D
   RED Packet #5:    FEC Packet,Media Packet E
           

RED packets #1 到 RED packets #4 結構如下所示:

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |                 RTP Header (RED) - 6 octets                   |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |        Primary Encoding Block Header (RED) - 1 octet          |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |                      Media Packet Data                        |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

         RED Packet Structure - Media Data Only
           

RED packet #1 的 RTP header 如下所示,其他 RED 包類似:

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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |1 0|0|0|0 0 0 0|0|1 1 0 0 1 0 0|0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

      Version:   2
      Padding:   0
      Extension: 0
      Marker:    0     [Even though media packet A has marker set]
      PT:        100   [Payload type for RED]
      SN:        1
      TS:        5
      SSRC:      2

               RTP Header of RED Packet #1
           

主編碼的 block header 如下所示:

0 1 2 3 4 5 6 7
   +-+-+-+-+-+-+-+-+
   |0|0 0 0 1 0 1 1|
   +-+-+-+-+-+-+-+-+

      F bit:     0     [This is the primary coding data]
      Block PT:  11    [The payload type of media]

   Primary Encoding Block Header of the RED packets
           

FEC 資料并不直接從 RED 包中生成,二十通過包含媒體包的虛拟 RTP 包。從RED 包到虛拟 RTP 包的轉化方式如下:

  1. 移除所有的 RED 標頭和備援編碼資料;
  2. 用主編碼的 PT 替換 RTP header 中的 PT 值。

注意:依據 RFC 2198,無論是否使用 FEC,一旦主編碼資料通過 RED 包傳輸, marker bit 都将丢失,不可恢複。

包含 FEC 資料的 RED 包結構如下所示:

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                 RTP Header (RED) - 6 octets                   |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |       Redundant Encoding Block Header (RED) - 4 octets        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                        FEC Packet Data                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |        Primary Encoding Block Header (RED) - 1 octet          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                       Media Packet Data                       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

            RED Packet Structure - With FEC Data
           

RED packet #5 中攜帶 FEC 與媒體資料,FEC 包的備援編碼 block header 如下所示:

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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |1|1 1 1 1 1 1 1|0 0 0 0 0 0 0 0 0 0 0 0 0 0|0 1 0 1 1 0 0 0 1 0|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

      F bit:     1     [This is the redundant coding data]
      Block PT:  127   [The dynamic payload type for FEC]
      TS Offset: 0     [The instance at which the FEC data is
                        transmitted]
      Block Len: 354   [FEC header (10 octets) plus ULP level 0 header
                        (4 octets) and ULP level 0 data (340 octets)]

          Redundant Encoding Block Header
           

Redundant Encoding Block Header 後面資料如下:

  • FEC header (10 octets)
  • ULP level 0 header (4 octets)
  • ULP level 0 data (340 octets for level 0)
  • The primary encoding block (the data of media packet E)

繼續閱讀