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::Scheduleis therefore a plain in-memory model with noParse/Serializepair — there is no wire format to be symmetric about. - This crate builds on
ssai-runtimerather than duplicating it.ssai_runtime::splice::condition_splice_pointalready owns nearest-boundary splice-point conditioning (with an explicit tolerance, refusing rather than silently snapping when nothing is close enough);scte35::build_splice_insertcalls 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 applytransition::TransitionPlan::pts_rebase_offsetto real sample PTS/DTS values; this crate computes the number, not the rewrite. Likewisebroadcast_hls::mark_init_discontinuitiesis what would act ontransition::TransitionPlan::discontinuityat the playlist/init-segment level — neither dependency is pulled in here. - No HTTP, no tokio. A
multimuxadapter driving a real channel clock against this crate’s planning is deliberately future work, not this crate — mirroring thertsp-runtime/hls-runtimeandssai-runtimesplit 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 withscte35-splice’s ownSerialize, not hand-assembled bytes. - transition
- Transition planning: given a
Scheduleand the current channel-timeline position, what transition happens next, at what instant, and what timeline-continuity actions it implies.
Structs§
- Conditioned
Splice Point - The result of conditioning one splice point against a set of candidate boundaries (segment starts, or sync-sample/IDR timestamps).