use crate::{Mp4Parser, ParsedBox, Result, bail, data};
#[derive(Debug, Clone)]
pub struct SidxRange {
pub end: u64,
pub start: u64,
}
#[derive(Debug, Clone)]
pub struct SidxBox {
pub ranges: Vec<SidxRange>,
}
impl SidxBox {
pub fn from_init(data: &[u8], offset: u64) -> Result<Option<Self>> {
let sidx_box = data!();
let sidx_box_c = sidx_box.clone();
Mp4Parser::new()
.full_box("sidx", move |mut box_| {
*sidx_box_c.borrow_mut() = Some(Self::new(&mut box_, offset)?);
Ok(())
})
.parse(data, false, false)?;
Ok(sidx_box.take())
}
pub fn new(box_: &mut ParsedBox, offset: u64) -> Result<Self> {
if box_.version.is_none() {
bail!("SIDX is a full box and should have a valid version.");
}
let reader = &mut box_.reader;
let version = box_.version.unwrap();
let mut references = Vec::new();
reader.skip(4)?;
let timescale = reader.read_u32()?;
if timescale == 0 {
bail!("SIDX box has invalid timescale.");
}
let _earliest_presentation_time;
let first_offset;
if version == 0 {
_earliest_presentation_time = reader.read_u32()? as u64;
first_offset = reader.read_u32()? as u64;
} else {
_earliest_presentation_time = reader.read_u64()?;
first_offset = reader.read_u64()?;
}
reader.skip(2)?;
let reference_count = reader.read_u16()?;
let mut start_byte = offset + box_.size as u64 + first_offset;
for _ in 0..reference_count {
let chunk = reader.read_u32()?;
let reference_type = (chunk & 0x80000000) >> 31;
let reference_size = chunk & 0x7FFFFFFF;
let _subsegment_duration = reader.read_u32()?;
reader.skip(4)?;
if reference_type == 1 {
bail!("Hierarchical SIDXs are not supported.");
}
references.push(SidxRange {
end: start_byte + reference_size as u64 - 1,
start: start_byte,
});
start_byte += reference_size as u64;
}
box_.parser.stop();
Ok(Self { ranges: references })
}
}