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), 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 Debug for CompositionOffsetBox {
103 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104 f.debug_struct("CompositionOffsetBox")
105 .field("full_header", &self.full_header)
106 .field("entry_count", &self.entry_count)
107 .field("entries.len", &self.entries.len())
108 .finish()
109 }
110}
111
112#[derive(Debug, PartialEq, Eq)]
114pub struct CompositionOffsetBoxEntry {
115 pub sample_count: u32,
117 pub sample_offset: i64,
119}
120
121impl<'a> DeserializeSeed<'a, u8> for CompositionOffsetBoxEntry {
122 fn deserialize_seed<R>(mut reader: R, seed: u8) -> io::Result<Self>
123 where
124 R: ZeroCopyReader<'a>,
125 {
126 Ok(Self {
127 sample_count: u32::deserialize(&mut reader)?,
128 sample_offset: if seed == 0 {
129 u32::deserialize(&mut reader)? as i64
130 } else if seed == 1 {
131 i32::deserialize(&mut reader)? as i64
132 } else {
133 return Err(io::Error::new(
134 io::ErrorKind::InvalidData,
135 "cannot be called with version > 1",
136 ));
137 },
138 })
139 }
140}
141
142impl Serialize for CompositionOffsetBoxEntry {
143 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
144 where
145 W: std::io::Write,
146 {
147 self.sample_count.serialize(&mut writer)?;
148 self.sample_offset.serialize(&mut writer)?;
149 Ok(())
150 }
151}
152
153impl IsoSized for CompositionOffsetBoxEntry {
154 fn size(&self) -> usize {
155 self.sample_count.size() + self.sample_offset.size()
156 }
157}
158
159#[derive(IsoBox, Debug, PartialEq, Eq)]
163#[iso_box(box_type = b"cslg", skip_impl(deserialize_seed, serialize, sized), crate_path = crate)]
164pub struct CompositionToDecodeBox {
165 pub full_header: FullBoxHeader,
167 pub composition_to_dt_shift: i64,
173 pub least_decode_to_display_delta: i64,
175 pub greatest_decode_to_display_delta: i64,
177 pub composition_start_time: i64,
179 pub composition_end_time: i64,
183}
184
185impl<'a> DeserializeSeed<'a, BoxHeader> for CompositionToDecodeBox {
186 fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> io::Result<Self>
187 where
188 R: ZeroCopyReader<'a>,
189 {
190 let full_header = FullBoxHeader::deserialize(&mut reader)?;
191
192 let composition_to_dt_shift = if full_header.version == 0 {
193 i32::deserialize(&mut reader)? as i64
194 } else {
195 i64::deserialize(&mut reader)?
196 };
197 let least_decode_to_display_delta = if full_header.version == 0 {
198 i32::deserialize(&mut reader)? as i64
199 } else {
200 i64::deserialize(&mut reader)?
201 };
202 let greatest_decode_to_display_delta = if full_header.version == 0 {
203 i32::deserialize(&mut reader)? as i64
204 } else {
205 i64::deserialize(&mut reader)?
206 };
207 let composition_start_time = if full_header.version == 0 {
208 i32::deserialize(&mut reader)? as i64
209 } else {
210 i64::deserialize(&mut reader)?
211 };
212 let composition_end_time = if full_header.version == 0 {
213 i32::deserialize(&mut reader)? as i64
214 } else {
215 i64::deserialize(&mut reader)?
216 };
217
218 Ok(Self {
219 full_header,
220 composition_to_dt_shift,
221 least_decode_to_display_delta,
222 greatest_decode_to_display_delta,
223 composition_start_time,
224 composition_end_time,
225 })
226 }
227}
228
229impl Serialize for CompositionToDecodeBox {
230 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
231 where
232 W: std::io::Write,
233 {
234 self.serialize_box_header(&mut writer)?;
235 self.full_header.serialize(&mut writer)?;
236 if self.full_header.version == 0 {
237 (self.composition_to_dt_shift as i32).serialize(&mut writer)?;
238 (self.least_decode_to_display_delta as i32).serialize(&mut writer)?;
239 (self.greatest_decode_to_display_delta as i32).serialize(&mut writer)?;
240 (self.composition_start_time as i32).serialize(&mut writer)?;
241 (self.composition_end_time as i32).serialize(&mut writer)?;
242 } else {
243 self.composition_to_dt_shift.serialize(&mut writer)?;
244 self.least_decode_to_display_delta.serialize(&mut writer)?;
245 self.greatest_decode_to_display_delta.serialize(&mut writer)?;
246 self.composition_start_time.serialize(&mut writer)?;
247 self.composition_end_time.serialize(&mut writer)?;
248 }
249 Ok(())
250 }
251}
252
253impl IsoSized for CompositionToDecodeBox {
254 fn size(&self) -> usize {
255 let mut size = self.full_header.size();
256 if self.full_header.version == 0 {
257 size += 4 + 4 + 4 + 4 + 4;
258 } else {
259 size += 8 + 8 + 8 + 8 + 8;
260 }
261
262 Self::add_header_size(size)
263 }
264}
265
266#[derive(IsoBox, Debug, PartialEq, Eq)]
270#[iso_box(box_type = b"stss", crate_path = crate)]
271pub struct SyncSampleBox {
272 pub full_header: FullBoxHeader,
274 pub entry_count: u32,
278 #[iso_box(repeated)]
280 pub sample_number: Vec<u32>,
281}
282
283#[derive(IsoBox, Debug, PartialEq, Eq)]
287#[iso_box(box_type = b"stsh", crate_path = crate)]
288pub struct ShadowSyncSampleBox {
289 pub full_header: FullBoxHeader,
291 pub entry_count: u32,
293 #[iso_box(repeated)]
295 pub entries: Vec<ShadowSyncSampleBoxEntry>,
296}
297
298#[derive(Debug, PartialEq, Eq)]
300pub struct ShadowSyncSampleBoxEntry {
301 pub shadowed_sample_number: u32,
303 pub sync_sample_number: u32,
305}
306
307impl<'a> Deserialize<'a> for ShadowSyncSampleBoxEntry {
308 fn deserialize<R>(mut reader: R) -> io::Result<Self>
309 where
310 R: ZeroCopyReader<'a>,
311 {
312 Ok(Self {
313 shadowed_sample_number: u32::deserialize(&mut reader)?,
314 sync_sample_number: u32::deserialize(&mut reader)?,
315 })
316 }
317}
318
319impl Serialize for ShadowSyncSampleBoxEntry {
320 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
321 where
322 W: std::io::Write,
323 {
324 self.shadowed_sample_number.serialize(&mut writer)?;
325 self.sync_sample_number.serialize(&mut writer)?;
326 Ok(())
327 }
328}
329
330impl IsoSized for ShadowSyncSampleBoxEntry {
331 fn size(&self) -> usize {
332 self.shadowed_sample_number.size() + self.sync_sample_number.size()
333 }
334}
335
336#[derive(IsoBox, Debug, PartialEq, Eq)]
340#[iso_box(box_type = b"sdtp", crate_path = crate)]
341pub struct SampleDependencyTypeBox {
342 pub full_header: FullBoxHeader,
344 #[iso_box(from = "u8", repeated)]
346 pub entries: Vec<SampleDependencyTypeBoxEntry>,
347}
348
349#[derive(Debug, PartialEq, Eq, Clone, Copy)]
351pub struct SampleDependencyTypeBoxEntry {
352 pub is_leading: u8,
359 pub sample_depends_on: u8,
364 pub sample_is_depended_on: u8,
369 pub sample_has_redundancy: u8,
374}
375
376impl From<u8> for SampleDependencyTypeBoxEntry {
377 fn from(value: u8) -> Self {
378 Self {
379 is_leading: (value >> 6) & 0b11,
380 sample_depends_on: (value >> 4) & 0b11,
381 sample_is_depended_on: (value >> 2) & 0b11,
382 sample_has_redundancy: value & 0b11,
383 }
384 }
385}
386
387impl From<SampleDependencyTypeBoxEntry> for u8 {
388 fn from(val: SampleDependencyTypeBoxEntry) -> Self {
389 ((val.is_leading & 0b11) << 6)
390 | ((val.sample_depends_on & 0b11) << 4)
391 | ((val.sample_is_depended_on & 0b11) << 2)
392 | (val.sample_has_redundancy & 0b11)
393 }
394}
395
396impl IsoSized for SampleDependencyTypeBoxEntry {
397 fn size(&self) -> usize {
398 1
399 }
400}
401
402#[derive(IsoBox, Debug, PartialEq, Eq)]
406#[iso_box(box_type = b"edts", crate_path = crate)]
407pub struct EditBox {
408 #[iso_box(nested_box(collect))]
410 pub elst: Option<EditListBox>,
411}
412
413#[derive(IsoBox, Debug, PartialEq, Eq)]
417#[iso_box(box_type = b"elst", skip_impl(deserialize_seed, serialize, sized), crate_path = crate)]
418pub struct EditListBox {
419 pub full_header: FullBoxHeader,
421 pub entry_count: u32,
423 #[iso_box(repeated)]
425 pub entries: Vec<EditListBoxEntry>,
426}
427
428impl<'a> DeserializeSeed<'a, BoxHeader> for EditListBox {
429 fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> io::Result<Self>
430 where
431 R: ZeroCopyReader<'a>,
432 {
433 let full_header = FullBoxHeader::deserialize(&mut reader)?;
434
435 let entry_count = u32::deserialize(&mut reader)?;
436
437 let mut entries = Vec::with_capacity(entry_count as usize);
438 for _ in 0..entry_count {
439 entries.push(EditListBoxEntry::deserialize_seed(&mut reader, full_header.version)?);
440 }
441
442 Ok(Self {
443 full_header,
444 entry_count,
445 entries,
446 })
447 }
448}
449
450impl Serialize for EditListBox {
451 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
452 where
453 W: std::io::Write,
454 {
455 self.serialize_box_header(&mut writer)?;
456 self.full_header.serialize(&mut writer)?;
457 self.entry_count.serialize(&mut writer)?;
458
459 for entry in &self.entries {
460 entry.serialize(&mut writer, self.full_header.version)?;
461 }
462
463 Ok(())
464 }
465}
466
467impl IsoSized for EditListBox {
468 fn size(&self) -> usize {
469 let mut size = 0;
470 size += self.full_header.size();
471 size += self.entry_count.size();
472 size += self
473 .entries
474 .iter()
475 .map(|entry| entry.size(self.full_header.version))
476 .sum::<usize>();
477
478 Self::add_header_size(size)
479 }
480}
481
482#[derive(Debug, PartialEq, Eq)]
484pub struct EditListBoxEntry {
485 pub edit_duration: u64,
488 pub media_time: i64,
493 pub media_rate: FixedI32<U16>,
497}
498
499impl<'a> DeserializeSeed<'a, u8> for EditListBoxEntry {
500 fn deserialize_seed<R>(mut reader: R, seed: u8) -> io::Result<Self>
501 where
502 R: ZeroCopyReader<'a>,
503 {
504 let edit_duration = if seed == 1 {
505 u64::deserialize(&mut reader)?
506 } else {
507 u32::deserialize(&mut reader)? as u64
508 };
509 let media_time = if seed == 1 {
510 i64::deserialize(&mut reader)?
511 } else {
512 i32::deserialize(&mut reader)? as i64
513 };
514 let media_rate = FixedI32::from_bits(i32::deserialize(&mut reader)?);
515
516 Ok(Self {
517 edit_duration,
518 media_time,
519 media_rate,
520 })
521 }
522}
523
524impl EditListBoxEntry {
525 fn serialize<W>(&self, mut writer: W, version: u8) -> io::Result<()>
526 where
527 W: std::io::Write,
528 {
529 if version == 1 {
530 self.edit_duration.serialize(&mut writer)?;
531 self.media_time.serialize(&mut writer)?;
532 } else {
533 (self.edit_duration as u32).serialize(&mut writer)?;
534 (self.media_time as i32).serialize(&mut writer)?;
535 }
536 self.media_rate.to_bits().serialize(&mut writer)?;
537
538 Ok(())
539 }
540}
541
542impl EditListBoxEntry {
543 pub fn size(&self, version: u8) -> usize {
545 let mut size = 0;
546 if version == 1 {
547 size += 8 + 8;
548 } else {
549 size += 4 + 4;
550 }
551 size + 2 + 2
552 }
553}