RFC 1889

RTP: A Transport Protocol for Real-Time Applications

๐Ÿ“… published January 1996, from ietf

RTP: A Transport Protocol for Real-Time Applications ๐ŸŽ€

Okay bestie, this is RFC 1889, and it's giving the foundational real-time transport spec ๐Ÿ’– It's a Standards Track document dated January 1996, from the Audio-Video Transport Working Group, and it sits under the Network Working Group header too. The authors are H. Schulzrinne (GMD Fokus), S. Casner (Precept Software, Inc.), R. Frederick (Xerox Palo Alto Research Center), and V. Jacobson (Lawrence Berkeley National Laboratory) ๐Ÿ‘‘ The title block doesn't list anything it obsoletes or updates, so it's a solo main character โœจ


Status of this Memo โœจ

This document specifies an Internet standards track protocol for the Internet community, and requests discussion and suggestions for improvements ๐Ÿ’… Please refer to the current edition of the "Internet Official Protocol Standards" (STD 1) for the standardization state and status of this protocol. Distribution of this memo is unlimited ๐Ÿฆ‹

Abstract ๐ŸŒธ

Okay so this memo describes RTP, the real-time transport protocol ๐ŸŽ€ RTP gives you end-to-end network transport functions for apps sending real-time data, like audio, video or simulation data, over multicast or unicast network services. It doesn't handle resource reservation, and it doesn't guarantee quality-of-service for real-time services ๐Ÿ™ˆ The data transport gets backup from a control protocol (RTCP), which lets you monitor data delivery in a way that scales to large multicast networks, and gives you minimal control and identification functionality. RTP and RTCP are designed to be independent of the underlying transport and network layers, and the protocol supports RTP-level translators and mixers. Iconic โœจ

Table of Contents ๐Ÿ“œ

   1.         Introduction ........................................    3
   2.         RTP Use Scenarios ...................................    5
   2.1        Simple Multicast Audio Conference ...................    5
   2.2        Audio and Video Conference ..........................    6
   2.3        Mixers and Translators ..............................    6
   3.         Definitions .........................................    7
   4.         Byte Order, Alignment, and Time Format ..............    9
   5.         RTP Data Transfer Protocol ..........................   10
   5.1        RTP Fixed Header Fields .............................   10
   5.2        Multiplexing RTP Sessions ...........................   13
   5.3        Profile-Specific Modifications to the RTP Header.....   14
   5.3.1      RTP Header Extension ................................   14
   6.         RTP Control Protocol -- RTCP ........................   15
   6.1        RTCP Packet Format ..................................   17
   6.2        RTCP Transmission Interval ..........................   19
   6.2.1      Maintaining the number of session members ...........   21
   6.2.2      Allocation of source description bandwidth ..........   21
   6.3        Sender and Receiver Reports .........................   22
   6.3.1      SR: Sender report RTCP packet .......................   23
   6.3.2      RR: Receiver report RTCP packet .....................   28
   6.3.3      Extending the sender and receiver reports ...........   29
   6.3.4      Analyzing sender and receiver reports ...............   29
   6.4        SDES: Source description RTCP packet ................   31
   6.4.1      CNAME: Canonical end-point identifier SDES item .....   32
   6.4.2      NAME: User name SDES item ...........................   34
   6.4.3      EMAIL: Electronic mail address SDES item ............   34
   6.4.4      PHONE: Phone number SDES item .......................   34
   6.4.5      LOC: Geographic user location SDES item .............   35
   6.4.6      TOOL: Application or tool name SDES item ............   35
   6.4.7      NOTE: Notice/status SDES item .......................   35
   6.4.8      PRIV: Private extensions SDES item ..................   36
   6.5        BYE: Goodbye RTCP packet ............................   37
   6.6        APP: Application-defined RTCP packet ................   38
   7.         RTP Translators and Mixers ..........................   39
   7.1        General Description .................................   39
   7.2        RTCP Processing in Translators ......................   41
   7.3        RTCP Processing in Mixers ...........................   43
   7.4        Cascaded Mixers .....................................   44
   8.         SSRC Identifier Allocation and Use ..................   44
   8.1        Probability of Collision ............................   44
   8.2        Collision Resolution and Loop Detection .............   45
   9.         Security ............................................   49
   9.1        Confidentiality .....................................   49
   9.2        Authentication and Message Integrity ................   50
   10.        RTP over Network and Transport Protocols ............   51
   11.        Summary of Protocol Constants .......................   51
   11.1       RTCP packet types ...................................   52
   11.2       SDES types ..........................................   52
   12.        RTP Profiles and Payload Format Specifications ......   53
   A.         Algorithms ..........................................   56
   A.1        RTP Data Header Validity Checks .....................   59
   A.2        RTCP Header Validity Checks .........................   63
   A.3        Determining the Number of RTP Packets Expected and
              Lost ................................................   63
   A.4        Generating SDES RTCP Packets ........................   64
   A.5        Parsing RTCP SDES Packets ...........................   65
   A.6        Generating a Random 32-bit Identifier ...............   66
   A.7        Computing the RTCP Transmission Interval ............   68
   A.8        Estimating the Interarrival Jitter ..................   71
   B.         Security Considerations .............................   72
   C.         Addresses of Authors ................................   72
   D.         Bibliography ........................................   73

1. Introduction โœจ

This memo specifies the real-time transport protocol (RTP), which gives you end-to-end delivery for data with real-time vibes, like interactive audio and video ๐Ÿงš Those services include payload type identification, sequence numbering, timestamping and delivery monitoring. Apps usually run RTP on top of UDP so they can use its multiplexing and checksum services, since both protocols contribute parts of the transport functionality. However, RTP may be used with other suitable underlying network or transport protocols (see Section 10). And if the underlying network provides multicast distribution, RTP supports sending data to multiple destinations ๐ŸŒˆ

Note that RTP itself doesn't have any mechanism to ensure timely delivery or provide other quality-of-service guarantees. It relies on lower-layer services to do that ๐Ÿซถ It doesn't guarantee delivery or prevent out-of-order delivery, and it doesn't assume the underlying network is reliable or delivers packets in sequence. The sequence numbers included in RTP let the receiver reconstruct the sender's packet sequence, but they might also be used to figure out where a packet belongs, for example in video decoding, without decoding packets in sequence ๐Ÿ’œ

RTP is primarily designed for multi-participant multimedia conferences, but it's not limited to that ๐Ÿฆ‹ Storage of continuous data, interactive distributed simulation, active badge, and control and measurement applications may also find RTP applicable.

This document defines RTP, which is made of two closely-linked parts:

  • the real-time transport protocol (RTP), to carry data that has real-time properties.
  • the RTP control protocol (RTCP), to monitor the quality of service and to convey information about the participants in an on-going session. The latter aspect of RTCP may be sufficient for "loosely controlled" sessions, i.e., where there is no explicit membership control and set-up, but it is not necessarily intended to support all of an application's control communication requirements. This functionality may be fully or partially subsumed by a separate session control protocol, which is beyond the scope of this document.

RTP is a brand new style of protocol ๐Ÿ’– It follows the principles of application level framing and integrated layer processing proposed by Clark and Tennenhouse [1]. That means RTP is meant to be malleable, so it can provide the info a particular application needs, and it often gets integrated into the application processing instead of living as a separate layer. RTP is a protocol framework that is deliberately not complete ๐Ÿงฉ This document only specifies the functions expected to be common across all the applications where RTP would be appropriate. Unlike conventional protocols, which might add features by making the protocol more general or by adding an option mechanism that needs parsing, RTP gets tailored through modifications and/or additions to the headers as needed. Examples are given in Sections 5.3 and 6.3.3.

So, in addition to this document, a complete specification of RTP for a particular application will need one or more companion documents (see Section 12):

  • a profile specification document, which defines a set of payload type codes and their mapping to payload formats (e.g., media encodings). A profile may also define extensions or modifications to RTP that are specific to a particular class of applications. Typically an application will operate under only one profile. A profile for audio and video data may be found in the companion RFC TBD.
  • payload format specification documents, which define how a particular payload, such as an audio or video encoding, is to be carried in RTP.

A discussion of real-time services and algorithms for their implementation, plus background on some of the RTP design decisions, can be found in [2] ๐Ÿ“š

Several RTP applications, both experimental and commercial, have already been implemented from draft specifications. These include audio and video tools along with diagnostic tools like traffic monitors. Users of these tools number in the thousands ๐Ÿ”ฅ However, the current Internet can't yet support the full potential demand for real-time services. High-bandwidth services using RTP, such as video, can potentially seriously degrade the quality of service of other network services. So implementors should take appropriate precautions to limit accidental bandwidth usage ๐Ÿ™ˆ Application documentation should clearly outline the limitations and possible operational impact of high-bandwidth real-time services on the Internet and other network services.

bestie, this is the part where the spec gets real about bandwidth. video can wreck everybody else's network service if nobody's careful ๐Ÿ’€

2. RTP Use Scenarios โœจ

okay bestie, let's look at how RTP actually gets used ๐Ÿฆ‹ these examples are just here to show the basic vibe of apps running RTP. they are NOT the only things RTP is allowed to do ๐Ÿ’… quick setup: in all of these, RTP rides on top of IP and UDP ๐ŸŒธ and it follows the conventions from the profile for audio and video in the companion Internet-Draft draft-ietf-avt-profile ๐ŸŽ€


2.1 Simple Multicast Audio Conference ๐ŸŽ™๏ธ

picture this: a working group of the IETF is meeting to talk about the newest protocol draft ๐Ÿ“ and they're doing it over voice, using the IP multicast services of the Internet ๐Ÿ”Š the working group chair gets a multicast group address and a pair of ports through some allocation mechanism ๐Ÿ—๏ธ one port is for audio data and the other is for control, which means RTCP packets ๐Ÿ’œ that address and port info gets passed along to the people who are supposed to join ๐Ÿ’Œ if they want privacy, the data and control packets may be encrypted like Section 9.1 says, and then an encryption key must also be generated and distributed ๐Ÿ” the exact details of how that allocation and distribution works are beyond the scope of RTP, so not our problem here ๐Ÿ™ˆ

the audio app on each participant's device sends audio in tiny chunks, like 20 ms each ๐ŸŽง every chunk gets an RTP header in front of it, and the RTP header plus the data then sits inside a UDP packet ๐Ÿ“ฆ the header says what kind of audio encoding is inside (PCM, ADPCM or LPC, for example), so senders can switch encodings during the call ๐Ÿ”„ like when someone new joins over a low-bandwidth link, or when they need to react to signs of network congestion ๐Ÿšฆ

the Internet, like other packet networks, sometimes loses packets, reorders them, and delays them by variable amounts of time ๐Ÿ˜ญ to cope with all that, the RTP header carries timing info and a sequence number so the receivers can rebuild the timing the source had. so in this example, the audio gets played out smoothly, every 20 ms โœจ this timing rebuild happens separately for each source of RTP packets in the conference ๐Ÿ‘ฏ the sequence number can also help the receiver estimate how many packets went missing ๐Ÿ•ต๏ธ

since people in the working group keep joining and leaving, it's really useful to know who's around right now and how well they're hearing the audio ๐Ÿ‘€ so each instance of the audio app periodically multicasts a reception report plus its user's name on the RTCP (control) port ๐Ÿ“ฃ the reception report shows how well the current speaker is being received, and it may be used to control adaptive encodings ๐ŸŽ›๏ธ other identifying info may also be included, subject to control bandwidth limits ๐Ÿ’… and when a site leaves the conference, it sends the RTCP BYE packet (Section 6.5) ๐Ÿ‘‹


2.2 Audio and Video Conference ๐ŸŽฅ

if both audio and video are being used in a conference, they get transmitted as separate RTP sessions ๐ŸŽฌ RTCP packets go out for each medium too, using two different UDP port pairs and/or multicast addresses. at the RTP level there's no direct coupling between the audio and video sessions ๐Ÿ™… except for one thing: a user in both sessions should use the same distinguished (canonical) name in the RTCP packets for both, so the sessions can be associated ๐Ÿ”—

why split them up? so some participants can receive only one medium if they choose, and Section 5.2 explains that more ๐Ÿง  even with the separation, synchronized playback of a source's audio and video can still be achieved, using the timing info carried in the RTCP packets for both sessions ๐Ÿซถ


2.3 Mixers and Translators ๐Ÿงฉ

so far we've assumed every site wants to receive media data in the same format ๐Ÿ™ƒ but that's not always appropriate. picture participants in one area connected through a low-speed link, while most of the conference people enjoy high-speed access ๐Ÿขโžก๏ธ๐Ÿš€ instead of forcing everyone onto a lower-bandwidth, reduced-quality audio encoding, an RTP-level relay called a mixer may be placed near the low-bandwidth area ๐Ÿ›ธ this mixer resynchronizes incoming audio packets to rebuild the constant 20 ms spacing from the sender, mixes those reconstructed audio streams into a single stream, translates the audio encoding to a lower-bandwidth one, and forwards that smaller packet stream across the low-speed link ๐Ÿ“‰ those packets might be unicast to a single recipient, or multicast on a different address to multiple recipients ๐Ÿ“ก the RTP header includes a means for mixers to identify the sources that contributed to a mixed packet, so correct talker indication can be provided at the receivers ๐Ÿ—ฃ๏ธ

some intended participants in the audio conference may have high-bandwidth links but might not be directly reachable via IP multicast. for example, they could be behind an application-level firewall that won't let any IP packets pass ๐Ÿงฑ for these sites, mixing may not be necessary, in which case another type of RTP-level relay called a translator may be used ๐Ÿ” two translators get installed, one on either side of the firewall. the outside one funnels all multicast packets it receives through a secure connection to the translator inside the firewall, and the inside one sends them again as multicast packets to a multicast group restricted to the site's internal network ๐Ÿ”’

mixers and translators may be designed for a variety of purposes ๐ŸŒˆ an example is a video mixer that scales the images of individual people in separate video streams and composites them into one video stream, to simulate a group scene ๐Ÿ–ผ๏ธ other examples of translation include connecting a group of hosts speaking only IP/UDP to a group of hosts that understand only ST-II, or doing packet-by-packet encoding translation of video streams from individual sources without resynchronization or mixing ๐Ÿ’ซ the details of how mixers and translators operate are given in Section 7 ๐Ÿ“–

3. Definitions โœจ

okay bestie, this part is basically the glossary ๐Ÿ“– and we NEED these words locked in before anything else makes sense ๐Ÿ’…

RTP payload: the data that RTP carries in a packet ๐ŸŽ€, like audio samples or compressed video data. ngl the payload format and how it gets interpreted are beyond the scope of this document, so we're not going there today ๐Ÿ™ˆ

RTP packet: a data packet made of the fixed RTP header ๐Ÿงš, a possibly empty list of contributing sources (more on those below ๐Ÿ‘€), and the payload data. Some underlying protocols may need an encapsulation of the RTP packet to be defined. Typically one packet of the underlying protocol contains a single RTP packet, but several RTP packets may be contained if the encapsulation method permits it (see Section 10).

RTCP packet: a control packet with a fixed header part that's similar to the one in RTP data packets, followed by structured elements that depend on the RTCP packet type ๐Ÿฆ‹. The formats are defined in Section 6. Typically, multiple RTCP packets get sent together as a compound RTCP packet inside a single packet of the underlying protocol ๐Ÿซถ, and that works because of the length field in the fixed header of each RTCP packet.

Port: the "abstraction that transport protocols use to distinguish among multiple destinations within a given host computer. TCP/IP protocols identify ports using small positive integers." [3] The transport selectors (TSEL) used by the OSI transport layer are equivalent to ports ๐Ÿ’œ. RTP depends on the lower-layer protocol to provide some mechanism, such as ports, to multiplex the RTP and RTCP packets of a session.

Transport address: the combo of a network address and a port that identifies a transport-level endpoint, like an IP address and a UDP port ๐ŸŒธ. Packets get transmitted from a source transport address to a destination transport address.

RTP session: the association among a set of participants communicating with RTP ๐ŸŒˆ. For each participant, the session is defined by a particular pair of destination transport addresses (one network address plus a port pair for RTP and RTCP). The destination transport address pair may be common for all participants, like with IP multicast, or it may be different for each, like with individual unicast network addresses plus a common port pair. In a multimedia session, each medium is carried in a separate RTP session with its own RTCP packets. The multiple RTP sessions are told apart by different port number pairs and/or different multicast addresses.

Synchronization source (SSRC): the source of a stream of RTP packets, identified by a 32-bit numeric SSRC identifier carried in the RTP header ๐Ÿ”ฅ, so it doesn't depend on the network address. All packets from a synchronization source form part of the same timing and sequence number space, so a receiver groups packets by synchronization source for playback. Examples include the sender of a stream of packets derived from a signal source like a microphone or a camera, or an RTP mixer (more below). A synchronization source may change its data format, e.g., audio encoding, over time. The SSRC identifier is a randomly chosen value meant to be globally unique within a particular RTP session (see Section 8). A participant doesn't need to use the same SSRC identifier for all the RTP sessions in a multimedia session. The binding of the SSRC identifiers is provided through RTCP (see Section 6.4.1). If a participant generates multiple streams in one RTP session, for example from separate video cameras, each must be identified as a different SSRC.

