mp4_atom/moof/traf/
tfhd.rs1use 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}
27
28impl AtomExt for Tfhd {
29 const KIND_EXT: FourCC = FourCC::new(b"tfhd");
30
31 type Ext = TfhdExt;
32
33 fn decode_body_ext<B: Buf>(buf: &mut B, ext: TfhdExt) -> Result<Self> {
34 let track_id = u32::decode(buf)?;
35
36 let base_data_offset = match ext.base_data_offset {
37 true => u64::decode(buf)?.into(),
38 false => None,
39 };
40
41 let sample_description_index = match ext.sample_description_index {
42 true => u32::decode(buf)?.into(),
43 false => None,
44 };
45
46 let default_sample_duration = match ext.default_sample_duration {
47 true => u32::decode(buf)?.into(),
48 false => None,
49 };
50
51 let default_sample_size = match ext.default_sample_size {
52 true => u32::decode(buf)?.into(),
53 false => None,
54 };
55
56 let default_sample_flags = match ext.default_sample_flags {
57 true => u32::decode(buf)?.into(),
58 false => None,
59 };
60
61 Ok(Tfhd {
62 track_id,
63 base_data_offset,
64 sample_description_index,
65 default_sample_duration,
66 default_sample_size,
67 default_sample_flags,
68 })
69 }
70
71 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<TfhdExt> {
72 let ext = TfhdExt {
73 base_data_offset: self.base_data_offset.is_some(),
74 sample_description_index: self.sample_description_index.is_some(),
75 default_sample_duration: self.default_sample_duration.is_some(),
76 default_sample_size: self.default_sample_size.is_some(),
77 default_sample_flags: self.default_sample_flags.is_some(),
78 ..Default::default()
79 };
80
81 self.track_id.encode(buf)?;
82 self.base_data_offset.encode(buf)?;
83 self.sample_description_index.encode(buf)?;
84 self.default_sample_duration.encode(buf)?;
85 self.default_sample_size.encode(buf)?;
86 self.default_sample_flags.encode(buf)?;
87
88 Ok(ext)
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 #[test]
97 fn test_tfhd() {
98 let expected = Tfhd {
99 track_id: 1,
100 base_data_offset: None,
101 sample_description_index: None,
102 default_sample_duration: None,
103 default_sample_size: None,
104 default_sample_flags: None,
105 };
106 let mut buf = Vec::new();
107 expected.encode(&mut buf).unwrap();
108
109 let mut buf = buf.as_ref();
110 let decoded = Tfhd::decode(&mut buf).unwrap();
111 assert_eq!(decoded, expected);
112 }
113
114 #[test]
115 fn test_tfhd_with_flags() {
116 let expected = Tfhd {
117 track_id: 1,
118 base_data_offset: None,
119 sample_description_index: Some(1),
120 default_sample_duration: Some(512),
121 default_sample_size: None,
122 default_sample_flags: Some(0x1010000),
123 };
124 let mut buf = Vec::new();
125 expected.encode(&mut buf).unwrap();
126
127 let mut buf = buf.as_ref();
128 let decoded = Tfhd::decode(&mut buf).unwrap();
129 assert_eq!(decoded, expected);
130 }
131}