RFC 8285

A General Mechanism for RTP Header Extensions

πŸ“… published October 2017, from ietf

πŸŽ€ RFC 8285: A General Mechanism for RTP Header Extensions πŸŽ€

okay bestie, let's get into it ✨ this one is about RTP (the Real-time Transport Protocol) and how you can stuff extra info into its header. Super cute πŸ¦‹

Title block facts: This is an IETF document, RFC 8285, published October 2017. It's a Standards Track doc πŸ’œ. It was written by D. Singer (Apple, Inc.), H. Desineni (Qualcomm), and R. Even, Ed. (Huawei Technologies) 🫢. It obsoletes RFC 5285 πŸ’…, which means this one replaces it. ISSN: 2070-1721 🌸.

1. Introduction ✨

okay so RTP already has a way to add extra stuff to its header, and it's described in Section 5.3.1 of [RFC3550] 🌷. The catch is that the old method only lets you have one extension per packet πŸ’€. Each one is tagged with a 16-bit identifier and has a 16-bit length field that counts how long the extension is in 32-bit words πŸ“.

The old setup had two big problems 😭. First, you could only ever fit one extension in a packet, which is so limiting πŸ™ˆ. Second, the spec didn't tell anyone how to pick those 16-bit IDs so they wouldn't clash, so people could accidentally collide πŸ’€.

This new spec fixes both of those things πŸ’–. It lets you pack multiple extension elements into one packet, and it stays backward-compatible, which is huge πŸ‘‘. It also names each extension with a URI, sets up an IANA registry for the ones defined in IETF specs 🧚, and gives you an SDP method to map those URIs to the ID values that actually show up in the packets πŸ¦‹.

This header extension is for RTP/AVP (the Audio/Visual Profile) and its extensions 🎬.

This document obsoletes [RFC5285] and also removes a limitation from RFC 5285 that stopped you from sending both one-byte and two-byte header extensions in the same RTP stream 🌈. Iconic glow-up, no cap ✨.

2. Requirements Notation ✨

The BCP 14 key words in this document are read as described in [RFC2119] and [RFC8174], but only when they're in ALL CAPS like here πŸ’…. Those words are:

  • "MUST"
  • "MUST NOT"
  • "REQUIRED"
  • "SHALL"
  • "SHALL NOT"
  • "SHOULD"
  • "SHOULD NOT"
  • "RECOMMENDED"
  • "NOT RECOMMENDED"
  • "MAY"
  • "OPTIONAL"

3. Design Goals 🌸

The whole goal here is a simple way to use multiple identified extensions in RTP packets 🧚. You don't need to formally register each one, but it still has to avoid collisions πŸ”₯. Lowkey genius.

This is also an alternative to the old habit of burying metadata inside the media format bitstream πŸŽ€. That's been done a lot with media sent over fixed-bandwidth channels πŸ¦‹. The problem is, once metadata is baked in like that, the decoder for that specific media format has to dig it back out 😡. And depending on the format, you might add the metadata while encoding so the bit-rate accounts for it, but sometimes the metadata isn't known yet at that point πŸ™ˆ. If you add it later, you might end up needing to decode and re-encode just to hit your bit-rate requirements πŸ’€. Nah.

Sometimes there's a better, higher-level mechanism available, and if so, you can use that πŸ‘‘. But if there isn't one, it's better to put the mechanism at the RTP level than to tie the metadata to one specific kind of media data πŸ’œ. Main character energy.

4. Packet Design ✨

4.1. General 🌷

The design here fits into the "header extension" of the RTP extension, as described above πŸ¦‹.

The presence and format of this header extension, and what's in it, are negotiated or defined out of band, like through signaling (more on SDP signaling below) 🫢. The 16-bit identifier for the two forms of the RTP extension defined here is only an architectural constant, for stuff like network analyzers 🧚. What actually tells you the header extension is there is the negotiation or definition, like in SDP πŸ’–.

The RTP spec [RFC3550] says RTP "is designed so that the header extension may be ignored by other interoperating implementations that have not been extended." 🌸 The point of that rule is that RTP header extensions MUST NOT be used to extend RTP itself in a way that's backward incompatible with non-extended implementations 🚫. So a header extension can't change the meaning or interpretation of the standard RTP header fields or of RTCP πŸ™…β€β™€οΈ. Extensions MAY carry metadata on top of the usual RTP header info, as long as the RTP layer still works when that metadata is missing πŸŽ€. For example, you can carry data that's also sent in RTCP inside a header extension as a latency optimization, since things just fall back to the original non-optimized behavior if the extension isn't there πŸ“.

Using header extensions to convey info that would mess up a higher-layer app built on RTP, if it went missing, is only okay if it doesn't hurt interoperability at the RTP layer 🌈. Like, apps using the SDP BUNDLE extension with the Media Identification (MID) RTP header extension [SDP-BUNDLE] to match RTP streams with SDP "m=" lines probably won't be fully functional without the MID, but the RTP layer of those apps keeps working just fine πŸ’…. Support for RTP header extensions based on this memo is negotiated using something like SDP Offer/Answer [RFC3264] 🫢. Intermediaries that know about RTP header extensions are advised to be cautious when they remove or generate them, see Section 4.7 of [RFC7667] ⭐.

