diff options
Diffstat (limited to 'third_party/rust/nom/tests/mp4.rs')
-rw-r--r-- | third_party/rust/nom/tests/mp4.rs | 320 |
1 files changed, 320 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..852bf29555 --- /dev/null +++ b/third_party/rust/nom/tests/mp4.rs @@ -0,0 +1,320 @@ +#![allow(dead_code)] + +use nom::{ + branch::alt, + bytes::streaming::{tag, take}, + combinator::{map, map_res}, + error::ErrorKind, + multi::many0, + number::streaming::{be_f32, be_u16, be_u32, be_u64}, + Err, IResult, Needed, +}; + +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::new(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 +} + +#[cfg_attr(rustfmt, rustfmt_skip)] +fn mvhd32(i: &[u8]) -> IResult<&[u8], MvhdBox> { + let (i, version_flags) = be_u32(i)?; + let (i, created_date) = be_u32(i)?; + let (i, modified_date) = be_u32(i)?; + let (i, scale) = be_u32(i)?; + let (i, duration) = be_u32(i)?; + let (i, speed) = be_f32(i)?; + let (i, volume) = be_u16(i)?; // actually a 2 bytes decimal + let (i, _) = take(10_usize)(i)?; + let (i, scale_a) = be_f32(i)?; + let (i, rotate_b) = be_f32(i)?; + let (i, angle_u) = be_f32(i)?; + let (i, rotate_c) = be_f32(i)?; + let (i, scale_d) = be_f32(i)?; + let (i, angle_v) = be_f32(i)?; + let (i, position_x) = be_f32(i)?; + let (i, position_y) = be_f32(i)?; + let (i, scale_w) = be_f32(i)?; + let (i, preview) = be_u64(i)?; + let (i, poster) = be_u32(i)?; + let (i, selection) = be_u64(i)?; + let (i, current_time) = be_u32(i)?; + let (i, track_id) = be_u32(i)?; + + let mvhd_box = MvhdBox::M32(Mvhd32 { + version_flags, + created_date, + modified_date, + scale, + duration, + speed, + 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, + poster, + selection, + current_time, + track_id, + }); + + Ok((i, mvhd_box)) +} + +#[cfg_attr(rustfmt, rustfmt_skip)] +fn mvhd64(i: &[u8]) -> IResult<&[u8], MvhdBox> { + let (i, version_flags) = be_u32(i)?; + let (i, created_date) = be_u64(i)?; + let (i, modified_date) = be_u64(i)?; + let (i, scale) = be_u32(i)?; + let (i, duration) = be_u64(i)?; + let (i, speed) = be_f32(i)?; + let (i, volume) = be_u16(i)?; // actually a 2 bytes decimal + let (i, _) = take(10_usize)(i)?; + let (i, scale_a) = be_f32(i)?; + let (i, rotate_b) = be_f32(i)?; + let (i, angle_u) = be_f32(i)?; + let (i, rotate_c) = be_f32(i)?; + let (i, scale_d) = be_f32(i)?; + let (i, angle_v) = be_f32(i)?; + let (i, position_x) = be_f32(i)?; + let (i, position_y) = be_f32(i)?; + let (i, scale_w) = be_f32(i)?; + let (i, preview) = be_u64(i)?; + let (i, poster) = be_u32(i)?; + let (i, selection) = be_u64(i)?; + let (i, current_time) = be_u32(i)?; + let (i, track_id) = be_u32(i)?; + + let mvhd_box = MvhdBox::M64(Mvhd64 { + version_flags, + created_date, + modified_date, + scale, + duration, + speed, + 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, + poster, + selection, + current_time, + track_id, + }); + + Ok((i, mvhd_box)) +} + +#[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, +} + +fn brand_name(input: &[u8]) -> IResult<&[u8], &str> { + map_res(take(4_usize), str::from_utf8)(input) +} + +fn filetype_parser(input: &[u8]) -> IResult<&[u8], FileType<'_>> { + let (i, name) = brand_name(input)?; + let (i, version) = take(4_usize)(i)?; + let (i, brands) = many0(brand_name)(i)?; + + let ft = FileType { + major_brand: name, + major_brand_version: version, + compatible_brands: brands, + }; + Ok((i, ft)) +} + +fn mvhd_box(input: &[u8]) -> IResult<&[u8], MvhdBox> { + let res = if input.len() < 100 { + Err(Err::Incomplete(Needed::new(100))) + } else if input.len() == 100 { + mvhd32(input) + } else if input.len() == 112 { + mvhd64(input) + } else { + Err(Err::Error(nom::error_position!(input, ErrorKind::TooLarge))) + }; + println!("res: {:?}", res); + res +} + +fn unknown_box_type(input: &[u8]) -> IResult<&[u8], MP4BoxType> { + Ok((input, MP4BoxType::Unknown)) +} + +fn box_type(input: &[u8]) -> IResult<&[u8], MP4BoxType> { + alt(( + map(tag("ftyp"), |_| MP4BoxType::Ftyp), + map(tag("moov"), |_| MP4BoxType::Moov), + map(tag("mdat"), |_| MP4BoxType::Mdat), + map(tag("free"), |_| MP4BoxType::Free), + map(tag("skip"), |_| MP4BoxType::Skip), + map(tag("wide"), |_| MP4BoxType::Wide), + unknown_box_type, + ))(input) +} + +// 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 +fn moov_type(input: &[u8]) -> IResult<&[u8], MP4BoxType> { + alt(( + map(tag("mdra"), |_| MP4BoxType::Mdra), + map(tag("dref"), |_| MP4BoxType::Dref), + map(tag("cmov"), |_| MP4BoxType::Cmov), + map(tag("rmra"), |_| MP4BoxType::Rmra), + map(tag("iods"), |_| MP4BoxType::Iods), + map(tag("mvhd"), |_| MP4BoxType::Mvhd), + map(tag("clip"), |_| MP4BoxType::Clip), + map(tag("trak"), |_| MP4BoxType::Trak), + map(tag("udta"), |_| MP4BoxType::Udta), + ))(input) +} + +fn box_header(input: &[u8]) -> IResult<&[u8], MP4BoxHeader> { + let (i, length) = be_u32(input)?; + let (i, tag) = box_type(i)?; + Ok((i, MP4BoxHeader { length, tag })) +} + +fn moov_header(input: &[u8]) -> IResult<&[u8], MP4BoxHeader> { + let (i, length) = be_u32(input)?; + let (i, tag) = moov_type(i)?; + Ok((i, MP4BoxHeader { length, tag })) +} |