Contributing source (CSRC): a source of a stream of RTP packets that has contributed to the combined stream produced by an RTP mixer (more below). The mixer inserts a list of the SSRC identifiers of the sources that contributed to generating a particular packet into the RTP header of that packet. This list is called the CSRC list. An example is audio conferencing, where a mixer indicates all the talkers whose speech was combined to produce the outgoing packet ๐ŸŽค. That lets the receiver show the current talker, even though all the audio packets contain the same SSRC identifier (that of the mixer).

End system: an application that generates the content to be sent in RTP packets and/or consumes the content of received RTP packets. An end system can act as one or more synchronization sources in a particular RTP session, but typically only one.

Mixer: an intermediate system that receives RTP packets from one or more sources, possibly changes the data format, combines the packets in some manner, and then forwards a new RTP packet. Since the timing among multiple input sources generally won't be synchronized, the mixer makes timing adjustments among the streams and generates its own timing for the combined stream. Thus, all data packets originating from a mixer will be identified as having the mixer as their synchronization source. ๐Ÿ‘‘

Translator: an intermediate system that forwards RTP packets with their synchronization source identifier intact ๐Ÿฆ„. Examples include devices that convert encodings without mixing, replicators from multicast to unicast, and application-level filters in firewalls.

Monitor: an application that receives RTCP packets sent by participants in an RTP session, in particular the reception reports, and estimates the current quality of service for distribution monitoring, fault diagnosis, and long-term statistics ๐Ÿ“Š. The monitor function is likely to be built into the application(s) participating in the session, but it may also be a separate application that doesn't otherwise participate and doesn't send or receive the RTP data packets. These are called third party monitors.

Non-RTP means: protocols and mechanisms that may be needed in addition to RTP to provide a usable service ๐ŸŒŸ. For multimedia conferences in particular, a conference control application may distribute multicast addresses and keys for encryption, negotiate the encryption algorithm to be used, and define dynamic mappings between RTP payload type values and the payload formats they represent, for formats that don't have a predefined payload type value. For simple applications, electronic mail or a conference database may also be used. The specification of such protocols and mechanisms is outside the scope of this document.


4. Byte Order, Alignment, and Time Format โฐ

All integer fields are carried in network byte order, which means most significant byte (octet) first ๐Ÿ’–. This byte order is commonly known as big-endian. The transmission order is described in detail in [4]. Unless otherwise noted, numeric constants are in decimal (base 10).

All header data is aligned to its natural length, i.e., 16-bit fields are aligned on even offsets, 32-bit fields are aligned at offsets divisible by four, etc. Octets designated as padding have the value zero ๐Ÿงธ.

Wallclock time (absolute time) is represented using the timestamp format of the Network Time Protocol (NTP), which is in seconds relative to 0h UTC on 1 January 1900 [5]. The full resolution NTP timestamp is a 64-bit unsigned fixed-point number, with the integer part in the first 32 bits and the fractional part in the last 32 bits. In some fields where a more compact representation is appropriate, only the middle 32 bits are used. That means the low 16 bits of the integer part and the high 16 bits of the fractional part. The high 16 bits of the integer part must be determined independently ๐Ÿซ .

5. RTP Data Transfer Protocol ๐Ÿš€

5.1. RTP Fixed Header Fields โœจ

Okay bestie, this is the RTP header, the little ID card glued onto every single packet ๐Ÿชช๐Ÿ’–. Here's the layout:

    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             |
   |                             ....                              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

The first twelve octets show up in every RTP packet ๐ŸŽ€. The CSRC list only appears when a mixer puts it there ๐Ÿงš. Here's what each field is giving:

version (V): 2 bits

This is the RTP version, and the one this spec is about is 2 ๐Ÿ‘‘. Fun history: 1 was the first draft version of RTP, and 0 was the protocol the "vat" audio tool originally ran ๐Ÿ™ˆ.

padding (P): 1 bit

If the padding bit is set, the packet has one or more extra padding octets tacked on at the end that aren't part of the payload ๐Ÿง. The very last octet is a count of how many padding octets SHOULD be ignored. Padding MAY be needed by some encryption algorithms with fixed block sizes, or for carrying several RTP packets in one lower-layer protocol data unit ๐Ÿ”.

extension (X): 1 bit

If the extension bit is set, the fixed header gets followed by exactly one header extension, formatted the way Section 5.3.1 defines ๐Ÿงฉ.

CSRC count (CC): 4 bits

CC tells you how many CSRC identifiers come after the fixed header ๐Ÿ”ข.

marker (M): 1 bit

What the marker means is up to a profile. It's meant to flag big moments like frame boundaries in the packet stream ๐Ÿšฉ. A profile MAY define additional marker bits, or say there's no marker bit at all by changing how many bits the payload type field gets (see Section 5.3) ๐Ÿฆ‹.

payload type (PT): 7 bits

This tells the receiver what format the payload is in, so the app knows how to read it ๐Ÿ“ฆ. A profile sets a default static mapping of payload type codes to payload formats. Additional payload type codes MAY be defined dynamically through non-RTP means (see Section 3). An initial set of default mappings for audio and video is in the companion profile Internet-Draft draft-ietf-avt-profile, and it MAY be extended in future editions of the Assigned Numbers RFC [6]. An RTP sender only emits one payload type at any given time, and this field is not intended for multiplexing separate media streams (see Section 5.2) ๐Ÿ™…โ€โ™€๏ธ.

sequence number: 16 bits

This goes up by one for each RTP data packet sent. The receiver MAY use it to detect packet loss and to restore packet sequence ๐Ÿ”ข. The initial value is random (unpredictable) to make known-plaintext attacks on encryption more difficult, even if the source itself doesn't encrypt, because the packets MAY flow through a translator that does ๐Ÿ•ต๏ธ. Techniques for choosing unpredictable numbers are discussed in [7].

timestamp: 32 bits

The timestamp reflects the sampling instant of the first octet in the RTP data packet โฐ. The sampling instant MUST be derived from a clock that increments monotonically and linearly in time, so synchronization and jitter calculations work (see Section 6.3.1) ๐Ÿ“. The clock's resolution MUST be sufficient for the synchronization accuracy you want and for measuring packet arrival jitter. One tick per video frame is typically not sufficient ๐Ÿ™….

The clock frequency depends on the format of the data carried as payload. It's specified statically in the profile or payload format spec that defines the format, or it MAY be specified dynamically for payload formats defined through non-RTP means. If RTP packets get generated periodically, the nominal sampling instant from the sampling clock is what gets used, not a reading of the system clock. For example, with fixed-rate audio the timestamp clock would likely go up by one for each sampling period. If an audio app reads blocks covering 160 sampling periods from the input device, the timestamp goes up by 160 for each such block, regardless of whether the block is transmitted in a packet or dropped as silent ๐Ÿคซ.

The initial value of the timestamp is random, same as the sequence number. Several consecutive RTP packets MAY have equal timestamps if they're (logically) generated at once, like packets belonging to the same video frame ๐ŸŽฌ. Consecutive RTP packets MAY contain timestamps that aren't monotonic if the data isn't transmitted in the order it was sampled, as with MPEG interpolated video frames. The sequence numbers of the packets as transmitted will still be monotonic ๐Ÿ”.

SSRC: 32 bits

The SSRC field identifies the synchronization source ๐Ÿ†”. It's chosen randomly, with the intent that no two synchronization sources within the same RTP session will have the same SSRC identifier. Appendix A.6 has an example algorithm for generating a random identifier. Even though the odds of multiple sources picking the same identifier are low, all RTP implementations MUST be prepared to detect and resolve collisions ๐ŸฅŠ. Section 8 describes the probability of collision, plus a mechanism for resolving collisions and detecting RTP-level forwarding loops based on the uniqueness of the SSRC identifier.

If a source changes its source transport address, it MUST also choose a new SSRC identifier, so it doesn't get interpreted as a looped source ๐Ÿ”„.

CSRC list: 0 to 15 items, 32 bits each

The CSRC list identifies the contributing sources for the payload in this packet. The number of identifiers is given by the CC field. If there are more than 15 contributing sources, only 15 MAY be identified ๐Ÿ™ƒ. Mixers insert CSRC identifiers, using the SSRC identifiers of the contributing sources. For example, for audio packets, the SSRC identifiers of all sources that were mixed together to create a packet get listed, which allows correct talker indication at the receiver ๐ŸŽค.


5.2. Multiplexing RTP Sessions ๐Ÿฆ‹

For efficient protocol processing, the number of multiplexing points SHOULD be minimized, as described in the integrated layer processing design principle [1] ๐Ÿ’ซ. In RTP, multiplexing is done by the destination transport address (network address and port number), which defines an RTP session. Say you've got a teleconference with audio and video encoded separately. Each medium SHOULD be carried in its own RTP session, with its own destination transport address ๐Ÿ“ž.

It is not intended that audio and video get carried in a single RTP session and demultiplexed based on the payload type or SSRC fields ๐Ÿ™…โ€โ™€๏ธ. Interleaving packets with different payload types but the same SSRC would cause several problems:

  1. If one payload type were switched during a session, there would be no general way to tell which of the old values the new one replaced.
  2. An SSRC is defined to identify a single timing and sequence number space. Interleaving multiple payload types would need different timing spaces if the media clock rates differ, and different sequence number spaces to tell which payload type suffered packet loss.
  3. The RTCP sender and receiver reports (see Section 6.3) can only describe one timing and sequence number space per SSRC, and they don't carry a payload type field.
  4. An RTP mixer wouldn't be able to combine interleaved streams of incompatible media into one stream.
  5. Carrying multiple media in one RTP session rules out using different network paths or network resource allocations where appropriate. It also rules out receiving a subset of the media if you want, like just audio when video would exceed the available bandwidth, and receiver implementations that use separate processes for the different media. Separate RTP sessions allow either single-process or multi-process implementations.

Using a different SSRC for each medium but sending them in the same RTP session would avoid the first three problems, but not the last two ๐Ÿซถ.


5.3. Profile-Specific Modifications to the RTP Header ๐Ÿ’…

The existing RTP data packet header is believed to be complete for the set of functions needed in common across all the application classes RTP might support. However, in keeping with the ALF design principle ๐Ÿงฉ, the header MAY be tailored through modifications or additions defined in a profile specification, while still allowing profile-independent monitoring and recording tools to function ๐Ÿ› ๏ธ.

  • The marker bit and payload type field carry profile-specific information, but they're allocated in the fixed header since many applications are expected to need them, and they might otherwise have to add another 32-bit word just to hold them ๐Ÿฐ. The octet containing these fields MAY be redefined by a profile to suit different requirements, for example with more or fewer marker bits. If there are any marker bits, one SHOULD be located in the most significant bit of the octet, since profile-independent monitors MAY be able to observe a correlation between packet loss patterns and the marker bit ๐Ÿ‘€.
  • Additional information that a particular payload format needs, like a video encoding, SHOULD be carried in the payload section of the packet ๐ŸŽž๏ธ. This might be in a header that's always present at the start of the payload section, or might be indicated by a reserved value in the data pattern.
  • If a particular class of applications needs additional functionality independent of payload format, the profile those applications operate under SHOULD define additional fixed fields to follow immediately after the SSRC field of the existing fixed header ๐Ÿง. Those applications can quickly and directly access the additional fields, while profile-independent monitors or recorders can still process the RTP packets by interpreting only the first twelve octets ๐Ÿฆ‹.

If it turns out that additional functionality is needed in common across all profiles, then a new version of RTP SHOULD be defined to make a permanent change to the fixed header ๐Ÿ‘‘.

5.3.1. RTP Header Extension

okay so there's this extension mechanism ๐ŸŽ€ that lets individual implementations experiment with brand-new, payload-format-independent functions that need extra info tucked into the RTP data packet header โœจ. The best part? Other implementations that haven't been extended can just ignore it, so nobody's experiment breaks the party ๐Ÿ’….

heads up bestie ๐Ÿ™ˆ this header extension is only meant for limited use. Most of the stuff you'd want to do with it is better done the other way, using the methods from the previous section ๐Ÿฆ‹. Like, a profile-specific extension to the fixed header is way cheaper to process because it's not conditional and it doesn't live in a variable location ๐Ÿ’€. And anything a particular payload format needs? Don't use this header extension for that. It should go in the payload section of the packet ๐Ÿ’–.

    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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |      defined by profile       |           length              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                        header extension                       |
   |                             ....                              |

So here's the deal: if the X bit in the RTP header is one, a variable-length header extension gets tacked onto the RTP header, right after the CSRC list if there is one ๐ŸŒธ. The header extension has a 16-bit length field that counts how many 32-bit words are in the extension, not including the four-octet extension header itself. So zero is a valid length, periodt โœจ.

Only a single extension may be appended to the RTP data header ๐Ÿ‘‘. Multiple interoperating implementations can each experiment independently with different header extensions, and one implementation can even try out more than one type. To make that work, the first 16 bits of the header extension are left open for identifiers or parameters that tell them apart ๐Ÿงš. Figuring out what those 16 bits look like is up to the profile specification the implementations are running under ๐Ÿซถ. And the RTP spec itself? It doesn't define any header extensions at all, not one ๐Ÿ˜ญ.


6. RTP Control Protocol -- RTCP โœจ

okay so RTCP (the RTP control protocol) sends control packets on a regular schedule to every participant in the session, using the same distribution mechanism the data packets use ๐Ÿฆ‹. The underlying protocol must provide multiplexing of the data and control packets, for example using separate port numbers with UDP ๐Ÿ”ฅ. RTCP has four jobs ๐Ÿ‘‘:

  1. Number one, the big one: it gives feedback on how good the data distribution is ๐Ÿ’–. This is a core part of RTP's role as a transport protocol, and it lines up with the flow and congestion control stuff other transport protocols do. The feedback can be directly handy for controlling adaptive encodings [8,9], but experiments with IP multicasting showed it's also critical to get feedback from the receivers so you can diagnose faults in the distribution. Sending reception feedback reports to everyone lets someone who's noticing problems figure out whether those problems are local or global ๐Ÿ”. With a distribution mechanism like IP multicast, it's also possible for an entity like a network service provider, one who isn't otherwise involved in the session, to receive the feedback and act as a third-party monitor for diagnosing network problems ๐Ÿ‘€. This feedback function is performed by the RTCP sender and receiver reports, described below in Section 6.3.
  2. Number two: RTCP carries a persistent transport-level identifier for an RTP source, called the canonical name or CNAME (Section 6.4.1) ๐ŸŽ€. The SSRC can change if a conflict gets discovered or a program gets restarted, so receivers need the CNAME to keep track of each participant. Receivers also need the CNAME to tie together multiple data streams from one participant across a set of related RTP sessions, for example lining up audio and video so they stay in sync ๐ŸŽถ.
  3. Number three: the first two jobs need every participant to send RTCP packets, so the rate has to be controlled for RTP to scale up to lots of participants ๐ŸŒˆ. Each participant sends its control packets to all the others, so everyone can independently observe how many participants there are. That number is used to work out the rate at which the packets are sent, as explained in Section 6.2 ๐Ÿงฎ.
  4. Number four, which is optional: RTCP can convey minimal session control information, like participant identification to show in the user interface ๐Ÿชช. This is most likely useful in "loosely controlled" sessions, where people join and leave without membership control or parameter negotiation ๐Ÿšช. RTCP is a convenient channel for reaching all the participants, but it isn't necessarily expected to support every control communication an application needs ๐Ÿ™ƒ. A higher-level session control protocol, which is beyond the scope of this document, may be needed.

Real talk: functions 1-3 are mandatory when RTP is used in the IP multicast environment, and they're recommended for all environments ๐Ÿซถ. RTP application designers are advised to steer clear of mechanisms that only work in unicast mode and won't scale to larger numbers ๐Ÿšซ.

6.1. RTCP Packet Format

the spec defines several RTCP packet types to carry all sorts of control info ๐ŸŽ:

  • SR: Sender report, for transmission and reception statistics from participants that are active senders
  • RR: Receiver report, for reception statistics from participants that are not active senders
  • SDES: Source description items, including CNAME
  • BYE: Indicates end of participation
  • APP: Application specific functions

each RTCP packet starts with a fixed part that looks a lot like the one on RTP data packets, followed by structured elements that can vary in length depending on the packet type. Those elements always end on a 32-bit boundary ๐Ÿ“. The alignment requirement and a length field in the fixed part are there to make RTCP packets "stackable" ๐Ÿฅž. You can concatenate multiple RTCP packets with no separators in between to form a compound RTCP packet, which gets sent in a single packet of the lower layer protocol (UDP, for example) ๐Ÿ“ฆ. There's no explicit count of the individual RTCP packets in the compound packet, because the lower layer protocols are expected to provide an overall length that marks where the compound packet ends.

Each individual RTCP packet in the compound packet may be processed independently, with no requirements on the order or combination of packets. But to actually do the protocol's jobs, these constraints apply ๐Ÿ’…:

  • Reception statistics (in SR or RR) should be sent as often as bandwidth constraints allow, to maximize the resolution of the statistics. So each periodically transmitted compound RTCP packet should include a report packet.
  • New receivers need the CNAME for a source as soon as possible, so they can identify the source and start associating media for things like lip-sync. So each compound RTCP packet should also include the SDES CNAME.
  • The number of packet types that may appear first in the compound packet should be limited. That keeps more constant bits in the first word, which boosts the odds of successfully validating RTCP packets against misaddressed RTP data packets or other unrelated packets ๐Ÿ•ต๏ธโ€โ™€๏ธ.