The RTP header extension is built as a sequence of extension elements, with possible padding 🧚. Each extension element has a local identifier and a length πŸ¦‹. The local identifiers MAY be mapped to a bigger namespace during negotiation (like in session signaling) πŸ’œ.


That's the first chunk, bestie πŸ’– Part 2 is coming up next, so stay tuned πŸŽ€ .

4.1.1. Transmission Considerations ✨

Okay bestie, the golden rule of network manners is to only send stuff when you actually need to πŸ’…. The RTP header extension SHOULD only be present in a packet if that packet also contains one or more extension elements, as defined here. An extension element SHOULD only be present in a packet when it's needed 🫢. The signaling setup only tells you those elements can show up in some packets, not that they're in every packet (or even any packet) πŸ₯Ί.

Here are some general considerations for getting header extensions delivered to the receiver πŸ¦‹:

  1. Packet loss and burst loss decide how many repeats of the header extensions you need to hit your delivery target. If burst loss is likely, you also need a distribution that stops all the repeats from getting wiped out in one burst πŸ’€.
  2. If a set of packets is needed to decode anything, there's commonly no reason to put the header extension in every one of them, since they share fate 🧚. Putting at most one copy per independently decodable set of media data is a much more efficient use of bandwidth.
  3. How soon the header extension item info is needed matters. If it's needed from the very first RTP data, or only after some set of packets arrives, that can guide whether the extensions go (1) in all of the first N packets or (2) only once per set of packets, like once per video frame 🎬.
  4. RTP-level robustness mechanisms, like RTP retransmission [RFC4588] or Forward Error Correction (e.g., [RFC5109]), may treat packets differently from a robustness perspective. Header extensions should be added to packets that get a treatment matching how important it is to receive the info πŸ‘‘.

The big picture: the number of header extension transmissions should be tailored to a desired probability of delivery, while taking the receiver population size into account 🌈. In the very basic case, N repetitions of the header extensions should be sufficient but may not be optimal. N is picked so the header extension target delivery probability reaches 1-P^N, where P is the probability of packet loss πŸ”₯.

For point-to-point or small receiver populations, it might also be possible to use feedback, like RTCP, to figure out when the info in the header extensions has reached all the receivers and then stop repeating it πŸ™ˆ. Feedback that can help includes the RTCP Extended Report (XR) Loss RLE Report Block [RFC3611], which indicates successful delivery of particular packets. If the RTP/AVPF transport-layer feedback messages for generic NACK [RFC4585] are used, they can show a failure to deliver an RTP packet with the header extension, which tells you more repeats are needed. The normal RTCP report blocks can also signal successful delivery if no losses are reported for a reporting interval covering the RTP packets with the header extension. Note carefully that losing an RTCP packet reporting on an interval where RTP header extension packets were sent does not necessarily mean those RTP header extension packets were lost 🫣.

4.1.2. Header Extension Type Considerations πŸ’–

Every extension element in a packet has a local identifier (ID) and a length πŸŽ€. The local identifiers present in the stream MUST have been negotiated or defined out of band. There are no static allocations of local identifiers. Each distinct extension MUST have a unique ID. The ID value 0 is reserved for padding and MUST NOT be used as a local identifier.

An extension element with an ID value equal to 0 MUST NOT have an associated length field greater than 0. If you run into one of these, its length field MUST be ignored, processing of the entire extension MUST terminate right there, and only the extension elements that came before the element with ID 0 (and that have a length field greater than 0) SHOULD be considered πŸ™…β€β™€οΈ.

There are two variants of the extension: one-byte and two-byte headers 🌸. Since it's expected that (a) the number of extensions in any given RTP session is small and (b) the extensions themselves are small, the one-byte header form is preferred and MUST be supported by all receivers. A stream MUST contain only one-byte headers or only two-byte headers, unless it's known that all recipients support mixing. That knowledge can come from SDP Offer/Answer [RFC3264] negotiation (see Section 6) or from out-of-band knowledge. Each RTP packet with an RTP header extension following this specification indicates whether it has one-byte or two-byte header extensions through the "defined by profile" field. Extension element types that don't match the header extension format, meaning one-byte or two-byte, MUST NOT be used in that RTP packet 🚫.

Transmitters SHOULD NOT use the two-byte header form when all extensions are small enough for the one-byte header form πŸ“. Transmitters that intend to send the two-byte form SHOULD negotiate the use of IDs above 14 if they want to let receivers know they plan to use the two-byte form. For example, that's the move if the RTP header extension is longer than 16 bytes. A transmitter may be aware that an intermediary may add RTP header extensions. In that case, the transmitter SHOULD use the two-byte form ✨.

A sequence of extension elements, possibly with padding, forms the header extension defined in the RTP specification. There are as many extension elements as will fit in the RTP header extension, as indicated by the RTP header extension length. That length is signaled in full 32-bit words, so padding bytes are used to pad to a 32-bit boundary. The entire extension is parsed byte by byte to find each extension element (no alignment is needed). Parsing stops at whichever comes first: (1) the end of the entire header extension, or (2) in the "one-byte headers only" case, when it hits an identifier with the reserved value of 15 🧩.

