async_mp4/mp4box/
trun.rs

1use std::hash::{Hash, Hasher};
2use bitregions::bitregions;
3use crate::{flag_option, full_box, mp4_versioned_data};
4use crate::types::versioned_signed_int::VersionedSignedU32;
5use crate::mp4box::trex::SampleFlags;
6use crate::types::array::{Mp4VersionedOffsetArray};
7
8bitregions! {
9    pub TrunFlags u32 {
10        HAS_DATA_OFFSET:                0b0000000000000000__0000_0000_0000_0001,
11        HAS_FIRST_SAMPLE_FLAGS:         0b0000000000000000__0000_0000_0000_0100,
12        HAS_SAMPLE_DURATION:            0b0000000000000000__0000_0001_0000_0000,
13        HAS_SAMPLE_SIZE:                0b0000000000000000__0000_0010_0000_0000,
14        HAS_SAMPLE_FLAGS:               0b0000000000000000__0000_0100_0000_0000,
15        HAS_SAMPLE_COMPOSITION:         0b0000000000000000__0000_1000_0000_0000,
16    }
17}
18
19impl Eq for TrunFlags {}
20impl Hash for TrunFlags {
21    fn hash<H: Hasher>(&self, state: &mut H) {
22        self.0.hash(state)
23    }
24}
25
26flag_option! {
27    #[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Hash)]
28    pub struct TrunDataOffset(pub i32, TrunFlags, HAS_DATA_OFFSET);
29}
30
31flag_option! {
32    #[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Hash)]
33    pub struct TrunFirstSampleFlags(pub SampleFlags, TrunFlags, HAS_FIRST_SAMPLE_FLAGS);
34}
35
36flag_option! {
37    #[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Hash)]
38    pub struct TrunSampleDuration(pub u32, TrunFlags, HAS_SAMPLE_DURATION);
39}
40
41flag_option! {
42    #[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Hash)]
43    pub struct TrunSampleSize(pub u32, TrunFlags, HAS_SAMPLE_SIZE);
44}
45
46flag_option! {
47    #[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Hash)]
48    pub struct TrunSampleFlags(pub SampleFlags, TrunFlags, HAS_SAMPLE_FLAGS);
49}
50
51flag_option! {
52    #[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Hash)]
53    pub struct TrunSampleCompositionOffset(pub VersionedSignedU32, TrunFlags, HAS_SAMPLE_COMPOSITION);
54}
55
56mp4_versioned_data! {
57     #[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Hash)]
58    pub struct TrunOffset {
59        pub data_offset: TrunDataOffset,
60        pub first_sample_flags: TrunFirstSampleFlags,
61    }
62}
63
64mp4_versioned_data! {
65     #[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Hash)]
66    pub struct TrunEntry {
67        pub sample_duration: TrunSampleDuration,
68        pub sample_size: TrunSampleSize,
69        pub sample_flags: TrunSampleFlags,
70        pub sample_composition_time_offset: TrunSampleCompositionOffset
71    }
72}
73
74full_box! {
75    box (b"trun", Trun, TrunBox, TrunFlags)
76    data {
77        entries: Mp4VersionedOffsetArray<u32, TrunOffset, TrunEntry>
78    }
79}
80
81impl Default for Trun {
82    fn default() -> Self {
83        Self {
84            entries: Default::default()
85        }
86    }
87}
88
89#[cfg(test)]
90mod test {
91    use crate::bytes_read::Mp4Readable;
92    use crate::error::MP4Error;
93    use crate::header::BoxHeader;
94    use crate::mp4box::box_trait::{BoxRead, BoxWrite, IBox};
95    use crate::mp4box::trun::{Trun, TrunBox, TrunDataOffset, TrunEntry, TrunOffset, TrunSampleSize};
96    use crate::types::array::Mp4VersionedOffsetArray;
97    use crate::mp4box::trex::SampleFlags;
98
99    #[test]
100    pub fn test_rebuild() -> Result<(), MP4Error> {
101        futures::executor::block_on(async {
102            let base: TrunBox = Trun {
103                entries: Mp4VersionedOffsetArray {
104                    data: vec![TrunEntry {
105                        sample_duration: 32u32.into(),
106                        sample_size: TrunSampleSize::from(100000u32),
107                        sample_flags: SampleFlags::from(37814272).into(),
108                        sample_composition_time_offset: Default::default()
109                    }],
110                    offset: TrunOffset {
111                        data_offset: TrunDataOffset(Some(100)),
112                        first_sample_flags: Default::default()
113                    },
114                    _p: Default::default()
115                }
116            }.into();
117            let mut buf = vec![];
118            let mut cursor = std::io::Cursor::new(&mut buf);
119            let pos = base.write(&mut cursor)?;
120            assert_eq!(pos, base.byte_size());
121            assert_eq!(pos as u64, cursor.position());
122            let mut cursor = futures::io::Cursor::new(&mut buf);
123            let header = BoxHeader::read(&mut cursor).await?;
124            assert_eq!(header.id, TrunBox::ID);
125            let new = TrunBox::read(header, &mut cursor).await?;
126            assert_eq!(base, new);
127            Ok(())
128        })
129    }
130
131}