Skip to main content

ssai_runtime/
lib.rs

1//! Sans-IO SCTE-35 server-side ad insertion (SSAI) session core — issue #929.
2//!
3//! Per-session ad-break state ([`session`]), a pluggable ad-decision trait
4//! ([`decision`]), SCTE-35 splice-point conditioning against real segment or
5//! keyframe boundaries ([`splice`]), and per-session HLS Interstitial
6//! (`EXT-X-DATERANGE CLASS="com.apple.hls.interstitial"`,
7//! draft-pantos-hls-rfc8216bis Appendix D, transcribed at
8//! `broadcast-hls/docs/interstitials.md`) playlist rendering over
9//! [`broadcast_hls::MediaPlaylist`] ([`playlist`]).
10//!
11//! Mirrors the `rtsp-runtime`/`hls-runtime` split the rest of the workspace
12//! uses: this crate is the driveable, sans-IO core; an HTTP-facing adapter
13//! (e.g. a `multimux` output) is separate, later work that layers on top of
14//! it rather than living inside it.
15//!
16//! ## What this crate is not
17//!
18//! - **No HTTP client, no VAST/VMAP.** [`decision::AdDecisionProvider`] is
19//!   the only extension point for "which ad to play" — implementing it (and
20//!   doing whatever network I/O that requires) is entirely the caller's
21//!   job. This crate never makes a network call.
22//! - **No media manipulation.** Splicing the actual CMAF/TS bytes at the
23//!   conditioned splice point is `transmux`'s job (its splice/SSAI IR
24//!   transforms and PTS/DTS rebase); this crate only decides *where* that
25//!   splice point is and *what* the per-session manifest should say about
26//!   it.
27//! - **No per-viewer media cursor.** Every viewer in a break watches one of
28//!   a small set of pre-conditioned ad assets, and outside a break sees
29//!   byte-identical primary content — see the issue's design-decision
30//!   comment. What differs per session is a small [`session::BreakState`]
31//!   record, never a `media_plane::Trunk` cursor; `media-plane`'s
32//!   O(N)-in-cursor-count rule is about the shared media rings, not this.
33//! - **No `multimux` HTTP wiring.** That adapter is future work, not this
34//!   crate.
35//!
36//! `no_std` + `alloc`.
37#![no_std]
38#![forbid(unsafe_code)]
39#![cfg_attr(docsrs, feature(doc_cfg))]
40
41extern crate alloc;
42
43pub mod decision;
44pub mod error;
45pub mod playlist;
46pub mod session;
47pub mod splice;
48
49pub use decision::{
50    AdBreakDecision, AdDecisionProvider, AssetSource, BreakContext, RestrictMode, SnapMode,
51};
52pub use error::{Error, Result};
53pub use playlist::{
54    INTERSTITIAL_CLASS, InterstitialDateRange, SessionPlaylistBase, render_session_playlist,
55};
56pub use session::{BreakState, SessionStore};
57pub use splice::{
58    ConditionedSplicePoint, PTS_MODULUS_33, SnapDirection, condition_splice_point,
59    condition_splice_point_wrapping,
60};