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).
§What it does / what it does not
Does: finds the next join a schedule implies and computes it (channel
instant, PTS-rebase offset, discontinuity flag), and builds the
splice_insert() for entering or returning from a break, conditioned against
real candidate boundaries.
Does not:
- No transcoding or conforming. A differing codec config is a
discontinuity to signal (
transition::TransitionPlan::discontinuity). - No sample-timestamp rewriting.
transmux’s IR transform would applytransition::TransitionPlan::pts_rebase_offset; this crate computes the number.broadcast_hls::mark_init_discontinuitieswould act on the discontinuity flag; neither is a dependency here. - No boundary conditioning of its own:
scte35::build_splice_insertcallsssai_runtime::splice::condition_splice_point_wrapping. - No schedule wire format, no SCTE 224 (it covers policy and blackout
signalling, not channel assembly):
schedule::Scheduleis an in-memory model with noParse/Serializepair. - No HTTP, no tokio, no real-time clock; a
multimuxadapter is future work.
§Standards supported
| Standard | Edition | Scope | Status |
|---|---|---|---|
| ANSI/SCTE 35 | 2023r1 | splice_insert() (section 9.7.3, Table 10) via scte35-splice; clear splice_info_section wrapper | Partial: splice_insert only (no time_signal, segmentation descriptors, encryption, components); 90 kHz ticks |
| schedule model | n/a | programme / ad / slate | Not a standard (SCTE 224 not adopted) |
§Features
| Feature | Default | Effect |
|---|---|---|
std | yes | Links std; off gives #![no_std] + alloc |
serde | no | serde derives on the public types |
§Quick start
use playout_runtime::{
BreakEdge, CodecConfigId, EntryKind, Schedule, ScheduleEntry, build_splice_insert,
next_transition,
};
let mut schedule = Schedule::new();
schedule
.push(ScheduleEntry {
id: "news".into(),
kind: EntryKind::Programme,
planned_start: 0,
source_start_pts: 0,
codec_config: CodecConfigId(1),
})
.unwrap();
// A 30 s ad at 10 minutes (90 kHz ticks), cut from an asset whose own clock
// starts at 5_000, with a different codec configuration.
schedule
.push(ScheduleEntry {
id: "ad".into(),
kind: EntryKind::Ad,
planned_start: 54_000_000,
source_start_pts: 5_000,
codec_config: CodecConfigId(2),
})
.unwrap();
// The join: when, how to rebase the incoming clock, and whether to signal a
// discontinuity.
let t = next_transition(&schedule, 0).unwrap();
assert_eq!(t.plan.at_pts, 54_000_000);
assert!(t.plan.discontinuity);
assert_eq!(t.plan.rebase(5_000), Some(54_000_000));
// The splice_insert() that entering the break implies, snapped to the nearest
// real boundary (2_000 ticks before the nominal instant beats 3_000 after).
let (point, insert) = build_splice_insert(
BreakEdge::Enter,
1,
t.plan.at_pts,
&[53_998_000, 54_003_000],
5_000,
Some(2_700_000),
)
.unwrap();
assert_eq!(point.snapped_pts, 53_998_000);
assert!(insert.out_of_network_indicator);§What is implemented
schedule:ScheduleofScheduleEntry(EntryKind,CodecConfigId).transition:next_transitionreturns aPlannedTransition;TransitionPlan::plancomputesat_pts,pts_rebase_offset(i128, never clamped) anddiscontinuity;TransitionPlan::rebasereturnsNonerather than wrapping, andTransitionPlan::rebase_wrappedunrolls a raw 33-bit PTS first.scte35:build_splice_insert(circular distances modulo 2^33) andto_section, withBreakEdgenaming the break edge.
§Design notes
Sans-IO, no_std + alloc, #![forbid(unsafe_code)], structured Errors.
“A schedule that plays the right thing at the wrong timestamp is worse than no
scheduler” — timeline correctness is the primary tested property (including a
real, non-IDR-aligned cue from fixtures/scte35-ssai/). Units are 90 kHz ticks.
§Related crates
Depends on broadcast-common, ssai-runtime and scte35-splice. MSRV 1.95.0;
MIT OR Apache-2.0.
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).