In both forms, padding bytes have the value of 0 (zero). They MAY be placed between extension elements if you want alignment, or after the last extension element if you need padding. A padding byte doesn't supply the ID of an element, and it doesn't supply the length field either. When a padding byte is found, it's ignored and the parser moves on to the next byte 🌷.

Note carefully that the one-byte header form allows data lengths between 1 and 16 bytes, by adding 1 to the signaled length value. So 0 in the length field means one byte of data follows. This allows for the important case of 16-byte payloads πŸ‘‘. This addition is not performed for two-byte headers, where the length field signals data lengths between 0 and 255 bytes.

Using RTP header extensions reduces the efficiency of RTP header compression, since the header extension gets sent uncompressed unless the RTP header compression module is updated to recognize the extension header 😭. If header extensions show up in some packets but not others, that can also reduce compression efficiency. It forces an update to the fixed header to be conveyed whenever header extensions start or stop being sent. The interactions between RTP header extensions and header compression are explored further in [RFC2508] and [RFC3095] πŸ“š.

4.2. One-Byte Header πŸ¦‹

In the one-byte header form of extensions, the 16-bit value that the RTP specification requires for a header extension, labeled "defined by profile" in the RTP specification, MUST have the fixed bit pattern 0xBEDE. (The pattern was picked for the trivial reason that the first version of this specification was written on May 25th, the feast day of the Venerable Bede πŸŽ‚.)

Each extension element MUST start with a byte containing an ID and a length 🧸:

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

The 4-bit ID is the local identifier of this element, in the range 1-14 inclusive. In the signaling section, this is referred to as the valid range πŸ”’.

The local identifier value 15 is reserved for a future extension and MUST NOT be used as an identifier. If the ID value 15 is encountered, its length field MUST be ignored, processing of the entire extension MUST terminate at that point, and only the extension elements present prior to the element with ID 15 SHOULD be considered πŸ›‘.

The 4-bit length is the number of data bytes of this header extension element following the one-byte header, minus one. So the value zero (0) in this field means one byte of data follows, and a value of 15 (the maximum) means element data of 16 bytes. This permits carriage of 16-byte values, which is a common length for labels and identifiers, while giving up the possibility of zero-length values, which would often be padded anyway 🍰.

Here's an example header extension, with three extension elements and some padding πŸ§šβ€β™€οΈ:

    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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |       0xBE    |    0xDE       |           length=3            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  ID   | L=0   |     data      |  ID   |  L=1  |   data...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         ...data   |    0 (pad)    |    0 (pad)    |  ID   | L=3   |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                          data                                 |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

4.3. Two-Byte Header ✨

okay so this is the two-byte form, and bestie, it's giving fancy but organized πŸ’… The 16-bit value that the RTP specification defines for a header extension, which it labels "defined by profile", looks like this:

    0                   1
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |         0x100         |appbits|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

So the appbits field is 4 bits, and the app gets to decide what those bits mean πŸŽ€ The text says they MAY be defined to be any value or meaning, and that topic is outside the scope of this spec, so don't come asking this doc for the details πŸ™ˆ For signaling purposes, this field is treated as a special extension value assigned to the local identifier 256. If nothing has been set up through configuration or signaling for that local identifier (256), then the sender SHOULD set all the appbits to 0s (zeros), and the receiver MUST ignore them. Those capitals are doing a lot of work, periodt πŸ’€

Next up, every extension element starts with two bytes: one for an ID and one for a length πŸ¦‹

    0                   1
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |       ID      |     length    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

The 8-bit ID is the local identifier for this element, and it has to be in the range 1-255 inclusive. In the signaling section, the range 1-256 is called the valid range. Values 1-255 point at extension elements, and the value 256 points at the 4-bit appbits field I just talked about 🌸 Here's the lowkey important bit: the one-byte form and the two-byte form share ONE ID space. So the lower values (1-14) can be used in the 4-bit ID field of the one-byte header format, and they keep the same meanings there ✨

The 8-bit length field is the length of the extension data in bytes, and it does NOT count the ID and length fields themselves. A value of zero (0) means there's no data after it 🧚

Here's an example header extension, with three extension elements and some padding πŸ“

    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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |       0x10    |    0x00       |           length=3            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |      ID       |     L=0       |     ID        |     L=1       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |       data    |    0 (pad)    |       ID      |      L=4      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                          data                                 |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

5. SDP Signaling Design πŸ’–

okay this part is where the signaling happens, and it's giving paperwork but make it cute πŸ“‹ The fact that this extension is in use, and the mapping of local identifiers to a bigger namespace, MUST be done out of band 🫢 An example is part of an SDP Offer/Answer [RFC3264]. This section is where the SDP signaling gets defined.

A usable mapping MUST use IDs from the valid range, and each ID in that range MUST be used only once per media section (or only once in total if the mappings are session level). Mappings that break these rules MAY still show up during SDP Offer/Answer [RFC3264] negotiation, which the next section covers, but they MUST be remapped to conformant values before they can actually be applied πŸ”₯

Every extension is named by a URI. That URI MUST be absolute, because it precisely identifies the format and meaning of the extension ✨ If a URI contains a domain name, it SHOULD also contain a month-date in the form mmyyyy. The definition of the element and the assignment of the URI MUST have been authorized by the owner of that domain name on or very close to that date. (This avoids problems when domain names change ownership πŸ‘‘) If the resource or document defines several extensions, the URI MUST identify the actual extension in use, for example with a fragment or query identifier (the characters after a "#" or "?" in the URI) 🌈

