1 #![allow(dead_code)]
2 
3 #[macro_use]
4 extern crate nom;
5 
6 use nom::{
7   IResult, Needed, Err,
8   error::ErrorKind,
9   number::streaming::{be_u16, be_u32, be_u64, be_f32}
10 };
11 
12 use std::str;
13 
14 fn mp4_box(input: &[u8]) -> IResult<&[u8], &[u8]> {
15   match be_u32(input) {
take_char(input: &[u8]) -> IResult<&[u8], char>16     Ok((i, offset)) => {
17       let sz: usize = offset as usize;
18       if i.len() >= sz - 4 {
19         Ok((&i[(sz - 4)..], &i[0..(sz - 4)]))
20       } else {
21         Err(Err::Incomplete(Needed::Size(offset as usize + 4)))
22       }
23     }
24     Err(e) => Err(e),
25   }
26 }
27 
28 #[cfg_attr(rustfmt, rustfmt_skip)]
29 #[derive(PartialEq,Eq,Debug)]
30 struct FileType<'a> {
31   major_brand:         &'a str,
32   major_brand_version: &'a [u8],
33   compatible_brands:   Vec<&'a str>
34 }
35 
36 #[cfg_attr(rustfmt, rustfmt_skip)]
37 #[allow(non_snake_case)]
38 #[derive(Debug,Clone)]
39 pub struct Mvhd32 {
40   version_flags: u32, // actually:
41   // version: u8,
42   // flags: u24       // 3 bytes
43   created_date:  u32,
44   modified_date: u32,
45   scale:         u32,
46   duration:      u32,
47   speed:         f32,
48   volume:        u16, // actually a 2 bytes decimal
49   /* 10 bytes reserved */
50   scaleA:        f32,
51   rotateB:       f32,
52   angleU:        f32,
53   rotateC:       f32,
54   scaleD:        f32,
55   angleV:        f32,
56   positionX:     f32,
57   positionY:     f32,
58   scaleW:        f32,
59   preview:       u64,
60   poster:        u32,
issue_58()61   selection:     u64,
62   current_time:  u32,
63   track_id:      u32
64 }
65 
66 #[cfg_attr(rustfmt, rustfmt_skip)]
67 #[allow(non_snake_case)]
68 #[derive(Debug,Clone)]
69 pub struct Mvhd64 {
70   version_flags: u32, // actually:
71   // version: u8,
72   // flags: u24       // 3 bytes
73   created_date:  u64,
74   modified_date: u64,
75   scale:         u32,
76   duration:      u64,
77   speed:         f32,
78   volume:        u16, // actually a 2 bytes decimal
79   /* 10 bytes reserved */
80   scaleA:        f32,
81   rotateB:       f32,
82   angleU:        f32,
83   rotateC:       f32,
84   scaleD:        f32,
85   angleV:        f32,
86   positionX:     f32,
87   positionY:     f32,
88   scaleW:        f32,
89   preview:       u64,
90   poster:        u32,
91   selection:     u64,
92   current_time:  u32,
93   track_id:      u32
94 }
95 
96 #[allow(non_snake_case)]
97 named!(mvhd32 <&[u8], MvhdBox>,
98   do_parse!(
99   version_flags: be_u32 >>
100   created_date:  be_u32 >>
101   modified_date: be_u32 >>
102   scale:         be_u32 >>
103   duration:      be_u32 >>
104   speed:         be_f32 >>
105   volume:        be_u16 >> // actually a 2 bytes decimal
usize_length_bytes_issue()106               take!(10) >>
107   scale_a:       be_f32 >>
108   rotate_b:      be_f32 >>
109   angle_u:       be_f32 >>
110   rotate_c:      be_f32 >>
111   scale_d:       be_f32 >>
112   angle_v:       be_f32 >>
113   position_x:    be_f32 >>
114   position_y:    be_f32 >>
115   scale_w:       be_f32 >>
116   preview:       be_u64 >>
117   poster:        be_u32 >>
118   selection:     be_u64 >>
119   current_time:  be_u32 >>
120   track_id:      be_u32 >>
121   (
122     MvhdBox::M32(Mvhd32 {
123       version_flags: version_flags,
124       created_date:  created_date,
125       modified_date: modified_date,
126       scale:         scale,
127       duration:      duration,
128       speed:         speed,
129       volume:        volume,
130       scaleA:        scale_a,
131       rotateB:       rotate_b,
132       angleU:        angle_u,
133       rotateC:       rotate_c,
134       scaleD:        scale_d,
135       angleV:        angle_v,
136       positionX:     position_x,
137       positionY:     position_y,
138       scaleW:        scale_w,
139       preview:       preview,
140       poster:        poster,
141       selection:     selection,
142       current_time:  current_time,
143       track_id:      track_id
144     })
145   ))
146 );
147 
148 #[allow(non_snake_case)]
149 named!(mvhd64 <&[u8], MvhdBox>,
150   do_parse!(
151   version_flags: be_u32 >>
issue_302(input: &[u8]) -> IResult<&[u8], Option<Vec<u64>>>152   created_date:  be_u64 >>
153   modified_date: be_u64 >>
154   scale:         be_u32 >>
155   duration:      be_u64 >>
156   speed:         be_f32 >>
157   volume:        be_u16 >> // actually a 2 bytes decimal
158               take!(10) >>
159   scale_a:       be_f32 >>
160   rotate_b:      be_f32 >>
161   angle_u:       be_f32 >>
162   rotate_c:      be_f32 >>
163   scale_d:       be_f32 >>
164   angle_v:       be_f32 >>
165   position_x:    be_f32 >>
166   position_y:    be_f32 >>
167   scale_w:       be_f32 >>
168   preview:       be_u64 >>
169   poster:        be_u32 >>
170   selection:     be_u64 >>
171   current_time:  be_u32 >>
172   track_id:      be_u32 >>
173   (
174     MvhdBox::M64(Mvhd64 {
175       version_flags: version_flags,
176       created_date:  created_date,
177       modified_date: modified_date,
178       scale:         scale,
179       duration:      duration,
180       speed:         speed,
181       volume:        volume,
182       scaleA:        scale_a,
183       rotateB:       rotate_b,
184       angleU:        angle_u,
185       rotateC:       rotate_c,
186       scaleD:        scale_d,
187       angleV:        angle_v,
188       positionX:     position_x,
189       positionY:     position_y,
190       scaleW:        scale_w,
191       preview:       preview,
192       poster:        poster,
193       selection:     selection,
194       current_time:  current_time,
195       track_id:      track_id
196     })
197   ))
198 );
199 
200 #[derive(Debug, Clone)]
201 pub enum MvhdBox {
202   M32(Mvhd32),
203   M64(Mvhd64),
204 }
issue_752()205 
206 #[derive(Debug, Clone)]
207 pub enum MoovBox {
208   Mdra,
209   Dref,
210   Cmov,
211   Rmra,
212   Iods,
213   Mvhd(MvhdBox),
214   Clip,
215   Trak,
216   Udta,
217 }
218 
219 #[derive(Debug)]
220 enum MP4BoxType {
221   Ftyp,
issue_759()222   Moov,
223   Mdat,
224   Free,
225   Skip,
226   Wide,
227   Mdra,
228   Dref,
229   Cmov,
230   Rmra,
231   Iods,
232   Mvhd,
233   Clip,
234   Trak,
235   Udta,
236   Unknown,
237 }
238 
239 #[derive(Debug)]
240 struct MP4BoxHeader {
241   length: u32,
242   tag: MP4BoxType,
243 }
244 
245 named!(brand_name<&[u8],&str>, map_res!(take!(4), str::from_utf8));
246 
247 named!(filetype_parser<&[u8], FileType>,
248   do_parse!(
249     m: brand_name          >>
250     v: take!(4)            >>
251     c: many0!(brand_name)  >>
252     (FileType{ major_brand: m, major_brand_version:v, compatible_brands: c })
253   )
254 );
255 
list<'a,'b>(input: Input<'a>, _cs: &'b f64) -> Result<(Input<'a>,Vec<f64>), Err<(&'a [u8], ErrorKind)>>256 fn mvhd_box(input: &[u8]) -> IResult<&[u8], MvhdBox> {
257   let res = if input.len() < 100 {
258     Err(Err::Incomplete(Needed::Size(100)))
259   } else if input.len() == 100 {
260     mvhd32(input)
261   } else if input.len() == 112 {
262     mvhd64(input)
263   } else {
264     Err(Err::Error(error_position!(input, ErrorKind::TooLarge)))
265   };
266   println!("res: {:?}", res);
267   res
268 }
269 
270 fn unknown_box_type(input: &[u8]) -> IResult<&[u8], MP4BoxType> {
271   Ok((input, MP4BoxType::Unknown))
272 }
273 
274 //named!(box_type<&[u8], MP4BoxType>,
275 fn box_type(input: &[u8]) -> IResult<&[u8], MP4BoxType> {
276   alt!(input,
277     tag!("ftyp") => { |_| MP4BoxType::Ftyp } |
issue_848_overflow_incomplete_bits_to_bytes()278     tag!("moov") => { |_| MP4BoxType::Moov } |
279     tag!("mdat") => { |_| MP4BoxType::Mdat } |
280     tag!("free") => { |_| MP4BoxType::Free } |
281     tag!("skip") => { |_| MP4BoxType::Skip } |
282     tag!("wide") => { |_| MP4BoxType::Wide } |
283     unknown_box_type
284   )
issue_942()285 }
286 
287 // warning, an alt combinator with 9 branches containing a tag combinator
288 // can make the compilation very slow. Use functions as sub parsers,
289 // or split into multiple alt! parsers if it gets slow
290 named!(moov_type<&[u8], MP4BoxType>,
291   alt!(
292     tag!("mdra") => { |_| MP4BoxType::Mdra } |
293     tag!("dref") => { |_| MP4BoxType::Dref } |
294     tag!("cmov") => { |_| MP4BoxType::Cmov } |
issue_many_m_n_with_zeros()295     tag!("rmra") => { |_| MP4BoxType::Rmra } |
296     tag!("iods") => { |_| MP4BoxType::Iods } |
297     tag!("mvhd") => { |_| MP4BoxType::Mvhd } |
298     tag!("clip") => { |_| MP4BoxType::Clip } |
299     tag!("trak") => { |_| MP4BoxType::Trak } |
300     tag!("udta") => { |_| MP4BoxType::Udta }
301   )
302 );
issue_1027_convert_error_panic_nonempty()303 
304 named!(box_header<&[u8],MP4BoxHeader>,
305   do_parse!(
306     length: be_u32 >>
307     tag: box_type  >>
308     (MP4BoxHeader{ length: length, tag: tag})
309   )
310 );
311 
312 named!(moov_header<&[u8],MP4BoxHeader>,
313   do_parse!(
314     length: be_u32 >>
315     tag: moov_type >>
316     (MP4BoxHeader{ length: length, tag: tag})
317   )
318 );
319 
320