Skip to main content

Crate playout_runtime

Crate playout_runtime 

Source
Expand description

Sans-IO linear channel playout — issue #748.

A schedule model for assembling a linear channel from an ordered list of sources (schedule), the transition planning that turns “what’s next” into a concrete timeline-continuity plan (transition), and the SCTE-35 splice_insert() emission points a transition implies (scte35).

§Design decisions (issue #748’s design-decision comment settles these)

  • The schedule format is ours to define. There is no applicable open standard for “ordered channel-assembly playlist” to adopt: SCTE 224 (ESNI) covers policy/blackout signalling, not channel assembly, and is paywalled besides. schedule::Schedule is therefore a plain in-memory model with no Parse/Serialize pair — there is no wire format to be symmetric about.
  • This crate builds on ssai-runtime rather than duplicating it. ssai_runtime::splice::condition_splice_point already owns nearest-boundary splice-point conditioning (with an explicit tolerance, refusing rather than silently snapping when nothing is close enough); scte35::build_splice_insert calls it rather than re-implementing the same nearest-boundary math a second time. This crate’s own job is deciding when a transition happens (the schedule); ssai-runtime’s is deciding how the splice lands against real boundaries.
  • The hard part is the transition, not the schedule. Joining two sources means timeline continuity: a PTS-rebase offset (transition::TransitionPlan::rebase) so the incoming source’s own clock lands continuously on the shared channel timeline, and a discontinuity flag (transition::TransitionPlan::discontinuity) when the codec configuration changes across the join. “A schedule that plays the right thing at the wrong timestamp is worse than no scheduler” — this crate’s tests hold timeline correctness as the primary property, not scheduling logic.

§What this crate is not

  • No transcoding or conforming. A differing codec config across a transition is a discontinuity to signal (transition::TransitionPlan::discontinuity), never something this crate re-encodes. This workspace parses containers and never touches the codec bitstream, and that holds here too.
  • No actual sample-timestamp rewriting. transmux’s IR transform is what would apply transition::TransitionPlan::pts_rebase_offset to real sample PTS/DTS values; this crate computes the number, not the rewrite. Likewise broadcast_hls::mark_init_discontinuities is what would act on transition::TransitionPlan::discontinuity at the playlist/init-segment level — neither dependency is pulled in here.
  • No HTTP, no tokio. A multimux adapter driving a real channel clock against this crate’s planning is deliberately future work, not this crate — mirroring the rtsp-runtime/hls-runtime and ssai-runtime split the rest of the workspace uses.

no_std + alloc.

Re-exports§

pub use error::Error;
pub use error::Result;
pub use schedule::CodecConfigId;
pub use schedule::EntryKind;
pub use schedule::Schedule;
pub use schedule::ScheduleEntry;
pub use scte35::BreakEdge;
pub use scte35::build_splice_insert;
pub use scte35::to_section;
pub use transition::PlannedTransition;
pub use transition::TransitionPlan;
pub use transition::next_transition;

Modules§

error
Crate error type.
schedule
The channel schedule: an ordered list of entries (programme / ad / slate).
scte35
SCTE-35 emission points a transition implies (issue #748): splice_insert() — ANSI/SCTE 35 2023r1 §9.7.3, Table 10 — built and serialized with scte35-splice’s own Serialize, not hand-assembled bytes.
transition
Transition planning: given a Schedule and the current channel-timeline position, what transition happens next, at what instant, and what timeline-continuity actions it implies.

Structs§

ConditionedSplicePoint
The result of conditioning one splice point against a set of candidate boundaries (segment starts, or sync-sample/IDR timestamps).