Rationale: URIs give us a huge, unallocated space and come with documentation for the extension. They do NOT have to be dereferencable πŸ’… This allows confidential or experimental use, and it covers the case where an extension keeps getting used after the organization that defined it is gone. Iconic πŸ¦‹

An extension URI with the same attributes MUST NOT appear more than once applying to the same stream, which means at session level, or in the declarations for a single stream at media level. (The same extension can, of course, be used for several streams and can show up with different <extensionattributes> for the same stream πŸŽ€)

For extensions defined in RFCs, the URI SHOULD be a URN that starts with "urn:ietf:params:rtp-hdrext:" and is followed by a registered, descriptive name πŸ’œ

The registration requirements are detailed in Section 10 ("IANA Considerations") πŸ“š

Here's an example where "avt-example-metadata" is the hypothetical name of a header extension:

   urn:ietf:params:rtp-hdrext:avt-example-metadata

And here's an example name that is NOT from the IETF:

   http://example.com/082005/ext.htm#example-metadata

The mapping MAY be provided per media stream (in the media-level sections of SDP, meaning after an "m=" line), or globally for all streams (before the first "m=" line, at session level) πŸ“ The definitions MUST be either all session level or all media level. Mixing the two styles is NOT permitted πŸ™ˆ Also, as noted above, the IDs used MUST be unique in each media section of the SDP, or unique in the session for session-level SDP declarations.

Each local identifier that might be used in the stream gets mapped to an extension, identified by a URI, using an attribute of this form:

   a=extmap:<value>["/"<direction>] <URI> <extensionattributes>

where

  • <value> is the local identifier (ID) of this extension, and it is an integer in the valid range (0 is reserved for padding in both forms, and 15 is reserved in the one-byte header form, as noted above) 🧚
  • <direction> is one of "sendonly", "recvonly", "sendrecv", or "inactive" (without the quotes), relative to the device being configured 🌸
  • <URI> is a URI, as above πŸ¦‹

The formal BNF syntax is presented in Section 8 of this specification πŸ“–

Example:

   a=extmap:1 http://example.com/082005/ext.htm#ttime

   a=extmap:2/sendrecv http://example.com/082005/ext.htm#xmeta short

When SDP signaling is used for the RTP session, it's the presence of the "extmap" attribute(s) that tells you this style of header extension is in use, NOT the magic number ("BEDE" or "100") mentioned above πŸ’–


6. SDP Signaling for Support of Mixed One-Byte and Two-Byte Header Extensions 🌈

okay so bestie, this section is about mixing the two forms, and it's giving careful about backward compat 🫢 To keep backward interoperability with systems that DON'T support mixing one-byte and two-byte header extensions, this document defines the "a=extmap-allow-mixed" Session Description Protocol (SDP) [RFC4566] attribute. It shows whether a participant can handle this new mode. The attribute takes no value, and it can be used at the session level or the media level. A participant that proposes using this mode SHALL itself support receiving mixed one-byte and two-byte header extensions ✨

If SDP Offer/Answer [RFC3264] is supported and used, the negotiation for mixed one-byte and two-byte extensions MUST be negotiated using SDP Offer/Answer per [RFC3264]. Without SDP Offer/Answer negotiation, for example when declarative SDP is used, mixed headers MUST NOT occur unless the transmitter has some (out-of-band) knowledge that every potential recipient supports this mode πŸ’€

The formal definition of this attribute is:

   Name: extmap-allow-mixed

   Value: None

   Usage Level: session, media

   Charset Dependent: No

   Example:

      a=extmap-allow-mixed

When doing SDP Offer/Answer [RFC3264], an offering client that wants to use both one-byte and two-byte extensions MUST include the attribute "a=extmap-allow-mixed" in the SDP offer. If "a=extmap-allow-mixed" is present in the offer, the answerer that supports this mode and wants to use it SHALL include the "a=extmap-allow-mixed" attribute in the answer. In the cases where the attribute has been excluded, both clients SHALL NOT use mixed one-byte and two-byte extensions in the same RTP stream, but they MAY use the one-byte or two-byte form exclusively (see Section 4.1.2) πŸŽ€

When used per [SDP-BUNDLE], this attribute is specified as the IDENTICAL category [SDP-MUX] πŸ¦‹

7. SDP Offer/Answer ✨

okay so the simple signaling we just talked about for the "extmap" attribute MAY get leveled up in an SDP Offer/Answer [RFC3264] context πŸ’… which lets you do three extra-cute things:

  • asymmetric behavior, where extensions only go one direction πŸ¦‹
  • offering mutually exclusive alternatives πŸŽ€
  • offering more extensions than can fit in one session 🫢

A direction attribute MAY be included in an "extmap" πŸ’– and if you skip it, the direction just inherits from the stream direction. For session-level attributes or extensions on "inactive" streams, it's "sendrecv" by default 🌸 The direction MUST be one of "sendonly", "recvonly", "sendrecv", or "inactive" as specified in [RFC3264]. no cap, these four are the whole menu πŸ’…

