Skip to main content

HlsOrigin

Struct HlsOrigin 

Source
pub struct HlsOrigin { /* private fields */ }
Available on crate feature 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

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn init_name(&self, track_id: u32, generation: u32) -> String

The wire name of init generation generation for track_id.

Source

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).

Source

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).

Source

pub fn init_bytes(&self) -> Option<Bytes>

The fMP4 init segment bytes, if set.

Source

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

Source§

type Request = HlsRequest

The protocol-specific request shape (e.g. LL-HLS’s Media Sequence Number + part index; a DASH segment/manifest request; a catch-up time range) — owned by the implementing crate, not this one.
Source§

type Body = HlsBody

The protocol-specific resolved body (a playlist string, manifest XML, segment bytes, …).
Source§

fn resolve( &self, request: HlsRequest, now: Timestamp, await_policy: AwaitPolicy, ) -> EgressResponse<HlsBody>

Resolve request against this implementation’s current state at time now, bounded by await_policy — see EgressResponse::Await’s contract.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more