1mod ainf;
2mod mvex;
3mod mvhd;
4mod trak;
5mod udta;
6
7pub use ainf::*;
8pub use mvex::*;
9pub use mvhd::*;
10pub use trak::*;
11pub use udta::*;
12
13use crate::*;
14
15#[derive(Debug, Clone, PartialEq, Default)]
16#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
17pub struct Moov {
18 pub mvhd: Mvhd,
19 pub meta: Option<Meta>,
20 pub mvex: Option<Mvex>,
21 pub trak: Vec<Trak>,
22 pub udta: Option<Udta>,
23 pub ainf: Option<Ainf>,
24}
25
26impl Atom for Moov {
27 const KIND: FourCC = FourCC::new(b"moov");
28
29 nested! {
30 required: [ Mvhd ],
31 optional: [ Ainf, Meta, Mvex, Udta ],
32 multiple: [ Trak ],
33 }
34}
35
36#[cfg(test)]
37mod test {
38 use super::*;
39
40 #[test]
41 fn rejects_truncated_child_body() {
42 let mut encoded = Vec::new();
43 Moov::default().encode(&mut encoded).unwrap();
44
45 encoded.extend_from_slice(b"\0\0\0\x20trak");
46 let size = u32::try_from(encoded.len()).unwrap();
47 encoded[..4].copy_from_slice(&size.to_be_bytes());
48
49 assert!(matches!(
50 Moov::decode(&mut encoded.as_slice()),
51 Err(Error::UnderDecode(kind)) if kind == Moov::KIND
52 ));
53 }
54
55 #[test]
56 fn test_meta() {
57 const ENCODED: &[u8] = &[
58 0x00, 0x00, 0x03, 0x3A, 0x6D, 0x6F, 0x6F, 0x76, 0x00, 0x00, 0x00, 0x6C, 0x6D, 0x76,
59 0x68, 0x64, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xEF, 0xCF, 0xD6, 0xE0, 0xEF, 0xCF, 0xD6,
60 0x00, 0x01, 0x5F, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00,
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x8D, 0x6D, 0x65, 0x74, 0x61, 0x00, 0x00,
67 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x68, 0x64, 0x6C, 0x72, 0x00, 0x00, 0x00, 0x00,
68 0x00, 0x00, 0x00, 0x00, 0x49, 0x44, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x49, 0x44, 0x33, 0x32,
70 0x00, 0x00, 0x00, 0x00, 0x15, 0xC7, 0x49, 0x44, 0x33, 0x04, 0x00, 0x00, 0x00, 0x00,
71 0x00, 0x49, 0x50, 0x52, 0x49, 0x56, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x68, 0x74,
72 0x74, 0x70, 0x73, 0x3A, 0x2F, 0x2F, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63,
73 0x6F, 0x6D, 0x2F, 0x67, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x2F, 0x73, 0x68, 0x61, 0x6B,
74 0x61, 0x2D, 0x70, 0x61, 0x63, 0x6B, 0x61, 0x67, 0x65, 0x72, 0x00, 0x76, 0x32, 0x2E,
75 0x36, 0x2E, 0x31, 0x2D, 0x36, 0x33, 0x34, 0x61, 0x66, 0x36, 0x35, 0x2D, 0x72, 0x65,
76 0x6C, 0x65, 0x61, 0x73, 0x65, 0x00, 0x00, 0x02, 0x01, 0x74, 0x72, 0x61, 0x6B, 0x00,
77 0x00, 0x00, 0x5C, 0x74, 0x6B, 0x68, 0x64, 0x00, 0x00, 0x00, 0x07, 0xE0, 0xEF, 0xCF,
78 0xD6, 0xE0, 0xEF, 0xCF, 0xD6, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
79 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x07,
83 0x80, 0x00, 0x00, 0x04, 0x38, 0x00, 0x00, 0x00, 0x00, 0x01, 0x79, 0x6D, 0x64, 0x69,
84 0x61, 0x00, 0x00, 0x00, 0x20, 0x6D, 0x64, 0x68, 0x64, 0x00, 0x00, 0x00, 0x00, 0xE0,
85 0xEF, 0xCF, 0xD6, 0xE0, 0xEF, 0xCF, 0xD6, 0x00, 0x01, 0x5F, 0x90, 0x00, 0x00, 0x00,
86 0x00, 0x55, 0xC4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x68, 0x64, 0x6C, 0x72, 0x00,
87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x64, 0x65, 0x00, 0x00, 0x00,
88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x69, 0x64, 0x65, 0x6F,
89 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00, 0x00, 0x00, 0x01, 0x24, 0x6D, 0x69,
90 0x6E, 0x66, 0x00, 0x00, 0x00, 0x24, 0x64, 0x69, 0x6E, 0x66, 0x00, 0x00, 0x00, 0x1C,
91 0x64, 0x72, 0x65, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
92 0x00, 0x0C, 0x75, 0x72, 0x6C, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xE4,
93 0x73, 0x74, 0x62, 0x6C, 0x00, 0x00, 0x00, 0x98, 0x73, 0x74, 0x73, 0x64, 0x00, 0x00,
94 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x88, 0x61, 0x76, 0x63, 0x31,
95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x04, 0x38,
97 0x00, 0x48, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
98 0x0A, 0x41, 0x56, 0x43, 0x20, 0x43, 0x6F, 0x64, 0x69, 0x6E, 0x67, 0x00, 0x00, 0x00,
99 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x32, 0x61, 0x76,
101 0x63, 0x43, 0x01, 0x64, 0x00, 0x28, 0xFF, 0xE1, 0x00, 0x1A, 0x67, 0x64, 0x00, 0x28,
102 0xAC, 0xD9, 0x40, 0x78, 0x02, 0x27, 0xE5, 0x84, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00,
103 0x00, 0x03, 0x00, 0xF0, 0x3C, 0x60, 0xC6, 0x58, 0x01, 0x00, 0x05, 0x68, 0xEB, 0xEC,
104 0xB2, 0x2C, 0x00, 0x00, 0x00, 0x10, 0x73, 0x74, 0x74, 0x73, 0x00, 0x00, 0x00, 0x00,
105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x73, 0x74, 0x73, 0x63, 0x00, 0x00,
106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x73, 0x74, 0x73, 0x7A,
107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
108 0x00, 0x10, 0x73, 0x74, 0x63, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109 0x00, 0x00, 0x00, 0x14, 0x76, 0x6D, 0x68, 0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x65, 0x64, 0x74, 0x73,
111 0x00, 0x00, 0x00, 0x1C, 0x65, 0x6C, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
112 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x70, 0x00, 0x01, 0x00, 0x00,
113 0x00, 0x00, 0x00, 0x38, 0x6D, 0x76, 0x65, 0x78, 0x00, 0x00, 0x00, 0x10, 0x6D, 0x65,
114 0x68, 0x64, 0x00, 0x00, 0x00, 0x00, 0x01, 0xB9, 0x31, 0x50, 0x00, 0x00, 0x00, 0x20,
115 0x74, 0x72, 0x65, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
116 0x00, 0x01, 0x00, 0x00, 0x0B, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
117 ];
118
119 let decoded = Moov::decode(&mut &ENCODED[..]).unwrap();
120 assert_eq!(
121 decoded,
122 Moov {
123 mvhd: Mvhd {
124 creation_time: 3773812694,
125 modification_time: 3773812694,
126 timescale: 90000,
127 rate: 1.into(),
128 volume: 1.into(),
129 next_track_id: 2,
130 ..Default::default()
131 },
132 meta: Some(Meta {
133 hdlr: Hdlr {
134 handler: FourCC::new(b"ID32"),
135 name: "".into()
136 },
137 items: vec![Any::Unknown(
138 FourCC::new(b"ID32"),
139 vec![
140 0, 0, 0, 0, 21, 199, 73, 68, 51, 4, 0, 0, 0, 0, 0, 73, 80, 82, 73, 86,
141 0, 0, 0, 63, 0, 0, 104, 116, 116, 112, 115, 58, 47, 47, 103, 105, 116,
142 104, 117, 98, 46, 99, 111, 109, 47, 103, 111, 111, 103, 108, 101, 47,
143 115, 104, 97, 107, 97, 45, 112, 97, 99, 107, 97, 103, 101, 114, 0, 118,
144 50, 46, 54, 46, 49, 45, 54, 51, 52, 97, 102, 54, 53, 45, 114, 101, 108,
145 101, 97, 115, 101
146 ]
147 )]
148 }),
149 mvex: Some(Mvex {
150 mehd: Some(Mehd {
151 fragment_duration: 28914000
152 }),
153 trex: vec![Trex {
154 track_id: 1,
155 default_sample_description_index: 1,
156 default_sample_duration: 3000,
157 ..Default::default()
158 }]
159 }),
160 trak: vec![Trak {
161 tkhd: Tkhd {
162 creation_time: 3773812694,
163 modification_time: 3773812694,
164 track_id: 1,
165 enabled: true,
166 in_movie: true,
167 width: 1920.into(),
168 height: 1080.into(),
169 ..Default::default()
170 },
171 edts: Some(Edts {
172 elst: Some(Elst {
173 entries: vec![ElstEntry {
174 media_time: Some(6000),
175 media_rate: 1.into(),
176 ..Default::default()
177 }]
178 })
179 }),
180 mdia: Mdia {
181 mdhd: Mdhd {
182 creation_time: 3773812694,
183 modification_time: 3773812694,
184 timescale: 90000,
185 duration: 0,
186 language: "und".to_string(),
187 },
188 hdlr: Hdlr {
189 handler: b"vide".into(),
190 name: "VideoHandler".to_string(),
191 },
192 minf: Minf {
193 vmhd: Some(Vmhd {
194 graphics_mode: 0,
195 op_color: RgbColor {
196 red: 0,
197 green: 0,
198 blue: 0
199 }
200 }),
201 dinf: Dinf {
202 dref: Dref {
203 urls: vec![Url::default()]
204 }
205 },
206 stbl: Stbl {
207 stsd: Stsd {
208 codecs: vec![Avc1 {
209 visual: Visual {
210 data_reference_index: 1,
211 width: 1920,
212 height: 1080,
213 horizresolution: 72.into(),
214 vertresolution: 72.into(),
215 frame_count: 1,
216 compressor: "AVC Coding".into(),
217 depth: 24,
218 },
219 avcc: Avcc {
220 configuration_version: 1,
221 avc_profile_indication: 100,
222 profile_compatibility: 0,
223 avc_level_indication: 40,
224 length_size: 4,
225 sequence_parameter_sets: vec![vec![
226 103, 100, 0, 40, 172, 217, 64, 120, 2, 39, 229,
227 132, 0, 0, 3, 0, 4, 0, 0, 3, 0, 240, 60, 96, 198,
228 88
229 ]],
230 picture_parameter_sets: vec![vec![
231 104, 235, 236, 178, 44
232 ]],
233 ext: None,
234 },
235 btrt: None,
236 colr: None,
237 pasp: None,
238 taic: None,
239 fiel: None,
240 }
241 .into()],
242 },
243 stco: Some(Stco::default()),
244 ..Default::default()
245 },
246 ..Default::default()
247 }
248 },
249 ..Default::default()
250 }],
251 ..Default::default()
252 }
253 )
254 }
255}