Skip to main content

mp4_atom/moof/traf/
tfhd.rs

1use crate::*;
2
3ext! {
4    name: Tfhd,
5    versions: [0],
6    flags: {
7        base_data_offset = 0,
8        sample_description_index = 1,
9        default_sample_duration = 3,
10        default_sample_size = 4,
11        default_sample_flags = 5,
12        duration_is_empty = 16,
13        default_base_is_moof = 17,
14    }
15}
16
17#[derive(Debug, Clone, PartialEq, Eq, Default)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19pub struct Tfhd {
20    pub track_id: u32,
21    pub base_data_offset: Option<u64>,
22    pub sample_description_index: Option<u32>,
23    pub default_sample_duration: Option<u32>,
24    pub default_sample_size: Option<u32>,
25    pub default_sample_flags: Option<u32>,
26    pub duration_is_empty: bool,
27    pub default_base_is_moof: bool,
28}
29
30impl AtomExt for Tfhd {
31    const KIND_EXT: FourCC = FourCC::new(b"tfhd");
32
33    type Ext = TfhdExt;
34
35    fn decode_body_ext<B: Buf>(buf: &mut B, ext: TfhdExt) -> Result<Self> {
36        let track_id = u32::decode(buf)?;
37
38        let base_data_offset = match ext.base_data_offset {
39            true => u64::decode(buf)?.into(),
40            false => None,
41        };
42
43        let sample_description_index = match ext.sample_description_index {
44            true => u32::decode(buf)?.into(),
45            false => None,
46        };
47
48        let default_sample_duration = match ext.default_sample_duration {
49            true => u32::decode(buf)?.into(),
50            false => None,
51        };
52
53        let default_sample_size = match ext.default_sample_size {
54            true => u32::decode(buf)?.into(),
55            false => None,
56        };
57
58        let default_sample_flags = match ext.default_sample_flags {
59            true => u32::decode(buf)?.into(),
60            false => None,
61        };
62
63        Ok(Tfhd {
64            track_id,
65            base_data_offset,
66            sample_description_index,
67            default_sample_duration,
68            default_sample_size,
69            default_sample_flags,
70            duration_is_empty: ext.duration_is_empty,
71            default_base_is_moof: ext.default_base_is_moof,
72        })
73    }
74
75    fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<TfhdExt> {
76        let ext = TfhdExt {
77            base_data_offset: self.base_data_offset.is_some(),
78            sample_description_index: self.sample_description_index.is_some(),
79            default_sample_duration: self.default_sample_duration.is_some(),
80            default_sample_size: self.default_sample_size.is_some(),
81            default_sample_flags: self.default_sample_flags.is_some(),
82            duration_is_empty: self.duration_is_empty,
83            default_base_is_moof: self.default_base_is_moof,
84            ..Default::default()
85        };
86
87        self.track_id.encode(buf)?;
88        self.base_data_offset.encode(buf)?;
89        self.sample_description_index.encode(buf)?;
90        self.default_sample_duration.encode(buf)?;
91        self.default_sample_size.encode(buf)?;
92        self.default_sample_flags.encode(buf)?;
93
94        Ok(ext)
95    }
96}
97
98#[cfg(test)]
99mod tests {
100    use super::*;
101
102    #[test]
103    fn test_tfhd() {
104        let expected = Tfhd {
105            track_id: 1,
106            base_data_offset: None,
107            sample_description_index: None,
108            default_sample_duration: None,
109            default_sample_size: None,
110            default_sample_flags: None,
111            duration_is_empty: false,
112            default_base_is_moof: false,
113        };
114        let mut buf = Vec::new();
115        expected.encode(&mut buf).unwrap();
116
117        let mut buf = buf.as_ref();
118        let decoded = Tfhd::decode(&mut buf).unwrap();
119        assert_eq!(decoded, expected);
120    }
121
122    #[test]
123    fn test_tfhd_with_flags() {
124        let expected = Tfhd {
125            track_id: 1,
126            base_data_offset: None,
127            sample_description_index: Some(1),
128            default_sample_duration: Some(512),
129            default_sample_size: None,
130            default_sample_flags: Some(0x1010000),
131            duration_is_empty: false,
132            default_base_is_moof: false,
133        };
134        let mut buf = Vec::new();
135        expected.encode(&mut buf).unwrap();
136
137        let mut buf = buf.as_ref();
138        let decoded = Tfhd::decode(&mut buf).unwrap();
139        assert_eq!(decoded, expected);
140    }
141
142    #[test]
143    fn test_tfhd_duration_is_empty() {
144        let expected = Tfhd {
145            track_id: 1,
146            duration_is_empty: true,
147            ..Default::default()
148        };
149        let mut buf = Vec::new();
150        expected.encode(&mut buf).unwrap();
151
152        let mut buf = buf.as_ref();
153        let decoded = Tfhd::decode(&mut buf).unwrap();
154        assert_eq!(decoded, expected);
155    }
156
157    #[test]
158    fn test_tfhd_default_base_is_moof() {
159        let expected = Tfhd {
160            track_id: 1,
161            default_base_is_moof: true,
162            default_sample_duration: Some(512),
163            default_sample_size: Some(0),
164            default_sample_flags: Some(0x1010000),
165            ..Default::default()
166        };
167        let mut buf = Vec::new();
168        expected.encode(&mut buf).unwrap();
169
170        let mut buf = buf.as_ref();
171        let decoded = Tfhd::decode(&mut buf).unwrap();
172        assert_eq!(decoded, expected);
173    }
174}