Encode and decode Real-time Transport Protocol (RTP) packets.
What problem this solves
Every audio or video frame in a VoIP or WebRTC call travels inside RTP packets
on UDP. Application code must read sequence numbers, timestamps, payload types,
and optional header extensions without reimplementing RFC 3550 bit layouts.
This module decodes incoming bytes into %XMediaLib.Rtp{}, encodes outbound
media, and helps classify STUN, ZRTP, or RTCP when those protocols share the
same port.
RTP carries timed media (audio, video) over UDP. Each packet has a small fixed header (version, sequence number, timestamp, synchronization source identifier) plus an opaque payload interpreted by the codec named in the payload type field. Receivers use the sequence number to detect loss and the timestamp to play samples at the right rate.
This module maps between on-the-wire binaries and %XMediaLib.Rtp{} structs.
It also exposes helpers for common telephony payloads (DTMF events, redundant
encoding) and static payload type constants from RFC 3551.
SRTP note: encrypted RTP must be classified before decryption (see RFC
7983 demux and RFC 5761 RTCP-mux). Do not rely on decode/1 alone to tell
SRTP ciphertext from plaintext RTP; decrypt first, then decode. Convenience
clauses in decode/1 still recognize plaintext RTCP (RFC 5761 PT range),
STUN, and ZRTP when those protocols share the same UDP port.
Nested structs:
%XMediaLib.Rtp.Extension{}- RFC 3550 header extension block%XMediaLib.Rtp.Dtmf{}- RFC 4733 telephone-event payload%XMediaLib.Rtp.Tone{}- RFC 4733 tone payload
RFCs
Summary
Functions
Decodes one RTP packet (or plaintext RTCP/STUN/ZRTP via convenience clauses).
Decodes an RFC 4733 telephone-event (DTMF) payload.
Parses or skips the RFC 3550 header extension.
Decodes an RFC 2198 redundant audio payload into a list of blocks.
Decodes RFC 2198 redundant block headers from data, accumulating headers.
Extracts redundant payloads using headers from decode_red_headers/2.
Internal accumulator clause for decode_red_payload/2.
Decodes an RFC 4733 tone payload.
Encodes %Rtp{} (or STUN/ZRTP/RTCP structs).
Encodes %Dtmf{} as RFC 4733 telephone-event octets.
Encodes an RFC 3550 header extension.
Encodes RFC 2198 redundant payloads.
Internal accumulator clause for encode_red/1.
Encodes %Tone{} as RFC 4733 tone octets.
Static payload type for CellB video (RFC 2029).
Static payload type for comfort noise (RFC 3389).
Static payload type for DVI4 at 8 kHz (RFC 3551).
Static payload type for DVI4 at 11.025 kHz (RFC 3551).
Static payload type for DVI4 at 16 kHz (RFC 3551).
Static payload type for DVI4 at 22.05 kHz (RFC 3551).
Static payload type for G.722 (RFC 3551).
Static payload type for G.723.1 (RFC 3551).
Static payload type for G.728 (RFC 3551).
Static payload type for G.729 (RFC 3551).
Static payload type for GSM full rate (RFC 3551).
Static payload type for H.261 video (RFC 4587).
Static payload type for H.263 video (RFC 3551).
Static payload type for JPEG video (RFC 2435).
Static payload type for 16-bit linear PCM mono (RFC 3551).
Static payload type for 16-bit linear PCM stereo (RFC 3551).
Static payload type for LPC (RFC 3551).
Static payload type for MPEG-2 transport (RFC 2250).
Static payload type for MPEG audio (RFC 3551).
Static payload type for MPEG video (RFC 2250).
Static payload type for nv video (RFC 3551).
Static payload type for G.711 A-law (PCMA) (RFC 3551).
Static RTP payload type constants (RFC 3551).
Static payload type for QCELP (RFC 3551).
Types
@type t() :: %XMediaLib.Rtp{ csrcs: [non_neg_integer()], extension: Extension.t() | nil, marker: 0 | 1, padding: 0 | 1, payload: binary() | Dtmf.t() | Tone.t(), payload_type: non_neg_integer() | nil, sequence_number: non_neg_integer() | nil, ssrc: non_neg_integer() | nil, timestamp: non_neg_integer() | nil }
Parsed RTP packet.
Fields
:padding- 1 when padding octets follow the payload (RFC 3550 pt.5.1):marker- profile-specific marker bit (often frame boundary for video):payload_type- 7-bit static or dynamic payload type (RFC 3551):sequence_number- 16-bit per-SSRC sequence counter:timestamp- 32-bit media clock sample associated with this packet:ssrc- synchronization source identifier for this stream:csrcs- contributing source identifiers (0..15 entries):extension-%XMediaLib.Rtp.Extension{}ornil:payload- media bytes, or%Dtmf{}/%Tone{}after dynamic PT decode
Functions
Decodes one RTP packet (or plaintext RTCP/STUN/ZRTP via convenience clauses).
Returns {:ok, struct} or {:error, :invalid} / {:error, :padding}.
RTCP is recognized when the payload type is 64-82 (RFC 5761). STUN and ZRTP are detected by magic cookie patterns.
Examples
iex> rtp = %XMediaLib.Rtp{
...> padding: 0, marker: 0, payload_type: 111, sequence_number: 1,
...> timestamp: 0, ssrc: 1, csrcs: [], extension: nil, payload: "hi"
...> }
iex> {:ok, decoded} = rtp |> XMediaLib.Rtp.encode() |> XMediaLib.Rtp.decode()
iex> decoded.payload
"hi"
Decodes an RFC 4733 telephone-event (DTMF) payload.
Returns {:ok, %Dtmf{}}. Some senders append extra octets; a warning is logged
and the first four octets are retried.
Examples
iex> bin = XMediaLib.Rtp.encode_dtmf(%XMediaLib.Rtp.Dtmf{event: 1, eof: false, volume: 10, duration: 160})
iex> {:ok, dtmf} = XMediaLib.Rtp.decode_dtmf(bin)
iex> {dtmf.event, dtmf.eof, dtmf.duration}
{1, false, 160}
Parses or skips the RFC 3550 header extension.
When extension_flag is 0, returns {:ok, data, nil}. When 1, reads
{type, words} and returns {:ok, remainder, %Extension{}}.
Examples
iex> ext = %XMediaLib.Rtp.Extension{type: 0xBEDE, payload: <<1, 2>>}
iex> {1, wire} = XMediaLib.Rtp.encode_extension(ext)
iex> {:ok, rest, decoded} = XMediaLib.Rtp.decode_extension(wire, 1)
iex> {decoded.type, byte_size(decoded.payload), rest}
{48862, 4, ""}
Decodes an RFC 2198 redundant audio payload into a list of blocks.
Each block is {payload_type, timestamp_offset, payload} where
timestamp_offset is 0 for the primary block.
Decodes RFC 2198 redundant block headers from data, accumulating headers.
Extracts redundant payloads using headers from decode_red_headers/2.
Internal accumulator clause for decode_red_payload/2.
Decodes an RFC 4733 tone payload.
Returns {:ok, %Tone{}} with :frequencies extracted from the remainder.
Encodes %Rtp{} (or STUN/ZRTP/RTCP structs).
When padding is 1, appends RFC 3550 padding so the packet length is a
multiple of four octets. %Dtmf{} and %Tone{} payloads are encoded
automatically.
Examples
iex> rtp = %XMediaLib.Rtp{
...> padding: 0, marker: 0, payload_type: 0, sequence_number: 100,
...> timestamp: 160, ssrc: 0x01020304, csrcs: [], extension: nil,
...> payload: <<>>
...> }
iex> bin = XMediaLib.Rtp.encode(rtp)
iex> byte_size(bin)
12
Encodes %Dtmf{} as RFC 4733 telephone-event octets.
Encodes an RFC 3550 header extension.
Returns {extension_flag, binary} where flag is 0 or 1.
Encodes RFC 2198 redundant payloads.
redundant_payloads is a list of {payload_type, timestamp_offset, payload}
with the primary block last (timestamp_offset 0).
Internal accumulator clause for encode_red/1.
Encodes %Tone{} as RFC 4733 tone octets.
Static payload type for CellB video (RFC 2029).
Static payload type for comfort noise (RFC 3389).
Static payload type for DVI4 at 8 kHz (RFC 3551).
Static payload type for DVI4 at 11.025 kHz (RFC 3551).
Static payload type for DVI4 at 16 kHz (RFC 3551).
Static payload type for DVI4 at 22.05 kHz (RFC 3551).
Static payload type for G.722 (RFC 3551).
Static payload type for G.723.1 (RFC 3551).
Static payload type for G.728 (RFC 3551).
Static payload type for G.729 (RFC 3551).
Static payload type for GSM full rate (RFC 3551).
Static payload type for H.261 video (RFC 4587).
Static payload type for H.263 video (RFC 3551).
Static payload type for JPEG video (RFC 2435).
Static payload type for 16-bit linear PCM mono (RFC 3551).
Static payload type for 16-bit linear PCM stereo (RFC 3551).
Static payload type for LPC (RFC 3551).
Static payload type for MPEG-2 transport (RFC 2250).
Static payload type for MPEG audio (RFC 3551).
Static payload type for MPEG video (RFC 2250).
Static payload type for nv video (RFC 3551).
Static payload type for G.711 A-law (PCMA) (RFC 3551).
Static RTP payload type constants (RFC 3551).
Dynamic types 96-127 are negotiated per session (SDP) and have no constants here.
Examples
iex> XMediaLib.Rtp.rtp_payload_pcmu()
0
iex> XMediaLib.Rtp.rtp_payload_pcma()
8
Static payload type for QCELP (RFC 3551).