Extensions, with their directions, MAY be signaled for an "inactive" stream ✨ But it is an error to use an extension direction that clashes with the stream direction, like a "sendonly" attribute on a "recvonly" stream πŸ’€ that's a hard no, bestie.

If an offer or answer has session-level mappings (so there are no media-level mappings), and you want different behavior for each stream, then the whole set of extension map declarations MAY be moved down into the media-level section(s) of the SDP 🧚 (Note that this specification does not permit mixing global and local declarations, to make identifier management easier πŸ™ˆ)

If an extension map is offered as "sendrecv", whether explicitly or implicitly, and you want asymmetric behavior, the SDP answer MAY be changed to modify or add direction qualifiers for that extension πŸ“

If an extension is marked as "sendonly" and the answerer wants to receive it, the extension MUST be marked as "recvonly" in the SDP answer πŸ”₯ An answerer that doesn't want to receive the extension, or doesn't understand it, SHOULD remove it from the SDP answer 😭 An answerer MAY want to say "yes, I support this, but I don't want it right now," and then they can mark the extension as "inactive" and maybe ask for it in a future offer 🌈

If an extension is marked as "recvonly" and the answerer wants to send it, the extension MUST be marked as "sendonly" in the SDP answer ⭐ An answerer that has no desire to send it, or can't send it, SHOULD remove it from the SDP answer πŸ’œ An answerer MAY want to respond that they support this extension but aren't sending it now; they can ask to send it in a future offer by marking the extension as "inactive" πŸ¦‹

Local identifiers in the valid range, inclusive, in an offer or answer must not be used more than once per media section (including the session-level section) πŸ‘‘ The local identifiers MUST be unique in an RTP session, and the same identifier MUST be used for the same offered extension in the answer ✨ A session update MAY change the direction qualifiers of extensions being used. A session update MAY add or remove extension(s). Identifier values in the valid range MUST NOT be altered (remapped) πŸ™…β€β™€οΈ no renumbering, period πŸ’…

Note that under this rule, the same local identifier can't be used for two extensions in the same media, even when one is "sendonly" and the other is "recvonly". Why? Because then neither of them could ever become "sendrecv", since renumbering isn't allowed either πŸ’€ it's a whole logic trap, iykyk 🫠

If a party wants to offer mutually exclusive alternatives, then multiple extensions with the same identifier in the extended range 4096-4351 MAY be offered πŸŽ€ The answerer SHOULD select, at most, one of the offered extensions with the same identifier, and remap it to a free identifier in the valid range for that extension so it can actually be used ✨

Similarly, if more extensions are offered than can fit in the valid range, identifiers in the range 4096-4351 MAY be offered 🌸 The answerer SHOULD choose the ones they want and remap them to a free identifier in the valid range πŸ’–

An answerer may copy an "extmap" for an identifier in the extended range into the answer, to tell the offerer "hey, I support that extension" 🫢 Of course, that extension can't be used, since there's no way to specify it in an extension header 😭 If needed, the offerer or answerer can update the session to assign a valid identifier to that extension URI 🧚

Rationale: The range 4096-4351 for these negotiation identifiers is deliberately restricted so the valid range can expand in the future 🌈 it's giving planning ahead πŸ’…

Either party MAY include extensions in the stream other than the ones negotiated, or the ones negotiated as "inactive" (for example, for the benefit of intermediate nodes) πŸ¦‹ Only extensions that appeared with an identifier in the valid range in SDP originated by the sender can be sent πŸ’œ

Example (port numbers, RTP profiles, payload IDs, rtpmaps, etc. all omitted for brevity):

The offer:

   a=extmap:1 URI-toffset
   a=extmap:14 URI-obscure
   a=extmap:4096 URI-gps-string
   a=extmap:4096 URI-gps-binary
   a=extmap:4097 URI-frametype
   m=video
   a=sendrecv
   m=audio
   a=sendrecv

The answerer is interested in receiving GPS in string format only on video, but can't send GPS at all 🎬 They aren't interested in transmission offsets on audio, and they don't understand the URI-obscure extension πŸ™ˆ So they move the extensions from session level to media level and adjust the declarations:

   m=video
   a=sendrecv
   a=extmap:1 URI-toffset
   a=extmap:2/recvonly URI-gps-string
   a=extmap:3 URI-frametype
   m=audio
   a=sendrecv
   a=extmap:1/sendonly URI-toffset

When using [SDP-BUNDLE] to bundle multiple "m=" lines, the "extmap" attribute falls under the SPECIAL category of [SDP-MUX] πŸ‘‘ All the "m=" lines in a BUNDLE group are considered to be part of the same local identifier (ID) space 🫢 If an RTP header extension, i.e., a particular extension URI and configuration using <extensionattributes>, is offered in multiple "m=" lines that are part of the same BUNDLE group, it MUST use the same ID in all of these "m=" lines πŸ”₯ Each "m=" line in a BUNDLE group can include different RTP header extensions, allowing, for example, audio and video sources to use different sets of RTP header extensions πŸŽ€ A difference in configuration using any of the <extensionattributes> is important. Unless an RTP header extension explicitly states otherwise, any such difference SHALL be communicated to all receivers and SHALL cause assignment of different IDs 🚨 An RTP header extension that doesn't follow this rule MUST explicitly define what would constitute compatible configurations that can be sent with the same ID 🧐 The directionality of the RTP header extensions in each "m=" line of the BUNDLE group is handled in the same way as for non-bundled "m=" lines, which means you can specify different directionality for each of the repeated extension URIs in a BUNDLE group 🌈 main character energy πŸ’…


