use crate::error::{Error, Result};
use alloc::{string::String, vec::Vec};
use mp4_emsg::{EmsgBox, PresentationTime};
pub const SCTE35_SCHEME: &str = "urn:scte:scte35:2013:bin";
#[derive(Debug, Clone)]
pub struct EmsgConfig {
pub timescale: u32,
pub presentation: PresentationTime,
pub event_duration: u32,
pub value: String,
pub id: u32,
}
pub fn scte35_to_emsg(splice_raw: &[u8], cfg: &EmsgConfig) -> Result<Vec<u8>> {
let boxx = EmsgBox {
scheme_id_uri: SCTE35_SCHEME,
value: &cfg.value,
timescale: cfg.timescale,
presentation_time: cfg.presentation,
event_duration: cfg.event_duration,
id: cfg.id,
message_data: splice_raw,
};
Ok(boxx.to_vec()?)
}
pub fn emsg_to_scte35(emsg_bytes: &[u8]) -> Result<Vec<u8>> {
let boxx = EmsgBox::parse(emsg_bytes)?;
if !boxx.is_scte35() {
return Err(Error::UnsupportedScheme {
scheme: String::from(boxx.scheme_id_uri),
});
}
Ok(boxx.message_data.to_vec())
}
#[cfg(test)]
mod tests {
use super::*;
use alloc::string::ToString;
fn splice_2002() -> alloc::vec::Vec<u8> {
let hex = "FC302100000000000000FFF01005000007D27FEF7F7E0020F580C0000000000088B9661D";
(0..hex.len())
.step_by(2)
.map(|i| u8::from_str_radix(&hex[i..i + 2], 16).unwrap())
.collect()
}
#[test]
fn scte35_to_emsg_embeds_splice_verbatim_then_round_trips() {
let splice = splice_2002();
let cfg = EmsgConfig {
timescale: 90_000,
presentation: PresentationTime::Delta(0),
event_duration: 2_160_000,
value: "1".to_string(),
id: 1,
};
let emsg = scte35_to_emsg(&splice, &cfg).unwrap();
let extracted = emsg_to_scte35(&emsg).unwrap();
assert_eq!(extracted, splice);
}
}