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 set_detected_closed_captions(&self, detected: Vec<InstreamId>)

Record the caption streams the video is now known to carry. The next master playlist advertises exactly these, one EXT-X-MEDIA TYPE=CLOSED-CAPTIONS per stream in group CLOSED_CAPTIONS_GROUP_ID, and every variant references the group. Until this is called with a non-empty list the master claims no captions.

Source

pub fn set_subtitle_renditions( &self, decls: Vec<SubtitleRenditionDecl>, ) -> Result<(), HlsOriginBuildError>

Replace the declared WebVTT subtitle renditions after construction, for a host that learns them only once the stream is seen (for example from a teletext descriptor). The next master playlist advertises exactly these in group SUBTITLES_GROUP_ID; an empty list removes the group.

§Errors

The same HlsOriginBuildError variants as HlsOriginBuilder::subtitle_renditions at build(); the previous declarations are kept on error.

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) or the operator-declared bandwidth, whichever is larger. Returns HlsMasterError::BandwidthUnknown until a segment with a measurable duration has closed and no declared bandwidth was configured.

§Errors

HlsMasterError::BandwidthUnknown when no measurable segment has been published and no declared bandwidth was configured; 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 master_playlist_with_iframes( &self, media_playlist_name: &str, iframe_playlist_name: &str, ) -> Result<String, HlsMasterError>

Like Self::master_playlist, but additionally advertises an #EXT-X-I-FRAME-STREAM-INF variant pointing at iframe_playlist_name when an I-frame playlist is currently available for this origin (fMP4, a video track, and at least one usable entry with no mid-stream gap). The plain variant is unchanged.

§Errors

As for Self::master_playlist.

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 iframe_playlist_name(&self, track_id: TrackId) -> String

The wire name of this origin’s I-frame playlist for track_id.

Source

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

The wire name of init generation generation for track_id.

Source

pub fn iframe_segment_name( &self, track_id: TrackId, seq: SegmentSeq, ext: &str, ) -> String

The wire name of the I-frame (trick-play) resource for track_id’s segment seq (issue #1422): iframe-seg-{track}-{instance}-{seq}.{ext}, the same grammar as segment_name but under the IFRAME_SEGMENT_PREFIX prefix, so the bytes it resolves to are always the stored segment bytes and never the emsg-spliced ones.

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 http_priority(&self, request: &HlsRequest) -> HttpPriority

HTTP Priority signalling for request (RFC 8216bis §6.2.6): the urgency the adapter should attach to the response. Playlists get urgency 1, parts and segments urgency 2.

Source

pub fn target_duration_violations(&self) -> u64

Number of segments whose (rounded) duration exceeded the frozen EXT-X-TARGETDURATION after first publication — a conformance degradation count (RFC 8216 §4.3.3.1).

Source

pub fn set_part_target_ms(&self, ms: u32)

Raise this origin’s PART-TARGET to ms when that exceeds the configured part target. An audio rendition whose frames do not divide the part target needs a Part Target Duration of a whole number of frames, because RFC 8216bis §4.4.4.9 requires every Partial Segment to be no longer than it. Has no effect on a classic-HLS origin.

Source

pub fn set_rendition_siblings(&self, siblings: Vec<RenditionSibling>)

Replace the sibling renditions whose live edge this origin reports.

Source

pub fn current_live_edge(&self) -> (u64, Option<u64>)

Snapshot of this origin’s current live edge as (LAST-MSN, LAST-PART), suitable for an #EXT-X-RENDITION-REPORT (RFC 8216bis §4.4.5.4). Drains this origin first and queries only this origin’s own Trunk, so callers never hold another origin’s lock.

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