use super::{ttml_text_parser, Subtitles};
use crate::{parser, parser::Mp4Parser, Error, Result};
use std::sync::{Arc, Mutex};
pub struct Mp4TtmlParser;
impl Mp4TtmlParser {
pub fn parse_init(data: &[u8]) -> Result<Self> {
let saw_stpp = Arc::new(Mutex::new(false));
let saw_stpp_c = saw_stpp.clone();
Mp4Parser::default()
._box("moov", Arc::new(parser::children))
._box("trak", Arc::new(parser::children))
._box("mdia", Arc::new(parser::children))
._box("minf", Arc::new(parser::children))
._box("stbl", Arc::new(parser::children))
.full_box("stsd", Arc::new(parser::sample_description))
._box(
"stpp",
Arc::new(move |mut _box| {
*saw_stpp_c.lock().unwrap() = true;
_box.parser.stop();
Ok(())
}),
)
.parse(data, None, None)?;
let saw_stpp = *saw_stpp.lock().unwrap();
if !saw_stpp {
return Err(Error::new("STPP box not found."));
}
Ok(Self)
}
pub fn parse_media(&self, data: &[u8]) -> Result<Subtitles> {
let saw_mdat = Arc::new(Mutex::new(false));
let cues = Arc::new(Mutex::new(vec![]));
let saw_mdat_c = saw_mdat.clone();
let cues_c = cues.clone();
Mp4Parser::default()
._box(
"mdat",
parser::alldata(Arc::new(move |data| {
*saw_mdat_c.lock().unwrap() = true;
let xml = String::from_utf8(data).map_err(|_| {
Error::new_decode("MDAT box payload as valid utf-8 data.")
})?;
cues_c.lock().unwrap().append(
&mut ttml_text_parser::parse(&xml)
.map_err(|x| {
Error::new_decode(format!(
"xml string as ttml content.\n\n{}\n\n{:#?}",
xml, x
))
})?
.into_cues(),
);
Ok(())
})),
)
.parse(data, Some(false), None)?;
let saw_mdat = *saw_mdat.lock().unwrap();
if !saw_mdat {
return Err(Error::new("MDAT box not found."));
}
let cues = cues.lock().unwrap().clone();
Ok(Subtitles::new(cues))
}
}