Skip to main content

scte35_to_dash/
scte35_to_dash.rs

1//! Demonstrate SCTE-35 → DASH `emsg` conversion.
2//!
3//! Parses a hex `splice_info_section` (Unified Streaming splice ID 2002),
4//! builds a [`Timeline`], and serializes the event as a DASH `emsg` box,
5//! printing the hex bytes.
6//!
7//! Run with:
8//! ```text
9//! cargo run -p timed-metadata --example scte35_to_dash
10//! ```
11
12use mp4_emsg::PresentationTime;
13use timed_metadata::{convert::EmsgConfig, TimeAnchor, Timeline};
14
15fn main() {
16    // Real Unified Streaming splice: ID 2002, out-of-network, break_duration 24 s.
17    let hex = "FC302100000000000000FFF01005000007D27FEF7F7E0020F580C0000000000088B9661D";
18    let raw: Vec<u8> = (0..hex.len())
19        .step_by(2)
20        .map(|i| u8::from_str_radix(&hex[i..i + 2], 16).unwrap())
21        .collect();
22
23    let anchor = TimeAnchor {
24        pts_90k: 0,
25        utc_epoch_ms: 1_705_320_000_000,
26    };
27    let mut timeline = Timeline::with_anchor(anchor);
28    let event = timeline.push_scte35(&raw).expect("valid splice");
29
30    // Build emsg config: 90 kHz timescale, segment-relative delta 0, 24 s duration.
31    let cfg = EmsgConfig {
32        timescale: 90_000,
33        presentation: PresentationTime::Delta(0),
34        event_duration: 2_160_000, // 24s * 90000
35        value: "34".to_string(),   // segmentation_type_id for Provider Ad Start
36        id: event.id.unwrap_or(0),
37    };
38
39    let emsg_bytes = timeline
40        .to_emsg(&event, &cfg)
41        .expect("SCTE-35-sourced event");
42
43    println!("Event kind  : {}", event.kind);
44    println!("Event id    : {:?}", event.id);
45    println!("emsg length : {} bytes", emsg_bytes.len());
46    println!();
47    println!(
48        "emsg hex: {}",
49        emsg_bytes
50            .iter()
51            .map(|b| format!("{:02X}", b))
52            .collect::<Vec<_>>()
53            .join("")
54    );
55
56    // Verify round-trip: extract the splice from the emsg and compare.
57    use timed_metadata::convert::emsg_to_scte35;
58    let extracted = emsg_to_scte35(&emsg_bytes).expect("round-trip");
59    assert_eq!(extracted, raw, "splice bytes must survive verbatim");
60    println!();
61    println!("Round-trip verified: splice bytes survive verbatim in emsg message_data.");
62}