So, all RTCP packets must be sent in a compound packet of at least two individual packets, with the following format recommended ๐ŸŽ€:

  • Encryption prefix: If and only if the compound packet is to be encrypted, it's prefixed by a random 32-bit quantity that gets redrawn for every compound packet transmitted.
  • SR or RR: The first RTCP packet in the compound packet must always be a report packet, to facilitate header validation as described in Appendix A.2. This is true even if no data has been sent nor received, in which case an empty RR is sent. It's also true even if the only other RTCP packet in the compound packet is a BYE.
  • Additional RRs: If the number of sources whose reception statistics are being reported exceeds 31 (the number that fits into one SR or RR packet), then additional RR packets should follow the initial report packet.
  • SDES: An SDES packet containing a CNAME item must be included in each compound RTCP packet. Other source description items may optionally be included if a particular application requires them, subject to bandwidth constraints (see Section 6.2.2).
  • BYE or APP: Other RTCP packet types, including ones yet to be defined, may follow in any order. The exception is that BYE should be the last packet sent with a given SSRC/CSRC. Packet types may appear more than once.

It is advisable for translators and mixers to combine individual RTCP packets from the multiple sources they forward into one compound packet whenever that's feasible, so they can amortize (spread out) the packet overhead (see Section 7) ๐Ÿง. An example RTCP compound packet, as might be produced by a mixer, is shown in Fig. 1. If the overall length of a compound packet would exceed the maximum transmission unit (MTU) of the network path, it may be segmented into multiple shorter compound packets, sent in separate packets of the underlying protocol. Note that each of the compound packets must begin with an SR or RR packet. ๐Ÿšจ

An implementation may ignore incoming RTCP packets with types unknown to it. Additional RTCP packet types may be registered with the Internet Assigned Numbers Authority (IANA) ๐Ÿฆ‹.

