# `XMediaLib.SDP.Media`
[🔗](https://github.com/Lazarus404/xmedialib/blob/main/lib/sdp/media.ex#L25)

One SDP media section (`m=` line) and its media-level attributes.

## What problem this solves

A WebRTC offer contains one or more `m=` sections (audio, video, application).
Each section lists ports, transports, payload types, and dozens of `a=`
attributes for ICE, codecs, and SSRC metadata. This struct holds one parsed
media block so SFU and gateway code can read or patch a single stream without
reparsing the whole session.

Each `m=` block describes a single media stream: type (audio, video,
application), port, transport protocol, and format list. Following `a=`
lines carry ICE credentials, DTLS fingerprints, codec mappings, SSRC
metadata, and WebRTC-specific extensions. The parser promotes well-known
attributes into typed fields; anything else remains in `:attributes`.

## RFCs

* [RFC 8866](https://www.rfc-editor.org/rfc/rfc8866) - SDP media descriptions
* [RFC 8445](https://www.rfc-editor.org/rfc/rfc8445) - ICE attributes
* [RFC 8122](https://www.rfc-editor.org/rfc/rfc8122) - DTLS fingerprint/setup
* [RFC 8841](https://www.rfc-editor.org/rfc/rfc8841) - SCTP/data channel attributes

# `attribute`

```elixir
@type attribute() :: {String.t(), String.t() | true}
```

Unpromoted media-level attribute as `{name, value}` or `{name, true}`.

# `direction`

```elixir
@type direction() :: :sendrecv | :sendonly | :recvonly | :inactive
```

Media direction from `a=sendrecv`, `a=sendonly`, `a=recvonly`, or `a=inactive`.

# `protocol`

```elixir
@type protocol() :: :UDP_TLS_RTP_SAVPF | :RTP_SAVPF | :UDP_DTLS_SCTP | String.t()
```

Transport protocol from the `m=` line.

Known WebRTC values include `:UDP_TLS_RTP_SAVPF` (DTLS-SRTP), `:RTP_SAVPF`,
and `:UDP_DTLS_SCTP` (data channels). Other strings pass through unchanged.

# `t`

```elixir
@type t() :: %XMediaLib.SDP.Media{
  attributes: [attribute()],
  candidates: [XMediaLib.SDP.Candidate.t()],
  codecs: [XMediaLib.SDP.Codec.t()],
  connection: XMediaLib.SDP.Connection.t() | nil,
  dcmap: [XMediaLib.SDP.Dcmap.t()],
  direction: direction() | nil,
  extmaps: [XMediaLib.SDP.Extmap.t()],
  fingerprint: XMediaLib.SDP.Fingerprint.t() | nil,
  fmtp: [XMediaLib.SDP.Fmtp.t()],
  formats: [String.t()],
  ice_pwd: String.t() | nil,
  ice_ufrag: String.t() | nil,
  max_message_size: non_neg_integer() | nil,
  mid: String.t() | nil,
  port: non_neg_integer() | nil,
  protocol: protocol() | nil,
  rtcp_fb: [XMediaLib.SDP.RtcpFb.t()],
  rtcp_mux: boolean(),
  sctp_port: non_neg_integer() | nil,
  setup: :active | :passive | :actpass | nil,
  ssrcs: [XMediaLib.SDP.Ssrc.t()],
  type: type() | nil
}
```

Media description fields for one `m=` section.

## Fields

* `:type` - media kind (`:audio`, `:video`, `:application`, or string)
* `:port` - port number from the `m=` line (`0` means rejected/hold)
* `:protocol` - transport, e.g. `:UDP_TLS_RTP_SAVPF`
* `:formats` - payload type or format tokens from the `m=` line
* `:connection` - optional media-level `c=` override
* `:ice_ufrag` - ICE username fragment (`a=ice-ufrag`)
* `:ice_pwd` - ICE password (`a=ice-pwd`)
* `:candidates` - parsed `a=candidate` lines
* `:fingerprint` - DTLS certificate fingerprint (`a=fingerprint`)
* `:setup` - DTLS role hint (`a=setup`: `:active`, `:passive`, or `:actpass`)
* `:mid` - media identification tag for BUNDLE (`a=mid`)
* `:direction` - send/receive direction attribute
* `:rtcp_mux` - true when `a=rtcp-mux` is present
* `:codecs` - dynamic payload mappings from `a=rtpmap`
* `:fmtp` - format parameters from `a=fmtp`
* `:rtcp_fb` - RTCP feedback tokens from `a=rtcp-fb`
* `:extmaps` - RTP header extension maps from `a=extmap`
* `:ssrcs` - SSRC attributes from `a=ssrc`
* `:sctp_port` - SCTP port for data channels (`a=sctp-port`)
* `:max_message_size` - SCTP max message size (`a=max-message-size`)
* `:dcmap` - data channel maps from `a=dcmap`
* `:attributes` - other media-level `a=` lines

# `type`

```elixir
@type type() :: :audio | :video | :application | String.t()
```

Media kind from the `m=` line; known atoms or the raw string.

---

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