8. BNF Syntax πŸ’œ

The syntax definition below uses ABNF according to [RFC5234] πŸ“ The syntax element "URI" is defined in [RFC3986] (only absolute URIs are permitted here). The syntax element "extmap" is an attribute as defined in [RFC4566], i.e., "a=" precedes the "extmap" definition. Specific <extensionattributes> are defined by the specification that defines a specific extension name, and there can be several 🫢

    Name: extmap

    Value: extmap-value

    Syntax:

       extmap-value = mapentry SP extensionname
                      [SP extensionattributes]

       mapentry = "extmap:" 1*5DIGIT ["/" direction]

       extensionname = URI

       extensionattributes = byte-string

       direction = "sendonly" / "recvonly" / "sendrecv" / "inactive"

       URI = <Defined in RFC 3986>

       byte-string = <Defined in RFC 4566>

       SP = <Defined in RFC 5234>

       DIGIT = <Defined in RFC 5234>

9. Security Considerations πŸ”

⚠️ Serious security time, bestie. Stay with me on this one! 🫠

This document defines only a place to transmit information πŸ“¦ the security implications of each of the extensions must be discussed with those extensions themselves.

Extension usage is negotiated using [RFC3264], so integrity protection and end-to-end authentication MUST be implemented πŸ”’ The security considerations of [RFC3264] MUST be followed to prevent, for example, extension-usage blocking 🚫

Header extensions have the same security coverage as the RTP header itself πŸŽ€ When the Secure Real-time Transport Protocol (SRTP) [RFC3711] is used to protect RTP sessions, the RTP payload can be both encrypted and integrity protected, while the RTP header is either unprotected or integrity protected 🧁 To prevent DoS attacks (for example, by changing the header extension), integrity protection SHOULD be used πŸ›‘οΈ Lower-layer security protection such as Datagram Transport Layer Security (DTLS) [RFC6347] MAY be used 🌊 RTP header extensions can carry sensitive information that participants in multimedia sessions want kept confidential 🀫 RFC 6904 [RFC6904] provides a mechanism that extends the mechanisms of SRTP to selectively encrypt RTP header extensions in SRTP πŸ”

The RTP application designer needs to consider their security needs, which includes cipher strength for SRTP packets in general and what that means for the integrity and confidentiality of the RTP header extensions πŸ’ͺ As defined by RFC 6904 [RFC6904], the encryption stream cipher for the header extension depends on the chosen SRTP cipher πŸ”‘

Other options for securing RTP are discussed in [RFC7201] πŸ¦‹


10. IANA Considerations πŸ—‚οΈ

This document updates the references in three IANA registries to point to this document instead of RFC 5285 ✨ It also updates and adds new SDP attributes in Sections 10.2 and 10.3, respectively πŸ’–

10.1. Identifier Space for IANA to Manage πŸ—‚οΈ

Okay so, IANA is the one managing the mapping from the naming URI form to a reference to a specification πŸ’…. Adding stuff to this registry runs under the "Expert Review" rules defined in [RFC8126] ✨.

IANA is also keeping a server with all the registered elements in a publicly accessible space 🌐.

Next up is the formal bit, which complies with the IETF URN sub-namespace specification [RFC3553] πŸ“œ. Here's the full registry info:

  • Registry name: RTP Compact Header Extensions
  • Specification: RFC 5285 and RFCs updating RFC 5285
  • Information required:
    • A. The desired extension naming URI
    • B. A formal reference to the publicly available specification
    • C. A short phrase describing the function of the extension
    • D. Contact information for the organization or person making the registration

For extensions defined in RFCs, the URI SHOULD be of the form urn:ietf:params:rtp-hdrext:, and the formal reference is the RFC number of the RFC documenting the extension πŸ¦‹.

  • Review process: Expert Review is REQUIRED. The expert reviewer SHOULD check the following requirements πŸ”:
    1. the specification is publicly available;
    2. the extension follows the RTP and header extension requirements of this specification (specifically, the header extension can be ignored or discarded without breaking the RTP layer);
    3. the extension specification is technically consistent (in itself and with RTP), complete, and comprehensible;
    4. the extension does not duplicate functionality in existing IETF specifications (including RTP itself) or other extensions already registered;
    5. the specification contains a security analysis regarding the content of the header extension;
    6. the extension is generally applicable (for example, point-to-multipoint safe), and the specification correctly describes limitations if they exist;
    7. the suggested naming URI form is appropriately chosen and unique; and
    8. for multiplexed m= lines [SDP-BUNDLE], any RTP header extension with differences in configurations of <extensionattributes> that do not require assignment of different IDs MUST explicitly indicate this and provide rules for what would constitute compatible configurations that can be sent with the same ID 🫢.
  • Size and format of entries: A mapping from a naming URI string to a formal reference to a publicly available specification, with a descriptive phrase and contact information.
  • Initial assignments: None

10.2. Registration of the SDP "extmap" Attribute πŸ’œ