6.2 RTCP Transmission Interval ๐Ÿฆ‹

   if encrypted: random 32-bit integer
    |
    |[------- packet -------][----------- packet -----------][-packet-]
    |
    |             receiver reports          chunk        chunk
    V                                    item  item     item  item
   --------------------------------------------------------------------
   |R[SR|# sender #site#site][SDES|# CNAME PHONE |#CNAME LOC][BYE##why]
   |R[  |# report #  1 #  2 ][    |#             |#         ][   ##   ]
   |R[  |#        #    #    ][    |#             |#         ][   ##   ]
   |R[  |#        #    #    ][    |#             |#         ][   ##   ]
   --------------------------------------------------------------------
   |<------------------  UDP packet (compound packet) --------------->|

   #: SSRC/CSRC

Figure 1: Example of an RTCP compound packet ๐ŸŽ€

Okay so RTP is built to scale from a tiny call with a few friends all the way up to thousands of people ๐ŸŒˆ. In an audio conference the data traffic basically takes care of itself, because only one or two people talk at a time, so with multicast the data rate on any given link stays pretty steady no matter how many people join โœจ. The control traffic is not like that though ๐Ÿ’€. If every participant sent reception reports at a constant rate, the control traffic would grow linearly with the number of participants, so the rate has to get scaled down ๐Ÿ“‰.

For each session, we assume the data traffic has an aggregate limit called the "session bandwidth" that gets split among everyone ๐Ÿ“. That bandwidth might be reserved, with the limit enforced by the network, or it might just be a reasonable share. It can be picked based on cost or on what you already know about the network bandwidth for the session. It's kind of independent of the media encoding, though the encoding choice might be limited by it. The session bandwidth parameter is expected to be supplied by a session management application when it invokes a media application, but media applications can also set a default based on the single-sender data bandwidth for the encoding picked for the session. The application can also enforce bandwidth limits based on multicast scope rules or other criteria ๐Ÿงš.

Bandwidth calculations for control and data traffic include lower-layer transport and network protocols (for example, UDP and IP), since that's what the resource reservation system would need to know. The application can also be expected to know which of these protocols are in use. Link-level headers are not included in the calculation, since the packet gets wrapped in different link-level headers as it travels ๐Ÿ›ฃ๏ธ.

The control traffic should be limited to a small and known fraction of the session bandwidth ๐Ÿ’…. Small so the main job of the transport protocol (carrying data) isn't impaired. Known so the control traffic can be included in the bandwidth specification given to a resource reservation protocol, and so each participant can independently work out its share. It's suggested that the fraction of the session bandwidth allocated to RTCP be fixed at 5%. The exact value of this and the other constants in the interval calculation isn't critical, but all participants in the session must use the same values so they all calculate the same interval. That's why these constants should be fixed for a particular profile ๐Ÿ”’.

The algorithm in Appendix A.7 was designed to hit the goals above. It calculates the interval between sending compound RTCP packets to divide the allowed control traffic bandwidth among the participants โญ. This gives a fast response for small sessions, where identifying everyone is important, and it still automatically adapts to large ones ๐Ÿ‘‘. The algorithm has these characteristics:

  • Senders are collectively allocated at least 1/4 of the control traffic bandwidth, so that in sessions with a large number of receivers but a small number of senders, newly joining participants will more quickly receive the CNAME for the sending sites ๐Ÿ™Œ.
  • The calculated interval between RTCP packets is required to be greater than a minimum of 5 seconds, to avoid having bursts of RTCP packets exceed the allowed bandwidth when the number of participants is small and the traffic isn't smoothed according to the law of large numbers ๐ŸŒธ.
  • The interval between RTCP packets is varied randomly over the range [0.5,1.5] times the calculated interval, to avoid unintended synchronization of all participants [10]. The first RTCP packet sent after joining a session is also delayed by a random variation of half the minimum RTCP interval, in case the application is started at multiple sites simultaneously, for example as initiated by a session announcement ๐ŸŽฒ.
  • A dynamic estimate of the average compound RTCP packet size is calculated, including all those received and sent, so it automatically adapts to changes in the amount of control information carried ๐Ÿ”„.

This algorithm may be used for sessions in which all participants are allowed to send. In that case, the session bandwidth parameter is the product of the individual sender's bandwidth times the number of participants, and the RTCP bandwidth is 5% of that ๐Ÿงฎ.


6.2.1 Maintaining the number of session members

Calculating the RTCP packet interval depends on an estimate of how many sites are participating in the session ๐Ÿ‘€. New sites get added to the count when they're heard, and each one gets an entry in a table indexed by the SSRC or CSRC identifier (see Section 8.2) so we can keep track of them. New entries may not be considered valid until multiple packets carrying the new SSRC have been received (see Appendix A.1). Entries may be deleted from the table when an RTCP BYE packet with the corresponding SSRC identifier is received ๐Ÿ—‘๏ธ.

A participant may mark another site inactive, or delete it if it's not valid yet, if no RTP or RTCP packet has been received for a small number of RTCP report intervals (5 is suggested) ๐Ÿ˜ญ. This gives some robustness against packet loss. All sites must calculate roughly the same value for the RTCP report interval in order for this timeout to work properly โฑ๏ธ.

Once a site has been validated, if it's later marked inactive, its state should still be retained, and the site should keep being counted in the total number of sites sharing RTCP bandwidth for a period long enough to span typical network partitions. This is to avoid excessive traffic when the partition heals, due to an RTCP report interval that's too small. A timeout of 30 minutes is suggested. Note that this is still larger than 5 times the largest value to which the RTCP report interval is expected to usefully scale, about 2 to 5 minutes ๐Ÿซ .


6.2.2 Allocation of source description bandwidth

This spec defines several source description (SDES) items on top of the mandatory CNAME item, like NAME (personal name) and EMAIL (email address) ๐Ÿ’Œ. It also gives a way to define new application-specific RTCP packet types. Applications should be careful about how much control bandwidth they hand to this extra info, because it slows down the rate at which reception reports and CNAME get sent, and that impairs the performance of the protocol ๐Ÿšจ. It is recommended that no more than 20% of the RTCP bandwidth allocated to a single participant be used to carry the additional information. Also, it's not intended that all SDES items get included in every application. The ones that are included should each get a fraction of the bandwidth according to their utility ๐Ÿ’–. Rather than estimate these fractions dynamically, it is recommended that the percentages be translated statically into report interval counts based on the typical length of an item ๐Ÿ“.

For example, an application might be designed to send only CNAME, NAME and EMAIL and nothing else. NAME might get much higher priority than EMAIL, because the NAME would be displayed continuously in the application's user interface, whereas EMAIL would only be displayed when requested ๐Ÿ™ˆ. At every RTCP interval, an RR packet and an SDES packet with the CNAME item would be sent. For a small session operating at the minimum interval, that's every 5 seconds on average. Every third interval (15 seconds), one extra item gets included in the SDES packet. Seven out of eight times that's the NAME item, and every eighth time (2 minutes) it's the EMAIL item ๐Ÿฌ.

When multiple applications operate in concert using cross-application binding through a common CNAME for each participant, like in a multimedia conference made of an RTP session for each medium, the additional SDES information might be sent in only one RTP session. The other sessions would only carry the CNAME item ๐Ÿซถ.


6.3 Sender and Receiver Reports

RTP receivers provide reception quality feedback using RTCP report packets ๐Ÿ”ฅ, which can take one of two forms depending on whether or not the receiver is also a sender. The only difference between the sender report (SR) and receiver report (RR) forms, besides the packet type code, is that the sender report includes a 20-byte sender information section for use by active senders. The SR is issued if a site has sent any data packets during the interval since issuing the last report or the previous one. Otherwise, the RR is issued ๐Ÿ“จ.

Both the SR and RR forms include zero or more reception report blocks, one for each of the synchronization sources from which this receiver has received RTP data packets since the last report. Reports are not issued for contributing sources listed in the CSRC list. Each reception report block provides statistics about the data received from the particular source indicated in that block. Since a maximum of 31 reception report blocks will fit in an SR or RR packet, additional RR packets may be stacked after the initial SR or RR packet as needed to contain the reception reports for all sources heard during the interval since the last report ๐Ÿ“ฆ.

The next sections define the formats of the two reports, how they may be extended in a profile-specific manner if an application requires additional feedback information, and how the reports may be used ๐Ÿง. Details of reception reporting by translators and mixers are given in Section 7 ๐ŸŽ€.


6.3.1 SR: Sender report RTCP packet

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|    RC   |   PT=SR=200   |             length            | header
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                         SSRC of sender                        |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|              NTP timestamp, most significant word             | sender
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ info
|             NTP timestamp, least significant word             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                         RTP timestamp                         |
|                     sender's packet count                     |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      sender's octet count                     |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|                 SSRC_1 (SSRC of first source)                 | report
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
| fraction lost |       cumulative number of packets lost       |   1
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           extended highest sequence number received           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      interarrival jitter                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                         last SR (LSR)                         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                   delay since last SR (DLSR)                  |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|                 SSRC_2 (SSRC of second source)                | report
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
:                               ...                             :   2
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|                  profile-specific extensions                  |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

okay so the sender information is the second section ๐Ÿ’… It's exactly 20 octets long and it shows up in every single sender report, no exceptions ๐ŸŒธ Think of it as the sender's little highlight reel of everything it's been transmitting.

NTP timestamp: 64 bits โœจ This is the wallclock time when the report went out, so other receivers can pair it with the timestamps that come back in their reception reports and work out the round-trip propagation to them. Receivers should expect the accuracy to be way less than the resolution of the NTP timestamp ๐Ÿ™ˆ The measurement uncertainty isn't indicated, because it might not even be known ๐Ÿ’€ A sender that can track elapsed time but has no wallclock can use the elapsed time since joining the session instead. That's assumed to be less than 68 years, so the high bit stays zero. It's totally permissible to use the sampling clock to estimate elapsed wallclock time ๐Ÿงš And a sender with no wallclock or elapsed time at all may set the NTP timestamp to zero ๐Ÿซถ

RTP timestamp: 32 bits ๐Ÿฆ‹ This one lines up with the same moment as the NTP timestamp, but it's in the same units and has the same random offset as the RTP timestamps in the data packets. It helps with intra- and inter-media synchronization for sources whose NTP timestamps are synced, and media-independent receivers can use it to estimate the nominal RTP clock frequency. Heads up though, in most cases it won't match the RTP timestamp of any adjacent data packet ๐Ÿ‘€ It's calculated from the NTP timestamp, using the relationship between the RTP timestamp counter and real time that gets maintained by periodically checking the wallclock at a sampling instant.

sender's packet count: 32 bits ๐Ÿ“ฆ This is the total number of RTP data packets the sender has transmitted since it started transmitting, up until this SR was generated. The count resets if the sender changes its SSRC identifier.

sender's octet count: 32 bits ๐Ÿ“ This is the total number of payload octets (so not counting the header or padding) sent in RTP data packets since the sender started transmitting, up until this SR was made. It also resets if the SSRC changes, and it's handy for estimating the average payload data rate ๐Ÿ“ˆ


The third section holds zero or more reception report blocks, depending on how many other sources this sender has heard since the last report ๐ŸŽ€ Each block is a stats card for one synchronization source. Receivers don't carry statistics over when a source changes its SSRC because of a collision, so no sneaky leftovers ๐Ÿ™…โ€โ™€๏ธ Here's what's on each card:

SSRC_n (source identifier): 32 bits ๐Ÿชช This is the SSRC of the source that the info in this reception report block is about.

fraction lost: 8 bits ๐Ÿ’” This is the fraction of RTP data packets from SSRC_n that got lost since the previous SR or RR was sent. It's a fixed point number with the binary point on the left edge of the field, which is the same as taking the integer part after multiplying the loss fraction by 256. The fraction is the number of packets lost divided by the number of packets expected (more on that in the next paragraph). There's an implementation in Appendix A.3. If the loss comes out negative because of duplicates, the fraction lost gets set to zero. And here's the tea โ˜• a receiver can't tell whether any packets went missing after the last one it received, and there won't be a reception report block for a source at all if every packet from that source during the last reporting interval was lost.

cumulative number of packets lost: 24 bits ๐Ÿ“‰ This is the total number of RTP data packets from SSRC_n that have been lost since the beginning of reception. It's defined as the number of packets expected minus the number actually received, where "received" includes any that are late or duplicates. So late packets don't count as lost, and the loss can go negative if there are duplicates ๐Ÿ™ƒ The number of packets expected is the extended last sequence number received (defined right after this) minus the initial sequence number received. You can calculate it the way shown in Appendix A.3.

extended highest sequence number received: 32 bits ๐Ÿ”ข The low 16 bits hold the highest sequence number received in an RTP data packet from SSRC_n. The most significant 16 bits extend that with the matching count of sequence number cycles, which can be maintained using the algorithm in Appendix A.1. Different receivers in the same session will come up with different extensions if their start times are way apart ๐Ÿ•ฐ๏ธ

interarrival jitter: 32 bits ๐ŸŒŠ This is an estimate of the statistical variance of the RTP data packet interarrival time. It's measured in timestamp units and expressed as an unsigned integer. The interarrival jitter J is the mean deviation (smoothed absolute value) of the difference D in packet spacing at the receiver compared to the sender, for a pair of packets. Equivalently, it's the difference in the "relative transit time" for the two packets, where the relative transit time is the difference between a packet's RTP timestamp and the receiver's clock at arrival, both measured in the same units ๐Ÿง 

If Si is the RTP timestamp from packet i, and Ri is the arrival time in RTP timestamp units for packet i, then for two packets i and j, D works out to:

D(i,j)=(Rj-Ri)-(Sj-Si)=(Rj-Sj)-(Ri-Si)

The jitter gets calculated continuously as each data packet i comes in from SSRC_n. It uses D for that packet and the previous packet i-1 in order of arrival (which isn't necessarily the sequence order), following this formula:

J=J+(|D(i-1,i)|-J)/16

Whenever a reception report gets issued, the current value of J is sampled ๐Ÿ“ธ

This jitter calculation is spelled out here so that profile-independent monitors can make valid readings of reports coming from different implementations ๐Ÿซถ It's the optimal first-order estimator, and the gain parameter of 1/16 gives a good noise reduction ratio while still converging at a reasonable rate [11]. A sample implementation is in Appendix A.8.

last SR timestamp (LSR): 32 bits โฑ๏ธ These are the middle 32 bits out of the 64 in the NTP timestamp (as explained in Section 4) that were received as part of the most recent RTCP sender report (SR) packet from SSRC_n. If no SR has been received yet, the field is set to zero.

delay since last SR (DLSR): 32 bits ๐Ÿ•’ This is the delay, in units of 1/65536 seconds, between receiving the last SR packet from SSRC_n and sending this reception report block. If no SR packet has come in from SSRC_n yet, the DLSR field is set to zero.

Now for the fun part, the math ๐Ÿงฎโœจ Let SSRC_r be the receiver issuing this receiver report. Source SSRC_n can work out the round propagation delay to SSRC_r by noting the time A when it receives this reception report block. It calculates the total round-trip time as A-LSR using the LSR field, then subtracts the DLSR field, which leaves the round-trip propagation delay as (A- LSR - DLSR). It's illustrated in Fig. 2 ๐Ÿฆ‹

And this can be used as an approximate measure of distance for clustering receivers ๐Ÿ—บ๏ธ Just keep in mind that some links have very asymmetric delays, so it's not perfect, bestie ๐Ÿ’œ

6.3.2 RR: Receiver report RTCP packet

okay bestie, the receiver report is where the numbers get juicy ๐Ÿฆ‹ Figure 2 is a worked example for round-trip time computation. The figure subtracts DLSR and LSR from A, and that leaves a delay of 6.125 s ๐Ÿงฎ

   [10 Nov 1995 11:33:25.125]           [10 Nov 1995 11:33:36.5]
   n                 SR(n)              A=b710:8000 (46864.500 s)
   ---------------------------------------------------------------->
                      v                 ^
   ntp_sec =0xb44db705 v               ^ dlsr=0x0005.4000 (    5.250s)
   ntp_frac=0x20000000  v             ^  lsr =0xb705:2000 (46853.125s)
     (3024992016.125 s)  v           ^
   r                      v         ^ RR(n)
   ---------------------------------------------------------------->
                          |<-DLSR->|
                           (5.250 s)

   A     0xb710:8000 (46864.500 s)
   DLSR -0x0005:4000 (    5.250 s)
   LSR  -0xb705:2000 (46853.125 s)
   -------------------------------
   delay 0x   6:2000 (    6.125 s)

           Figure 2: Example for round-trip time computation

Now the RR packet itself ๐Ÿ’– Here's the layout:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|    RC   |   PT=RR=201   |             length            | header
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                     SSRC of packet sender                     |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|                 SSRC_1 (SSRC of first source)                 | report
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
| fraction lost |       cumulative number of packets lost       |   1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           extended highest sequence number received           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      interarrival jitter                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                         last SR (LSR)                         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                   delay since last SR (DLSR)                  |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|                 SSRC_2 (SSRC of second source)                | report
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
:                               ...                             :   2
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|                  profile-specific extensions                  |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

The RR packet is basically the SR packet's twin ๐Ÿ‘ฏ It has the same layout, the same fields, and the same meanings, with two differences. The packet type field holds the constant 201 instead, and the five words of sender information are left out. Those five words are the NTP and RTP timestamps plus the sender's packet and octet counts. Everything else means exactly what it means in SR โœจ

When there's no data transmission or reception to report, an empty RR packet (RC = 0) goes at the head of a compound RTCP packet ๐ŸŽ€

6.3.3 Extending the sender and receiver reports

A profile should define profile- or application-specific extensions to the sender report and receiver if there is additional information that should be reported regularly about the sender or receivers ๐Ÿ“ฃ This method should be used in preference to defining another RTCP packet type, because it requires less overhead. Here's why it's giving efficiency ๐Ÿ’…

  • fewer octets in the packet (no RTCP header or SSRC field);
  • simpler and faster parsing, because applications running under that profile would be programmed to always expect the extension fields in the directly accessible location after the reception reports.

If additional sender information is required, it should be included first in the extension for sender reports, but would not be present in receiver reports ๐ŸŒธ If information about receivers is to be included, that data may be structured as an array of blocks parallel to the existing array of reception report blocks. That means the number of blocks would be indicated by the RC field.

6.3.4 Analyzing sender and receiver reports

Reception quality feedback is expected to be useful not just for the sender but also for other receivers and third-party monitors ๐Ÿ‘€ The sender may modify its transmissions based on the feedback. Receivers can determine whether problems are local, regional or global. Network managers may use profile-independent monitors that receive only the RTCP packets and not the corresponding RTP data packets, so they can evaluate how their networks are doing for multicast distribution ๐Ÿฆ‹

Cumulative counts are used in both the sender information and receiver report blocks, so differences can be calculated between any two reports. That means you can measure over both short and long time periods, and you get resilience against the loss of a report ๐Ÿซถ The difference between the last two reports received can be used to estimate the recent quality of the distribution. The NTP timestamp is included so that rates can be calculated from these differences over the interval between two reports. Since that timestamp is independent of the clock rate for the data encoding, it is possible to implement encoding- and profile-independent quality monitors ๐Ÿงš

Here's an example calculation, the packet loss rate over the interval between two reception reports. The difference in the cumulative number of packets lost gives the number lost during that interval. The difference in the extended last sequence numbers received gives the number of packets expected during the interval. The ratio of these two is the packet loss fraction over the interval. This ratio should equal the fraction lost field if the two reports are consecutive, but otherwise not. The loss rate per second can be obtained by dividing the loss fraction by the difference in NTP timestamps, expressed in seconds. The number of packets received is the number of packets expected minus the number lost. The number of packets expected may also be used to judge the statistical validity of any loss estimates. For example, 1 out of 5 packets lost has a lower significance than 200 out of 1000 ๐Ÿ“Š

From the sender information, a third-party monitor can calculate the average payload data rate and the average packet rate over an interval without receiving the data. Taking the ratio of the two gives the average payload size. If it can be assumed that packet loss is independent of packet size, then the number of packets received by a particular receiver times the average payload size (or the corresponding packet size) gives the apparent throughput available to that receiver ๐Ÿ’ธ

In addition to the cumulative counts, which allow long-term packet loss measurements using differences between reports, the fraction lost field provides a short-term measurement from a single report. This becomes more important as the size of a session scales up enough that reception state information might not be kept for all receivers, or as the interval between reports becomes long enough that only one report might have been received from a particular receiver ๐Ÿ™ˆ

The interarrival jitter field provides a second short-term measure of network congestion. Packet loss tracks persistent congestion while the jitter measure tracks transient congestion. The jitter measure may indicate congestion before it leads to packet loss ๐Ÿ”ฅ Since the interarrival jitter field is only a snapshot of the jitter at the time of a report, it may be necessary to analyze a number of reports from one receiver over time, or from multiple receivers, e.g., within a single network.


6.4 SDES: Source description RTCP packet

Next up is SDES, the source description packet ๐Ÿ“ Here's the layout:

 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|    SC   |  PT=SDES=202  |             length            | header
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|                          SSRC/CSRC_1                          | chunk
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+   1
|                           SDES items                          |
|                              ...                              |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|                          SSRC/CSRC_2                          | chunk
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+   2
|                           SDES items                          |
|                              ...                              |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+

The SDES packet is a three-level structure ๐Ÿงฑ It's made of a header and zero or more chunks. Each chunk is made of items that describe the source identified in that chunk. The items are described individually in subsequent sections ๐Ÿ’–

version (V), padding (P), length: As described for the SR packet (see Section 6.3.1).

packet type (PT): 8 bits Contains the constant 202 to identify this as an RTCP SDES packet.

source count (SC): 5 bits The number of SSRC/CSRC chunks contained in this SDES packet. A value of zero is valid but useless ๐Ÿ’€

Each chunk consists of an SSRC/CSRC identifier followed by a list of zero or more items, which carry information about the SSRC/CSRC. Each chunk starts on a 32-bit boundary โœจ Each item consists of an 8-bit type field, an 8-bit octet count describing the length of the text (thus, not including this two-octet header), and the text itself. Note that the text can be no longer than 255 octets, but this is consistent with the need to limit RTCP bandwidth consumption ๐ŸŽ€

The text is encoded according to the UTF-2 encoding specified in Annex F of ISO standard 10646 [12,13]. This encoding is also known as UTF-8 or UTF-FSS ๐ŸŒˆ It is described in "File System Safe UCS Transformation Format (FSS_UTF)", X/Open Preliminary Specification, Document Number P316 and Unicode Technical Report #4. US-ASCII is a subset of this encoding and requires no additional encoding. The presence of multi-octet encodings is indicated by setting the most significant bit of a character to a value of one.

Items are contiguous, which means items are not individually padded to a 32-bit boundary ๐Ÿงฉ Text is not null terminated, because some multi-octet encodings include null octets. The list of items in each chunk is terminated by one or more null octets. The first of those null octets is interpreted as an item type of zero, which denotes the end of the list, and the remainder are used as needed to pad until the next 32-bit boundary. A chunk with zero items (four null octets) is valid but useless ๐Ÿ™ƒ

End systems send one SDES packet containing their own source identifier, which is the same as the SSRC in the fixed RTP header ๐Ÿซถ A mixer sends one SDES packet containing a chunk for each contributing source from which it is receiving SDES information. If there are more than 31 such sources, it sends multiple complete SDES packets in the format above instead (see Section 7) ๐Ÿ‘‘

The SDES items currently defined are described in the next sections. Only the CNAME item is mandatory ๐Ÿ’… Some items shown here may be useful only for particular profiles, but the item types are all assigned from one common space to promote shared use and to simplify profile-independent applications. Additional items may be defined in a profile by registering the type numbers with IANA ๐Ÿฆ‹

6.4.1 CNAME: Canonical end-point identifier SDES item ๐Ÿ’–

    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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |    CNAME=1    |     length    | user and domain name         ...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Okay so the CNAME is the bestie who never changes ๐Ÿซถ. The SSRC is randomly picked and can switch up if a conflict shows up or a program restarts, so the CNAME is the one that stays steady. The CNAME item is required to provide the binding from the SSRC identifier to an identifier for the source that remains constant. It's giving stability ๐ŸŽ€

The CNAME has a few main vibes:

  • Because the randomly allocated SSRC identifier may change if a conflict is discovered or if a program is restarted, the CNAME item is required to provide the binding from the SSRC identifier to an identifier for the source that remains constant.
  • Like the SSRC identifier, the CNAME identifier should also be unique among all participants within one RTP session. ๐Ÿ”ฅ
  • To provide a binding across multiple media tools used by one participant in a set of related RTP sessions, the CNAME should be fixed for that participant. ๐Ÿงš
  • To facilitate third-party monitoring, the CNAME should be suitable for either a program or a person to locate the source. ๐Ÿ‘‘

Therefore, the CNAME should be derived algorithmically and not entered manually, when possible. To meet these requirements, the following format should be used unless a profile specifies an alternate syntax or semantics. The CNAME item should have the format "user@host", or "host" if a user name is not available as on single-user systems. ๐Ÿ’…

For both formats, "host" is either the fully qualified domain name of the host from which the real-time data originates, formatted according to the rules specified in RFC 1034 [14], RFC 1035 [15] and Section 2.1 of RFC 1123 [16]; or the standard ASCII representation of the host's numeric address on the interface used for the RTP communication. For example, the standard ASCII representation of an IP Version 4 address is "dotted decimal", also known as dotted quad. Other address types are expected to have ASCII representations that are mutually unique.

The fully qualified domain name is more convenient for a human observer and may avoid the need to send a NAME item in addition, but it may be difficult or impossible to obtain reliably in some operating environments. Applications that may be run in such environments should use the ASCII representation of the address instead. Not me being the one stuck with an unreliable hostname ๐Ÿ™ˆ

Examples are "doe@sleepy.megacorp.com" or "doe@192.0.2.89" for a multi-user system. On a system with no user name, examples would be "sleepy.megacorp.com" or "192.0.2.89". โœจ

The user name should be in a form that a program such as "finger" or "talk" could use, i.e., it typically is the login name rather than the personal name. The host name is not necessarily identical to the one in the participant's electronic mail address. ๐Ÿฆ‹

This syntax will not provide unique identifiers for each source if an application permits a user to generate multiple sources from one host. Such an application would have to rely on the SSRC to further identify the source, or the profile for that application would have to specify additional syntax for the CNAME identifier. Ngl this is the one edge case that's a little messy ๐Ÿ’€

If each application creates its CNAME independently, the resulting CNAMEs may not be identical as would be required to provide a binding across multiple media tools belonging to one participant in a set of related RTP sessions. If cross-media binding is required, it may be necessary for the CNAME of each tool to be externally configured with the same value by a coordination tool. ๐ŸŒธ

Application writers should be aware that private network address assignments such as the Net-10 assignment proposed in RFC 1597 [17] may create network addresses that are not globally unique. This would lead to non-unique CNAMEs if hosts with private addresses and no direct IP connectivity to the public Internet have their RTP packets forwarded to the public Internet through an RTP-level translator. (See also RFC 1627 [18].) To handle this case, applications may provide a means to configure a unique CNAME, but the burden is on the translator to translate CNAMEs from private addresses to public addresses if necessary to keep private addresses from being exposed. ๐Ÿ”’

6.4.2 NAME: User name SDES item ๐ŸŒˆ

    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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     NAME=2    |     length    | common name of source        ...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

This is the real name used to describe the source, e.g., "John Doe, Bit Recycler, Megacorp". It can be in any form the user wants ๐ŸŽ€ For things like conferencing, this kind of name is probably the most useful for showing in participant lists, so it might get sent more often than any item other than CNAME. Profiles may establish such priorities. The NAME value is expected to remain constant at least for the duration of a session. It should not be relied upon to be unique among all participants in the session. Not unique, so don't count on it being a unique ID, bestie ๐Ÿ™…โ€โ™€๏ธ


6.4.3 EMAIL: Electronic mail address SDES item ๐Ÿ’Œ

    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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |    EMAIL=3    |     length    | email address of source      ...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

The email address is formatted according to RFC 822 [19], for example, "John.Doe@megacorp.com". The EMAIL value is expected to remain constant for the duration of a session. Simple and clean, iconic ๐Ÿ˜Œ


6.4.4 PHONE: Phone number SDES item ๐Ÿ“ž

    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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |    PHONE=4    |     length    | phone number of source       ...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

The phone number should be formatted with the plus sign replacing the international access code. For example, "+1 908 555 1212" for a number in the United States. ๐Ÿ“ฑ


6.4.5 LOC: Geographic user location SDES item ๐Ÿ—บ๏ธ

    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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     LOC=5     |     length    | geographic location of site  ...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Depending on the application, different degrees of detail are appropriate for this item. For conference applications, a string like "Murray Hill, New Jersey" may be sufficient, while, for an active badge system, strings like "Room 2A244, AT&T BL MH" might be appropriate. The degree of detail is left to the implementation and/or user, but format and content may be prescribed by a profile. The LOC value is expected to remain constant for the duration of a session, except for mobile hosts. So the vibe changes depending on the app, but mobile hosts get a pass ๐Ÿš—๐Ÿ’จ


6.4.6 TOOL: Application or tool name SDES item ๐Ÿ› ๏ธ

    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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     TOOL=6    |     length    | name/version of source appl. ...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

A string giving the name and possibly version of the application generating the stream, e.g., "videotool 1.2". This information may be useful for debugging purposes and is similar to the Mailer or Mail-System-Version SMTP headers. The TOOL value is expected to remain constant for the duration of the session. It's basically the app's little ID badge, great for debugging ๐Ÿงธ


6.4.7 NOTE: Notice/status SDES item ๐Ÿ“

    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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     NOTE=7    |     length    | note about the source        ...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

The following semantics are suggested for this item, but these or other semantics may be explicitly defined by a profile. The NOTE item is intended for transient messages describing the current state of the source, e.g., "on the phone, can't talk". Or, during a seminar, this item might be used to convey the title of the talk. It should be used only to carry exceptional information and should not be included routinely by all participants because this would slow down the rate at which reception reports and CNAME are sent, thus impairing the performance of the protocol. In particular, it should not be included as an item in a user's configuration file nor automatically generated as in a quote-of-the-day. ๐Ÿ™…โ€โ™€๏ธ Save the NOTE for the big moments, not every single message.

Since the NOTE item may be important to display while it is active, the rate at which other non-CNAME items such as NAME are transmitted might be reduced so that the NOTE item can take that part of the RTCP bandwidth. When the transient message becomes inactive, the NOTE item should continue to be transmitted a few times at the same repetition rate but with a string of length zero to signal the receivers. However, receivers should also consider the NOTE item inactive if it is not received for a small multiple of the repetition rate, or perhaps 20-30 RTCP intervals. ๐Ÿ•ต๏ธโ€โ™€๏ธ So when a note goes quiet, it sends a few empty ones to say "I'm done," and receivers can also call it inactive if it's been missing for a while.


6.4.8 PRIV: Private extensions SDES item ๐Ÿ”ฎ

      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
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |     PRIV=8    |     length    | prefix length | prefix string...
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    ...              |                  value string                ...
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

This item is used to define experimental or application-specific SDES extensions. The item contains a prefix consisting of a length-string pair, followed by the value string filling the remainder of the item and carrying the desired information. The prefix length field is 8 bits long. The prefix string is a name chosen by the person defining the PRIV item to be unique with respect to other PRIV items this application might receive. The application creator might choose to use the application name plus an additional subtype identification if needed. Alternatively, it is recommended that others choose a name based on the entity they represent, then coordinate the use of the name within that entity. ๐Ÿฆ„

Note that the prefix consumes some space within the item's total length of 255 octets, so the prefix should be kept as short as possible. This facility and the constrained RTCP bandwidth should not be overloaded; it is not intended to satisfy all the control communication requirements of all applications. Keep it short and don't overload it, it's not built to run your whole life ๐Ÿ’…

SDES PRIV prefixes will not be registered by IANA. If some form of the PRIV item proves to be of general utility, it should instead be assigned a regular SDES item type registered with IANA so that no prefix is required. This simplifies use and increases transmission efficiency. โœจ Basically, if your PRIV thing becomes popular, it should graduate to its own official item type.

6.5. BYE: Goodbye RTCP packet ๐Ÿ‘‹

    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|    SC   |   PT=BYE=203  |             length            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                           SSRC/CSRC                           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   :                              ...                              :
   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
   |     length    |               reason for leaving             ... (opt)
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

okay bestie, the BYE packet is literally the "I'm out" message ๐Ÿ’… It tells everyone that one or more sources have stopped being active โœจ

  • V, P, length: these work exactly like the SR packet, so check out Section 6.3.1 for the deets ๐ŸŽ€
  • PT (8 bits): it holds the constant 203, which is how you know it's a BYE packet ๐Ÿฆ‹
  • SC (5 bits, source count): this is how many SSRC/CSRC identifiers are in the BYE packet. A count of zero is valid, but ngl it's kinda useless ๐Ÿ’€

Mixers get a little extra responsibility here ๐Ÿซถ If a BYE packet is received by a mixer, the mixer forwards it with the SSRC/CSRC identifier(s) unchanged. If a mixer shuts down, it SHOULD send a BYE packet listing all the contributing sources it handles, plus its own SSRC identifier ๐Ÿ”ฅ

The reason for leaving is totally optional, but it's so cute when it's there ๐ŸŒธ The BYE packet MAY include an 8-bit octet count followed by that many octets of text, like "camera malfunction" or "RTP loop detected" ๐Ÿ˜ญ The string uses the same encoding as described for SDES. If the string fills the packet right up to the next 32-bit boundary, it is not null terminated. If it doesn't, the BYE packet gets padded with null octets ๐Ÿ’œ


6.6. APP: Application-defined RTCP packet ๐Ÿงฉ

    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| subtype |   PT=APP=204  |             length            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                           SSRC/CSRC                           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                          name (ASCII)                         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                   application-dependent data                 ...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

APP packets are the experimental playground ๐Ÿงชโœจ They're meant for trying out brand new applications and features without needing to register a packet type value first. APP packets with unrecognized names SHOULD be ignored, so no drama there ๐Ÿ™ˆ

After testing, if wider use is actually justified, it is RECOMMENDED that each APP packet be redefined without the subtype and name fields and registered with the Internet Assigned Numbers Authority using an RTCP packet type ๐Ÿ‘‘

  • V, P, length: same as the SR packet (see Section 6.3.1) ๐ŸŽ€
  • subtype (5 bits): this can be used as a subtype so a whole set of APP packets can live under one unique name, or it can hold any application-dependent data ๐Ÿ“
  • PT (8 bits): it contains the constant 204 to identify this as an RTCP APP packet ๐Ÿฆ‹
  • name (4 octets): a name picked by whoever defines the set of APP packets, so it's unique compared to other APP packets the application might receive. The application creator might use the application name and then coordinate subtype values with anyone else who wants new packet types for the app. Alternatively, it is RECOMMENDED that others choose a name based on the entity they represent, then coordinate the use of that name within the entity. The name is read as four ASCII characters, and uppercase and lowercase are treated as totally distinct ๐Ÿ’…
  • application-dependent data (variable length): this MAY or MAY NOT show up in an APP packet. The application interprets it, not RTP itself. It MUST be a multiple of 32 bits long ๐ŸŒˆ

7. RTP Translators and Mixers ๐Ÿ”€

In addition to end systems, RTP supports the idea of "translators" and "mixers", which you could think of as "intermediate systems" at the RTP level ๐Ÿงš Yes, this adds some complexity, but the need for these functions has been clearly proven by experiments with multicast audio and video apps on the Internet. The example uses of translators and mixers given in Section 2.3 come from firewalls and low bandwidth connections, and both of those are likely to stick around ๐Ÿซถ

7.1. General Description ๐Ÿ—บ๏ธ

An RTP translator/mixer connects two or more transport-level "clouds" ๐Ÿ’ซ Usually each cloud is defined by a common network and transport protocol (for example, IP/UDP), a multicast address or a pair of unicast addresses, and a transport-level destination port. (Network-level protocol translators, like IP version 4 to IP version 6, may be present within a cloud invisibly to RTP.) One system MAY serve as a translator or mixer for a number of RTP sessions, but each one is treated as a logically separate entity ๐Ÿฆ‹

Okay, now the important rules ๐Ÿšจ To avoid creating a loop when a translator or mixer gets installed, the following rules MUST be observed:

  • Each of the clouds connected by translators and mixers in one RTP session either MUST be distinct from all the others in at least one of these parameters (protocol, address, port), or MUST be isolated at the network level from the others.
  • A derivative of the first rule is that there MUST NOT be multiple translators or mixers connected in parallel, unless by some arrangement they partition the set of sources to be forwarded ๐Ÿ’€

Also, all RTP end systems that can communicate through one or more RTP translators or mixers share the same SSRC space. That means the SSRC identifiers MUST be unique among all of these end systems. Section 8.2 explains the collision resolution algorithm that keeps SSRC identifiers unique and detects loops ๐Ÿ”

There can be many varieties of translators and mixers, designed for different purposes and apps. Some examples are adding or removing encryption, changing the encoding of the data or the underlying protocols, or replicating between a multicast address and one or more unicast addresses โœจ The big difference between them is this: a translator passes through the data streams from different sources separately, whereas a mixer combines them into one new stream ๐Ÿ‘‘

Translator: this forwards RTP packets with their SSRC identifier intact ๐ŸŽ€ That means receivers can still tell individual sources apart, even though everything passes through the same translator and carries the translator's network source address. Some translators pass the data through untouched, but others MAY change the encoding of the data, and so the RTP data payload type and timestamp might change too. If multiple data packets get re-encoded into one (or the other way around), a translator MUST assign new sequence numbers to the outgoing packets. Losses in the incoming packet stream may cause matching gaps in the outgoing sequence numbers ๐Ÿซ  Receivers cannot detect that a translator is there unless they know, by some other means, which payload type or transport address the original source used ๐Ÿ™ˆ

Mixer: this receives streams of RTP data packets from one or more sources, possibly changes the data format, combines the streams somehow, and then forwards the combined stream ๐ŸŒธ Since the timing among multiple input sources won't generally be synchronized, the mixer makes timing adjustments among the streams and generates its own timing for the combined stream. That makes it the synchronization source. So all data packets a mixer forwards get marked with the mixer's own SSRC identifier. To keep track of the original sources that contributed to the mixed packet, the mixer SHOULD insert their SSRC identifiers into the CSRC identifier list, following the fixed RTP header of the packet. A mixer that is also itself a contributing source for some packet SHOULD explicitly include its own SSRC identifier in the CSRC list for that packet ๐Ÿ’–

For some applications, it MAY be acceptable for a mixer not to identify sources in the CSRC list. However, this brings the danger that loops involving those sources could not be detected ๐Ÿ˜ญ

Now the tradeoff, bestie ๐Ÿ’… The advantage of a mixer over a translator for things like audio is that the output bandwidth is limited to that of one source, even when multiple sources are active on the input side. That may be important for low-bandwidth links ๐Ÿ“ The disadvantage is that receivers on the output side don't get any control over which sources are passed through or muted, unless some mechanism exists for remote control of the mixer. The regeneration of synchronization information by mixers also means receivers can't do inter-media synchronization of the original streams. A multi-media mixer could do it โœจ

         [E1]                                    [E6]
          |                                       |
    E1:17 |                                 E6:15 |
          |                                       |   E6:15
          V  M1:48 (1,17)         M1:48 (1,17)    V   M1:48 (1,17)
         (M1)-------------><T1>-----------------><T2>-------------->[E7]
          ^                 ^     E4:47           ^   E4:47
     E2:1 |           E4:47 |                     |   M3:89 (64,45)
          |                 |                     |
         [E2]              [E4]     M3:89 (64,45) |
                                                  |        legend:
   [E3] --------->(M2)----------->(M3)------------|        [End system]
          E3:64        M2:12 (64)  ^                       (Mixer)
                                   | E5:45                 <Translator>
                                   |
                                  [E5]          source: SSRC (CSRCs)
                                                ------------------->

Figure 3: Sample RTP network with end systems, mixers and translators ๐Ÿงฉ

A bunch of mixers and translators are shown in Figure 3 so you can see how they affect SSRC and CSRC identifiers ๐Ÿฆ‹ In the figure, end systems are drawn as rectangles (named E), translators as triangles (named T), and mixers as ovals (named M). The notation "M1: 48(1,17)" describes a packet originating from mixer M1, identified with M1's (random) SSRC value of 48, plus two CSRC identifiers, 1 and 17, copied from the SSRC identifiers of packets from E1 and E2 ๐ŸŒˆ

7.2 RTCP Processing in Translators โœจ

okay so besides forwarding the data packets (maybe tweaked, maybe not ๐Ÿ’…), translators and mixers must also process RTCP packets ๐ŸŽ€. A lot of the time they'll have to take apart the compound RTCP packets that came in from end systems, gather up the SDES info, and tweak the SR or RR packets. Sending this stuff back out can get triggered by a packet showing up, or by the translator's or mixer's own RTCP interval timer โฐ.

A translator that doesn't modify the data packets, like one that just copies stuff between a multicast address and a unicast address ๐Ÿฆ‹, can simply forward RTCP packets unmodified too. But a translator that transforms the payload somehow must make matching changes in the SR and RR info, so it still reflects the characteristics of the data and the reception quality ๐Ÿ“Š. These translators must not simply forward RTCP packets, bestie ๐Ÿ™…โ€โ™€๏ธ. In general, a translator should not combine SR and RR packets from different sources into one packet, because that would make the propagation delay measurements based on the LSR and DLSR fields less accurate ๐Ÿ“‰.

  • SR sender information: A translator doesn't make up its own sender info ๐Ÿ™…โ€โ™€๏ธ. It just forwards the SR packets it gets from one cloud to the others. The SSRC stays intact, but the sender info has to be changed if the translation needs it. If the translator changes the data encoding, it must change the sender's byte count field. If it also combines several data packets into one output packet, it must change the sender's packet count field. And if it changes the timestamp frequency, it must change the RTP timestamp field in the SR packet ๐Ÿ•ฐ๏ธ.
  • SR/RR reception report blocks: A translator forwards reception reports from one cloud to the others. Note that these flow in the opposite direction to the data ๐Ÿ”„. The SSRC stays intact. If a translator combines several data packets into one output packet, and therefore changes the sequence numbers, it must make the inverse manipulation for the packet loss fields and the extended last sequence number field. This may be complex ๐Ÿ˜ตโ€๐Ÿ’ซ. In the extreme case, there may be no meaningful way to translate the reception reports, so the translator may pass on no reception report at all, or a synthetic report based on its own reception. The general rule is to do what makes sense for a particular translation ๐Ÿง .
  • SDES: Translators typically forward the SDES info they get from one cloud to the others without changing it, but they may, for example, filter out non-CNAME SDES info if bandwidth is limited ๐Ÿ“ถ. The CNAMEs must be forwarded so SSRC identifier collision detection can work ๐Ÿ”. A translator that generates its own RR packets must send SDES CNAME info about itself to the same clouds that it sends those RR packets to ๐Ÿ’Œ.
  • BYE: Translators forward BYE packets unchanged ๐Ÿ‘‹. Translators with their own SSRC should generate BYE packets with that SSRC identifier if they're about to cease forwarding packets ๐Ÿซก.
  • APP: Translators forward APP packets unchanged ๐Ÿ“ฆ.

A translator doesn't need an SSRC identifier of its own, but it may choose to allocate one so it can send reports about what it has received ๐Ÿ“ฃ. These would be sent to all the connected clouds, each one corresponding to the translation of the data stream as sent to that cloud, since reception reports are normally multicast to all participants ๐Ÿซถ.


7.3 RTCP Processing in Mixers

since a mixer generates a brand-new data stream of its own ๐Ÿ†•, it doesn't pass through SR or RR packets at all. Instead, it generates new info for both sides ๐Ÿ’œ.

  • SR sender information: A mixer doesn't pass through sender info from the sources it mixes, because the characteristics of the source streams get lost in the mix ๐ŸŒ€. As a synchronization source, the mixer generates its own SR packets with sender info about the mixed data stream, and sends them in the same direction as the mixed stream โžก๏ธ.
  • SR/RR reception report blocks: A mixer generates its own reception reports for sources in each cloud and sends them out only to that same cloud ๐ŸŽฏ. It doesn't send these reception reports to the other clouds, and it doesn't forward reception reports from one cloud to the others, because the sources wouldn't be SSRCs there (only CSRCs) ๐Ÿ™…โ€โ™€๏ธ.
  • SDES: Mixers typically forward the SDES info they receive from one cloud to the others without change, but they may, for example, filter out non-CNAME SDES info if bandwidth is limited ๐Ÿ“ถ. The CNAMEs must be forwarded so SSRC identifier collision detection can work ๐Ÿ”. (An identifier in a CSRC list generated by a mixer might collide with an SSRC identifier generated by an end system ๐Ÿ˜ฌ.) A mixer must send SDES CNAME info about itself to the same clouds that it sends SR or RR packets to ๐Ÿ’Œ.

Since mixers don't forward SR or RR packets, they'll typically be pulling SDES packets out of a compound RTCP packet. To keep overhead down, chunks from the SDES packets may be aggregated into a single SDES packet, which is then stacked on an SR or RR packet originating from the mixer ๐Ÿฅž. The RTCP packet rate may be different on each side of the mixer ๐Ÿ“Š.

A mixer that doesn't insert CSRC identifiers may also skip forwarding SDES CNAMEs ๐Ÿ™ˆ. In this case, the SSRC identifier spaces in the two clouds are independent. As mentioned earlier, this mode of operation creates a danger that loops can't be detected.

this mode of operation creates a danger that loops can't be detected ๐Ÿ’€
  • BYE: Mixers need to forward BYE packets. They should generate BYE packets with their own SSRC identifiers if they're about to cease forwarding packets ๐Ÿ‘‹.
  • APP: The treatment of APP packets by mixers is application-specific ๐Ÿคทโ€โ™€๏ธ.

7.4 Cascaded Mixers

An RTP session may involve a whole collection of mixers and translators, as shown in Figure 3 ๐Ÿ“ธ. If two mixers are cascaded, such as M2 and M3 in the figure, packets received by a mixer may already have been mixed and may include a CSRC list with multiple identifiers ๐ŸŒˆ. The second mixer should build the CSRC list for the outgoing packet using the CSRC identifiers from already-mixed input packets and the SSRC identifiers from unmixed input packets. This is shown in the output arc from mixer M3 labeled M3:89(64,45) in the figure ๐Ÿงฉ. As in the case of mixers that are not cascaded, if the resulting CSRC list has more than 15 identifiers, the remainder cannot be included ๐Ÿšซ.


8. SSRC Identifier Allocation and Use โœจ

The SSRC identifier carried in the RTP header and in various fields of RTCP packets is a random 32-bit number that is required to be globally unique within an RTP session ๐Ÿ†”. It is crucial that the number be chosen with care, so that participants on the same network or starting at the same time are not likely to choose the same number ๐ŸŽฒ.

It is not sufficient to use the local network address (such as an IPv4 address) for the identifier, because the address may not be unique ๐Ÿ™ƒ. Since RTP translators and mixers enable interoperation among multiple networks with different address spaces, the allocation patterns for addresses within two spaces might result in a much higher rate of collision than would occur with random allocation ๐Ÿ“ˆ.

Multiple sources running on one host would also conflict ๐Ÿ’ป.

It is also not sufficient to obtain an SSRC identifier simply by calling random() without carefully initializing the state. An example of how to generate a random identifier is presented in Appendix A.6 ๐Ÿ“–.


8.1 Probability of Collision

Since the identifiers are chosen randomly, it's possible that two or more sources will choose the same number ๐ŸŽฐ. Collision occurs with the highest probability when all sources are started simultaneously, for example when triggered automatically by some session management event ๐Ÿšฆ. If N is the number of sources and L the length of the identifier (here, 32 bits), the probability that two sources independently pick the same value can be approximated for large N [20] as 1 - exp(-N**2 / 2**(L+1)). For N=1000, the probability is roughly 10**-4 ๐Ÿงฎ.

The typical collision probability is much lower than the worst-case above. When one new source joins an RTP session in which all the other sources already have unique identifiers, the probability of collision is just the fraction of numbers used out of the space. Again, if N is the number of sources and L the length of the identifier, the probability of collision is N / 2**L. For N=1000, the probability is roughly 2*10**-7 ๐ŸŽฏ.

The probability of collision is further reduced by the opportunity for a new source to receive packets from other participants before sending its first packet (either data or control) ๐Ÿ“จ. If the new source keeps track of the other participants (by SSRC identifier), then before transmitting its first packet the new source can verify that its identifier does not conflict with any that have been received, or else choose again ๐Ÿ”„โœจ.

8.2. Collision Resolution and Loop Detection ๐Ÿ’…

Okay so SSRC collisions are super unlikely ๐Ÿฅบ, but every RTP implementation MUST be ready to catch them and fix them ๐Ÿ”ง. If a source finds out at any point that someone else is using the same SSRC as its own, it MUST send an RTCP BYE packet for the old identifier and pick another random one. Like, two girls in the same group chat cannot have the same name ๐Ÿ™ˆ. If a receiver notices two other sources colliding, it MAY keep the packets from one and toss the packets from the other, but only when it can tell them apart by different source transport addresses or CNAMEs. Both sources are expected to sort it out so the drama doesn't last forever ๐Ÿ’€.

Because the random identifiers are kept globally unique for each RTP session, they can also be used to detect loops that may be introduced by mixers or translators โœจ. A loop causes duplication of data and control information, either unmodified or possibly mixed. Here are some examples ๐Ÿฆ‹:

  • A translator may incorrectly forward a packet to the same multicast group it received the packet from, either directly or through a chain of translators. In that case, the same packet shows up several times, coming from different network sources ๐ŸŒ€.
  • Two translators set up incorrectly in parallel, i.e., with the same multicast groups on both sides, would both forward packets from one multicast group to the other. Unidirectional translators would produce two copies, and bidirectional translators would form a loop ๐Ÿ”.
  • A mixer can close a loop by sending to the same transport destination it receives packets from, either directly or through another mixer or translator. In this case, a source might show up both as an SSRC on a data packet and as a CSRC in a mixed data packet ๐Ÿ‘€.

A source may discover that its own packets are being looped, or that packets from another source are being looped (a third-party loop) ๐Ÿ™ƒ.

Both loops and collisions in the random selection of a source identifier result in packets arriving with the same SSRC identifier but a different source transport address. That address may belong to the end system that originated the packet or to an intermediate system ๐Ÿ›ฐ๏ธ. So if a source changes its source transport address, it MUST also choose a new SSRC identifier, so it doesn't get mistaken for a looped source ๐Ÿ™…โ€โ™€๏ธ. Loops or collisions happening on the far side of a translator or mixer can't be detected using the source transport address if all copies of the packets go through the translator or mixer. Collisions can still be caught, though, when chunks from two RTCP SDES packets contain the same SSRC identifier but different CNAMEs ๐Ÿ•ต๏ธโ€โ™€๏ธ.

To detect and resolve these conflicts, an RTP implementation MUST include an algorithm similar to the one described below ๐Ÿง . It ignores packets from a new source or loop that collides with an established source. It resolves collisions with the participant's own SSRC identifier by sending an RTCP BYE for the old identifier and choosing a new one. However, when the collision was caused by a loop of the participant's own packets, the algorithm will choose a new identifier only once and then ignore packets from the looping source transport address. This is REQUIRED to avoid a flood of BYE packets ๐Ÿ›‘.

This algorithm depends on the source transport address being the same for both RTP and RTCP packets from a source. The algorithm would need modifications to support applications that don't meet this constraint ๐ŸŽ€.

This algorithm requires keeping a table indexed by source identifiers. Each entry contains the source transport address the identifier was (first) received from, along with other state for that source ๐Ÿ“’. Every SSRC or CSRC identifier received in a data or control packet gets looked up in this table so that its data or control information can be processed. For control packets, each element with its own SSRC, such as an SDES chunk, needs a separate lookup. (The SSRC in a reception report block is an exception.) If the SSRC or CSRC isn't found, a new entry is created. These table entries are removed when an RTCP BYE packet arrives with the corresponding SSRC, or after no packets have arrived for a relatively long time (see Section 6.2.1) โณ.

To track loops of the participant's own data packets, you also need a separate list of source transport addresses (not identifiers) that have been found to be conflicting. Note that this should be a short list, usually empty ๐Ÿค. Each element in this list stores the source address plus the time when the most recent conflicting packet was received. An element MAY be removed from the list when no conflicting packet has arrived from that source for a time on the order of 10 RTCP report intervals (see Section 6.2) ๐Ÿ—‘๏ธ.

For the algorithm as shown, the participant's own source identifier and state are assumed to be included in the source identifier table. The algorithm could be restructured to first make a separate comparison against the participant's own source identifier ๐Ÿชž.

Here's the algorithm itself, bestie ๐Ÿ“œ:

       IF the SSRC or CSRC identifier is not found in the source
          identifier table:
       THEN create a new entry storing the source transport address
            and the SSRC or CSRC along with other state.
            CONTINUE with normal processing.

       (identifier is found in the table)

       IF the source transport address from the packet matches
          the one saved in the table entry for this identifier:
       THEN CONTINUE with normal processing.

       (an identifier collision or a loop is indicated)

       IF the source identifier is not the participant's own:
       THEN IF the source identifier is from an RTCP SDES chunk
               containing a CNAME item that differs from the CNAME
               in the table entry:
            THEN (optionally) count a third-party collision.
            ELSE (optionally) count a third-party loop.
            ABORT processing of data packet or control element.

       (a collision or loop of the participant's own data)

       IF the source transport address is found in the list of
         conflicting addresses:
       THEN IF the source identifier is not from an RTCP SDES chunk
               containing a CNAME item OR if that CNAME is the
               participant's own:

            THEN (optionally) count occurrence of own traffic looped.
                 mark current time in conflicting address list entry.
                 ABORT processing of data packet or control element.
       log occurrence of a collision.
       create a new entry in the conflicting address list and
       mark current time.
       send an RTCP BYE packet with the old SSRC identifier.
       choose a new identifier.
       create a new entry in the source identifier table with the
         old SSRC plus the source transport address from the packet
         being processed.
       CONTINUE with normal processing.

In this algorithm, packets from a newly conflicting source address get ignored, and packets from the original source get kept ๐Ÿ™Œ. (If the original source was reached through a mixer and the same source is later received directly, the receiver may be well advised to switch, unless other sources in the mix would be lost ๐Ÿค”.) If no packets arrive from the original source for an extended period, its table entry times out and the new source is free to take over. This might happen if the original source detects the collision and moves to a new source identifier. Usually, though, an RTCP BYE packet comes in from the original source to delete the state, so nobody has to wait around for a timeout ๐Ÿ‘‹.

When a new SSRC identifier is chosen because of a collision, the candidate identifier SHOULD first be looked up in the source identifier table to see if another source is already using it. If so, another candidate SHOULD be generated and the process repeated ๐Ÿ”„.

A loop of data packets sent to a multicast destination can cause severe network flooding ๐ŸŒŠ. All mixers and translators are REQUIRED to implement a loop detection algorithm like the one here so they can break loops ๐Ÿ› ๏ธ. That should limit the excess traffic to no more than one duplicate copy of the original traffic, which may let the session keep going so the cause of the loop can be found and fixed ๐Ÿ”. However, in extreme cases where a mixer or translator doesn't properly break the loop and heavy traffic results, it may be necessary for end systems to stop transmitting data or control packets entirely ๐Ÿšจ. Whether to do that may depend on the application. An error condition SHOULD be indicated as appropriate ๐Ÿ“ฃ. Transmission might be tried again periodically after a long, random time (on the order of minutes) โฐ.


9. Security ๐Ÿ”

Lower layer protocols may eventually provide all the security services that might be wanted for RTP applications, including authentication, integrity, and confidentiality ๐Ÿ›ก๏ธ. These services have recently been specified for IP. Since the need for a confidentiality service is well established in the initial audio and video applications that are expected to use RTP, a confidentiality service is defined in the next section for use with RTP and RTCP until lower layer services are available. The overhead this service adds to the protocol is low, so the penalty will be minimal if the service gets obsoleted by lower layer services in the future ๐Ÿซถ.

Alternatively, other services, other implementations of services, and other algorithms may be defined for RTP in the future if warranted ๐Ÿ”ฎ. The selection presented here is meant to simplify implementation of interoperable, secure applications and to guide implementors ๐Ÿง‘โ€๐Ÿ’ป. No claim is made that the methods presented here are appropriate for a particular security need, so please don't assume they are ๐Ÿ™…โ€โ™€๏ธ. A profile SHOULD specify which services and algorithms applications offer, and it may give guidance on their appropriate use ๐Ÿ“‹.

Key distribution and certificates are outside the scope of this document. Whatever you do, don't skip working out how keys get to people. That part is not handled here ๐Ÿ—๏ธ๐Ÿ’€.

9.1 Confidentiality ๐Ÿ”

okay so confidentiality just means only the intended receiver(s) can decode the packets ๐Ÿ’– for everyone else, the packet contains no useful information, no cap. The way we get it is encryption โœจ

When you want encryption on RTP or RTCP, all the octets that will get packed into one lower-layer packet are encrypted as a single unit ๐ŸŽ€. For RTCP, a 32-bit random number gets stuck on the front of that unit before encryption, to deter known plaintext attacks ๐Ÿ™ˆ. For RTP, no prefix is needed, bc the sequence number and timestamp fields are already initialized with random offsets ๐Ÿ’….

For RTCP, it's allowed to split a compound RTCP packet into two lower-layer packets: one gets encrypted, and one gets sent in the clear ๐Ÿฆ‹. For example, the SDES info might be encrypted while the reception reports go out unencrypted, so third-party monitors who don't have the encryption key can still see them ๐Ÿ‘€. In this example, shown in Fig. 4 below, the SDES information must be appended to an RR packet with no reports (and the encrypted) to satisfy the requirement that all compound RTCP packets begin with an SR or RR packet.

             UDP packet                        UDP packet
   -------------------------------------  -------------------------
   [32-bit ][       ][     #           ]  [    # sender # receiver]
   [random ][  RR   ][SDES # CNAME, ...]  [ SR # report # report  ]
   [integer][(empty)][     #           ]  [    #        #         ]
   -------------------------------------  -------------------------
                 encrypted                       not encrypted

   #: SSRC
           Figure 4: Encrypted and non-encrypted RTCP packets

The receiver confirms that encryption is present and that the right key is being used by running header or payload validity checks ๐Ÿ”‘. Examples of those checks for RTP and RTCP headers are in Appendices A.1 and A.2 ๐ŸŒธ.

The default encryption algorithm is the Data Encryption Standard (DES) algorithm in cipher block chaining (CBC) mode, as described in Section 1.1 of RFC 1423 [21] ๐Ÿงš. The one twist is that padding to a multiple of 8 octets is indicated the way it's described for the P bit in Section 5.1. The initialization vector is zero, because random values are already supplied either in the RTP header or by the random prefix for compound RTCP packets. If you want the deep dive on CBC initialization vectors, check out [22] ๐Ÿ“š.

Implementations that support encryption should always support DES in CBC mode as the default to maximize interoperability ๐Ÿซถ. This method got chosen because it's been shown to be easy and practical to use in experimental audio and video tools running on the Internet ๐Ÿ”ฅ. Other encryption algorithms may be specified dynamically for a session by non-RTP means โœจ.

As an alternative to encryption at the RTP level, profiles can define additional payload types for encrypted encodings ๐Ÿฆ„. Those encodings have to specify how padding and other aspects of the encryption get handled. This approach lets you encrypt only the data and leave the headers in the clear, which is useful for applications that want that setup ๐Ÿ’œ. It may be especially handy for hardware devices that handle both decryption and decoding ๐Ÿค–.

9.2 Authentication and Message Integrity ๐Ÿชช

Authentication and message integrity are not defined in the current spec of RTP, because these services wouldn't be directly feasible without a key management infrastructure ๐Ÿ™ƒ. The expectation is that authentication and integrity services will be provided by lower-layer protocols in the future ๐Ÿ”ฎ.

10. RTP over Network and Transport Protocols ๐ŸŒˆ

This section is all about the issues specific to carrying RTP packets inside particular network and transport protocols ๐Ÿšš. The rules below apply unless a protocol-specific definition outside this spec says otherwise ๐Ÿ“œ.

RTP leans on the underlying protocol(s) to demultiplex the RTP data and RTCP control streams ๐Ÿงฉ. For UDP and similar protocols, RTP uses an even port number, and the matching RTCP stream uses the next higher (odd) port number ๐Ÿ’–. If an application hands you an odd number to use as the RTP port, it should swap in the next lower (even) number instead ๐Ÿ™Œ.

RTP data packets have no length field or other delineation, so RTP relies on the underlying protocol(s) to tell it the length ๐Ÿ“. The maximum length of RTP packets is limited only by those underlying protocols ๐Ÿ’….

If RTP packets are going to ride on an underlying protocol that gives you a continuous octet stream instead of messages (packets), an encapsulation of the RTP packets must be defined to provide a framing mechanism ๐Ÿงต. Framing is also needed if the underlying protocol may contain padding, so the extent of the RTP payload can't be determined. The framing mechanism itself is not defined here ๐Ÿ™ˆ.

A profile may specify a framing method to be used even when RTP is carried in protocols that already do provide framing ๐ŸŽ. The reason is to allow carrying several RTP packets in one lower-layer protocol data unit, like a UDP packet. Carrying several RTP packets in one network or transport packet cuts down on header overhead and may simplify synchronization between different streams ๐Ÿ“.

11. Summary of Protocol Constants ๐Ÿ’œ

This section is the cheat sheet ๐Ÿ“‹. It lists the constants defined in this specification.

The RTP payload type (PT) constants are defined in profiles, not in this document ๐ŸŽ€. However, the octet of the RTP header that contains the marker bit(s) and payload type must avoid the reserved values 200 and 201 (decimal). That's how you tell RTP packets apart from the RTCP SR and RR packet types during the header validation procedure in Appendix A.1 ๐Ÿ•ต๏ธโ€โ™€๏ธ. For the standard definition of one marker bit and a 7-bit payload type field, as shown in this specification, that restriction means payload types 72 and 73 are reserved ๐Ÿซฃ.

11.1 RTCP packet types ๐Ÿ“ฆ

   abbrev.    name                   value
   SR         sender report            200
   RR         receiver report          201
   SDES       source description       202
   BYE        goodbye                  203
   APP        application-defined      204

These type values were picked from the range 200-204 for better header validity checking of RTCP packets, compared to RTP packets or other unrelated packets ๐Ÿ”. When the RTCP packet type field gets compared to the matching octet of the RTP header, this range lines up with the marker bit being 1 (which it usually isn't in data packets). It also lines up with the high bit of the standard payload type field being 1, since the static payload types are typically defined in the low half ๐Ÿง . The range was also picked to sit some distance numerically from 0 and 255, since all-zeros and all-ones are common data patterns ๐ŸŒธ.

Since all compound RTCP packets must begin with SR or RR, these codes were chosen as an even/odd pair. That lets the RTCP validity check test the maximum number of bits with mask and value ๐Ÿงฎ.

Other constants are assigned by IANA ๐Ÿ›๏ธ. Experimenters are encouraged to register the numbers they need for experiments, and then unregister the ones that prove to be unneeded ๐Ÿงช.

11.2 SDES types ๐Ÿท๏ธ

   abbrev.    name                              value
   END        end of SDES list                      0
   CNAME      canonical name                        1
   NAME       user name                             2
   EMAIL      user's electronic mail address        3
   PHONE      user's phone number                   4
   LOC        geographic user location              5
   TOOL       name of application or tool           6
   NOTE       notice about the source               7
   PRIV       private extensions                    8

Other constants are assigned by IANA ๐ŸŒท. Experimenters are encouraged to register the numbers they need for experiments, and then unregister the ones that prove to be unneeded ๐Ÿ’….

12. RTP Profiles and Payload Format Specifications โœจ

okay bestie, so a complete RTP spec for one specific app is gonna need one or more companion docs ๐Ÿ“š, and they come in two flavors: profiles and payload format specs ๐ŸŽ€

RTP gets used for a bunch of different apps with kinda different needs, and it stays flexible by offering multiple choices in the main protocol spec. Then you pick the right ones, or define extensions, for your environment and class of apps in a separate profile document ๐Ÿ’– An app usually runs under just one profile, so there's no explicit indication of which profile is in use ๐Ÿฆ‹ A profile for audio and video apps can be found in the companion Internet-Draft draft-ietf-avt-profile for

The second type is a payload format specification ๐Ÿ“, which defines how a particular kind of payload data (like H.261 encoded video) should be carried in RTP. These docs are usually titled "RTP Payload Format for XYZ Audio/Video Encoding" ๐ŸŒธ Payload formats can be useful under multiple profiles, so they can be defined independently of any particular profile. The profile docs are then responsible for assigning a default mapping of that format to a payload type value, if needed ๐Ÿซถ

Within this spec, the following items have been identified for possible definition within a profile. This list is not meant to be exhaustive, so don't treat it as the full menu ๐Ÿ’…

  • RTP data header: the octet in the RTP data header that holds the marker bit and payload type field may be redefined by a profile to suit different requirements, like with more or fewer marker bits (Section 5.3) ๐ŸŽ€
  • Payload types: assuming a payload type field is included, the profile will usually define a set of payload formats (e.g., media encodings) and a default static mapping of those formats to payload type values ๐Ÿฆ‹ Some of the payload formats may be defined by reference to separate payload format specifications. For each payload type defined, the profile must specify the RTP timestamp clock rate to be used (Section 5.1) โฐ
  • RTP data header additions: additional fields may be appended to the fixed RTP data header if some extra functionality is required across the profile's class of applications, independent of payload type (Section 5.3) โœจ
  • RTP data header extensions: the contents of the first 16 bits of the RTP data header extension structure must be defined if use of that mechanism is to be allowed under the profile for implementation-specific extensions (Section 5.3.1) ๐Ÿงฉ
  • RTCP packet types: new application-class-specific RTCP packet types may be defined and registered with IANA ๐Ÿ“ฎ
  • RTCP report interval: a profile should specify that the values suggested in Section 6.2 for the constants used in calculating the RTCP report interval will be used. Those constants are the RTCP fraction of session bandwidth, the minimum report interval, and the bandwidth split between senders and receivers. A profile may specify alternate values if they have been demonstrated to work in a scalable manner ๐Ÿ“Š
  • SR/RR extension: an extension section may be defined for the RTCP SR and RR packets if there's additional information that should be reported regularly about the sender or receivers (Section 6.3.3) ๐Ÿ“ฃ
  • SDES use: the profile may specify the relative priorities for RTCP SDES items to be transmitted, or excluded entirely (Section 6.2.2). It can also specify an alternate syntax or semantics for the CNAME item (Section 6.4.1), the format of the LOC item (Section 6.4.5), the semantics and use of the NOTE item (Section 6.4.7), or new SDES item types to be registered with IANA ๐Ÿท๏ธ
  • Security: a profile may specify which security services and algorithms should be offered by applications, and may provide guidance as to their appropriate use (Section 9). This is a big one, so pay attention ๐Ÿ”
  • String-to-key mapping: a profile may specify how a user-provided password or pass phrase is mapped into an encryption key ๐Ÿ—๏ธ
  • Underlying protocol: using a particular underlying network or transport layer protocol to carry RTP packets may be required ๐Ÿšš
  • Transport mapping: a mapping of RTP and RTCP to transport-level addresses (e.g., UDP ports) other than the standard mapping defined in Section 10 may be specified ๐Ÿ—บ๏ธ
  • Encapsulation: an encapsulation of RTP packets may be defined to allow multiple RTP data packets to be carried in one lower-layer packet, or to provide framing over underlying protocols that don't already do so (Section 10) ๐Ÿฑ

It's not expected that a new profile will be needed for every app. Within one app class, it's way better to extend an existing profile than to make a new one, since that keeps the apps able to interoperate, and each one will typically run under only one profile ๐Ÿซถ Simple extensions, like defining extra payload type values or RTCP packet types, can be done by registering them through the Internet Assigned Numbers Authority and publishing their descriptions in an addendum to the profile or in a payload format specification ๐Ÿ’œ


A. Algorithms ๐Ÿงฎ

We're gonna look at some examples of C code for parts of the RTP sender and receiver algorithms. There may be other implementation methods that are faster in particular operating environments or have other advantages. These implementation notes are for informational purposes only, and they're meant to clarify the RTP specification ๐Ÿ’…

The following definitions are used for all examples. For clarity and brevity, the structure definitions are only valid for 32-bit big-endian (most significant octet first) architectures. Bit fields are assumed to be packed tightly in big-endian bit order, with no additional padding. Modifications would be required to construct a portable implementation ๐ŸŽ€

/*
 * rtp.h  --  RTP header file (RFC XXXX)
 */
#include <sys/types.h>

/*
 * The type definitions below are valid for 32-bit architectures and
 * may have to be adjusted for 16- or 64-bit architectures.
 */
typedef unsigned char  u_int8;
typedef unsigned short u_int16;
typedef unsigned int   u_int32;
typedef          short int16;

/*
 * Current protocol version.
 */
#define RTP_VERSION    2

#define RTP_SEQ_MOD (1<<16)
#define RTP_MAX_SDES 255      /* maximum text length for SDES */

typedef enum {
    RTCP_SR   = 200,
    RTCP_RR   = 201,
    RTCP_SDES = 202,
    RTCP_BYE  = 203,
    RTCP_APP  = 204
} rtcp_type_t;

typedef enum {
    RTCP_SDES_END   = 0,
    RTCP_SDES_CNAME = 1,
    RTCP_SDES_NAME  = 2,
    RTCP_SDES_EMAIL = 3,
    RTCP_SDES_PHONE = 4,
    RTCP_SDES_LOC   = 5,
    RTCP_SDES_TOOL  = 6,
    RTCP_SDES_NOTE  = 7,
    RTCP_SDES_PRIV  = 8
} rtcp_sdes_type_t;

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

/*
 * RTCP common header word
 */
typedef struct {
    unsigned int version:2;   /* protocol version */
    unsigned int p:1;         /* padding flag */
    unsigned int count:5;     /* varies by packet type */
    unsigned int pt:8;        /* RTCP packet type */
    u_int16 length;           /* pkt len in words, w/o this word */
} rtcp_common_t;

/*
 * Big-endian mask for version, padding bit and packet type pair
 */
#define RTCP_VALID_MASK (0xc000 | 0x2000 | 0xfe)
#define RTCP_VALID_VALUE ((RTP_VERSION << 14) | RTCP_SR)

/*
 * Reception report block
 */
typedef struct {
    u_int32 ssrc;             /* data source being reported */
    unsigned int fraction:8;  /* fraction lost since last SR/RR */
    int lost:24;              /* cumul. no. pkts lost (signed!) */
    u_int32 last_seq;         /* extended last seq. no. received */
    u_int32 jitter;           /* interarrival jitter */
    u_int32 lsr;              /* last SR packet from this source */
    u_int32 dlsr;             /* delay since last SR packet */
} rtcp_rr_t;

/*
 * SDES item
 */
typedef struct {
    u_int8 type;              /* type of item (rtcp_sdes_type_t) */
    u_int8 length;            /* length of item (in octets) */
    char data[1];             /* text, not null-terminated */
} rtcp_sdes_item_t;

/*
 * One RTCP packet
 */
typedef struct {
    rtcp_common_t common;     /* common header */
    union {
        /* sender report (SR) */
        struct {
            u_int32 ssrc;     /* sender generating this report */
            u_int32 ntp_sec;  /* NTP timestamp */
            u_int32 ntp_frac;
            u_int32 rtp_ts;   /* RTP timestamp */
            u_int32 psent;    /* packets sent */
            u_int32 osent;    /* octets sent */
            rtcp_rr_t rr[1];  /* variable-length list */
        } sr;

        /* reception report (RR) */
        struct {
            u_int32 ssrc;     /* receiver generating this report */
            rtcp_rr_t rr[1];  /* variable-length list */
        } rr;

        /* source description (SDES) */
        struct rtcp_sdes {
            u_int32 src;      /* first SSRC/CSRC */
            rtcp_sdes_item_t item[1]; /* list of SDES items */
        } sdes;

        /* BYE */
        struct {
            u_int32 src[1];   /* list of sources */
            /* can't express trailing text for reason */
        } bye;
    } r;
} rtcp_t;

typedef struct rtcp_sdes rtcp_sdes_t;

/*
 * Per-source state information
 */
typedef struct {
    u_int16 max_seq;        /* highest seq. number seen */
    u_int32 cycles;         /* shifted count of seq. number cycles */
    u_int32 base_seq;       /* base seq number */
    u_int32 bad_seq;        /* last 'bad' seq number + 1 */
    u_int32 probation;      /* sequ. packets till source is valid */
    u_int32 received;       /* packets received */
    u_int32 expected_prior; /* packet expected at last interval */
    u_int32 received_prior; /* packet received at last interval */
    u_int32 transit;        /* relative trans time for prev pkt */
    u_int32 jitter;         /* estimated jitter */
    /* ... */
} source;

A.1 RTP Data Header Validity Checks โœจ

okay bestie, the receiver should check the RTP header on every incoming packet ๐Ÿ’… because it might be encrypted, or it might be some other app's traffic that got misaddressed ๐Ÿ™ˆ. If encryption is on, this check is also how you confirm the packet was actually decrypted properly. A failed header check (say, an unknown payload type) doesn't always mean decryption failed though, so don't panic too fast ๐Ÿซถ

Only weak validity checks are possible on an RTP data packet from a source that has not been heard before:

  • RTP version field must equal 2.
  • The payload type must be known, in particular it must not be equal to SR or RR.
  • If the P bit is set, then the last octet of the packet must contain a valid octet count, in particular, less than the total packet length minus the header size.
  • The X bit must be zero if the profile does not specify that the header extension mechanism may be used. Otherwise, the extension length field must be less than the total packet size minus the fixed header length and padding.
  • The length of the packet must be consistent with CC and payload type (if payloads have a known length).

The last three checks are kinda complex and not always possible ๐Ÿ˜ญ, which leaves only the first two. Those two add up to just a few bits of info, so it's not a lot to work with. If the SSRC identifier is one you've already received, the packet is probably valid, and checking that the sequence number falls in the expected range gives you extra validation ๐Ÿฆ‹ If the SSRC is brand new, then data packets carrying it may be treated as invalid until a small number of them show up with consecutive sequence numbers.

The update_seq routine below makes sure a source only gets declared valid after MIN_SEQUENTIAL packets have arrived in sequence. It also checks the sequence number seq of each newly received packet, and it updates the sequence state for that packet's source inside the structure that s points to ๐Ÿ’–

When a new source shows up for the first time (meaning its SSRC isn't in the table yet, see Section 8.2, and its per-source state gets allocated), s->probation should be set to the number of sequential packets required before declaring a source valid (parameter MIN_SEQUENTIAL), and s->max_seq should be initialized to seq-1. Setting s->probation marks the source as not yet valid, so its state can get tossed after a short timeout instead of a long one, as discussed in Section 6.2.1 ๐Ÿงš

Once a source is considered valid, a sequence number counts as valid if it's no more than MAX_DROPOUT ahead of s->max_seq, and no more than MAX_MISORDER behind. If the new sequence number is ahead of max_seq modulo the RTP sequence number range (16 bits) but is smaller than max_seq, it has wrapped around, so the (shifted) count of sequence number cycles gets incremented. A value of one is returned to say the sequence number is valid ๐ŸŒˆ

Otherwise, zero is returned to say validation failed, and the bad sequence number gets stored. If the next packet received carries the next higher sequence number, it's treated as the valid start of a new packet sequence. That usually means there was an extended dropout or the source restarted ๐Ÿ”„ Since multiple complete sequence number cycles might have been missed, the packet loss statistics get reset.

Typical values for the parameters are shown below, based on a maximum misordering time of 2 seconds at 50 packets/second and a maximum dropout of 1 minute โญ The dropout parameter MAX_DROPOUT should be a small fraction of the 16-bit sequence number space, so new sequence numbers after a restart have a reasonable chance of not landing in the acceptable range for sequence numbers from before the restart ๐Ÿ‘‘

void init_seq(source *s, u_int16 seq)
{
    s->base_seq = seq - 1;
    s->max_seq = seq;
    s->bad_seq = RTP_SEQ_MOD + 1;
    s->cycles = 0;
    s->received = 0;
    s->received_prior = 0;
    s->expected_prior = 0;
    /* other initialization */
}
int update_seq(source *s, u_int16 seq)
{
    u_int16 udelta = seq - s->max_seq;
    const int MAX_DROPOUT = 3000;
    const int MAX_MISORDER = 100;
    const int MIN_SEQUENTIAL = 2;

    /*
     * Source is not valid until MIN_SEQUENTIAL packets with
     * sequential sequence numbers have been received.
     */
    if (s->probation) {
        /* packet is in sequence */
        if (seq == s->max_seq + 1) {
            s->probation--;
            s->max_seq = seq;
            if (s->probation == 0) {
                init_seq(s, seq);
                s->received++;
                return 1;
            }
        } else {
            s->probation = MIN_SEQUENTIAL - 1;
            s->max_seq = seq;
        }
        return 0;
    } else if (udelta < MAX_DROPOUT) {
        /* in order, with permissible gap */
        if (seq < s->max_seq) {
            /*

             * Sequence number wrapped - count another 64K cycle.
             */
            s->cycles += RTP_SEQ_MOD;
        }
        s->max_seq = seq;
    } else if (udelta <= RTP_SEQ_MOD - MAX_MISORDER) {
        /* the sequence number made a very large jump */
        if (seq == s->bad_seq) {
            /*
             * Two sequential packets -- assume that the other side
             * restarted without telling us so just re-sync
             * (i.e., pretend this was the first packet).
             */
            init_seq(s, seq);
        }
        else {
            s->bad_seq = (seq + 1) & (RTP_SEQ_MOD-1);
            return 0;
        }
    } else {
        /* duplicate or reordered packet */
    }
    s->received++;
    return 1;
}

The validity check can be made stronger by requiring more than two packets in sequence ๐Ÿค“ The downsides are that a bigger number of initial packets get discarded, and high packet loss rates could stop validation from ever happening. However, because the RTCP header validation is pretty strong, if an RTCP packet comes in from a source before its data packets do, the count can be adjusted so only two packets are needed in sequence. If losing data for a few seconds at the start is okay, an application could choose to discard all data packets from a source until a valid RTCP packet has been received from that source ๐Ÿ’œ

Depending on the application and encoding, algorithms may use extra knowledge about the payload format for more validation. For payload types where the timestamp increment is the same for every packet, the timestamp values can be predicted from the previous packet received from the same source, using the sequence number difference (assuming no change in payload type) โœจ

A strong "fast-path" check is possible, since with high probability the first four octets in the header of a newly received RTP data packet will be just the same as the previous packet from the same SSRC, except the sequence number will have gone up by one ๐Ÿƒโ€โ™€๏ธ

Similarly, a single-entry cache may be used for faster SSRC lookups in applications where data is typically received from one source at a time ๐Ÿ“


A.2 RTCP Header Validity Checks

The following checks can be applied to RTCP packets.

  • RTP version field must equal 2.
  • The payload type field of the first RTCP packet in a compound packet must be equal to SR or RR.
  • The padding bit (P) should be zero for the first packet of a compound RTCP packet because only the last should possibly need padding.
  • The length fields of the individual RTCP packets must total to the overall length of the compound RTCP packet as received. This is a fairly strong check ๐Ÿ”ฅ

The code fragment below performs all of these checks. The packet type is not checked for subsequent packets, since unknown packet types may be present and should be ignored ๐Ÿ™ˆ

u_int32 len;        /* length of compound RTCP packet in words */
rtcp_t *r;          /* RTCP header */
rtcp_t *end;        /* end of compound RTCP packet */

if ((*(u_int16 *)r & RTCP_VALID_MASK) != RTCP_VALID_VALUE) {
    /* something wrong with packet format */
}
end = (rtcp_t *)((u_int32 *)r + len);

do r = (rtcp_t *)((u_int32 *)r + r->common.length + 1);
while (r < end && r->common.version == 2);

if (r != end) {
    /* something wrong with packet format */
}

A.3 Determining the Number of RTP Packets Expected and Lost ๐Ÿ“Š

okay so to work out packet loss rates, you need to know how many packets were expected and how many actually got received from each source ๐Ÿซถ That info lives in per-source state, the struct source that the code below reaches through the pointer s. The received count is just a tally of packets as they arrive, including late and duplicate ones. The expected count is the difference between the highest sequence number received (s->max_seq) and the first sequence number received (s->base_seq) ๐Ÿงฎ

The sequence number is only 16 bits and it wraps around, so you have to extend the highest sequence number with the (shifted) count of wraparounds (s->cycles). Both the received packet count and the cycle count are maintained by the RTP header validity check routine in Appendix A.1 ๐Ÿ’…

extended_max = s->cycles + s->max_seq;
expected = extended_max - s->base_seq + 1;

The number of packets lost is defined to be the number of packets expected, less the number of packets actually received:

lost = expected - s->received;

Since this number is carried in 24 bits, it should be clamped at 0xffffff rather than wrapping around to zero ๐Ÿ’€

The fraction of packets lost during the last reporting interval (since the previous SR or RR packet was sent) is worked out from the differences in the expected and received counts across that interval ๐ŸŒธ Here, expected_prior and received_prior are the values saved when the previous reception report was generated:

expected_interval = expected - s->expected_prior;
s->expected_prior = expected;
received_interval = s->received - s->received_prior;
s->received_prior = s->received;
lost_interval = expected_interval - received_interval;
if (expected_interval == 0 || lost_interval <= 0) fraction = 0;
else fraction = (lost_interval << 8) / expected_interval;

The resulting fraction is an 8-bit fixed point number with the binary point at the left edge. ๐ŸŒˆโœจ

A.4 Generating SDES RTCP Packets ๐ŸŽ€

okay bestie, this one's a builder ๐Ÿงฑ It packs one SDES chunk into buffer b, made of argc items pulled from the type, value and length arrays. โœจ

char *rtp_write_sdes(char *b, u_int32 src, int argc,
                     rtcp_sdes_type_t type[], char *value[],
                     int length[])
{
    rtcp_sdes_t *s = (rtcp_sdes_t *)b;
    rtcp_sdes_item_t *rsp;
    int i;
    int len;
    int pad;

    /* SSRC header */
    s->src = src;
    rsp = &s->item[0];

    /* SDES items */
    for (i = 0; i < argc; i++) {
        rsp->type = type[i];
        len = length[i];
        if (len > RTP_MAX_SDES) {
            /* invalid length, may want to take other action */
            len = RTP_MAX_SDES;
        }
        rsp->length = len;
        memcpy(rsp->data, value[i], len);
        rsp = (rtcp_sdes_item_t *)&rsp->data[len];
    }

    /* terminate with end marker and pad to next 4-octet boundary */
    len = ((char *) rsp) - b;
    pad = 4 - (len & 0x3);
    b = (char *) rsp;
    while (pad--) *b++ = RTCP_SDES_END;

    return b;
}

A.5 Parsing RTCP SDES Packets ๐Ÿ’…

this is the reverse, the unpacking side ๐Ÿ“ฆ It parses an SDES packet and calls find_member() to get a pointer to the info for a session member, using the SSRC identifier. Then it calls member_sdes() to store the new SDES info for that member. This function expects a pointer to the header of the RTCP packet.

void rtp_read_sdes(rtcp_t *r)
{
    int count = r->common.count;
    rtcp_sdes_t *sd = &r->r.sdes;
    rtcp_sdes_item_t *rsp, *rspn;
    rtcp_sdes_item_t *end = (rtcp_sdes_item_t *)
                            ((u_int32 *)r + r->common.length + 1);
    source *s;

    while (--count >= 0) {

        rsp = &sd->item[0];
        if (rsp >= end) break;
        s = find_member(sd->src);

        for (; rsp->type; rsp = rspn ) {
            rspn = (rtcp_sdes_item_t *)((char*)rsp+rsp->length+2);
            if (rspn >= end) {
                rsp = rspn;
                break;
            }
            member_sdes(s, rsp->type, rsp->data, rsp->length);
        }
        sd = (rtcp_sdes_t *)
             ((u_int32 *)sd + (((char *)rsp - (char *)sd) >> 2)+1);
    }
    if (count >= 0) {
        /* invalid packet format */
    }
}

A.6 Generating a Random 32-bit Identifier ๐ŸŽฒ

this subroutine makes a random 32-bit identifier using the MD5 routines from RFC 1321 [23]. ngl, system routines might not exist on every OS ๐Ÿ™ˆ but they're good hints for what kinds of info you can mix in. Other system calls that could be a good fit include:

  • getdomainname()
  • getwd()
  • getrusage()

"Live" video or audio samples are also a great source of randomness ๐ŸŽฅ but be careful about using a turned-off microphone or a blinded camera as a source [7]. ๐Ÿ˜ญ

Using this routine (or something similar) is suggested for a few jobs: generating the initial seed for the random number generator that produces the RTCP period (as shown in Appendix A.7), generating the initial values for the sequence number and timestamp, and generating SSRC values. โœจ Since this routine is likely to be CPU-intensive, using it directly to generate RTCP periods is inappropriate, because predictability is not an issue there. Also note that this routine gives the same result on repeated calls until the system clock changes, unless you supply different values for the type argument. ๐Ÿ•ฐ๏ธ

/*
 * Generate a random 32-bit quantity.
 */
#include <sys/types.h>   /* u_long */
#include <sys/time.h>    /* gettimeofday() */
#include <unistd.h>      /* get..() */
#include <stdio.h>       /* printf() */
#include <time.h>        /* clock() */
#include <sys/utsname.h> /* uname() */
#include "global.h"      /* from RFC 1321 */
#include "md5.h"         /* from RFC 1321 */

#define MD_CTX MD5_CTX
#define MDInit MD5Init
#define MDUpdate MD5Update
#define MDFinal MD5Final

static u_long md_32(char *string, int length)
{
    MD_CTX context;
    union {
        char   c[16];
        u_long x[4];
    } digest;
    u_long r;
    int i;

    MDInit (&context);
    MDUpdate (&context, string, length);
    MDFinal ((unsigned char *)&digest, &context);
    r = 0;
    for (i = 0; i < 3; i++) {
        r ^= digest.x[i];
    }
    return r;
}                               /* md_32 */


/*
 * Return random unsigned 32-bit quantity. Use 'type' argument if you
 * need to generate several different values in close succession.
 */
u_int32 random32(int type)
{
    struct {
        int     type;
        struct  timeval tv;
        clock_t cpu;
        pid_t   pid;
        u_long  hid;
        uid_t   uid;
        gid_t   gid;
        struct  utsname name;
    } s;

    gettimeofday(&s.tv, 0);
    uname(&s.name);
    s.type = type;
    s.cpu  = clock();
    s.pid  = getpid();
    s.hid  = gethostid();
    s.uid  = getuid();
    s.gid  = getgid();

    return md_32((char *)&s, sizeof(s));
}                               /* random32 */

A.7 Computing the RTCP Transmission Interval โฑ๏ธ

this function gives you the time between RTCP packet transmissions, in seconds ๐Ÿ’– Call it after sending one compound RTCP packet to work out how long to wait until the next one. You should also call it before sending the very first RTCP packet at startup, instead of sending right away ๐Ÿ™Œ That stops a burst of RTCP packets if lots of sites start the app at the same time, like after a session announcement. iconic, right? ๐Ÿฆ‹

Here's what each parameter means:

  • rtcp_bw: the target RTCP bandwidth, meaning the total bandwidth all members of this session will use for RTCP packets, in octets per second. It should be 5% of the "session bandwidth" parameter given to the app at startup. ๐ŸŒธ
  • senders: the number of active senders since the last report was sent, known from building the receiver reports for this RTCP packet. It includes us, if we also sent during this interval. ๐Ÿ’œ
  • members: the estimated number of session members, including us. It goes up as we find new members from RTP or RTCP packets, and goes down when members leave (via RTCP BYE) or their state times out (30 minutes is recommended). On the first call, this should be 1. ๐Ÿงš
  • we_sent: a flag that's true if we sent data during the last two RTCP intervals. If the flag is true, the compound RTCP packet we just sent contained an SR packet. ๐Ÿ“
  • packet_size: the size of the compound RTCP packet we just sent, in octets, including the network encapsulation (for example, 28 octets for UDP over IP). ๐Ÿ“ฆ
  • avg_rtcp_size: a pointer to the estimator for the compound RTCP packet size. It's initialized and updated by this function for the packet we just sent, and it's also updated by an identical line of code in the RTCP receive routine for every RTCP packet received from other session participants. ๐Ÿซถ
  • initial: a flag that's true for the first call at startup, when we're working out the time until the first report should go out. ๐ŸŒˆ
#include <math.h>

double rtcp_interval(int members,
                     int senders,
                     double rtcp_bw,
                     int we_sent,
                     int packet_size,
                     int *avg_rtcp_size,
                     int initial)
{
    /*
     * Minimum time between RTCP packets from this site (in seconds).
     * This time prevents the reports from `clumping' when sessions
     * are small and the law of large numbers isn't helping to smooth
     * out the traffic.  It also keeps the report interval from
     * becoming ridiculously small during transient outages like a
     * network partition.
     */
    double const RTCP_MIN_TIME = 5.;
    /*
     * Fraction of the RTCP bandwidth to be shared among active
     * senders.  (This fraction was chosen so that in a typical
     * session with one or two active senders, the computed report
     * time would be roughly equal to the minimum report time so that
     * we don't unnecessarily slow down receiver reports.) The
     * receiver fraction must be 1 - the sender fraction.
     */
    double const RTCP_SENDER_BW_FRACTION = 0.25;
    double const RTCP_RCVR_BW_FRACTION = (1-RTCP_SENDER_BW_FRACTION);
    /*
     * Gain (smoothing constant) for the low-pass filter that
     * estimates the average RTCP packet size (see Cadzow reference).
     */
    double const RTCP_SIZE_GAIN = (1./16.);

    double t;                   /* interval */
    double rtcp_min_time = RTCP_MIN_TIME;
    int n;                      /* no. of members for computation */

    /*
     * Very first call at application start-up uses half the min
     * delay for quicker notification while still allowing some time
     * before reporting for randomization and to learn about other
     * sources so the report interval will converge to the correct
     * interval more quickly.  The average RTCP size is initialized
     * to 128 octets which is conservative (it assumes everyone else
     * is generating SRs instead of RRs: 20 IP + 8 UDP + 52 SR + 48
     * SDES CNAME).
     */
    if (initial) {
        rtcp_min_time /= 2;
        *avg_rtcp_size = 128;
    }

    /*
     * If there were active senders, give them at least a minimum
     * share of the RTCP bandwidth.  Otherwise all participants share
     * the RTCP bandwidth equally.
     */
    n = members;
    if (senders > 0 && senders < members * RTCP_SENDER_BW_FRACTION) {
        if (we_sent) {
            rtcp_bw *= RTCP_SENDER_BW_FRACTION;
            n = senders;
        } else {
            rtcp_bw *= RTCP_RCVR_BW_FRACTION;
            n -= senders;
        }
    }

    /*
     * Update the average size estimate by the size of the report
     * packet we just sent.
     */
    *avg_rtcp_size += (packet_size - *avg_rtcp_size)*RTCP_SIZE_GAIN;

    /*
     * The effective number of sites times the average packet size is
     * the total number of octets sent when each site sends a report.

     * Dividing this by the effective bandwidth gives the time
     * interval over which those packets must be sent in order to
     * meet the bandwidth target, with a minimum enforced.  In that
     * time interval we send one report so this time is also our
     * average time between reports.
     */
    t = (*avg_rtcp_size) * n / rtcp_bw;
    if (t < rtcp_min_time) t = rtcp_min_time;

    /*
     * To avoid traffic bursts from unintended synchronization with
     * other sites, we then pick our actual next report interval as a
     * random number uniformly distributed between 0.5*t and 1.5*t.
     */
    return t * (drand48() + 0.5);
}

A.8 Estimating the Interarrival Jitter โœจ

okay so this is where we actually work out how wobbly the arrival times are ๐Ÿฆ‹ These snippets carry out the algorithm from Section 6.3.1 to estimate the statistical variance of the RTP data interarrival time, which then goes into the interarrival jitter field of reception reports. The inputs are r->ts, the timestamp from the incoming packet, and arrival, the current time in the same units. s points to the state for the source, s->transit holds the relative transit time for the previous packet, and s->jitter holds the estimated jitter. ๐Ÿงš

The jitter field of the reception report is measured in timestamp units and written as an unsigned integer, but the estimate itself is kept as a floating point number. Every time a data packet arrives, the estimate gets updated like this:

int transit = arrival - r->ts;
int d = transit - s->transit;
s->transit = transit;
if (d < 0) d = -d;
s->jitter += (1./16.) * ((double)d - s->jitter);

When a reception report block (where rr points) gets generated for this member, the current jitter estimate is returned like this:

rr->jitter = (u_int32) s->jitter;

Or, if you're extra, you can keep the jitter estimate as an integer that's scaled up to cut down on round-off error ๐Ÿ“ The math is the same except for the last line:

s->jitter += d - ((s->jitter + 8) >> 4);

In that case, the estimate gets sampled for the reception report like this:

rr->jitter = s->jitter >> 4;

B. Security Considerations ๐Ÿ”

bestie, this part is SERIOUS so pls pay attention ๐Ÿ’€ RTP has the exact same security liabilities as the protocols it sits on top of. For example, an impostor can fake source or destination network addresses, or change the header or payload ๐Ÿ˜ญ Inside RTCP, the CNAME and NAME information may be used to impersonate another participant. On top of that, RTP may be sent via IP multicast, and multicast gives a sender no direct way to know all the receivers of the data it sent, so there's no measure of privacy either. Rightly or not, users may be more sensitive to privacy concerns with audio and video calls than they've been with more traditional kinds of network traffic [24]. So yeah, using security mechanisms with RTP is important ๐Ÿซถ Section 9 covers those mechanisms.

RTP-level translators or mixers may be used to let RTP traffic reach hosts behind firewalls. Appropriate firewall security principles and practices are beyond the scope of this document, but they should be followed when these devices are designed and installed, and when RTP applications get admitted for use behind the firewall ๐Ÿšจ

C. Authors' Addresses ๐Ÿ’Œ

Here are the people who wrote this ๐ŸŽ€

Henning Schulzrinne
GMD Fokus
Hardenbergplatz 2
D-10623 Berlin
Germany

EMail: schulzrinne@fokus.gmd.de
Stephen L. Casner
Precept Software, Inc.
21580 Stevens Creek Boulevard, Suite 207
Cupertino, CA 95014
United States

EMail: casner@precept.com
Ron Frederick
Xerox Palo Alto Research Center
3333 Coyote Hill Road
Palo Alto, CA 94304
United States

EMail: frederic@parc.xerox.com
Van Jacobson
MS 46a-1121
Lawrence Berkeley National Laboratory
Berkeley, CA 94720
United States

EMail: van@ee.lbl.gov

Acknowledgments ๐Ÿซถ

shoutouts time ๐Ÿ“ฃ This memorandum is based on discussions within the IETF Audio/Video Transport working group chaired by Stephen Casner. The current protocol has its origins in the Network Voice Protocol and the Packet Video Protocol (Danny Cohen and Randy Cole), and in the protocol implemented by the vat application (Van Jacobson and Steve McCanne). Christian Huitema gave ideas for the random identifier generator ๐Ÿ’œ


D. Bibliography ๐Ÿ“š

[1] D. D. Clark and D. L. Tennenhouse, "Architectural considerations for a new generation of protocols," in SIGCOMM Symposium on Communications Architectures and Protocols , (Philadelphia, Pennsylvania), pp. 200--208, IEEE, Sept. 1990. Computer Communications Review, Vol. 20(4), Sept. 1990.

[2] H. Schulzrinne, "Issues in designing a transport protocol for audio and video conferences and other multiparticipant real-time applications", Work in Progress.

[3] D. E. Comer, Internetworking with TCP/IP , vol. 1. Englewood Cliffs, New Jersey: Prentice Hall, 1991.

[4] Postel, J., "Internet Protocol", STD 5, RFC 791, USC/Information Sciences Institute, September 1981.

[5] Mills, D., "Network Time Protocol Version 3", RFC 1305, UDEL, March 1992.

[6] Reynolds, J., and J. Postel, "Assigned Numbers", STD 2, RFC 1700, USC/Information Sciences Institute, October 1994.

[7] Eastlake, D., Crocker, S., and J. Schiller, "Randomness Recommendations for Security", RFC 1750, DEC, Cybercash, MIT, December 1994.

[8] J.-C. Bolot, T. Turletti, and I. Wakeman, "Scalable feedback control for multicast video distribution in the internet," in SIGCOMM Symposium on Communications Architectures and Protocols , (London, England), pp. 58--67, ACM, Aug. 1994.

[9] I. Busse, B. Deffner, and H. Schulzrinne, "Dynamic QoS control of multimedia applications based on RTP," Computer Communications , Jan. 1996.

[10] S. Floyd and V. Jacobson, "The synchronization of periodic routing messages," in SIGCOMM Symposium on Communications Architectures and Protocols (D. P. Sidhu, ed.), (San Francisco, California), pp. 33--44, ACM, Sept. 1993. also in [25].

[11] J. A. Cadzow, Foundations of digital signal processing and data analysis New York, New York: Macmillan, 1987.

[12] International Standards Organization, "ISO/IEC DIS 10646-1:1993 information technology -- universal multiple-octet coded character set (UCS) -- part I: Architecture and basic multilingual plane," 1993.

[13] The Unicode Consortium, The Unicode Standard New York, New York: Addison-Wesley, 1991.

[14] Mockapetris, P., "Domain Names - Concepts and Facilities", STD 13, RFC 1034, USC/Information Sciences Institute, November 1987.

[15] Mockapetris, P., "Domain Names - Implementation and Specification", STD 13, RFC 1035, USC/Information Sciences Institute, November 1987.

[16] Braden, R., "Requirements for Internet Hosts - Application and Support", STD 3, RFC 1123, Internet Engineering Task Force, October 1989.

[17] Rekhter, Y., Moskowitz, R., Karrenberg, D., and G. de Groot, "Address Allocation for Private Internets", RFC 1597, T.J. Watson Research Center, IBM Corp., Chrysler Corp., RIPE NCC, March 1994.

[18] Lear, E., Fair, E., Crocker, D., and T. Kessler, "Network 10 Considered Harmful (Some Practices Shouldn't be Codified)", RFC 1627, Silicon Graphics, Inc., Apple Computer, Inc., Silicon Graphics, Inc., July 1994.

[19] Crocker, D., "Standard for the Format of ARPA Internet Text Messages", STD 11, RFC 822, UDEL, August 1982.

[20] W. Feller, An Introduction to Probability Theory and its Applications, Volume 1 , vol. 1. New York, New York: John Wiley and Sons, third ed., 1968.

[21] Balenson, D., "Privacy Enhancement for Internet Electronic Mail: Part III: Algorithms, Modes, and Identifiers", RFC 1423, TIS, IAB IRTF PSRG, IETF PEM WG, February 1993.

[22] V. L. Voydock and S. T. Kent, "Security mechanisms in high-level network protocols," ACM Computing Surveys , vol. 15, pp. 135-- 171, June 1983.

[23] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, MIT Laboratory for Computer Science and RSA Data Security, Inc., April 1992.

[24] S. Stubblebine, "Security services for multimedia conferencing," in 16th National Computer Security Conference , (Baltimore, Maryland), pp. 391--395, Sept. 1993.

[25] S. Floyd and V. Jacobson, "The synchronization of periodic routing messages," IEEE/ACM Transactions on Networking , vol. 2, pp. 122-136, April 1994.

๐Ÿ“ฆ where this page comes from