1use std::io;
2
3use scuffle_bytes_util::zero_copy::{Deserialize, DeserializeSeed, Serialize, U24Be, ZeroCopyReader};
4use scuffle_bytes_util::{BitReader, BitWriter};
5
6use super::{
7 CompositionToDecodeBox, MetaBox, SampleAuxiliaryInformationOffsetsBox, SampleAuxiliaryInformationSizesBox,
8 SampleGroupDescriptionBox, SampleToGroupBox, SubSampleInformationBox, UserDataBox,
9};
10use crate::{BoxHeader, FullBoxHeader, IsoBox, IsoSized, UnknownBox};
11
12#[derive(IsoBox, Debug, PartialEq, Eq)]
16#[iso_box(box_type = b"mvex", crate_path = crate)]
17pub struct MovieExtendsBox {
18 #[iso_box(nested_box(collect))]
20 pub mehd: Option<MovieExtendsHeaderBox>,
21 #[iso_box(nested_box(collect))]
23 pub trex: Vec<TrackExtendsBox>,
24 #[iso_box(nested_box(collect))]
26 pub leva: Option<LevelAssignmentBox>,
27}
28
29#[derive(IsoBox, Debug, PartialEq, Eq)]
33#[iso_box(box_type = b"mehd", skip_impl(deserialize_seed, serialize, sized), crate_path = crate)]
34pub struct MovieExtendsHeaderBox {
35 pub full_header: FullBoxHeader,
37 pub fragment_duration: u64,
39}
40
41impl<'a> DeserializeSeed<'a, BoxHeader> for MovieExtendsHeaderBox {
42 fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> io::Result<Self>
43 where
44 R: ZeroCopyReader<'a>,
45 {
46 let full_header = FullBoxHeader::deserialize(&mut reader)?;
47
48 let fragment_duration = if full_header.version == 1 {
49 u64::deserialize(&mut reader)?
50 } else {
51 u32::deserialize(&mut reader)? as u64
52 };
53
54 Ok(Self {
55 full_header,
56 fragment_duration,
57 })
58 }
59}
60
61impl Serialize for MovieExtendsHeaderBox {
62 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
63 where
64 W: std::io::Write,
65 {
66 self.serialize_box_header(&mut writer)?;
67 self.full_header.serialize(&mut writer)?;
68
69 if self.full_header.version == 1 {
70 self.fragment_duration.serialize(&mut writer)?;
71 } else {
72 (self.fragment_duration as u32).serialize(&mut writer)?;
73 }
74
75 Ok(())
76 }
77}
78
79impl IsoSized for MovieExtendsHeaderBox {
80 fn size(&self) -> usize {
81 let mut size = self.full_header.size(); if self.full_header.version == 1 {
83 size += 8; } else {
85 size += 4; }
87 Self::add_header_size(size)
88 }
89}
90
91#[derive(Debug, PartialEq, Eq, Clone, Copy)]
95pub struct SampleFlags {
96 pub reserved: u8,
98 pub is_leading: u8,
105 pub sample_depends_on: u8,
110 pub sample_is_depended_on: u8,
115 pub sample_has_redundancy: u8,
120 pub sample_padding_value: u8,
122 pub sample_is_non_sync_sample: bool,
127 pub sample_degradation_priority: u16,
129}
130
131impl<'a> Deserialize<'a> for SampleFlags {
132 fn deserialize<R>(mut reader: R) -> io::Result<Self>
133 where
134 R: ZeroCopyReader<'a>,
135 {
136 let mut reader = BitReader::new(reader.as_std());
137 let reserved = reader.read_bits(4)? as u8;
138 let is_leading = reader.read_bits(2)? as u8;
139 let sample_depends_on = reader.read_bits(2)? as u8;
140 let sample_is_depended_on = reader.read_bits(2)? as u8;
141 let sample_has_redundancy = reader.read_bits(2)? as u8;
142 let sample_padding_value = reader.read_bits(3)? as u8;
143 let sample_is_non_sync_sample = reader.read_bit()?;
144 let sample_degradation_priority = reader.read_bits(16)? as u16;
145
146 Ok(Self {
147 reserved,
148 is_leading,
149 sample_depends_on,
150 sample_is_depended_on,
151 sample_has_redundancy,
152 sample_padding_value,
153 sample_is_non_sync_sample,
154 sample_degradation_priority,
155 })
156 }
157}
158
159impl Serialize for SampleFlags {
160 fn serialize<W>(&self, writer: W) -> io::Result<()>
161 where
162 W: std::io::Write,
163 {
164 let mut bit_writer = BitWriter::new(writer);
165 bit_writer.write_bits(self.reserved as u64, 4)?;
166 bit_writer.write_bits(self.is_leading as u64, 2)?;
167 bit_writer.write_bits(self.sample_depends_on as u64, 2)?;
168 bit_writer.write_bits(self.sample_is_depended_on as u64, 2)?;
169 bit_writer.write_bits(self.sample_has_redundancy as u64, 2)?;
170 bit_writer.write_bits(self.sample_padding_value as u64, 3)?;
171 bit_writer.write_bit(self.sample_is_non_sync_sample)?;
172 bit_writer.write_bits(self.sample_degradation_priority as u64, 16)?;
173
174 Ok(())
175 }
176}
177
178impl IsoSized for SampleFlags {
179 fn size(&self) -> usize {
180 4
181 }
182}
183
184#[derive(IsoBox, Debug, PartialEq, Eq)]
188#[iso_box(box_type = b"trex", crate_path = crate)]
189pub struct TrackExtendsBox {
190 pub full_header: FullBoxHeader,
192 pub track_id: u32,
194 pub default_sample_description_index: u32,
197 pub default_sample_duration: u32,
199 pub default_sample_size: u32,
201 pub default_sample_flags: SampleFlags,
203}
204
205impl TrackExtendsBox {
206 pub fn new(track_id: u32) -> Self {
208 Self {
209 full_header: FullBoxHeader::default(),
210 track_id,
211 default_sample_description_index: 1,
212 default_sample_duration: 0,
213 default_sample_size: 0,
214 default_sample_flags: SampleFlags {
215 reserved: 0,
216 is_leading: 0,
217 sample_depends_on: 0,
218 sample_is_depended_on: 0,
219 sample_has_redundancy: 0,
220 sample_padding_value: 0,
221 sample_is_non_sync_sample: false,
222 sample_degradation_priority: 0,
223 },
224 }
225 }
226}
227
228#[derive(IsoBox, Debug, PartialEq, Eq)]
232#[iso_box(box_type = b"moof", crate_path = crate)]
233pub struct MovieFragmentBox<'a> {
234 #[iso_box(nested_box)]
236 pub mfhd: MovieFragmentHeaderBox,
237 #[iso_box(nested_box(collect))]
239 pub meta: Option<MetaBox<'a>>,
240 #[iso_box(nested_box(collect))]
242 pub traf: Vec<TrackFragmentBox<'a>>,
243 #[iso_box(nested_box(collect))]
245 pub udta: Option<UserDataBox<'a>>,
246}
247
248#[derive(IsoBox, Debug, PartialEq, Eq)]
252#[iso_box(box_type = b"mfhd", crate_path = crate)]
253pub struct MovieFragmentHeaderBox {
254 pub full_header: FullBoxHeader,
256 pub sequence_number: u32,
258}
259
260impl MovieFragmentHeaderBox {
261 pub fn new(sequence_number: u32) -> Self {
263 Self {
264 full_header: FullBoxHeader::default(),
265 sequence_number,
266 }
267 }
268}
269
270#[derive(IsoBox, Debug, PartialEq, Eq)]
274#[iso_box(box_type = b"traf", crate_path = crate)]
275pub struct TrackFragmentBox<'a> {
276 #[iso_box(nested_box)]
278 pub tfhd: TrackFragmentHeaderBox,
279 #[iso_box(nested_box(collect))]
281 pub trun: Vec<TrackRunBox>,
282 #[iso_box(nested_box(collect))]
284 pub sbgp: Vec<SampleToGroupBox>,
285 #[iso_box(nested_box(collect))]
287 pub sgpd: Vec<SampleGroupDescriptionBox<'a>>,
288 #[iso_box(nested_box(collect))]
290 pub subs: Vec<SubSampleInformationBox>,
291 #[iso_box(nested_box(collect))]
293 pub saiz: Vec<SampleAuxiliaryInformationSizesBox<'a>>,
294 #[iso_box(nested_box(collect))]
296 pub saio: Vec<SampleAuxiliaryInformationOffsetsBox>,
297 #[iso_box(nested_box(collect))]
299 pub tfdt: Option<TrackFragmentBaseMediaDecodeTimeBox>,
300 #[iso_box(nested_box(collect))]
302 pub meta: Option<MetaBox<'a>>,
303 #[iso_box(nested_box(collect))]
305 pub udta: Option<UserDataBox<'a>>,
306}
307
308#[derive(IsoBox, Debug, PartialEq, Eq)]
312#[iso_box(box_type = b"tfhd", skip_impl(deserialize_seed, serialize), crate_path = crate)]
313pub struct TrackFragmentHeaderBox {
314 pub version: u8,
317 pub flags: TfFlags,
319 pub track_id: u32,
322 pub base_data_offset: Option<u64>,
326 pub sample_description_index: Option<u32>,
331 pub default_sample_duration: Option<u32>,
335 pub default_sample_size: Option<u32>,
339 pub default_sample_flags: Option<SampleFlags>,
343}
344
345impl TrackFragmentHeaderBox {
346 pub fn new(
348 track_id: u32,
349 base_data_offset: Option<u64>,
350 sample_description_index: Option<u32>,
351 default_sample_duration: Option<u32>,
352 default_sample_size: Option<u32>,
353 default_sample_flags: Option<SampleFlags>,
354 ) -> Self {
355 let mut flags = TfFlags::DefaultBaseIsMoof;
356
357 if base_data_offset.is_some() {
358 flags |= TfFlags::BaseDataOffsetPresent;
359 }
360
361 if sample_description_index.is_some() {
362 flags |= TfFlags::SampleDescriptionIndexPresent;
363 }
364
365 if default_sample_duration.is_some() {
366 flags |= TfFlags::DefaultSampleDurationPresent;
367 }
368
369 if default_sample_size.is_some() {
370 flags |= TfFlags::DefaultSampleSizePresent;
371 }
372
373 if default_sample_flags.is_some() {
374 flags |= TfFlags::DefaultSampleFlagsPresent;
375 }
376
377 Self {
378 version: 0,
379 flags,
380 track_id,
381 base_data_offset,
382 sample_description_index,
383 default_sample_duration,
384 default_sample_size,
385 default_sample_flags,
386 }
387 }
388}
389
390bitflags::bitflags! {
391 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
393 pub struct TfFlags: u32 {
394 const BaseDataOffsetPresent = 0x000001;
397 const SampleDescriptionIndexPresent = 0x000002;
400 const DefaultSampleDurationPresent = 0x000008;
402 const DefaultSampleSizePresent = 0x000010;
404 const DefaultSampleFlagsPresent = 0x000020;
406 const DurationIsEmpty = 0x010000;
413 const DefaultBaseIsMoof = 0x020000;
417 }
418}
419
420impl<'a> Deserialize<'a> for TfFlags {
421 fn deserialize<R>(reader: R) -> io::Result<Self>
422 where
423 R: ZeroCopyReader<'a>,
424 {
425 let flags = U24Be::deserialize(reader)?;
426 Ok(TfFlags::from_bits_truncate(*flags))
427 }
428}
429
430impl Serialize for TfFlags {
431 fn serialize<W>(&self, writer: W) -> io::Result<()>
432 where
433 W: std::io::Write,
434 {
435 U24Be(self.bits()).serialize(writer)
436 }
437}
438
439impl IsoSized for TfFlags {
440 fn size(&self) -> usize {
441 3
442 }
443}
444
445impl<'a> DeserializeSeed<'a, BoxHeader> for TrackFragmentHeaderBox {
446 fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> io::Result<Self>
447 where
448 R: ZeroCopyReader<'a>,
449 {
450 let version = u8::deserialize(&mut reader)?;
451 let flags = TfFlags::deserialize(&mut reader)?;
452
453 let track_id = u32::deserialize(&mut reader)?;
454 let base_data_offset = if flags.contains(TfFlags::BaseDataOffsetPresent) {
455 Some(u64::deserialize(&mut reader)?)
456 } else {
457 None
458 };
459 let sample_description_index = if flags.contains(TfFlags::SampleDescriptionIndexPresent) {
460 Some(u32::deserialize(&mut reader)?)
461 } else {
462 None
463 };
464 let default_sample_duration = if flags.contains(TfFlags::DefaultSampleDurationPresent) {
465 Some(u32::deserialize(&mut reader)?)
466 } else {
467 None
468 };
469 let default_sample_size = if flags.contains(TfFlags::DefaultSampleSizePresent) {
470 Some(u32::deserialize(&mut reader)?)
471 } else {
472 None
473 };
474 let default_sample_flags = if flags.contains(TfFlags::DefaultSampleFlagsPresent) {
475 Some(SampleFlags::deserialize(&mut reader)?)
476 } else {
477 None
478 };
479
480 Ok(Self {
481 version,
482 flags,
483 track_id,
484 base_data_offset,
485 sample_description_index,
486 default_sample_duration,
487 default_sample_size,
488 default_sample_flags,
489 })
490 }
491}
492
493impl Serialize for TrackFragmentHeaderBox {
494 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
495 where
496 W: std::io::Write,
497 {
498 self.serialize_box_header(&mut writer)?;
499 self.version.serialize(&mut writer)?;
500 self.flags.serialize(&mut writer)?;
501
502 self.track_id.serialize(&mut writer)?;
503 if self.flags.contains(TfFlags::BaseDataOffsetPresent) {
504 self.base_data_offset
505 .ok_or(io::Error::new(io::ErrorKind::InvalidData, "base_data_offset is required"))?
506 .serialize(&mut writer)?;
507 }
508 if self.flags.contains(TfFlags::SampleDescriptionIndexPresent) {
509 self.sample_description_index
510 .ok_or(io::Error::new(
511 io::ErrorKind::InvalidData,
512 "sample_description_index is required",
513 ))?
514 .serialize(&mut writer)?;
515 }
516 if self.flags.contains(TfFlags::DefaultSampleDurationPresent) {
517 self.default_sample_duration
518 .ok_or(io::Error::new(
519 io::ErrorKind::InvalidData,
520 "default_sample_duration is required",
521 ))?
522 .serialize(&mut writer)?;
523 }
524 if self.flags.contains(TfFlags::DefaultSampleSizePresent) {
525 self.default_sample_size
526 .ok_or(io::Error::new(io::ErrorKind::InvalidData, "default_sample_size is required"))?
527 .serialize(&mut writer)?;
528 }
529 if self.flags.contains(TfFlags::DefaultSampleFlagsPresent) {
530 self.default_sample_flags
531 .ok_or(io::Error::new(io::ErrorKind::InvalidData, "default_sample_flags is required"))?
532 .serialize(&mut writer)?;
533 }
534
535 Ok(())
536 }
537}
538
539#[derive(IsoBox, Debug, PartialEq, Eq)]
543#[iso_box(box_type = b"trun", skip_impl(deserialize_seed, serialize, sized), crate_path = crate)]
544pub struct TrackRunBox {
545 pub version: u8,
548 pub flags: TrFlags,
550 pub sample_count: u32,
553 pub data_offset: Option<i32>,
555 pub first_sample_flags: Option<SampleFlags>,
557 pub samples: Vec<TrackRunBoxSample>,
559}
560
561impl TrackRunBox {
562 pub fn new(samples: Vec<TrackRunBoxSample>, first_sample_flags: Option<SampleFlags>) -> Self {
564 let mut flags = TrFlags::DataOffsetPresent;
565
566 if let Some(first_sample) = samples.first() {
567 if first_sample.sample_duration.is_some() {
568 flags |= TrFlags::SampleDurationPresent;
569 }
570 if first_sample.sample_size.is_some() {
571 flags |= TrFlags::SampleSizePresent;
572 }
573 if first_sample.sample_flags.is_some() {
574 flags |= TrFlags::SampleFlagsPresent;
575 }
576 if first_sample.sample_composition_time_offset.is_some() {
577 flags |= TrFlags::SampleCompositionTimeOffsetsPresent;
578 }
579 }
580
581 let version = if samples
582 .iter()
583 .any(|s| s.sample_composition_time_offset.is_some_and(|o| o < 0))
584 {
585 1
586 } else {
587 0
588 };
589
590 Self {
591 version,
592 flags,
593 sample_count: samples.len() as u32,
594 data_offset: Some(0),
595 first_sample_flags,
596 samples,
597 }
598 }
599}
600
601impl<'a> DeserializeSeed<'a, BoxHeader> for TrackRunBox {
602 fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> io::Result<Self>
603 where
604 R: ZeroCopyReader<'a>,
605 {
606 let version = u8::deserialize(&mut reader)?;
607 let flags = TrFlags::deserialize(&mut reader)?;
608
609 let sample_count = u32::deserialize(&mut reader)?;
610 let data_offset = if flags.contains(TrFlags::DataOffsetPresent) {
611 Some(i32::deserialize(&mut reader)?)
612 } else {
613 None
614 };
615 let first_sample_flags = if flags.contains(TrFlags::FirstSampleFlagsPresent) {
616 Some(SampleFlags::deserialize(&mut reader)?)
617 } else {
618 None
619 };
620
621 let mut samples = Vec::with_capacity(sample_count as usize);
622 for _ in 0..sample_count {
623 samples.push(TrackRunBoxSample::deserialize_seed(&mut reader, (version, flags))?);
624 }
625
626 Ok(Self {
627 version,
628 flags,
629 sample_count,
630 data_offset,
631 first_sample_flags,
632 samples,
633 })
634 }
635}
636
637impl IsoSized for TrackRunBox {
638 fn size(&self) -> usize {
639 let mut size = 0;
640 size += self.version.size(); size += self.flags.size(); size += 4; if self.flags.contains(TrFlags::DataOffsetPresent) {
644 size += 4; }
646 if self.flags.contains(TrFlags::FirstSampleFlagsPresent) {
647 size += 4; }
649
650 size += self.samples.iter().map(|s| s.size(self.flags)).sum::<usize>();
651
652 Self::add_header_size(size)
653 }
654}
655
656impl Serialize for TrackRunBox {
657 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
658 where
659 W: std::io::Write,
660 {
661 self.serialize_box_header(&mut writer)?;
662 self.version.serialize(&mut writer)?;
663 self.flags.serialize(&mut writer)?;
664
665 self.sample_count.serialize(&mut writer)?;
666 if self.flags.contains(TrFlags::DataOffsetPresent) {
667 self.data_offset
668 .ok_or(io::Error::new(io::ErrorKind::InvalidData, "data_offset is required"))?
669 .serialize(&mut writer)?;
670 }
671 if self.flags.contains(TrFlags::FirstSampleFlagsPresent) {
672 self.first_sample_flags
673 .ok_or(io::Error::new(io::ErrorKind::InvalidData, "first_sample_flags is required"))?
674 .serialize(&mut writer)?;
675 }
676
677 for sample in &self.samples {
678 sample.serialize(&mut writer, (self.version, self.flags))?;
679 }
680
681 Ok(())
682 }
683}
684
685#[derive(Debug, PartialEq, Eq)]
687pub struct TrackRunBoxSample {
688 pub sample_duration: Option<u32>,
692 pub sample_size: Option<u32>,
696 pub sample_flags: Option<SampleFlags>,
700 pub sample_composition_time_offset: Option<i64>,
705}
706
707bitflags::bitflags! {
708 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
710 pub struct TrFlags: u32 {
711 const DataOffsetPresent = 0x000001;
713 const FirstSampleFlagsPresent = 0x000004;
721 const SampleDurationPresent = 0x000100;
725 const SampleSizePresent = 0x000200;
729 const SampleFlagsPresent = 0x000400;
733 const SampleCompositionTimeOffsetsPresent = 0x000800;
738 }
739}
740
741impl<'a> Deserialize<'a> for TrFlags {
742 fn deserialize<R>(reader: R) -> io::Result<Self>
743 where
744 R: ZeroCopyReader<'a>,
745 {
746 let flags = U24Be::deserialize(reader)?;
747 Ok(TrFlags::from_bits_truncate(*flags))
748 }
749}
750
751impl Serialize for TrFlags {
752 fn serialize<W>(&self, writer: W) -> io::Result<()>
753 where
754 W: std::io::Write,
755 {
756 U24Be(self.bits()).serialize(writer)
757 }
758}
759
760impl IsoSized for TrFlags {
761 fn size(&self) -> usize {
762 3
763 }
764}
765
766impl<'a> DeserializeSeed<'a, (u8, TrFlags)> for TrackRunBoxSample {
767 fn deserialize_seed<R>(mut reader: R, seed: (u8, TrFlags)) -> std::io::Result<Self>
768 where
769 R: ZeroCopyReader<'a>,
770 {
771 let (version, flags) = seed;
772
773 let sample_duration = if flags.contains(TrFlags::SampleDurationPresent) {
774 Some(u32::deserialize(&mut reader)?)
775 } else {
776 None
777 };
778 let sample_size = if flags.contains(TrFlags::SampleSizePresent) {
779 Some(u32::deserialize(&mut reader)?)
780 } else {
781 None
782 };
783 let sample_flags = if flags.contains(TrFlags::SampleFlagsPresent) {
784 Some(SampleFlags::deserialize(&mut reader)?)
785 } else {
786 None
787 };
788 let sample_composition_time_offset = if flags.contains(TrFlags::SampleCompositionTimeOffsetsPresent) {
789 if version == 0 {
790 Some(u32::deserialize(&mut reader)? as i64)
791 } else {
792 Some(i32::deserialize(&mut reader)? as i64)
793 }
794 } else {
795 None
796 };
797
798 Ok(Self {
799 sample_duration,
800 sample_size,
801 sample_flags,
802 sample_composition_time_offset,
803 })
804 }
805}
806
807impl TrackRunBoxSample {
808 fn serialize<W>(&self, mut writer: W, full_header: (u8, TrFlags)) -> io::Result<()>
809 where
810 W: io::Write,
811 {
812 let (version, flags) = full_header;
813
814 if flags.contains(TrFlags::SampleDurationPresent) {
815 self.sample_duration
816 .ok_or(io::Error::new(io::ErrorKind::InvalidData, "sample_duration is required"))?
817 .serialize(&mut writer)?;
818 }
819 if flags.contains(TrFlags::SampleSizePresent) {
820 self.sample_size
821 .ok_or(io::Error::new(io::ErrorKind::InvalidData, "sample_size is required"))?
822 .serialize(&mut writer)?;
823 }
824 if flags.contains(TrFlags::SampleFlagsPresent) {
825 self.sample_flags
826 .ok_or(io::Error::new(io::ErrorKind::InvalidData, "sample_flags is required"))?
827 .serialize(&mut writer)?;
828 }
829 if flags.contains(TrFlags::SampleCompositionTimeOffsetsPresent) {
830 let sample_composition_time_offset = self.sample_composition_time_offset.ok_or(io::Error::new(
831 io::ErrorKind::InvalidData,
832 "sample_composition_time_offset is required",
833 ))?;
834 if version == 0 {
835 (sample_composition_time_offset as u32).serialize(&mut writer)?;
836 } else {
837 (sample_composition_time_offset as i32).serialize(&mut writer)?;
838 }
839 }
840
841 Ok(())
842 }
843}
844
845impl TrackRunBoxSample {
846 pub fn size(&self, flags: TrFlags) -> usize {
848 let mut size = 0;
849 if flags.contains(TrFlags::SampleDurationPresent) {
850 size += 4; }
852 if flags.contains(TrFlags::SampleSizePresent) {
853 size += 4; }
855 if flags.contains(TrFlags::SampleFlagsPresent) {
856 size += 4; }
858 if flags.contains(TrFlags::SampleCompositionTimeOffsetsPresent) {
859 size += 4; }
861
862 size
863 }
864}
865
866#[derive(IsoBox, Debug, PartialEq, Eq)]
870#[iso_box(box_type = b"mfra", crate_path = crate)]
871pub struct MovieFragmentRandomAccessBox {
872 #[iso_box(nested_box(collect))]
874 pub tfra: Vec<TrackFragmentRandomAccessBox>,
875 #[iso_box(nested_box)]
877 pub mfro: MovieFragmentRandomAccessOffsetBox,
878}
879
880#[derive(IsoBox, Debug, PartialEq, Eq)]
884#[iso_box(box_type = b"tfra", skip_impl(deserialize_seed, serialize, sized), crate_path = crate)]
885pub struct TrackFragmentRandomAccessBox {
886 pub full_header: FullBoxHeader,
888 pub track_id: u32,
890 pub length_size_of_traf_num: u8,
892 pub length_size_of_trun_num: u8,
894 pub length_size_of_sample_num: u8,
896 pub number_of_entry: u32,
899 pub entries: Vec<TrackFragmentRandomAccessBoxEntry>,
901}
902
903impl<'a> DeserializeSeed<'a, BoxHeader> for TrackFragmentRandomAccessBox {
904 fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> io::Result<Self>
905 where
906 R: ZeroCopyReader<'a>,
907 {
908 let full_header = FullBoxHeader::deserialize(&mut reader)?;
909
910 let track_id = u32::deserialize(&mut reader)?;
911 let bytes = u32::deserialize(&mut reader)?;
913 let length_size_of_traf_num = ((bytes >> 4) & 0b11) as u8;
914 let length_size_of_trun_num = ((bytes >> 2) & 0b11) as u8;
915 let length_size_of_sample_num = (bytes & 0b11) as u8;
916 let number_of_entry = u32::deserialize(&mut reader)?;
917
918 let mut entries = Vec::with_capacity(number_of_entry as usize);
919 for _ in 0..number_of_entry {
920 let time = if full_header.version == 1 {
921 u64::deserialize(&mut reader)?
922 } else {
923 u32::deserialize(&mut reader)? as u64
924 };
925 let moof_offset = if full_header.version == 1 {
926 u64::deserialize(&mut reader)?
927 } else {
928 u32::deserialize(&mut reader)? as u64
929 };
930
931 let traf_number = reader.try_read(length_size_of_traf_num as usize + 1)?.pad_to_u32_be();
933 let trun_number = reader.try_read(length_size_of_trun_num as usize + 1)?.pad_to_u32_be();
934 let sample_number = reader.try_read(length_size_of_sample_num as usize + 1)?.pad_to_u32_be();
935
936 entries.push(TrackFragmentRandomAccessBoxEntry {
937 time,
938 moof_offset,
939 traf_number,
940 trun_number,
941 sample_delta: sample_number,
942 });
943 }
944
945 Ok(Self {
946 full_header,
947 track_id,
948 length_size_of_traf_num,
949 length_size_of_trun_num,
950 length_size_of_sample_num,
951 number_of_entry,
952 entries,
953 })
954 }
955}
956
957impl Serialize for TrackFragmentRandomAccessBox {
958 fn serialize<W>(&self, writer: W) -> io::Result<()>
959 where
960 W: std::io::Write,
961 {
962 let mut bit_writer = BitWriter::new(writer);
963
964 self.serialize_box_header(&mut bit_writer)?;
965 self.full_header.serialize(&mut bit_writer)?;
966
967 self.track_id.serialize(&mut bit_writer)?;
968 bit_writer.write_bits(0, 26)?;
969 bit_writer.write_bits(self.length_size_of_traf_num as u64, 2)?;
970 bit_writer.write_bits(self.length_size_of_trun_num as u64, 2)?;
971 bit_writer.write_bits(self.length_size_of_sample_num as u64, 2)?;
972 self.number_of_entry.serialize(&mut bit_writer)?;
973
974 for entry in &self.entries {
975 entry.serialize(&mut bit_writer, self)?;
976 }
977
978 Ok(())
979 }
980}
981
982impl IsoSized for TrackFragmentRandomAccessBox {
983 fn size(&self) -> usize {
984 let mut size = self.full_header.size(); size += 4; size += 4; size += 4; size += self.entries.iter().map(|e| e.size(self)).sum::<usize>();
989
990 Self::add_header_size(size)
991 }
992}
993
994#[derive(Debug, PartialEq, Eq)]
996pub struct TrackFragmentRandomAccessBoxEntry {
997 pub time: u64,
1000 pub moof_offset: u64,
1003 pub traf_number: u32,
1006 pub trun_number: u32,
1009 pub sample_delta: u32,
1012}
1013
1014impl TrackFragmentRandomAccessBoxEntry {
1015 fn serialize<W>(&self, writer: W, parent: &TrackFragmentRandomAccessBox) -> io::Result<()>
1016 where
1017 W: std::io::Write,
1018 {
1019 let mut bit_writer = BitWriter::new(writer);
1020
1021 if parent.full_header.version == 1 {
1022 self.time.serialize(&mut bit_writer)?;
1023 self.moof_offset.serialize(&mut bit_writer)?;
1024 } else {
1025 (self.time as u32).serialize(&mut bit_writer)?;
1026 (self.moof_offset as u32).serialize(&mut bit_writer)?;
1027 }
1028
1029 bit_writer.write_bits(self.traf_number as u64, (parent.length_size_of_traf_num + 1) * 8)?;
1030 bit_writer.write_bits(self.trun_number as u64, (parent.length_size_of_trun_num + 1) * 8)?;
1031 bit_writer.write_bits(self.sample_delta as u64, (parent.length_size_of_sample_num + 1) * 8)?;
1032
1033 Ok(())
1034 }
1035}
1036
1037impl TrackFragmentRandomAccessBoxEntry {
1038 pub fn size(&self, parent: &TrackFragmentRandomAccessBox) -> usize {
1040 let mut size = 0;
1041 if parent.full_header.version == 1 {
1042 size += 8;
1043 size += 8;
1044 } else {
1045 size += 4;
1046 size += 4;
1047 }
1048 size += parent.length_size_of_traf_num as usize + 1;
1049 size += parent.length_size_of_trun_num as usize + 1;
1050 size += parent.length_size_of_sample_num as usize + 1;
1051 size
1052 }
1053}
1054
1055#[derive(IsoBox, Debug, PartialEq, Eq)]
1059#[iso_box(box_type = b"mfro", crate_path = crate)]
1060pub struct MovieFragmentRandomAccessOffsetBox {
1061 pub full_header: FullBoxHeader,
1063 pub parent_size: u32,
1067}
1068
1069#[derive(IsoBox, Debug, PartialEq, Eq)]
1073#[iso_box(box_type = b"tfdt", skip_impl(deserialize_seed, serialize, sized), crate_path = crate)]
1074pub struct TrackFragmentBaseMediaDecodeTimeBox {
1075 pub full_header: FullBoxHeader,
1077 pub base_media_decode_time: u64,
1081}
1082
1083impl TrackFragmentBaseMediaDecodeTimeBox {
1084 pub fn new(base_media_decode_time: u64) -> Self {
1086 let version = if base_media_decode_time > u32::MAX as u64 { 1 } else { 0 };
1087
1088 Self {
1089 full_header: FullBoxHeader {
1090 version,
1091 flags: U24Be(0),
1092 },
1093 base_media_decode_time,
1094 }
1095 }
1096}
1097
1098impl<'a> DeserializeSeed<'a, BoxHeader> for TrackFragmentBaseMediaDecodeTimeBox {
1099 fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> io::Result<Self>
1100 where
1101 R: ZeroCopyReader<'a>,
1102 {
1103 let full_header = FullBoxHeader::deserialize(&mut reader)?;
1104
1105 let base_media_decode_time = if full_header.version == 1 {
1106 u64::deserialize(&mut reader)?
1107 } else {
1108 u32::deserialize(&mut reader)? as u64
1109 };
1110
1111 Ok(Self {
1112 full_header,
1113 base_media_decode_time,
1114 })
1115 }
1116}
1117
1118impl Serialize for TrackFragmentBaseMediaDecodeTimeBox {
1119 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
1120 where
1121 W: std::io::Write,
1122 {
1123 self.serialize_box_header(&mut writer)?;
1124 self.full_header.serialize(&mut writer)?;
1125
1126 if self.full_header.version == 1 {
1127 self.base_media_decode_time.serialize(&mut writer)?;
1128 } else {
1129 (self.base_media_decode_time as u32).serialize(&mut writer)?;
1130 }
1131
1132 Ok(())
1133 }
1134}
1135
1136impl IsoSized for TrackFragmentBaseMediaDecodeTimeBox {
1137 fn size(&self) -> usize {
1138 let mut size = self.full_header.size(); if self.full_header.version == 1 {
1140 size += 8; } else {
1142 size += 4; }
1144 Self::add_header_size(size)
1145 }
1146}
1147
1148#[derive(IsoBox, Debug, PartialEq, Eq)]
1152#[iso_box(box_type = b"leva", crate_path = crate)]
1153pub struct LevelAssignmentBox {
1154 pub full_header: FullBoxHeader,
1156 pub level_count: u8,
1159 #[iso_box(repeated)]
1161 pub levels: Vec<LevelAssignmentBoxLevel>,
1162}
1163
1164#[derive(Debug, PartialEq, Eq)]
1166pub struct LevelAssignmentBoxLevel {
1167 pub track_id: u32,
1169 pub padding_flag: bool,
1174 pub assignment_type: LevelAssignmentBoxLevelAssignmentType,
1176}
1177
1178impl<'a> Deserialize<'a> for LevelAssignmentBoxLevel {
1179 fn deserialize<R>(mut reader: R) -> io::Result<Self>
1180 where
1181 R: ZeroCopyReader<'a>,
1182 {
1183 let track_id = u32::deserialize(&mut reader)?;
1184 let byte = u8::deserialize(&mut reader)?;
1185 let padding_flag = (byte >> 7) == 1;
1186 let assignment_type = byte & 0b01111111;
1187 let assignment_type = match assignment_type {
1188 0 => LevelAssignmentBoxLevelAssignmentType::Type0 {
1189 grouping_type: <[u8; 4]>::deserialize(&mut reader)?,
1190 },
1191 1 => LevelAssignmentBoxLevelAssignmentType::Type1 {
1192 grouping_type: <[u8; 4]>::deserialize(&mut reader)?,
1193 grouping_type_parameter: u32::deserialize(&mut reader)?,
1194 },
1195 2 => LevelAssignmentBoxLevelAssignmentType::Type2,
1196 3 => LevelAssignmentBoxLevelAssignmentType::Type3,
1197 4 => LevelAssignmentBoxLevelAssignmentType::Type4 {
1198 sub_track_id: u32::deserialize(&mut reader)?,
1199 },
1200 _ => LevelAssignmentBoxLevelAssignmentType::Other(assignment_type),
1201 };
1202
1203 Ok(Self {
1204 track_id,
1205 padding_flag,
1206 assignment_type,
1207 })
1208 }
1209}
1210
1211impl Serialize for LevelAssignmentBoxLevel {
1212 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
1213 where
1214 W: std::io::Write,
1215 {
1216 self.track_id.serialize(&mut writer)?;
1217
1218 let mut byte = (self.padding_flag as u8) << 7;
1219 byte |= self.assignment_type.assignment_type() & 0b01111111;
1220 byte.serialize(&mut writer)?;
1221
1222 match self.assignment_type {
1223 LevelAssignmentBoxLevelAssignmentType::Type0 { grouping_type } => {
1224 grouping_type.serialize(&mut writer)?;
1225 }
1226 LevelAssignmentBoxLevelAssignmentType::Type1 {
1227 grouping_type,
1228 grouping_type_parameter,
1229 } => {
1230 grouping_type.serialize(&mut writer)?;
1231 grouping_type_parameter.serialize(&mut writer)?;
1232 }
1233 LevelAssignmentBoxLevelAssignmentType::Type4 { sub_track_id } => {
1234 sub_track_id.serialize(&mut writer)?;
1235 }
1236 _ => {}
1237 }
1238
1239 Ok(())
1240 }
1241}
1242
1243impl IsoSized for LevelAssignmentBoxLevel {
1244 fn size(&self) -> usize {
1245 let mut size = 4; size += 1; match self.assignment_type {
1249 LevelAssignmentBoxLevelAssignmentType::Type0 { .. } => size += 4,
1250 LevelAssignmentBoxLevelAssignmentType::Type1 { .. } => size += 8,
1251 LevelAssignmentBoxLevelAssignmentType::Type4 { .. } => size += 4,
1252 _ => {}
1253 }
1254
1255 size
1256 }
1257}
1258
1259#[derive(Debug, PartialEq, Eq)]
1261pub enum LevelAssignmentBoxLevelAssignmentType {
1262 Type0 {
1266 grouping_type: [u8; 4],
1272 },
1273 Type1 {
1275 grouping_type: [u8; 4],
1281 grouping_type_parameter: u32,
1287 },
1288 Type2,
1291 Type3,
1294 Type4 {
1298 sub_track_id: u32,
1300 },
1301 Other(u8),
1303}
1304
1305impl LevelAssignmentBoxLevelAssignmentType {
1306 pub fn assignment_type(&self) -> u8 {
1308 match self {
1309 LevelAssignmentBoxLevelAssignmentType::Type0 { .. } => 0,
1310 LevelAssignmentBoxLevelAssignmentType::Type1 { .. } => 1,
1311 LevelAssignmentBoxLevelAssignmentType::Type2 => 2,
1312 LevelAssignmentBoxLevelAssignmentType::Type3 => 3,
1313 LevelAssignmentBoxLevelAssignmentType::Type4 { .. } => 4,
1314 LevelAssignmentBoxLevelAssignmentType::Other(v) => *v,
1315 }
1316 }
1317}
1318
1319#[derive(IsoBox, Debug, PartialEq, Eq)]
1323#[iso_box(box_type = b"trep", crate_path = crate)]
1324pub struct TrackExtensionPropertiesBox<'a> {
1325 pub full_header: FullBoxHeader,
1327 pub track_id: u32,
1329 #[iso_box(nested_box(collect))]
1331 pub cslg: Option<CompositionToDecodeBox>,
1332 #[iso_box(nested_box(collect))]
1334 pub assp: Option<AlternativeStartupSequencePropertiesBox>,
1335 #[iso_box(nested_box(collect_unknown))]
1337 pub unknown_boxes: Vec<UnknownBox<'a>>,
1338}
1339
1340#[derive(IsoBox, Debug, PartialEq, Eq)]
1344#[iso_box(box_type = b"assp", skip_impl(deserialize_seed, serialize), crate_path = crate)]
1345pub struct AlternativeStartupSequencePropertiesBox {
1346 pub full_header: FullBoxHeader,
1348 pub version: AlternativeStartupSequencePropertiesBoxVersion,
1351}
1352
1353impl<'a> DeserializeSeed<'a, BoxHeader> for AlternativeStartupSequencePropertiesBox {
1354 fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> io::Result<Self>
1355 where
1356 R: ZeroCopyReader<'a>,
1357 {
1358 let full_header = FullBoxHeader::deserialize(&mut reader)?;
1359
1360 let version = match full_header.version {
1361 0 => AlternativeStartupSequencePropertiesBoxVersion::Version0 {
1362 min_initial_alt_startup_offset: i32::deserialize(&mut reader)?,
1363 },
1364 1 => {
1365 let num_entries = u32::deserialize(&mut reader)?;
1366 AlternativeStartupSequencePropertiesBoxVersion::Version1 {
1367 num_entries,
1368 entries: {
1369 let mut entries = Vec::with_capacity(num_entries as usize);
1370
1371 for _ in 0..num_entries {
1372 entries.push(AlternativeStartupSequencePropertiesBoxVersion1Entry::deserialize(
1373 &mut reader,
1374 )?);
1375 }
1376
1377 entries
1378 },
1379 }
1380 }
1381 v => AlternativeStartupSequencePropertiesBoxVersion::Other(v),
1382 };
1383
1384 Ok(Self { full_header, version })
1385 }
1386}
1387
1388impl Serialize for AlternativeStartupSequencePropertiesBox {
1389 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
1390 where
1391 W: std::io::Write,
1392 {
1393 self.serialize_box_header(&mut writer)?;
1394 self.full_header.serialize(&mut writer)?;
1395
1396 match &self.version {
1397 AlternativeStartupSequencePropertiesBoxVersion::Version0 {
1398 min_initial_alt_startup_offset,
1399 } => {
1400 min_initial_alt_startup_offset.serialize(&mut writer)?;
1401 }
1402 AlternativeStartupSequencePropertiesBoxVersion::Version1 { num_entries, entries } => {
1403 num_entries.serialize(&mut writer)?;
1404 for entry in entries {
1405 entry.serialize(&mut writer)?;
1406 }
1407 }
1408 _ => {}
1409 }
1410
1411 Ok(())
1412 }
1413}
1414
1415#[derive(Debug, PartialEq, Eq)]
1417pub enum AlternativeStartupSequencePropertiesBoxVersion {
1418 Version0 {
1420 min_initial_alt_startup_offset: i32,
1427 },
1428 Version1 {
1430 num_entries: u32,
1432 entries: Vec<AlternativeStartupSequencePropertiesBoxVersion1Entry>,
1434 },
1435 Other(u8),
1437}
1438
1439impl IsoSized for AlternativeStartupSequencePropertiesBoxVersion {
1440 fn size(&self) -> usize {
1441 match self {
1442 AlternativeStartupSequencePropertiesBoxVersion::Version0 { .. } => 4,
1443 AlternativeStartupSequencePropertiesBoxVersion::Version1 { entries, .. } => 4 + entries.size(),
1444 _ => 0,
1445 }
1446 }
1447}
1448
1449#[derive(Debug, PartialEq, Eq)]
1453pub struct AlternativeStartupSequencePropertiesBoxVersion1Entry {
1454 pub grouping_type_parameter: u32,
1456 pub min_initial_alt_startup_offset: i32,
1463}
1464
1465impl<'a> Deserialize<'a> for AlternativeStartupSequencePropertiesBoxVersion1Entry {
1466 fn deserialize<R>(mut reader: R) -> io::Result<Self>
1467 where
1468 R: ZeroCopyReader<'a>,
1469 {
1470 let grouping_type_parameter = u32::deserialize(&mut reader)?;
1471 let min_initial_alt_startup_offset = i32::deserialize(&mut reader)?;
1472
1473 Ok(Self {
1474 grouping_type_parameter,
1475 min_initial_alt_startup_offset,
1476 })
1477 }
1478}
1479
1480impl Serialize for AlternativeStartupSequencePropertiesBoxVersion1Entry {
1481 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
1482 where
1483 W: std::io::Write,
1484 {
1485 self.grouping_type_parameter.serialize(&mut writer)?;
1486 self.min_initial_alt_startup_offset.serialize(&mut writer)?;
1487 Ok(())
1488 }
1489}
1490
1491impl IsoSized for AlternativeStartupSequencePropertiesBoxVersion1Entry {
1492 fn size(&self) -> usize {
1493 4 + 4
1494 }
1495}