std only.Expand description
LL-HLS origin engine (issue #663/#717 Stage 2): the sans-IO rolling
window/store, the blocking-reload + part-availability decision logic,
and playlist rendering, moved out of multimux so it can be shared with
any async runtime — not just tokio+axum.
§Sans-IO shape
Nothing here ever .awaits or opens a socket. MediaStore is fed
synchronously (add_part/add_segment/set_init/set_health) by
whatever pipeline produces media; MediaStore::resolve_playlist/
MediaStore::resolve_resource are poll methods returning
PlaylistOutcome/ResourceOutcome — Ready, WouldBlock,
BadRequest, or NotFound — never blocking the caller. The only
asynchrony is MediaStore::listen, which hands back a runtime-agnostic
event_listener::EventListener (a plain Future<Output = ()>) that any
executor can await or time out — not a tokio::sync::watch.
§The caller-driven wait loop
An async adapter (e.g. multimux::output::llhls) turns a WouldBlock
into an actual wait like this — the same shape as client’s poll/step
contract, mirrored on the server side:
loop {
let listener = store.listen(); // register BEFORE re-checking (no missed-wakeup race)
match store.resolve_playlist(track_id, query) {
PlaylistOutcome::Ready(body) => return Ready(body),
PlaylistOutcome::BadRequest => return BadRequest,
PlaylistOutcome::WouldBlock => {
// caller's own bounded timeout wraps `listener.await` here
}
}
}The 5 s blocking-reload cap (RFC 8216bis §6.2.5.2) and the actual
.await/tokio::time::timeout live entirely in the adapter — this module
never assumes a clock.
§std-only
Unlike crate::client, this module needs std::sync::Mutex (and the
event-listener crate’s std feature), so it is only compiled when the
crate’s std feature is enabled (the default). A caller building
--no-default-features (e.g. an embedded playback-only client) gets
crate::client but not server.
Structs§
- Blocking
Query - Blocking playlist reload query parameters (RFC 8216bis §6.2.5.2) — the
sans-IO counterpart of an adapter’s own (likely serde-
Deserialize) query-string type; the adapter maps its wire query params into this. - Media
Store - In-RAM rolling window for one served stream: bytes + timing, shared by every adapter serving that stream.
- Segment
Window Entry - One closed segment’s identity/timing — a protocol-neutral snapshot entry
returned by
MediaStore::window_segments(issue #663 P4).
Enums§
- Cache
Policy Cache-Controlpolicy an adapter applies to a resolved resource — playlists are always re-fetched for liveness (not modeled here sincePlaylistOutcome::Readyis playlist-only), while a produced init/ segment/part byte range never changes once produced.- Health
State - Ingest health of the pipeline feeding a
MediaStore, set by the caller’s supervisor loop (e.g.multimux::origin::supervisor::supervise) as it connects/reconnects the source. - Playlist
Outcome - The result of
MediaStore::resolve_playlist: either the rendered playlist is ready now, the request is malformed/abusive (RFC 8216bis §6.2.5.2 abuse prevention — reject immediately, no wait), or the awaited segment/part isn’t available yet (the caller should wait for the next change notification and re-resolve). - Resource
Outcome - The result of
MediaStore::resolve_resource: the resource’s bytes are ready, the request should wait (a preload-hinted part not yet produced), or the resource does not (and, for a part whose segment already closed without it, will never) exist.
Constants§
- DEFAULT_
TRACK_ ID - Track id for the single rendition served per stream (no multi-track/ multi-rendition support yet).
Functions§
- master_
playlist_ m3u8 - A minimal single-variant master playlist pointing at
media_playlist_name(the caller’s configured media-playlist filename — e.g. multimux’sConfig::playlist_name, defaulting to"media.m3u8") — the same regardless ofMediaStorestate (no multi-rendition support yet), so this takes no store argument. - media_
playlist_ m3u8 - Render the LL-HLS media playlist for
track_idfromstore’s current segments/live parts.