diff options
Diffstat (limited to 'third_party/rust/nom/tests/mp4.rs')
-rw-r--r-- | third_party/rust/nom/tests/mp4.rs | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/third_party/rust/nom/tests/mp4.rs b/third_party/rust/nom/tests/mp4.rs new file mode 100644 index 0000000000..1432621611 --- /dev/null +++ b/third_party/rust/nom/tests/mp4.rs @@ -0,0 +1,319 @@ +#![allow(dead_code)] + +#[macro_use] +extern crate nom; + +use nom::{ + IResult, Needed, Err, + error::ErrorKind, + number::streaming::{be_u16, be_u32, be_u64, be_f32} +}; + +use std::str; + +fn mp4_box(input: &[u8]) -> IResult<&[u8], &[u8]> { + match be_u32(input) { + Ok((i, offset)) => { + let sz: usize = offset as usize; + if i.len() >= sz - 4 { + Ok((&i[(sz - 4)..], &i[0..(sz - 4)])) + } else { + Err(Err::Incomplete(Needed::Size(offset as usize + 4))) + } + } + Err(e) => Err(e), + } +} + +#[cfg_attr(rustfmt, rustfmt_skip)] +#[derive(PartialEq,Eq,Debug)] +struct FileType<'a> { + major_brand: &'a str, + major_brand_version: &'a [u8], + compatible_brands: Vec<&'a str> +} + +#[cfg_attr(rustfmt, rustfmt_skip)] +#[allow(non_snake_case)] +#[derive(Debug,Clone)] +pub struct Mvhd32 { + version_flags: u32, // actually: + // version: u8, + // flags: u24 // 3 bytes + created_date: u32, + modified_date: u32, + scale: u32, + duration: u32, + speed: f32, + volume: u16, // actually a 2 bytes decimal + /* 10 bytes reserved */ + scaleA: f32, + rotateB: f32, + angleU: f32, + rotateC: f32, + scaleD: f32, + angleV: f32, + positionX: f32, + positionY: f32, + scaleW: f32, + preview: u64, + poster: u32, + selection: u64, + current_time: u32, + track_id: u32 +} + +#[cfg_attr(rustfmt, rustfmt_skip)] +#[allow(non_snake_case)] +#[derive(Debug,Clone)] +pub struct Mvhd64 { + version_flags: u32, // actually: + // version: u8, + // flags: u24 // 3 bytes + created_date: u64, + modified_date: u64, + scale: u32, + duration: u64, + speed: f32, + volume: u16, // actually a 2 bytes decimal + /* 10 bytes reserved */ + scaleA: f32, + rotateB: f32, + angleU: f32, + rotateC: f32, + scaleD: f32, + angleV: f32, + positionX: f32, + positionY: f32, + scaleW: f32, + preview: u64, + poster: u32, + selection: u64, + current_time: u32, + track_id: u32 +} + +#[allow(non_snake_case)] +named!(mvhd32 <&[u8], MvhdBox>, + do_parse!( + version_flags: be_u32 >> + created_date: be_u32 >> + modified_date: be_u32 >> + scale: be_u32 >> + duration: be_u32 >> + speed: be_f32 >> + volume: be_u16 >> // actually a 2 bytes decimal + take!(10) >> + scale_a: be_f32 >> + rotate_b: be_f32 >> + angle_u: be_f32 >> + rotate_c: be_f32 >> + scale_d: be_f32 >> + angle_v: be_f32 >> + position_x: be_f32 >> + position_y: be_f32 >> + scale_w: be_f32 >> + preview: be_u64 >> + poster: be_u32 >> + selection: be_u64 >> + current_time: be_u32 >> + track_id: be_u32 >> + ( + MvhdBox::M32(Mvhd32 { + version_flags: version_flags, + created_date: created_date, + modified_date: modified_date, + scale: scale, + duration: duration, + speed: speed, + volume: volume, + scaleA: scale_a, + rotateB: rotate_b, + angleU: angle_u, + rotateC: rotate_c, + scaleD: scale_d, + angleV: angle_v, + positionX: position_x, + positionY: position_y, + scaleW: scale_w, + preview: preview, + poster: poster, + selection: selection, + current_time: current_time, + track_id: track_id + }) + )) +); + +#[allow(non_snake_case)] +named!(mvhd64 <&[u8], MvhdBox>, + do_parse!( + version_flags: be_u32 >> + created_date: be_u64 >> + modified_date: be_u64 >> + scale: be_u32 >> + duration: be_u64 >> + speed: be_f32 >> + volume: be_u16 >> // actually a 2 bytes decimal + take!(10) >> + scale_a: be_f32 >> + rotate_b: be_f32 >> + angle_u: be_f32 >> + rotate_c: be_f32 >> + scale_d: be_f32 >> + angle_v: be_f32 >> + position_x: be_f32 >> + position_y: be_f32 >> + scale_w: be_f32 >> + preview: be_u64 >> + poster: be_u32 >> + selection: be_u64 >> + current_time: be_u32 >> + track_id: be_u32 >> + ( + MvhdBox::M64(Mvhd64 { + version_flags: version_flags, + created_date: created_date, + modified_date: modified_date, + scale: scale, + duration: duration, + speed: speed, + volume: volume, + scaleA: scale_a, + rotateB: rotate_b, + angleU: angle_u, + rotateC: rotate_c, + scaleD: scale_d, + angleV: angle_v, + positionX: position_x, + positionY: position_y, + scaleW: scale_w, + preview: preview, + poster: poster, + selection: selection, + current_time: current_time, + track_id: track_id + }) + )) +); + +#[derive(Debug, Clone)] +pub enum MvhdBox { + M32(Mvhd32), + M64(Mvhd64), +} + +#[derive(Debug, Clone)] +pub enum MoovBox { + Mdra, + Dref, + Cmov, + Rmra, + Iods, + Mvhd(MvhdBox), + Clip, + Trak, + Udta, +} + +#[derive(Debug)] +enum MP4BoxType { + Ftyp, + Moov, + Mdat, + Free, + Skip, + Wide, + Mdra, + Dref, + Cmov, + Rmra, + Iods, + Mvhd, + Clip, + Trak, + Udta, + Unknown, +} + +#[derive(Debug)] +struct MP4BoxHeader { + length: u32, + tag: MP4BoxType, +} + +named!(brand_name<&[u8],&str>, map_res!(take!(4), str::from_utf8)); + +named!(filetype_parser<&[u8], FileType>, + do_parse!( + m: brand_name >> + v: take!(4) >> + c: many0!(brand_name) >> + (FileType{ major_brand: m, major_brand_version:v, compatible_brands: c }) + ) +); + +fn mvhd_box(input: &[u8]) -> IResult<&[u8], MvhdBox> { + let res = if input.len() < 100 { + Err(Err::Incomplete(Needed::Size(100))) + } else if input.len() == 100 { + mvhd32(input) + } else if input.len() == 112 { + mvhd64(input) + } else { + Err(Err::Error(error_position!(input, ErrorKind::TooLarge))) + }; + println!("res: {:?}", res); + res +} + +fn unknown_box_type(input: &[u8]) -> IResult<&[u8], MP4BoxType> { + Ok((input, MP4BoxType::Unknown)) +} + +//named!(box_type<&[u8], MP4BoxType>, +fn box_type(input: &[u8]) -> IResult<&[u8], MP4BoxType> { + alt!(input, + tag!("ftyp") => { |_| MP4BoxType::Ftyp } | + tag!("moov") => { |_| MP4BoxType::Moov } | + tag!("mdat") => { |_| MP4BoxType::Mdat } | + tag!("free") => { |_| MP4BoxType::Free } | + tag!("skip") => { |_| MP4BoxType::Skip } | + tag!("wide") => { |_| MP4BoxType::Wide } | + unknown_box_type + ) +} + +// warning, an alt combinator with 9 branches containing a tag combinator +// can make the compilation very slow. Use functions as sub parsers, +// or split into multiple alt! parsers if it gets slow +named!(moov_type<&[u8], MP4BoxType>, + alt!( + tag!("mdra") => { |_| MP4BoxType::Mdra } | + tag!("dref") => { |_| MP4BoxType::Dref } | + tag!("cmov") => { |_| MP4BoxType::Cmov } | + tag!("rmra") => { |_| MP4BoxType::Rmra } | + tag!("iods") => { |_| MP4BoxType::Iods } | + tag!("mvhd") => { |_| MP4BoxType::Mvhd } | + tag!("clip") => { |_| MP4BoxType::Clip } | + tag!("trak") => { |_| MP4BoxType::Trak } | + tag!("udta") => { |_| MP4BoxType::Udta } + ) +); + +named!(box_header<&[u8],MP4BoxHeader>, + do_parse!( + length: be_u32 >> + tag: box_type >> + (MP4BoxHeader{ length: length, tag: tag}) + ) +); + +named!(moov_header<&[u8],MP4BoxHeader>, + do_parse!( + length: be_u32 >> + tag: moov_type >> + (MP4BoxHeader{ length: length, tag: tag}) + ) +); + |