RTP Payload Format for Generic Forward Error Correction
obsoletes
Extracted elements (29)
Multiple protection at levels higher than level 0 is disallowed because it increases recovery complexity with diminishing benefit. Requiring that a packet protected at level p also appear at level p-1 allows the protection offset to be derived from protection lengths without explicit signaling in the protocol.
RFC 5109 fixes an inconsistency in RFC 2733 and RFC 3009 where the P, X, and CC fields of the RTP header were set in ways incompatible with RFC 3550, preventing payload-independent RTP validity checks. RFC 5109 places all recovery values in the FEC header and uses standard RFC 3550 RTP header semantics.
Separate RTP sessions for FEC and media are preferred because SSRC or payload-type multiplexing within a single session prevents use of different network paths, precludes selective reception by non-FEC hosts, affects the original stream's sequence number space, and prevents separate process implementations.
ULP provides stronger protection to the beginning of each packet because most media codecs (video macroblock headers, motion vectors; audio frame headers) place the most important data at the front in descending order of importance, making per-level protection naturally aligned with codec structure.
XOR parity code was chosen over alternatives such as Reed-Solomon because of its effectiveness and simplicity in both protocol design and implementation, making it suitable for nodes with limited computational resources.
The FEC payload format defined in RFC 5109 is not backward compatible with RFC 2733 or RFC 3009. Different MIME types (ulpfec) are used to prevent misidentification; hosts that implement the older RFCs are recommended to update to RFC 5109 when possible.
The scheme is fully compatible with non-FEC-capable hosts: media packets are transmitted unmodified as if no FEC is present. FEC packets use a dynamically assigned payload type that non-FEC receivers will discard per RFC 3550, making the scheme safe for multicast groups with mixed FEC and non-FEC receivers.
When FEC is used with RFC 2198 redundant coding (RED), the marker bit is lost as soon as primary coding is carried in RED packets and cannot be recovered by FEC. The FEC data must be generated from virtual RTP packets (RED packets stripped of block headers and redundant data) rather than directly from RED packets.
A media packet SHALL be protected only once at each protection level higher than level 0. At level 0, a media packet MAY be protected by more than one FEC packet provided the protection lengths of level 0 are equal across those packets.
Different encryption keys MUST be used for each stream (media and FEC) when they are sent as separate streams. Applications utilizing encryption SHOULD encrypt both the media and FEC streams; encrypting only one stream creates a layering violation and may enable known-plaintext attacks.
For a media packet to be protected at level p, it MUST also be protected at level p-1 in some FEC packet (not necessarily the same one). If a ULP FEC packet contains protection at level p, it MUST also contain protection at level p-1.
Implementations MUST NOT substantially increase the total amount of bandwidth in use (payload plus FEC) as network losses increase, to prevent contributing to congestion or congestion collapse.
The E bit in the FEC header SHALL be set to 0 and SHOULD be ignored by receivers; it is reserved for future extensions to this specification.
The FEC packet sequence number MUST be one higher than the sequence number in the previously transmitted FEC packet. The timestamp MUST be set to the value of the media RTP clock at the instant the FEC packet is transmitted, so TS is always monotonically increasing.
The FEC stream and payload stream SHOULD be sent through two separate RTP sessions; multiplexing by payload type into one RTP session SHOULD be avoided. The FEC and payload MUST NOT be multiplexed by SSRC into one single RTP session since they always share the same SSRC.
The Marker bit in the RTP header of FEC packets SHALL be set to 0. The SSRC value SHALL be the same as the SSRC of the media stream the FEC packet protects.
The SN base field in the FEC header MUST be set to the lowest sequence number, taking wrap-around into account, of all media packets protected by the FEC packet at all levels.
There is no static payload type assignment for ulpfec, so dynamic payload type numbers MUST be used. The binding is indicated by an rtpmap attribute with the name 'ulpfec'.
When FEC is sent as redundant encoding per RFC 2198, the FEC MUST protect only the main codec. The FEC payload MUST be generated from virtual RTP packets derived from the main codec data, not directly from the RED packets.
When generating the FEC payload, if the lengths of the protected RTP packets are not equal, each shorter packet MUST be padded to the length of the longest packet by appending octet 0 at the end.
A FEC packet consists of an RTP header (12+ octets), a 10-octet FEC header, and one or more FEC level headers each immediately followed by their FEC level payload. All protection parameters (mask, protection length, SN base) are conveyed in-band within this structure.
Recovery requires two steps: determining which packets to combine (any algorithm permitted) and applying the XOR reconstruction procedure (MUST follow the spec). Partial recovery is possible and detectable by comparing the length recovered from the FEC header against the actual length of reconstructed payload data.
The protection operation builds an FEC bit string as the bitwise XOR of 'protected bit strings' from associated media packets. For the FEC header, the protected bit string is 80 bits formed from the first 64 bits of the RTP header plus a 16-bit payload-length representation; for the FEC payload, full RTP packet data are XOR'd per level.
The Uneven Level Protection (ULP) algorithm applies independent XOR parity protection at multiple levels, each with its own protection length and packet mask. Lower-numbered levels cover the beginning of packets (more important data); a single FEC packet carries parity data for all its levels concatenated after their respective level headers.
RFC 5109 registers four new MIME subtypes with IANA: audio/ulpfec, video/ulpfec, text/ulpfec, and application/ulpfec. All require a 'rate' parameter (RTP timestamp clock rate, MUST be >1000 Hz in a separate stream) and support an optional 'onelevelonly' parameter (0 or 1, default 0) indicating whether only one FEC level is used.
Tampering with FEC data can significantly impact reconstruction: modifying the length recovery field may cause recovery of a packet that is too long, and the computational complexity of recovery can be affected by at least an order of magnitude. Implementations should sanity-check received payload and FEC data before and after recovery.
When encryption keys change while FEC spans packets encrypted under different keys, old keys must be cached until key rotation is confirmed for FEC packets. The new key SHOULD be used to encrypt FEC packets generated from a mix of old- and new-key payloads; the sender and receiver must agree on how encryption is performed.
The FEC header is exactly 10 octets containing: E bit (1), L bit (1), P/X/CC/M/PT recovery fields (14 bits total), SN base (16 bits), TS recovery (32 bits), and length recovery (16 bits). The E bit SHALL be set to 0; the L bit selects 16-bit vs. 48-bit masks.
The FEC level header is 4 octets when L=0 (16-bit mask) or 8 octets when L=1 (48-bit mask), containing a 16-bit protection length field followed by the mask. If bit i in the mask is set, media packet with sequence number N+i (where N is SN base) is associated with this FEC packet at this level.