pub struct HlsOrigin { /* private fields */ }std only.Expand description
The LL-HLS origin ServedEgress: renders playlists and resolves
blocking-reload/part-availability requests for one stream, backed by a
shared Trunk. See this module’s own doc for exactly what comes
straight from the Trunk and what needs the small synced Window.
Implementations§
Source§impl HlsOrigin
impl HlsOrigin
Sourcepub fn builder(trunk: Arc<Trunk>) -> HlsOriginBuilder
pub fn builder(trunk: Arc<Trunk>) -> HlsOriginBuilder
Start building an HlsOrigin over trunk — see HlsOriginBuilder
for the required fields (target_duration_secs/window_segments),
the container choice, and how to opt into LL-HLS.
Sourcepub fn set_init(&self, bytes: impl Into<Bytes>)
pub fn set_init(&self, bytes: impl Into<Bytes>)
Store the init segment bytes — see this module’s doc for why an init
segment is not something any Trunk ring holds.
Documented no-op under Container::MpegTs: this origin’s
MpegTs grammar has no init resource and never emits #EXT-X-MAP
by default (see Container’s own doc), so bytes stored here are
never advertised or served in that mode. The method stays callable
regardless of container so a caller sharing one code path across
both (e.g. a segmenter that always calls set_init once available)
does not need to branch on which container it configured.
Under Container::Fmp4 the init segment is also parsed for its
tracks, from which the master playlist’s CODECS is derived (see
Self::master_playlist); bytes that do not parse (or a track whose
codec string cannot be built) make CODECS unknown (omitted, and any
value from an earlier init is dropped), never guessed at.
Sourcepub fn set_track_specs(&self, specs: &[TrackSpec]) -> Result<(), Error>
pub fn set_track_specs(&self, specs: &[TrackSpec]) -> Result<(), Error>
Tell the origin which tracks it serves, so the master playlist can
carry CODECS (RFC 8216 §4.3.4.2: every EXT-X-STREAM-INF SHOULD) —
derived from each track’s codec config with the RFC 6381 builders
transmux uses for DASH. Opaque data/subtitle tracks have no codec
string and are left out. Self::set_init does this itself for
fMP4; call this for a Container::MpegTs origin, whose segments
carry no init segment to read the codecs from.
§Errors
The transmux error for a track whose codec string cannot be built
(for example a malformed AAC esds); CODECS is then left as it was.
Sourcepub fn master_playlist(
&self,
media_playlist_name: &str,
) -> Result<String, HlsMasterError>
pub fn master_playlist( &self, media_playlist_name: &str, ) -> Result<String, HlsMasterError>
The master playlist for this origin, pointing at media_playlist_name:
one #EXT-X-STREAM-INF whose BANDWIDTH is the highest segment
bitrate this origin has published (RFC 8216 §4.3.4.2: an upper bound
of the peak segment bitrate, measured as segment bytes over its
duration, rounded up) and whose CODECS comes from
Self::set_init/Self::set_track_specs (omitted while unknown).
Until a segment with a measurable duration has closed there is
nothing to measure and BANDWIDTH is the fixed 5 Mb/s estimate
master_playlist_m3u8 uses.
§Errors
HlsMasterError::BandwidthOverflow when the measured BANDWIDTH
does not fit the u32 of a master playlist variant;
HlsMasterError::Render when the playlist cannot be rendered.
Sourcepub fn instance(&self) -> u64
pub fn instance(&self) -> u64
This origin’s instance token: a number that differs for every origin
built, in this process and across restarts (see
HlsOriginBuilder::instance), and is part of every resource name
served immutable — init-{track}-{instance}-{generation}.mp4,
seg-{track}-{instance}-{msn}.{ext},
part-{track}-{instance}-{msn}.{idx}.{ext}. A name therefore maps to
one origin’s bytes for ever: a reconnect (new Trunk, numbers
restarting, possibly a different SPS/ASC), a process restart with no
DVR, a replacement origin reusing the open segment’s number — none can
put new bytes under a name a cache may already hold. Playlists name
these URIs, so players are unaffected. A request carrying another
instance’s token is NotFound. The unnamed legacy forms
(seg-{track}-{msn}, part-{track}-{msn}.{idx}, used by DASH/Smooth
templates that cannot carry the token) still resolve but are
CachePolicy::NoCache; the bare init-{track}.mp4 is the current
init, also CachePolicy::NoCache.
Sourcepub fn init_name(&self, track_id: u32, generation: u32) -> String
pub fn init_name(&self, track_id: u32, generation: u32) -> String
The wire name of init generation generation for track_id.
Sourcepub fn media_sequence_offset(&self) -> u64
pub fn media_sequence_offset(&self) -> u64
The offset added to every Media Sequence Number this origin shows (see
HlsOriginBuilder::media_sequence_offset): the number in a segment’s
URI/playlist is this plus its origin sequence number
(ClosedSegment::sequence_number).
Sourcepub fn next_media_sequence(&self) -> u64
pub fn next_media_sequence(&self) -> u64
The Media Sequence Number the next closed segment will be shown with (last closed segment + 1, plus the configured offset).
A fresh Trunk numbers its segments from 1 again, so an origin
replacing this one over a new Trunk (a reconnect) must pass
next_media_sequence() to
HlsOriginBuilder::media_sequence_offset: the new origin’s first
segment (sequence number one) is then shown one above this value — the
number this origin’s open segment was shown with is skipped, since
its parts were already served — and the Media Sequence Number clients
see keeps increasing (RFC 8216bis §6.2.2).
Sourcepub fn init_bytes(&self) -> Option<Bytes>
pub fn init_bytes(&self) -> Option<Bytes>
The fMP4 init segment bytes, if set.
Sourcepub fn closed_segments(&self) -> Vec<ClosedSegment>
pub fn closed_segments(&self) -> Vec<ClosedSegment>
A snapshot of this origin’s currently-advertised closed segments
(drains the cursor first, same as render_playlist) — ascending by
sequence number.
Exists for a caller that needs to merge this origin’s live window
with a different source of segments over the same numbering
(multimux’s DVR archive, issue #900: catch-up serving must present
one continuous playlist spanning the archive and the still-live
tail that hasn’t been archived yet). Reuses the one cursor drain
already maintains rather than making the caller open a second
cursor on the same Trunk just to learn the same window
render_playlist itself renders — media_plane’s own module doc:
writer cost is O(N) in cursor count, so a cursor is per distinct
consumer, never per peer, and never duplicated for data another
cursor already tracks.
Trait Implementations§
Source§impl ServedEgress for HlsOrigin
impl ServedEgress for HlsOrigin
Source§type Request = HlsRequest
type Request = HlsRequest
Source§type Body = HlsBody
type Body = HlsBody
Source§fn resolve(
&self,
request: HlsRequest,
now: Timestamp,
await_policy: AwaitPolicy,
) -> EgressResponse<HlsBody>
fn resolve( &self, request: HlsRequest, now: Timestamp, await_policy: AwaitPolicy, ) -> EgressResponse<HlsBody>
request against this implementation’s current state at
time now, bounded by await_policy — see
EgressResponse::Await’s contract.