Skip to main content

mp4_atom/moov/
mod.rs

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}