IANA has updated the registration of the "extmap" SDP attribute [RFC4566] in the "att-field (both session and media level)" subregistry of the "Session Description Protocol (SDP) Parameters" registry πŸŽ€.

  • Contact Name and email address: IETF, contacted via <mmusic@ietf.org> (or a successor address designated by the IESG)
  • Attribute Name: extmap
  • Attribute Syntax: See Section 8 of RFC 8285.
  • Attribute Semantics: The details of appropriate values are given in RFC 8285.
  • Usage Level: Media or session level
  • Charset Dependent: No
  • Purpose: Defines the mapping from the extension numbers used in packet headers into extension names.
  • Offer/Answer (O/A) Procedures: See Section 7 of RFC 8285.
  • MUX Category: SPECIAL
  • Reference: RFC 8285

10.3. Registration of the SDP "extmap-allow-mixed" Attribute 🌈

IANA has registered one new SDP attribute in the "att-field (both session and media level)" subregistry of the "Session Description Protocol (SDP) Parameters" registry πŸ“:

  • Contact Name and email address: IETF, contacted via <mmusic@ietf.org> (or a successor address designated by the IESG)
  • Attribute Name: extmap-allow-mixed
  • Attribute Syntax: See Section 6 of RFC 8285.
  • Attribute Semantics: See Section 6 of RFC 8285.
  • Attribute Value: None
  • Usage Level: Media or session level
  • Charset Dependent: No
  • Purpose: Negotiate the use of one byte and two bytes in the same RTP stream.
  • O/A Procedures: See Section 6 of RFC 8285.
  • MUX Category: IDENTICAL
  • Reference: RFC 8285

11. Changes from RFC 5285 🧚

Bestie, here's the tea on what changed from RFC 5285 β˜•. The big motivation was letting one-byte and two-byte RTP header extensions live in the same RTP stream (but not in the same RTP packet) πŸ’…. That support is negotiated with a brand-new SDP attribute called extmap-allow-mixed, which is specified in this document ✨.

The other major glow-up is the update to the requirement from the RTP specifications [RFC3550] and [RFC5285] that the header extension "is designed so that the header extension may be ignored." That's described in Section 4.1 πŸ’–.

Section 4.1.1 ("Transmission Considerations") got more text too, clarifying when and how many times to send the RTP header extension so it has a higher probability of delivery πŸš€.

The Security Considerations section was expanded πŸ”, and the rest of the changes are editorial πŸ™ˆ.


12. References πŸ“š

12.1. Normative References

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119,
           DOI 10.17487/RFC2119, March 1997,
           <https://www.rfc-editor.org/info/rfc2119>.

[RFC2508]  Casner, S. and V. Jacobson, "Compressing IP/UDP/RTP
           Headers for Low-Speed Serial Links", RFC 2508,
           DOI 10.17487/RFC2508, February 1999,
           <https://www.rfc-editor.org/info/rfc2508>.

[RFC3095]  Bormann, C., Burmeister, C., Degermark, M., Fukushima, H.,
           Hannu, H., Jonsson, L-E., Hakenberg, R., Koren, T., Le,
           K., Liu, Z., Martensson, A., Miyazaki, A., Svanbro, K.,
           Wiebke, T., Yoshimura, T., and H. Zheng, "RObust Header
           Compression (ROHC): Framework and four profiles: RTP, UDP,
           ESP, and uncompressed", RFC 3095, DOI 10.17487/RFC3095,
           July 2001, <https://www.rfc-editor.org/info/rfc3095>.

[RFC3264]  Rosenberg, J. and H. Schulzrinne, "An Offer/Answer Model
           with Session Description Protocol (SDP)", RFC 3264,
           DOI 10.17487/RFC3264, June 2002,
           <https://www.rfc-editor.org/info/rfc3264>.

[RFC3711]  Baugher, M., McGrew, D., Naslund, M., Carrara, E., and K.
           Norrman, "The Secure Real-time Transport Protocol (SRTP)",
           RFC 3711, DOI 10.17487/RFC3711, March 2004,
           <https://www.rfc-editor.org/info/rfc3711>.

[RFC3986]  Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
           Resource Identifier (URI): Generic Syntax", STD 66,
           RFC 3986, DOI 10.17487/RFC3986, January 2005,
           <https://www.rfc-editor.org/info/rfc3986>.

[RFC4566]  Handley, M., Jacobson, V., and C. Perkins, "SDP: Session
           Description Protocol", RFC 4566, DOI 10.17487/RFC4566,
           July 2006, <https://www.rfc-editor.org/info/rfc4566>.

[RFC5234]  Crocker, D., Ed., and P. Overell, "Augmented BNF for
           Syntax Specifications: ABNF", STD 68, RFC 5234,
           DOI 10.17487/RFC5234, January 2008,
           <https://www.rfc-editor.org/info/rfc5234>.

[RFC6904]  Lennox, J., "Encryption of Header Extensions in the Secure
           Real-time Transport Protocol (SRTP)", RFC 6904,
           DOI 10.17487/RFC6904, April 2013,
           <https://www.rfc-editor.org/info/rfc6904>.

[RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in
           RFC 2119 Key Words", BCP 14, RFC 8174,
           DOI 10.17487/RFC8174, May 2017,
           <https://www.rfc-editor.org/info/rfc8174>.

12.2. Informative References

[RFC3550]  Schulzrinne, H., Casner, S., Frederick, R., and V.
           Jacobson, "RTP: A Transport Protocol for Real-Time
           Applications", STD 64, RFC 3550, DOI 10.17487/RFC3550,
           July 2003, <https://www.rfc-editor.org/info/rfc3550>.

[RFC3553]  Mealling, M., Masinter, L., Hardie, T., and G. Klyne, "An
           IETF URN Sub-namespace for Registered Protocol
           Parameters", BCP 73, RFC 3553, DOI 10.17487/RFC3553,
           June 2003, <https://www.rfc-editor.org/info/rfc3553>.

[RFC3611]  Friedman, T., Ed., Caceres, R., Ed., and A. Clark, Ed.,
           "RTP Control Protocol Extended Reports (RTCP XR)",
           RFC 3611, DOI 10.17487/RFC3611, November 2003,
           <https://www.rfc-editor.org/info/rfc3611>.

[RFC4585]  Ott, J., Wenger, S., Sato, N., Burmeister, C., and J. Rey,
           "Extended RTP Profile for Real-time Transport Control
           Protocol (RTCP)-Based Feedback (RTP/AVPF)", RFC 4585,
           DOI 10.17487/RFC4585, July 2006,
           <https://www.rfc-editor.org/info/rfc4585>.

[RFC4588]  Rey, J., Leon, D., Miyazaki, A., Varsa, V., and R.
           Hakenberg, "RTP Retransmission Payload Format", RFC 4588,
           DOI 10.17487/RFC4588, July 2006,
           <https://www.rfc-editor.org/info/rfc4588>.

[RFC5109]  Li, A., Ed., "RTP Payload Format for Generic Forward Error
           Correction", RFC 5109, DOI 10.17487/RFC5109,
           December 2007, <https://www.rfc-editor.org/info/rfc5109>.

[RFC5285]  Singer, D. and H. Desineni, "A General Mechanism for RTP
           Header Extensions", RFC 5285, DOI 10.17487/RFC5285,
           July 2008, <https://www.rfc-editor.org/info/rfc5285>.

[RFC6347]  Rescorla, E. and N. Modadugu, "Datagram Transport Layer
           Security Version 1.2", RFC 6347, DOI 10.17487/RFC6347,
           January 2012, <https://www.rfc-editor.org/info/rfc6347>.

[RFC7201]  Westerlund, M. and C. Perkins, "Options for Securing RTP
           Sessions", RFC 7201, DOI 10.17487/RFC7201, April 2014,
           <https://www.rfc-editor.org/info/rfc7201>.

[RFC7667]  Westerlund, M. and S. Wenger, "RTP Topologies", RFC 7667,
           DOI 10.17487/RFC7667, November 2015,
           <https://www.rfc-editor.org/info/rfc7667>.

[RFC8126]  Cotton, M., Leiba, B., and T. Narten, "Guidelines for
           Writing an IANA Considerations Section in RFCs", BCP 26,
           RFC 8126, DOI 10.17487/RFC8126, June 2017,
           <https://www.rfc-editor.org/info/rfc8126>.

[SDP-BUNDLE]
           Holmberg, C., Alvestrand, H., and C. Jennings,
           "Negotiating Media Multiplexing Using the Session
           Description Protocol (SDP)", Work in Progress,
           draft-ietf-mmusic-sdp-bundle-negotiation-39, August 2017.

[SDP-MUX]  Nandakumar, S., "A Framework for SDP Attributes when
           Multiplexing", Work in Progress, draft-ietf-mmusic-sdp-
           mux-attributes-16, December 2016.

Acknowledgments 🫢

Huge shoutout to Brian Link and John Lazzaro, who gave helpful comments on an early draft 🌸. Colin Perkins was a total star for reviewing and sorting out the details 🌟. Jonathan Lennox suggested using URNs for IETF-defined extensions πŸ¦‹, and Pete Cordell was the reason the padding wording got better πŸ’–. Dave Oran gave feedback and text during review 🧚, Mike Dolan contributed the two-byte header form πŸŽ€, and Magnus Westerlund and Tom Taylor were instrumental in managing the registration text πŸ‘‘.

Authors' Addresses πŸ’…

okay bestie, this is the cute little contact card section at the very end πŸŽ€ the people who wrote this whole thing, and where to find them if you have Questions 🫢

David Singer, Harikishan Desineni, and Roni Even (editor) are the names on the list, and you can reach them at these addresses 🌸

   David Singer
   Apple, Inc.
   1 Infinite Loop
   Cupertino, CA  95014
   United States of America

   Phone: +1 408 996 1010
   Email: singer@apple.com
   URI:   https://support.apple.com/quicktime


   Harikishan Desineni
   Qualcomm
   10001 Pacific Heights Blvd.
   San Diego, CA  92121
   United States of America

   Phone: +1 858 845 8996
   Email: h3dnvb@gmail.com


   Roni Even (editor)
   Huawei Technologies
   Tel Aviv
   Israel

   Email: Roni.even@huawei.com

Roni is the editor, so that's the name to know if you're wondering who kept this whole document together 🧚

And that's the end of RFC 8285! You made it through the whole thing, bestie, and you are officially a little protocol nerd now πŸ’œβœ¨

πŸ“¦ where this page comes from