# `Membrane.MPEG.TS.Muxer`
[🔗](https://github.com/kim-company/membrane_mpeg_ts_plugin/blob/main/lib/membrane/mpeg/ts/muxer.ex#L1)

Experimental MPEG-TS Muxer. Supports 1 program with AAC and H264 in it only for now.

Inputs must be attached before the element enters the playing state. Audio&Video
are going to be interleaved by their timing.

Each buffer is going to end in its own PES packet, hence NALu units must be grouped
accordingly, as well as ADTS AAC frames.

Use `profile:` for well-known stream_type+descriptor combinations (e.g. `:opus_mpeg_ts`).
Custom payloads can be muxed by supplying `stream_type:` and `descriptors:`.

## Timestamp sanitization for non-AV streams

Non-audio/video streams (e.g. subtitles, data, cues) may produce out-of-order
timestamps — for instance, a speech-to-text editor emitting a corrected sentence
whose start time precedes an already-emitted sentence's end time.

Rather than crashing (as `TimestampQueue` requires monotonic per-pad timestamps),
the muxer applies best-effort sanitization for these streams:

  * **Clamp**: when `dts || pts` is earlier than the last timestamp on the pad,
    but the buffer still has remaining duration (`metadata.to > last_ts`), the
    timestamp field used by that buffer is clamped to `last_ts`.
  * **Drop**: when the buffer is entirely in the past (`metadata.to <= last_ts`),
    or when `metadata.to` is absent and the buffer timestamp regresses, the
    buffer is dropped.

Both cases emit a warning log. Audio and video pads are never sanitized — an
out-of-order buffer on those pads indicates a serious upstream bug and will
crash as before.
## Pads

### `:input`

Accepted formats:
```
_any
```

Direction: | `:input`
Availability: | `:on_request`
Flow control: | `:auto`
Pad options:

- `stream_type`  

  ```
  atom() | nil
  ```
  
  Default value: `nil`  
  Each input is going to become a stream in the PMT with this assigned type.
  See MPEG.TS.PMT.

- `profile`  

  ```
  atom() | nil
  ```
  
  Default value: `nil`  
  Well-known stream profile (e.g. :opus_mpeg_ts, :scte35).

- `pid`  

  ```
  pos_integer() | nil
  ```
  
  Default value: `nil`  
  Allows to specify the PID in which this stream should be muxed.

- `wait_on_buffers?`  

  ```
  boolean()
  ```
  
  Default value: `true`  
  Block muxer until a buffer on this pad arrives.

- `descriptors`  

  ```
  list()
  ```
  
  Default value: `[]`  
  List of ES descriptors to add to the PMT for this stream.

- `pcr?`  

  ```
  boolean()
  ```
  
  Default value: `false`  
  Mark this stream as the PCR (Program Clock Reference) stream.
  This sets the stream's PID as pcr_pid in the PMT and embeds PCR values
  in the adaptation field of packets. Typically used for video streams.

### `:output`

Accepted formats:
```
Membrane.RemoteStream
```

Direction: | `:output`
Availability: | `:always`
Flow control: | `:auto`

# `input_pad_opts`

```elixir
@type input_pad_opts() :: [
  stream_type: atom() | nil,
  profile: atom() | nil,
  pid: pos_integer() | nil,
  wait_on_buffers?: boolean(),
  descriptors: list(),
  pcr?: boolean()
]
```

Options for pad `:input`

---

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