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};