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

Encode and decode RTP Control Protocol (RTCP) packets.

## What problem this solves

RTP carries media; RTCP carries session control: sender and receiver reports,
source descriptions, BYE, and AVPF feedback such as NACK or PLI. An SFU or
endpoint must parse compound RTCP from UDP and generate replies for loss
recovery, bitrate hints, and diagnostics. This module maps wire bytes to typed
structs and back, after SRTCP decryption when keys are available.

RTCP rides alongside RTP on the same UDP session (often the same port when
RFC 5761 mux is enabled). Senders publish statistics; receivers report loss
and jitter; both sides exchange source descriptions (CNAME) and session
teardown (BYE). Feedback packets (NACK, PLI, FIR) support loss recovery and
keyframe requests in video calls.

Wire format: each RTCP packet has a common header (version, type, length) and
a type-specific body. Multiple packets are concatenated into a **compound
packet** without extra framing; `decode/1` walks the buffer recursively.

`%XMediaLib.Rtcp{}` wraps a list of decoded payload structs in `:payloads`.
When trailing bytes cannot be parsed (typical for SRTCP ciphertext), decode
sets `:encrypted` to the original binary and still returns `{:ok, _}`.

SRTCP decryption belongs in `XMediaLib.Srtp` before calling `decode/1` on
plaintext RTCP.

## RFCs

* [RFC 3550](https://www.rfc-editor.org/rfc/rfc3550) - RTCP common format, SR,
  RR, SDES, BYE, APP
* [RFC 5761](https://www.rfc-editor.org/rfc/rfc5761) - RTP and RTCP on one port
* [RFC 3711](https://www.rfc-editor.org/rfc/rfc3711) - SRTCP encryption
* [RFC 2032](https://www.rfc-editor.org/rfc/rfc2032) - FIR and NACK (H.261)
* [RFC 3611](https://www.rfc-editor.org/rfc/rfc3611) - RTCP XR
* [RFC 4585](https://www.rfc-editor.org/rfc/rfc4585) - RTP/AVPF feedback (NACK,
  PLI, SLI, RPSI, AFB)
* [RFC 5450](https://www.rfc-editor.org/rfc/rfc5450) - inter-arrival jitter
* [RFC 5484](https://www.rfc-editor.org/rfc/rfc5484) - SMPTE timecode
* [draft-holmer-rmcat-transport-wide-cc-extensions](https://datatracker.ietf.org/doc/html/draft-holmer-rmcat-transport-wide-cc-extensions)
  - transport-wide congestion control feedback (`Twcc`, RTPFB fmt 15)
* [draft-alvestrand-rmcat-remb](https://datatracker.ietf.org/doc/html/draft-alvestrand-rmcat-remb)
  - Receiver Estimated Maximum Bitrate (`Remb`, PSFB AFB `"REMB"`)

# `t`

```elixir
@type t() :: %XMediaLib.Rtcp{encrypted: binary() | nil, payloads: [struct()]}
```

Compound RTCP message.

## Fields

* `:payloads` - list of decoded packet structs (`Sr`, `Rr`, `Sdes`, etc.)
* `:encrypted` - original binary when trailing SRTCP bytes could not be parsed

# `decode`

Decodes a compound RTCP packet (or SRTCP plaintext after `XMediaLib.Srtp`).

Returns `{:ok, %Rtcp{}}`. Unparsed trailing bytes set `:encrypted` on the struct.

## Examples

    iex> fir = %XMediaLib.Rtcp.Fir{ssrc: 4096}
    iex> bin = XMediaLib.Rtcp.encode(fir)
    iex> {:ok, %XMediaLib.Rtcp{payloads: [decoded]}} = XMediaLib.Rtcp.decode(bin)
    iex> decoded.ssrc
    4096

# `decode`

Internal accumulator for `decode/1`; prefer the public `decode/1` entry point.

# `decode_bye`

Decodes RFC 3550 BYE SSRC list and optional reason text.

# `decode_rblocks`

Decodes RFC 3550 report blocks from SR/RR packet bodies.

Returns `{rblocks, padding}` where `padding` is any unconsumed tail bytes.

# `decode_rblocks`

Accumulator clause for `decode_rblocks/2`.

# `decode_sdes_item`

Decodes SDES items inside one chunk.

Returns `{items, rest}` when the chunk ends; recurses for known item types.
Handles a known AddPac CNAME quirk with extra padding.

# `decode_sdes_items`

Decodes RFC 3550 SDES chunks into a list of keyword proplists.

# `decode_xrblocks`

Decodes RFC 3611 XR report blocks from an XR packet body.

# `decode_xrblocks`

Accumulator clause for `decode_xrblocks/2`.

# `encode`

Encodes `%Rtcp{}` or a single RTCP payload struct to binary.

When `:encrypted` is set, returns that binary unchanged (already SRTCP).

## Examples

    iex> bye = %XMediaLib.Rtcp.Bye{ssrc: [1, 2], message: ~c"done"}
    iex> bin = XMediaLib.Rtcp.encode(bye)
    iex> {:ok, rtcp} = XMediaLib.Rtcp.decode(bin)
    iex> [decoded] = rtcp.payloads
    iex> decoded.ssrc
    [1, 2]

# `encode_app`

Encodes RFC 3550 APP packet.

`name` must be exactly four bytes; `data` length must be a multiple of four.
Returns binary or `{:error, :bad_data}`.

# `encode_bye`

Encodes RFC 3550 BYE for `ssrcs_list` with optional `message` charlist.

# `encode_fir`

Encodes RFC 2032 FIR for `ssrc`.

# `encode_nack`

Encodes RFC 2032 legacy NACK for `ssrc`.

# `encode_rblock`

Encodes one `%Rblock{}` or equivalent tuple fields.

# `encode_rblock`

Encodes one report block from raw field values.

# `encode_rblocks`

Encodes a list of `%Rblock{}` structs.

# `encode_rr`

Encodes RFC 3550 Receiver Report with `report_blocks`.

# `encode_sdes`

Encodes RFC 3550 SDES compound from a list of item proplists.

# `encode_sdes_item`

Encodes one SDES item or chunk field.

Accepts `:ssrc`, `:cname`, `:name`, `:email`, `:phone`, `:loc`, `:tool`,
`:note`, `:priv`, `:eof`, or a raw type octet with binary value.

# `encode_sdes_item`

# `encode_sdes_items`

Encodes one SDES chunk (keyword proplist) with 32-bit padding.

# `encode_sr`

Encodes RFC 3550 Sender Report with `report_blocks`.

# `encode_xr`

Encodes RFC 3611 Extended Report with `xrblocks`.

# `encode_xrblock`

Encodes one `%Xrblock{}` or `{type, ts, data}` tuple.

# `encode_xrblock`

Encodes one XR block; `data` length must be a multiple of four.

# `encode_xrblocks`

Encodes a list of `%Xrblock{}` structs.

---

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