dash_runtime/address/
base_index.rs1use broadcast_common::Parse;
9use transmux::SegmentIndexBox;
10
11use super::AddressError;
12use crate::error::Unsupported;
13use broadcast_dash::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 time = time
70 .checked_add(u64::from(r.subsegment_duration))
71 .ok_or(AddressError::Overflow)?;
72 continue;
73 }
74 let size = u64::from(r.referenced_size);
75 let last = offset
76 .checked_add(size)
77 .and_then(|e| e.checked_sub(1))
78 .ok_or(AddressError::Overflow)?;
79 let duration = u64::from(r.subsegment_duration);
80 out.push(IndexedSegment {
81 time,
82 duration,
83 range: ByteRange::new(offset, last),
84 starts_with_sap: r.starts_with_sap != 0,
85 });
86 offset = last.checked_add(1).ok_or(AddressError::Overflow)?;
87 time = time.checked_add(duration).ok_or(AddressError::Overflow)?;
88 }
89 Ok(out)
90}