media-plane
The ingress and egress spine of a live media origin: sources are dialled or listened for, bytes pass through stages into a container demuxer, and the resulting samples, segments and timed events land in a per-program Trunk that any number of egress shapes read from.
What it does / what it does not
Does: define and implement the four-layer shape that every protocol adapter plugs into, instead of each protocol gluing its own pipeline.
Dialer|Listener ──► [ByteStage]* ──► IngestSession ──► [IrTransform]* ──► TrunkWriter
(N sources) byte→byte demux IR→IR │
▼
┌──────── Trunk ────────┐
│ sample ring │
│ segment + part log │
│ EVENT log (90 kHz) │
└───────────────────────┘
subscribe() ─► SampleCursor ─► PushEgress (defined shape, no in-tree impl)
subscribe() ─► SegmentCursor ─► SegmentEgress (DVR, MABR, ROUTE, Smooth)
resolve() ─────────────────► ServedEgress (LL-HLS, DASH, catch-up)
A Trunk is bounded everywhere: sample, segment, part and event rings evict their oldest entry rather than block the writer, and a slow reader is told so in-band (Lagged), never silently skipped. Writer cost is linear in the number of cursors, so a cursor is per distinct consumer, not per peer (single-digit reader counts by design).
Does not: open sockets or speak any wire protocol (rtsp-runtime, rtmp-runtime, srt-runtime, multimux and others supply IngestSession implementors), mux or demux containers (that is transmux), implement ST 2022-7 hitless merge (MergePolicy has no such variant, tracked as #752), provide a disk or object-store archive (the caller supplies a SegmentSink), or support pull-style sources (HLS/DASH/Smooth) in the ingest session yet (a recorded seam: IngestSession::poll_transmit cannot express "issue a GET").
Standards supported
media-plane implements an architecture, not a wire standard, so there is no spec edition to cite. The standards it touches:
| Standard | Edition | Scope here | Status | Notes |
|---|---|---|---|---|
| ISO/IEC 13818-1 (MPEG-2 Systems) | n/a | 90 kHz timestamp clock for the event log; 33-bit PTS wrap-unroll via timed-metadata |
Time base only | Container parsing lives in transmux |
ANSI/SCTE 35, DASH emsg, HLS EXT-X-DATERANGE |
n/a | Timed events stored as timed_metadata::TimedEvent, anchored by media time or segment, never given a fabricated time |
Typed (via timed-metadata) |
|
| SMPTE ST 2022-7 | 2019 (vendored) | Not implemented | Not implemented | The byte_merge module documents why it is absent rather than stubbed |
Features
| Feature | Default | Description |
|---|---|---|
std |
yes | Trunk, ingress, egress, retention and their re-exports, plus the transmux, timed-metadata, event-listener and parking_lot dependencies. Without it only the byte layer exists. |
no_std note: only the byte layer (byte_stage, byte_tap, byte_merge, ids) is no_std + alloc. Trunk and everything above it need std. cargo build --no-default-features builds the byte layer alone.
Quick start
Demux a real broadcast capture with transmux, publish every sample into a Trunk, and read them back through a SampleCursor:
use NonZeroUsize;
use ;
use ;
let nz = ;
// timed, sparse, segment, event and part ring capacities.
let trunk = new;
let writer = trunk.writer.expect;
let mut cursor = trunk.subscribe; // live tail: reads what is published from now on
let ts = read.unwrap;
let mut demux = new;
for chunk in ts.chunks
demux.finish;
while let Some = demux.poll_event
let mut timed = 0;
while let Some = cursor.poll
assert!;
The byte layer's multi-input primitive, with two UDP-style sources reduced to one stream:
use Timestamp;
use Bytes;
use ;
let mut merge = new;
merge.feed.unwrap;
let = merge.poll.expect;
assert_eq!;
The full ingress to Trunk to cursor pipeline, driven by IngestDriver against the same capture, is examples/ingest_trunk_playback.rs; examples/byte_tap_wire_observer.rs shows ByteTap's non-blocking observer contract.
What is implemented
- Byte layer:
ByteStage(pre-demux byte-to-byte work, a specialisation ofbroadcast_common::Stage),ByteTap(non-blocking positional observer for conformance and analysis, withLagged),ByteMerge(the single bounded N-to-1 primitive, withMergePolicy::FirstArrivalandFailover; messages, not a byte soup). Trunk: dual-retention sample ring (Timed,Sparse), segment log with pinning cursors for lossless DVR (pin_segments,ArchiveOverrunpolicy instead of writer back-pressure), live part log, 90 kHz event log (EventCursor,EventAnchor,events_between,events_in_segment), reader wake throughlisten(), single-writer enforcement with handover across reconnects,time_anchor().- Typed ids (
ids):SegmentSeqandPartIndexnewtypes with checked arithmetic (checked_next,checked_add,checked_sub,checked_distance_from), explicitwrapping_nextandsaturating_next, and no overflowing operators. Tracks aretransmux::TrackId. A swapped segment/part argument is a compile error. ingress:Dialer,Listener,IngestSession,IngestDriver,ListenDriver,DialSupervisor,ReconnectPolicy,HandshakePolicy,HealthState, with amax_programsbound on how many trunks one session may mint.egress:ServedEgress(request/response with boundedAwait; production implementors inhls-runtimeandmultimux),SegmentEgress(production implementors inmultimux),PushEgress(a defined shape; its only impls are test doubles,multimux's push path drives its own transport off a sample cursor).retention:Retention::HotOnlyandTiered,RetentionDriverdraining a pinning segment cursor into a caller-supplied sans-IOSegmentSink, andlocatefor catch-up against an evicted segment.
Design notes
Sans-IO and bounded: no thread or socket is created here, every queue has a cap, and over-capacity is an explicit event (Lagged, Degraded, Discontinuity), never silent loss. The event log never fabricates a media time for a segment-relative (emsg v0) or wall-clock-only (SCTE 35 splice_schedule) event until the anchor it needs exists. #[non_exhaustive] on policies and errors; a lexical no-hand-roll guard and label-coverage tests apply.
Related crates
Depends on broadcast-common (Stage, Timestamp, Demand), transmux (the neutral IR and TrackId) and timed-metadata (event model). Consumed by hls-runtime (HlsOrigin as a ServedEgress) and multimux (origins and the DVR recorder), and by compliance-probe (a Trunk/ByteTap consumer). The design document is docs/superpowers/specs/2026-07-26-media-plane-architecture.md in the workspace.
MSRV and licence
MSRV 1.95.0. Licensed under MIT OR Apache-2.0.