1use thiserror::Error;
15
16use super::model::{
17 AdaptationSet, BaseInfo, CommonAttributes, MultiInfo, Period, Representation, SegmentLayer,
18 SegmentTemplate, SegmentTimeline, SegmentUrl,
19};
20
21pub const DEFAULT_TIMESCALE: u64 = 1;
23pub const DEFAULT_START_NUMBER: u64 = 1;
25pub const DEFAULT_PRESENTATION_TIME_OFFSET: u64 = 0;
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
30#[non_exhaustive]
31pub enum InheritError {
32 #[error(
34 "SegmentTemplate and SegmentList both appear along one Period/AdaptationSet/Representation chain"
35 )]
36 TemplateAndList,
37 #[error("both @duration and SegmentTimeline are present (on one level or across inheritance)")]
41 DurationAndTimeline,
42}
43
44#[derive(Debug, Clone, PartialEq)]
46#[non_exhaustive]
47pub struct ResolvedMulti {
48 pub base: BaseInfo,
50 pub timescale: u64,
52 pub presentation_time_offset: u64,
54 pub duration: Option<u64>,
56 pub start_number: u64,
58 pub end_number: Option<u64>,
60 pub timeline: Option<SegmentTimeline>,
62}
63
64#[derive(Debug, Clone, PartialEq)]
66#[non_exhaustive]
67pub struct TemplateInfo {
68 pub multi: ResolvedMulti,
70 pub media: Option<String>,
72 pub index: Option<String>,
74 pub initialization: Option<String>,
76 pub bitstream_switching: Option<String>,
78}
79
80#[derive(Debug, Clone, PartialEq)]
82#[non_exhaustive]
83pub struct ListInfo {
84 pub multi: ResolvedMulti,
86 pub urls: Vec<SegmentUrl>,
88}
89
90#[derive(Debug, Clone, PartialEq)]
93#[non_exhaustive]
94pub enum SegmentInfo {
95 Template(TemplateInfo),
97 List(ListInfo),
99 Base(BaseInfo),
102}
103
104fn with_inherited_timeline<'a>(
108 enclosing: impl Iterator<Item = &'a SegmentLayer>,
109 level: &'a SegmentLayer,
110) -> Result<SegmentLayer, InheritError> {
111 let Some(template) = &level.template else {
112 return Ok(level.clone());
113 };
114 let inherited = enclosing
115 .filter_map(|l| l.template.as_ref())
116 .map(|t| &t.multi)
117 .try_fold(MultiInfo::default(), |merged, multi| {
118 merge_multi(&merged, multi)
119 })?;
120 let mut layer = level.clone();
121 layer.template = Some(SegmentTemplate {
122 multi: merge_multi(&inherited, &template.multi)?,
123 media: template.media.clone(),
124 index: template.index.clone(),
125 initialization: template.initialization.clone(),
126 bitstream_switching: template.bitstream_switching.clone(),
127 });
128 Ok(layer)
129}
130
131fn merge_base(parent: &BaseInfo, child: &BaseInfo) -> BaseInfo {
132 BaseInfo {
133 timescale: child.timescale.or(parent.timescale),
134 presentation_time_offset: child
135 .presentation_time_offset
136 .or(parent.presentation_time_offset),
137 ept_delta: child.ept_delta.or(parent.ept_delta),
138 pd_delta: child.pd_delta.or(parent.pd_delta),
139 presentation_duration: child.presentation_duration.or(parent.presentation_duration),
140 time_shift_buffer_depth: child
141 .time_shift_buffer_depth
142 .or(parent.time_shift_buffer_depth),
143 index_range: child.index_range.or(parent.index_range),
144 index_range_exact: child.index_range_exact.or(parent.index_range_exact),
145 availability_time_offset: child
146 .availability_time_offset
147 .or(parent.availability_time_offset),
148 availability_time_complete: child
149 .availability_time_complete
150 .or(parent.availability_time_complete),
151 initialization: child
152 .initialization
153 .clone()
154 .or_else(|| parent.initialization.clone()),
155 representation_index: child
156 .representation_index
157 .clone()
158 .or_else(|| parent.representation_index.clone()),
159 }
160}
161
162fn merge_multi(parent: &MultiInfo, child: &MultiInfo) -> Result<MultiInfo, InheritError> {
163 let (duration, timeline) = (
164 child.duration.or(parent.duration),
165 child.timeline.clone().or_else(|| parent.timeline.clone()),
166 );
167 Ok(MultiInfo {
168 base: merge_base(&parent.base, &child.base),
169 duration,
170 start_number: child.start_number.or(parent.start_number),
171 end_number: child.end_number.or(parent.end_number),
172 timeline,
173 bitstream_switching: child
174 .bitstream_switching
175 .clone()
176 .or_else(|| parent.bitstream_switching.clone()),
177 })
178}
179
180fn finish_multi(m: MultiInfo) -> Result<ResolvedMulti, InheritError> {
181 if m.duration.is_some() && m.timeline.is_some() {
182 return Err(InheritError::DurationAndTimeline);
183 }
184 Ok(ResolvedMulti {
185 timescale: m.base.timescale.unwrap_or(DEFAULT_TIMESCALE),
186 presentation_time_offset: m
187 .base
188 .presentation_time_offset
189 .unwrap_or(DEFAULT_PRESENTATION_TIME_OFFSET),
190 base: m.base,
191 duration: m.duration,
192 start_number: m.start_number.unwrap_or(DEFAULT_START_NUMBER),
193 end_number: m.end_number,
194 timeline: m.timeline,
195 })
196}
197
198pub fn resolve_segment_info(
204 period: &Period,
205 set: &AdaptationSet,
206 rep: &Representation,
207) -> Result<SegmentInfo, InheritError> {
208 let segments = [&period.segment, &set.segment, &rep.segment];
209 let resolved: Vec<SegmentLayer> = segments
210 .iter()
211 .copied()
212 .enumerate()
213 .map(|(i, l)| with_inherited_timeline(segments[..i].iter().copied(), l))
214 .collect::<Result<_, _>>()?;
215 let layers = [&resolved[0], &resolved[1], &resolved[2]];
216 let has_template = layers.iter().any(|l| l.template.is_some());
217 let has_list = layers.iter().any(|l| l.list.is_some());
218 if has_template && has_list {
219 return Err(InheritError::TemplateAndList);
220 }
221 if has_template {
222 let mut merged = crate::model::SegmentTemplate::default();
223 for t in layers.iter().filter_map(|l| l.template.as_ref()) {
224 merged = crate::model::SegmentTemplate {
225 multi: merge_multi(&merged.multi, &t.multi)?,
226 media: t.media.clone().or(merged.media),
227 index: t.index.clone().or(merged.index),
228 initialization: t.initialization.clone().or(merged.initialization),
229 bitstream_switching: t.bitstream_switching.clone().or(merged.bitstream_switching),
230 };
231 }
232 return Ok(SegmentInfo::Template(TemplateInfo {
233 multi: finish_multi(merged.multi)?,
234 media: merged.media,
235 index: merged.index,
236 initialization: merged.initialization,
237 bitstream_switching: merged.bitstream_switching,
238 }));
239 }
240 if has_list {
241 let mut multi = MultiInfo::default();
242 let mut urls: Vec<SegmentUrl> = Vec::new();
243 for l in layers.iter().filter_map(|l| l.list.as_ref()) {
244 multi = merge_multi(&multi, &l.multi)?;
245 if !l.urls.is_empty() {
246 urls.clone_from(&l.urls);
247 }
248 }
249 return Ok(SegmentInfo::List(ListInfo {
250 multi: finish_multi(multi)?,
251 urls,
252 }));
253 }
254 let mut base = BaseInfo::default();
255 for b in layers.iter().filter_map(|l| l.base.as_ref()) {
256 base = merge_base(&base, &b.info);
257 }
258 Ok(SegmentInfo::Base(base))
259}
260
261#[must_use]
263pub fn effective_common(set: &AdaptationSet, rep: &Representation) -> CommonAttributes {
264 let (s, r) = (&set.common, &rep.common);
265 CommonAttributes {
266 profiles: r.profiles.clone().or_else(|| s.profiles.clone()),
267 width: r.width.or(s.width),
268 height: r.height.or(s.height),
269 sar: r.sar.clone().or_else(|| s.sar.clone()),
270 frame_rate: r.frame_rate.clone().or_else(|| s.frame_rate.clone()),
271 audio_sampling_rate: r
272 .audio_sampling_rate
273 .clone()
274 .or_else(|| s.audio_sampling_rate.clone()),
275 mime_type: r.mime_type.clone().or_else(|| s.mime_type.clone()),
276 codecs: r.codecs.clone().or_else(|| s.codecs.clone()),
277 max_playout_rate: r.max_playout_rate.or(s.max_playout_rate),
278 coding_dependency: r.coding_dependency.or(s.coding_dependency),
279 }
280}