# `XMediaLib.Rtp`
[🔗](https://github.com/Lazarus404/xmedialib/blob/main/lib/rtp.ex#L31)

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

* [RFC 3550](https://www.rfc-editor.org/rfc/rfc3550) - RTP
* [RFC 3551](https://www.rfc-editor.org/rfc/rfc3551) - static payload types
* [RFC 5761](https://www.rfc-editor.org/rfc/rfc5761) - RTP/RTCP multiplexing
* [RFC 7983](https://www.rfc-editor.org/rfc/rfc7983) - STUN/RTP/DTLS demux
* [RFC 2198](https://www.rfc-editor.org/rfc/rfc2198) - redundant audio data
* [RFC 2833](https://www.rfc-editor.org/rfc/rfc2833) / [RFC 4733](https://www.rfc-editor.org/rfc/rfc4733) - DTMF and tones
* [RFC 5285](https://www.rfc-editor.org/rfc/rfc5285) / [RFC 8285](https://www.rfc-editor.org/rfc/rfc8285) - header extensions (see `XMediaLib.Rtp.HeaderExtension`)

# `t`

```elixir
@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{}` or `nil`
* `:payload` - media bytes, or `%Dtmf{}` / `%Tone{}` after dynamic PT decode

# `decode`

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"

# `decode_dtmf`

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}

# `decode_extension`

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, ""}

# `decode_red`

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.

# `decode_red_headers`

Decodes RFC 2198 redundant block headers from `data`, accumulating `headers`.

# `decode_red_payload`

Extracts redundant payloads using headers from `decode_red_headers/2`.

# `decode_red_payload`

Internal accumulator clause for `decode_red_payload/2`.

# `decode_tone`

Decodes an RFC 4733 tone payload.

Returns `{:ok, %Tone{}}` with `:frequencies` extracted from the remainder.

# `encode`

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

# `encode_dtmf`

Encodes `%Dtmf{}` as RFC 4733 telephone-event octets.

# `encode_extension`

Encodes an RFC 3550 header extension.

Returns `{extension_flag, binary}` where flag is 0 or 1.

# `encode_red`

Encodes RFC 2198 redundant payloads.

`redundant_payloads` is a list of `{payload_type, timestamp_offset, payload}`
with the primary block last (`timestamp_offset` 0).

# `encode_red`

Internal accumulator clause for `encode_red/1`.

# `encode_tone`

Encodes `%Tone{}` as RFC 4733 tone octets.

# `rtp_payload_celb`

Static payload type for CellB video (RFC 2029).

# `rtp_payload_cn`

Static payload type for comfort noise (RFC 3389).

# `rtp_payload_dvi4_8khz`

Static payload type for DVI4 at 8 kHz (RFC 3551).

# `rtp_payload_dvi4_11khz`

Static payload type for DVI4 at 11.025 kHz (RFC 3551).

# `rtp_payload_dvi4_16khz`

Static payload type for DVI4 at 16 kHz (RFC 3551).

# `rtp_payload_dvi4_22khz`

Static payload type for DVI4 at 22.05 kHz (RFC 3551).

# `rtp_payload_g722`

Static payload type for G.722 (RFC 3551).

# `rtp_payload_g723`

Static payload type for G.723.1 (RFC 3551).

# `rtp_payload_g728`

Static payload type for G.728 (RFC 3551).

# `rtp_payload_g729`

Static payload type for G.729 (RFC 3551).

# `rtp_payload_gsm`

Static payload type for GSM full rate (RFC 3551).

# `rtp_payload_h261`

Static payload type for H.261 video (RFC 4587).

# `rtp_payload_h263`

Static payload type for H.263 video (RFC 3551).

# `rtp_payload_jpeg`

Static payload type for JPEG video (RFC 2435).

# `rtp_payload_l16_1ch`

Static payload type for 16-bit linear PCM mono (RFC 3551).

# `rtp_payload_l16_2ch`

Static payload type for 16-bit linear PCM stereo (RFC 3551).

# `rtp_payload_lpc`

Static payload type for LPC (RFC 3551).

# `rtp_payload_mp2t`

Static payload type for MPEG-2 transport (RFC 2250).

# `rtp_payload_mpa`

Static payload type for MPEG audio (RFC 3551).

# `rtp_payload_mpv`

Static payload type for MPEG video (RFC 2250).

# `rtp_payload_nv`

Static payload type for nv video (RFC 3551).

# `rtp_payload_pcma`

Static payload type for G.711 A-law (PCMA) (RFC 3551).

# `rtp_payload_pcmu`

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

# `rtp_payload_qcelp`

Static payload type for QCELP (RFC 3551).

---

*Consult [api-reference.md](api-reference.md) for complete listing*
