1use std::fmt::Debug;
2use std::io;
3
4use fixed::FixedI32;
5use fixed::types::extra::U16;
6use scuffle_bytes_util::zero_copy::{Deserialize, DeserializeSeed, Serialize, ZeroCopyReader};
7
8use crate::{BoxHeader, FullBoxHeader, IsoBox, IsoSized};
9
10#[derive(IsoBox, Debug, PartialEq, Eq, Default)]
14#[iso_box(box_type = b"stts", crate_path = crate)]
15pub struct TimeToSampleBox {
16 pub full_header: FullBoxHeader,
18 pub entry_count: u32,
20 #[iso_box(repeated)]
22 pub entries: Vec<TimeToSampleBoxEntry>,
23}
24
25#[derive(Debug, PartialEq, Eq)]
27pub struct TimeToSampleBoxEntry {
28 pub sample_count: u32,
30 pub sample_delta: u32,
33}
34
35impl<'a> Deserialize<'a> for TimeToSampleBoxEntry {
36 fn deserialize<R>(mut reader: R) -> io::Result<Self>
37 where
38 R: ZeroCopyReader<'a>,
39 {
40 Ok(Self {
41 sample_count: u32::deserialize(&mut reader)?,
42 sample_delta: u32::deserialize(&mut reader)?,
43 })
44 }
45}
46
47impl Serialize for TimeToSampleBoxEntry {
48 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
49 where
50 W: std::io::Write,
51 {
52 self.sample_count.serialize(&mut writer)?;
53 self.sample_delta.serialize(&mut writer)?;
54 Ok(())
55 }
56}
57
58impl IsoSized for TimeToSampleBoxEntry {
59 fn size(&self) -> usize {
60 self.sample_count.size() + self.sample_delta.size()
61 }
62}
63
64#[derive(IsoBox, PartialEq, Eq)]
68#[iso_box(box_type = b"ctts", skip_impl(deserialize_seed, serialize), crate_path = crate)]
69pub struct CompositionOffsetBox {
70 pub full_header: FullBoxHeader,
72 pub entry_count: u32,
74 #[iso_box(repeated)]
76 pub entries: Vec<CompositionOffsetBoxEntry>,
77}
78
79impl<'a> DeserializeSeed<'a, BoxHeader> for CompositionOffsetBox {
80 fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> io::Result<Self>
81 where
82 R: ZeroCopyReader<'a>,
83 {
84 let full_header = FullBoxHeader::deserialize(&mut reader)?;
85 let entry_count = u32::deserialize(&mut reader)?;
86
87 let mut entries = Vec::new();
88 if full_header.version == 0 || full_header.version == 1 {
89 for _ in 0..entry_count {
90 entries.push(CompositionOffsetBoxEntry::deserialize_seed(&mut reader, full_header.version)?);
91 }
92 }
93
94 Ok(Self {
95 full_header,
96 entry_count,
97 entries,
98 })
99 }
100}
101
102impl Serialize for CompositionOffsetBox {
103 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
104 where
105 W: std::io::Write,
106 {
107 self.serialize_box_header(&mut writer)?;
108 self.full_header.serialize(&mut writer)?;
109 self.entry_count.serialize(&mut writer)?;
110
111 for entry in &self.entries {
112 entry.serialize(&mut writer, self)?;
113 }
114
115 Ok(())
116 }
117}
118
119impl Debug for CompositionOffsetBox {
120 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
121 f.debug_struct("CompositionOffsetBox")
122 .field("full_header", &self.full_header)
123 .field("entry_count", &self.entry_count)
124 .field("entries.len", &self.entries.len())
125 .finish()
126 }
127}
128
129#[derive(Debug, PartialEq, Eq)]
131pub struct CompositionOffsetBoxEntry {
132 pub sample_count: u32,
134 pub sample_offset: i64,
136}
137
138impl<'a> DeserializeSeed<'a, u8> for CompositionOffsetBoxEntry {
139 fn deserialize_seed<R>(mut reader: R, seed: u8) -> io::Result<Self>
140 where
141 R: ZeroCopyReader<'a>,
142 {
143 Ok(Self {
144 sample_count: u32::deserialize(&mut reader)?,
145 sample_offset: if seed == 0 {
146 u32::deserialize(&mut reader)? as i64
147 } else if seed == 1 {
148 i32::deserialize(&mut reader)? as i64
149 } else {
150 return Err(io::Error::new(
151 io::ErrorKind::InvalidData,
152 "cannot be called with version > 1",
153 ));
154 },
155 })
156 }
157}
158
159impl CompositionOffsetBoxEntry {
160 fn serialize<W>(&self, mut writer: W, parent: &CompositionOffsetBox) -> io::Result<()>
161 where
162 W: std::io::Write,
163 {
164 self.sample_count.serialize(&mut writer)?;
165 if parent.full_header.version == 0 {
166 (self.sample_offset as u32).serialize(&mut writer)?;
167 } else if parent.full_header.version == 1 {
168 (self.sample_offset as i32).serialize(&mut writer)?;
169 }
170 Ok(())
171 }
172}
173
174impl IsoSized for CompositionOffsetBoxEntry {
175 fn size(&self) -> usize {
176 self.sample_count.size() + 4
177 }
178}
179
180#[derive(IsoBox, Debug, PartialEq, Eq)]
184#[iso_box(box_type = b"cslg", skip_impl(deserialize_seed, serialize, sized), crate_path = crate)]
185pub struct CompositionToDecodeBox {
186 pub full_header: FullBoxHeader,
188 pub composition_to_dt_shift: i64,
194 pub least_decode_to_display_delta: i64,
196 pub greatest_decode_to_display_delta: i64,
198 pub composition_start_time: i64,
200 pub composition_end_time: i64,
204}
205
206impl<'a> DeserializeSeed<'a, BoxHeader> for CompositionToDecodeBox {
207 fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> io::Result<Self>
208 where
209 R: ZeroCopyReader<'a>,
210 {
211 let full_header = FullBoxHeader::deserialize(&mut reader)?;
212
213 let composition_to_dt_shift = if full_header.version == 0 {
214 i32::deserialize(&mut reader)? as i64
215 } else {
216 i64::deserialize(&mut reader)?
217 };
218 let least_decode_to_display_delta = if full_header.version == 0 {
219 i32::deserialize(&mut reader)? as i64
220 } else {
221 i64::deserialize(&mut reader)?
222 };
223 let greatest_decode_to_display_delta = if full_header.version == 0 {
224 i32::deserialize(&mut reader)? as i64
225 } else {
226 i64::deserialize(&mut reader)?
227 };
228 let composition_start_time = if full_header.version == 0 {
229 i32::deserialize(&mut reader)? as i64
230 } else {
231 i64::deserialize(&mut reader)?
232 };
233 let composition_end_time = if full_header.version == 0 {
234 i32::deserialize(&mut reader)? as i64
235 } else {
236 i64::deserialize(&mut reader)?
237 };
238
239 Ok(Self {
240 full_header,
241 composition_to_dt_shift,
242 least_decode_to_display_delta,
243 greatest_decode_to_display_delta,
244 composition_start_time,
245 composition_end_time,
246 })
247 }
248}
249
250impl Serialize for CompositionToDecodeBox {
251 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
252 where
253 W: std::io::Write,
254 {
255 self.serialize_box_header(&mut writer)?;
256 self.full_header.serialize(&mut writer)?;
257 if self.full_header.version == 0 {
258 (self.composition_to_dt_shift as i32).serialize(&mut writer)?;
259 (self.least_decode_to_display_delta as i32).serialize(&mut writer)?;
260 (self.greatest_decode_to_display_delta as i32).serialize(&mut writer)?;
261 (self.composition_start_time as i32).serialize(&mut writer)?;
262 (self.composition_end_time as i32).serialize(&mut writer)?;
263 } else {
264 self.composition_to_dt_shift.serialize(&mut writer)?;
265 self.least_decode_to_display_delta.serialize(&mut writer)?;
266 self.greatest_decode_to_display_delta.serialize(&mut writer)?;
267 self.composition_start_time.serialize(&mut writer)?;
268 self.composition_end_time.serialize(&mut writer)?;
269 }
270 Ok(())
271 }
272}
273
274impl IsoSized for CompositionToDecodeBox {
275 fn size(&self) -> usize {
276 let mut size = self.full_header.size();
277 if self.full_header.version == 0 {
278 size += 4 + 4 + 4 + 4 + 4;
279 } else {
280 size += 8 + 8 + 8 + 8 + 8;
281 }
282
283 Self::add_header_size(size)
284 }
285}
286
287#[derive(IsoBox, Debug, PartialEq, Eq)]
291#[iso_box(box_type = b"stss", crate_path = crate)]
292pub struct SyncSampleBox {
293 pub full_header: FullBoxHeader,
295 pub entry_count: u32,
299 #[iso_box(repeated)]
301 pub sample_number: Vec<u32>,
302}
303
304#[derive(IsoBox, Debug, PartialEq, Eq)]
308#[iso_box(box_type = b"stsh", crate_path = crate)]
309pub struct ShadowSyncSampleBox {
310 pub full_header: FullBoxHeader,
312 pub entry_count: u32,
314 #[iso_box(repeated)]
316 pub entries: Vec<ShadowSyncSampleBoxEntry>,
317}
318
319#[derive(Debug, PartialEq, Eq)]
321pub struct ShadowSyncSampleBoxEntry {
322 pub shadowed_sample_number: u32,
324 pub sync_sample_number: u32,
326}
327
328impl<'a> Deserialize<'a> for ShadowSyncSampleBoxEntry {
329 fn deserialize<R>(mut reader: R) -> io::Result<Self>
330 where
331 R: ZeroCopyReader<'a>,
332 {
333 Ok(Self {
334 shadowed_sample_number: u32::deserialize(&mut reader)?,
335 sync_sample_number: u32::deserialize(&mut reader)?,
336 })
337 }
338}
339
340impl Serialize for ShadowSyncSampleBoxEntry {
341 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
342 where
343 W: std::io::Write,
344 {
345 self.shadowed_sample_number.serialize(&mut writer)?;
346 self.sync_sample_number.serialize(&mut writer)?;
347 Ok(())
348 }
349}
350
351impl IsoSized for ShadowSyncSampleBoxEntry {
352 fn size(&self) -> usize {
353 self.shadowed_sample_number.size() + self.sync_sample_number.size()
354 }
355}
356
357#[derive(IsoBox, Debug, PartialEq, Eq)]
361#[iso_box(box_type = b"sdtp", crate_path = crate)]
362pub struct SampleDependencyTypeBox {
363 pub full_header: FullBoxHeader,
365 #[iso_box(from = "u8", repeated)]
367 pub entries: Vec<SampleDependencyTypeBoxEntry>,
368}
369
370#[derive(Debug, PartialEq, Eq, Clone, Copy)]
372pub struct SampleDependencyTypeBoxEntry {
373 pub is_leading: u8,
380 pub sample_depends_on: u8,
385 pub sample_is_depended_on: u8,
390 pub sample_has_redundancy: u8,
395}
396
397impl From<u8> for SampleDependencyTypeBoxEntry {
398 fn from(value: u8) -> Self {
399 Self {
400 is_leading: (value >> 6) & 0b11,
401 sample_depends_on: (value >> 4) & 0b11,
402 sample_is_depended_on: (value >> 2) & 0b11,
403 sample_has_redundancy: value & 0b11,
404 }
405 }
406}
407
408impl From<SampleDependencyTypeBoxEntry> for u8 {
409 fn from(val: SampleDependencyTypeBoxEntry) -> Self {
410 ((val.is_leading & 0b11) << 6)
411 | ((val.sample_depends_on & 0b11) << 4)
412 | ((val.sample_is_depended_on & 0b11) << 2)
413 | (val.sample_has_redundancy & 0b11)
414 }
415}
416
417impl IsoSized for SampleDependencyTypeBoxEntry {
418 fn size(&self) -> usize {
419 1
420 }
421}
422
423#[derive(IsoBox, Debug, PartialEq, Eq)]
427#[iso_box(box_type = b"edts", crate_path = crate)]
428pub struct EditBox {
429 #[iso_box(nested_box(collect))]
431 pub elst: Option<EditListBox>,
432}
433
434#[derive(IsoBox, Debug, PartialEq, Eq)]
438#[iso_box(box_type = b"elst", skip_impl(deserialize_seed, serialize, sized), crate_path = crate)]
439pub struct EditListBox {
440 pub full_header: FullBoxHeader,
442 pub entry_count: u32,
444 #[iso_box(repeated)]
446 pub entries: Vec<EditListBoxEntry>,
447}
448
449impl<'a> DeserializeSeed<'a, BoxHeader> for EditListBox {
450 fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> io::Result<Self>
451 where
452 R: ZeroCopyReader<'a>,
453 {
454 let full_header = FullBoxHeader::deserialize(&mut reader)?;
455
456 let entry_count = u32::deserialize(&mut reader)?;
457
458 let mut entries = Vec::with_capacity(entry_count as usize);
459 for _ in 0..entry_count {
460 entries.push(EditListBoxEntry::deserialize_seed(&mut reader, full_header.version)?);
461 }
462
463 Ok(Self {
464 full_header,
465 entry_count,
466 entries,
467 })
468 }
469}
470
471impl Serialize for EditListBox {
472 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
473 where
474 W: std::io::Write,
475 {
476 self.serialize_box_header(&mut writer)?;
477 self.full_header.serialize(&mut writer)?;
478 self.entry_count.serialize(&mut writer)?;
479
480 for entry in &self.entries {
481 entry.serialize(&mut writer, self.full_header.version)?;
482 }
483
484 Ok(())
485 }
486}
487
488impl IsoSized for EditListBox {
489 fn size(&self) -> usize {
490 let mut size = 0;
491 size += self.full_header.size();
492 size += self.entry_count.size();
493 size += self
494 .entries
495 .iter()
496 .map(|entry| entry.size(self.full_header.version))
497 .sum::<usize>();
498
499 Self::add_header_size(size)
500 }
501}
502
503#[derive(Debug, PartialEq, Eq)]
505pub struct EditListBoxEntry {
506 pub edit_duration: u64,
509 pub media_time: i64,
514 pub media_rate: FixedI32<U16>,
518}
519
520impl<'a> DeserializeSeed<'a, u8> for EditListBoxEntry {
521 fn deserialize_seed<R>(mut reader: R, seed: u8) -> io::Result<Self>
522 where
523 R: ZeroCopyReader<'a>,
524 {
525 let edit_duration = if seed == 1 {
526 u64::deserialize(&mut reader)?
527 } else {
528 u32::deserialize(&mut reader)? as u64
529 };
530 let media_time = if seed == 1 {
531 i64::deserialize(&mut reader)?
532 } else {
533 i32::deserialize(&mut reader)? as i64
534 };
535 let media_rate = FixedI32::from_bits(i32::deserialize(&mut reader)?);
536
537 Ok(Self {
538 edit_duration,
539 media_time,
540 media_rate,
541 })
542 }
543}
544
545impl EditListBoxEntry {
546 fn serialize<W>(&self, mut writer: W, version: u8) -> io::Result<()>
547 where
548 W: std::io::Write,
549 {
550 if version == 1 {
551 self.edit_duration.serialize(&mut writer)?;
552 self.media_time.serialize(&mut writer)?;
553 } else {
554 (self.edit_duration as u32).serialize(&mut writer)?;
555 (self.media_time as i32).serialize(&mut writer)?;
556 }
557 self.media_rate.to_bits().serialize(&mut writer)?;
558
559 Ok(())
560 }
561}
562
563impl EditListBoxEntry {
564 pub fn size(&self, version: u8) -> usize {
566 let mut size = 0;
567 if version == 1 {
568 size += 8 + 8;
569 } else {
570 size += 4 + 4;
571 }
572 size + 2 + 2
573 }
574}