dash_runtime/address/
base_index.rs1use broadcast_common::Parse;
9use transmux::SegmentIndexBox;
10
11use super::AddressError;
12use crate::error::Unsupported;
13use crate::mpd::model::ByteRange;
14
15const REFERENCE_TYPE_SIDX: u8 = 1;
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20#[non_exhaustive]
21pub struct IndexedSegment {
22 pub time: u64,
24 pub duration: u64,
26 pub range: ByteRange,
28 pub starts_with_sap: bool,
30}
31
32pub fn anchor_after(index_range: &ByteRange) -> Result<u64, AddressError> {
38 index_range
39 .last
40 .and_then(|l| l.checked_add(1))
41 .ok_or(AddressError::Unsupported(Unsupported::OpenEndedRange))
42}
43
44pub fn parse_index(bytes: &[u8]) -> Result<SegmentIndexBox, AddressError> {
49 SegmentIndexBox::parse(bytes).map_err(|e| AddressError::Sidx(e.to_string()))
50}
51
52pub fn segments(sidx: &SegmentIndexBox, anchor: u64) -> Result<Vec<IndexedSegment>, AddressError> {
59 let mut offset = anchor
60 .checked_add(sidx.first_offset)
61 .ok_or(AddressError::Overflow)?;
62 let mut time = sidx.earliest_presentation_time;
63 let mut out = Vec::with_capacity(sidx.references.len());
64 for r in &sidx.references {
65 if r.reference_type == REFERENCE_TYPE_SIDX {
66 return Err(AddressError::Unsupported(Unsupported::HierarchicalSidx));
67 }
68 if r.referenced_size == 0 {
69 continue;
70 }
71 let size = u64::from(r.referenced_size);
72 let last = offset
73 .checked_add(size)
74 .and_then(|e| e.checked_sub(1))
75 .ok_or(AddressError::Overflow)?;
76 let duration = u64::from(r.subsegment_duration);
77 out.push(IndexedSegment {
78 time,
79 duration,
80 range: ByteRange::new(offset, last),
81 starts_with_sap: r.starts_with_sap != 0,
82 });
83 offset = last.checked_add(1).ok_or(AddressError::Overflow)?;
84 time = time.checked_add(duration).ok_or(AddressError::Overflow)?;
85 }
86 Ok(out)
87}