16855e09eSopenharmony_ci#![allow(dead_code)] 26855e09eSopenharmony_ci 36855e09eSopenharmony_ciuse nom::{ 46855e09eSopenharmony_ci branch::alt, 56855e09eSopenharmony_ci bytes::streaming::{tag, take}, 66855e09eSopenharmony_ci combinator::{map, map_res}, 76855e09eSopenharmony_ci error::ErrorKind, 86855e09eSopenharmony_ci multi::many0, 96855e09eSopenharmony_ci number::streaming::{be_f32, be_u16, be_u32, be_u64}, 106855e09eSopenharmony_ci Err, IResult, Needed, 116855e09eSopenharmony_ci}; 126855e09eSopenharmony_ci 136855e09eSopenharmony_ciuse std::str; 146855e09eSopenharmony_ci 156855e09eSopenharmony_cifn mp4_box(input: &[u8]) -> IResult<&[u8], &[u8]> { 166855e09eSopenharmony_ci match be_u32(input) { 176855e09eSopenharmony_ci Ok((i, offset)) => { 186855e09eSopenharmony_ci let sz: usize = offset as usize; 196855e09eSopenharmony_ci if i.len() >= sz - 4 { 206855e09eSopenharmony_ci Ok((&i[(sz - 4)..], &i[0..(sz - 4)])) 216855e09eSopenharmony_ci } else { 226855e09eSopenharmony_ci Err(Err::Incomplete(Needed::new(offset as usize + 4))) 236855e09eSopenharmony_ci } 246855e09eSopenharmony_ci } 256855e09eSopenharmony_ci Err(e) => Err(e), 266855e09eSopenharmony_ci } 276855e09eSopenharmony_ci} 286855e09eSopenharmony_ci 296855e09eSopenharmony_ci#[cfg_attr(rustfmt, rustfmt_skip)] 306855e09eSopenharmony_ci#[derive(PartialEq,Eq,Debug)] 316855e09eSopenharmony_cistruct FileType<'a> { 326855e09eSopenharmony_ci major_brand: &'a str, 336855e09eSopenharmony_ci major_brand_version: &'a [u8], 346855e09eSopenharmony_ci compatible_brands: Vec<&'a str> 356855e09eSopenharmony_ci} 366855e09eSopenharmony_ci 376855e09eSopenharmony_ci#[cfg_attr(rustfmt, rustfmt_skip)] 386855e09eSopenharmony_ci#[allow(non_snake_case)] 396855e09eSopenharmony_ci#[derive(Debug,Clone)] 406855e09eSopenharmony_cipub struct Mvhd32 { 416855e09eSopenharmony_ci version_flags: u32, // actually: 426855e09eSopenharmony_ci // version: u8, 436855e09eSopenharmony_ci // flags: u24 // 3 bytes 446855e09eSopenharmony_ci created_date: u32, 456855e09eSopenharmony_ci modified_date: u32, 466855e09eSopenharmony_ci scale: u32, 476855e09eSopenharmony_ci duration: u32, 486855e09eSopenharmony_ci speed: f32, 496855e09eSopenharmony_ci volume: u16, // actually a 2 bytes decimal 506855e09eSopenharmony_ci /* 10 bytes reserved */ 516855e09eSopenharmony_ci scaleA: f32, 526855e09eSopenharmony_ci rotateB: f32, 536855e09eSopenharmony_ci angleU: f32, 546855e09eSopenharmony_ci rotateC: f32, 556855e09eSopenharmony_ci scaleD: f32, 566855e09eSopenharmony_ci angleV: f32, 576855e09eSopenharmony_ci positionX: f32, 586855e09eSopenharmony_ci positionY: f32, 596855e09eSopenharmony_ci scaleW: f32, 606855e09eSopenharmony_ci preview: u64, 616855e09eSopenharmony_ci poster: u32, 626855e09eSopenharmony_ci selection: u64, 636855e09eSopenharmony_ci current_time: u32, 646855e09eSopenharmony_ci track_id: u32 656855e09eSopenharmony_ci} 666855e09eSopenharmony_ci 676855e09eSopenharmony_ci#[cfg_attr(rustfmt, rustfmt_skip)] 686855e09eSopenharmony_ci#[allow(non_snake_case)] 696855e09eSopenharmony_ci#[derive(Debug,Clone)] 706855e09eSopenharmony_cipub struct Mvhd64 { 716855e09eSopenharmony_ci version_flags: u32, // actually: 726855e09eSopenharmony_ci // version: u8, 736855e09eSopenharmony_ci // flags: u24 // 3 bytes 746855e09eSopenharmony_ci created_date: u64, 756855e09eSopenharmony_ci modified_date: u64, 766855e09eSopenharmony_ci scale: u32, 776855e09eSopenharmony_ci duration: u64, 786855e09eSopenharmony_ci speed: f32, 796855e09eSopenharmony_ci volume: u16, // actually a 2 bytes decimal 806855e09eSopenharmony_ci /* 10 bytes reserved */ 816855e09eSopenharmony_ci scaleA: f32, 826855e09eSopenharmony_ci rotateB: f32, 836855e09eSopenharmony_ci angleU: f32, 846855e09eSopenharmony_ci rotateC: f32, 856855e09eSopenharmony_ci scaleD: f32, 866855e09eSopenharmony_ci angleV: f32, 876855e09eSopenharmony_ci positionX: f32, 886855e09eSopenharmony_ci positionY: f32, 896855e09eSopenharmony_ci scaleW: f32, 906855e09eSopenharmony_ci preview: u64, 916855e09eSopenharmony_ci poster: u32, 926855e09eSopenharmony_ci selection: u64, 936855e09eSopenharmony_ci current_time: u32, 946855e09eSopenharmony_ci track_id: u32 956855e09eSopenharmony_ci} 966855e09eSopenharmony_ci 976855e09eSopenharmony_ci#[cfg_attr(rustfmt, rustfmt_skip)] 986855e09eSopenharmony_cifn mvhd32(i: &[u8]) -> IResult<&[u8], MvhdBox> { 996855e09eSopenharmony_ci let (i, version_flags) = be_u32(i)?; 1006855e09eSopenharmony_ci let (i, created_date) = be_u32(i)?; 1016855e09eSopenharmony_ci let (i, modified_date) = be_u32(i)?; 1026855e09eSopenharmony_ci let (i, scale) = be_u32(i)?; 1036855e09eSopenharmony_ci let (i, duration) = be_u32(i)?; 1046855e09eSopenharmony_ci let (i, speed) = be_f32(i)?; 1056855e09eSopenharmony_ci let (i, volume) = be_u16(i)?; // actually a 2 bytes decimal 1066855e09eSopenharmony_ci let (i, _) = take(10_usize)(i)?; 1076855e09eSopenharmony_ci let (i, scale_a) = be_f32(i)?; 1086855e09eSopenharmony_ci let (i, rotate_b) = be_f32(i)?; 1096855e09eSopenharmony_ci let (i, angle_u) = be_f32(i)?; 1106855e09eSopenharmony_ci let (i, rotate_c) = be_f32(i)?; 1116855e09eSopenharmony_ci let (i, scale_d) = be_f32(i)?; 1126855e09eSopenharmony_ci let (i, angle_v) = be_f32(i)?; 1136855e09eSopenharmony_ci let (i, position_x) = be_f32(i)?; 1146855e09eSopenharmony_ci let (i, position_y) = be_f32(i)?; 1156855e09eSopenharmony_ci let (i, scale_w) = be_f32(i)?; 1166855e09eSopenharmony_ci let (i, preview) = be_u64(i)?; 1176855e09eSopenharmony_ci let (i, poster) = be_u32(i)?; 1186855e09eSopenharmony_ci let (i, selection) = be_u64(i)?; 1196855e09eSopenharmony_ci let (i, current_time) = be_u32(i)?; 1206855e09eSopenharmony_ci let (i, track_id) = be_u32(i)?; 1216855e09eSopenharmony_ci 1226855e09eSopenharmony_ci let mvhd_box = MvhdBox::M32(Mvhd32 { 1236855e09eSopenharmony_ci version_flags, 1246855e09eSopenharmony_ci created_date, 1256855e09eSopenharmony_ci modified_date, 1266855e09eSopenharmony_ci scale, 1276855e09eSopenharmony_ci duration, 1286855e09eSopenharmony_ci speed, 1296855e09eSopenharmony_ci volume, 1306855e09eSopenharmony_ci scaleA: scale_a, 1316855e09eSopenharmony_ci rotateB: rotate_b, 1326855e09eSopenharmony_ci angleU: angle_u, 1336855e09eSopenharmony_ci rotateC: rotate_c, 1346855e09eSopenharmony_ci scaleD: scale_d, 1356855e09eSopenharmony_ci angleV: angle_v, 1366855e09eSopenharmony_ci positionX: position_x, 1376855e09eSopenharmony_ci positionY: position_y, 1386855e09eSopenharmony_ci scaleW: scale_w, 1396855e09eSopenharmony_ci preview, 1406855e09eSopenharmony_ci poster, 1416855e09eSopenharmony_ci selection, 1426855e09eSopenharmony_ci current_time, 1436855e09eSopenharmony_ci track_id, 1446855e09eSopenharmony_ci }); 1456855e09eSopenharmony_ci 1466855e09eSopenharmony_ci Ok((i, mvhd_box)) 1476855e09eSopenharmony_ci} 1486855e09eSopenharmony_ci 1496855e09eSopenharmony_ci#[cfg_attr(rustfmt, rustfmt_skip)] 1506855e09eSopenharmony_cifn mvhd64(i: &[u8]) -> IResult<&[u8], MvhdBox> { 1516855e09eSopenharmony_ci let (i, version_flags) = be_u32(i)?; 1526855e09eSopenharmony_ci let (i, created_date) = be_u64(i)?; 1536855e09eSopenharmony_ci let (i, modified_date) = be_u64(i)?; 1546855e09eSopenharmony_ci let (i, scale) = be_u32(i)?; 1556855e09eSopenharmony_ci let (i, duration) = be_u64(i)?; 1566855e09eSopenharmony_ci let (i, speed) = be_f32(i)?; 1576855e09eSopenharmony_ci let (i, volume) = be_u16(i)?; // actually a 2 bytes decimal 1586855e09eSopenharmony_ci let (i, _) = take(10_usize)(i)?; 1596855e09eSopenharmony_ci let (i, scale_a) = be_f32(i)?; 1606855e09eSopenharmony_ci let (i, rotate_b) = be_f32(i)?; 1616855e09eSopenharmony_ci let (i, angle_u) = be_f32(i)?; 1626855e09eSopenharmony_ci let (i, rotate_c) = be_f32(i)?; 1636855e09eSopenharmony_ci let (i, scale_d) = be_f32(i)?; 1646855e09eSopenharmony_ci let (i, angle_v) = be_f32(i)?; 1656855e09eSopenharmony_ci let (i, position_x) = be_f32(i)?; 1666855e09eSopenharmony_ci let (i, position_y) = be_f32(i)?; 1676855e09eSopenharmony_ci let (i, scale_w) = be_f32(i)?; 1686855e09eSopenharmony_ci let (i, preview) = be_u64(i)?; 1696855e09eSopenharmony_ci let (i, poster) = be_u32(i)?; 1706855e09eSopenharmony_ci let (i, selection) = be_u64(i)?; 1716855e09eSopenharmony_ci let (i, current_time) = be_u32(i)?; 1726855e09eSopenharmony_ci let (i, track_id) = be_u32(i)?; 1736855e09eSopenharmony_ci 1746855e09eSopenharmony_ci let mvhd_box = MvhdBox::M64(Mvhd64 { 1756855e09eSopenharmony_ci version_flags, 1766855e09eSopenharmony_ci created_date, 1776855e09eSopenharmony_ci modified_date, 1786855e09eSopenharmony_ci scale, 1796855e09eSopenharmony_ci duration, 1806855e09eSopenharmony_ci speed, 1816855e09eSopenharmony_ci volume, 1826855e09eSopenharmony_ci scaleA: scale_a, 1836855e09eSopenharmony_ci rotateB: rotate_b, 1846855e09eSopenharmony_ci angleU: angle_u, 1856855e09eSopenharmony_ci rotateC: rotate_c, 1866855e09eSopenharmony_ci scaleD: scale_d, 1876855e09eSopenharmony_ci angleV: angle_v, 1886855e09eSopenharmony_ci positionX: position_x, 1896855e09eSopenharmony_ci positionY: position_y, 1906855e09eSopenharmony_ci scaleW: scale_w, 1916855e09eSopenharmony_ci preview, 1926855e09eSopenharmony_ci poster, 1936855e09eSopenharmony_ci selection, 1946855e09eSopenharmony_ci current_time, 1956855e09eSopenharmony_ci track_id, 1966855e09eSopenharmony_ci }); 1976855e09eSopenharmony_ci 1986855e09eSopenharmony_ci Ok((i, mvhd_box)) 1996855e09eSopenharmony_ci} 2006855e09eSopenharmony_ci 2016855e09eSopenharmony_ci#[derive(Debug, Clone)] 2026855e09eSopenharmony_cipub enum MvhdBox { 2036855e09eSopenharmony_ci M32(Mvhd32), 2046855e09eSopenharmony_ci M64(Mvhd64), 2056855e09eSopenharmony_ci} 2066855e09eSopenharmony_ci 2076855e09eSopenharmony_ci#[derive(Debug, Clone)] 2086855e09eSopenharmony_cipub enum MoovBox { 2096855e09eSopenharmony_ci Mdra, 2106855e09eSopenharmony_ci Dref, 2116855e09eSopenharmony_ci Cmov, 2126855e09eSopenharmony_ci Rmra, 2136855e09eSopenharmony_ci Iods, 2146855e09eSopenharmony_ci Mvhd(MvhdBox), 2156855e09eSopenharmony_ci Clip, 2166855e09eSopenharmony_ci Trak, 2176855e09eSopenharmony_ci Udta, 2186855e09eSopenharmony_ci} 2196855e09eSopenharmony_ci 2206855e09eSopenharmony_ci#[derive(Debug)] 2216855e09eSopenharmony_cienum MP4BoxType { 2226855e09eSopenharmony_ci Ftyp, 2236855e09eSopenharmony_ci Moov, 2246855e09eSopenharmony_ci Mdat, 2256855e09eSopenharmony_ci Free, 2266855e09eSopenharmony_ci Skip, 2276855e09eSopenharmony_ci Wide, 2286855e09eSopenharmony_ci Mdra, 2296855e09eSopenharmony_ci Dref, 2306855e09eSopenharmony_ci Cmov, 2316855e09eSopenharmony_ci Rmra, 2326855e09eSopenharmony_ci Iods, 2336855e09eSopenharmony_ci Mvhd, 2346855e09eSopenharmony_ci Clip, 2356855e09eSopenharmony_ci Trak, 2366855e09eSopenharmony_ci Udta, 2376855e09eSopenharmony_ci Unknown, 2386855e09eSopenharmony_ci} 2396855e09eSopenharmony_ci 2406855e09eSopenharmony_ci#[derive(Debug)] 2416855e09eSopenharmony_cistruct MP4BoxHeader { 2426855e09eSopenharmony_ci length: u32, 2436855e09eSopenharmony_ci tag: MP4BoxType, 2446855e09eSopenharmony_ci} 2456855e09eSopenharmony_ci 2466855e09eSopenharmony_cifn brand_name(input: &[u8]) -> IResult<&[u8], &str> { 2476855e09eSopenharmony_ci map_res(take(4_usize), str::from_utf8)(input) 2486855e09eSopenharmony_ci} 2496855e09eSopenharmony_ci 2506855e09eSopenharmony_cifn filetype_parser(input: &[u8]) -> IResult<&[u8], FileType<'_>> { 2516855e09eSopenharmony_ci let (i, name) = brand_name(input)?; 2526855e09eSopenharmony_ci let (i, version) = take(4_usize)(i)?; 2536855e09eSopenharmony_ci let (i, brands) = many0(brand_name)(i)?; 2546855e09eSopenharmony_ci 2556855e09eSopenharmony_ci let ft = FileType { 2566855e09eSopenharmony_ci major_brand: name, 2576855e09eSopenharmony_ci major_brand_version: version, 2586855e09eSopenharmony_ci compatible_brands: brands, 2596855e09eSopenharmony_ci }; 2606855e09eSopenharmony_ci Ok((i, ft)) 2616855e09eSopenharmony_ci} 2626855e09eSopenharmony_ci 2636855e09eSopenharmony_cifn mvhd_box(input: &[u8]) -> IResult<&[u8], MvhdBox> { 2646855e09eSopenharmony_ci let res = if input.len() < 100 { 2656855e09eSopenharmony_ci Err(Err::Incomplete(Needed::new(100))) 2666855e09eSopenharmony_ci } else if input.len() == 100 { 2676855e09eSopenharmony_ci mvhd32(input) 2686855e09eSopenharmony_ci } else if input.len() == 112 { 2696855e09eSopenharmony_ci mvhd64(input) 2706855e09eSopenharmony_ci } else { 2716855e09eSopenharmony_ci Err(Err::Error(nom::error_position!(input, ErrorKind::TooLarge))) 2726855e09eSopenharmony_ci }; 2736855e09eSopenharmony_ci println!("res: {:?}", res); 2746855e09eSopenharmony_ci res 2756855e09eSopenharmony_ci} 2766855e09eSopenharmony_ci 2776855e09eSopenharmony_cifn unknown_box_type(input: &[u8]) -> IResult<&[u8], MP4BoxType> { 2786855e09eSopenharmony_ci Ok((input, MP4BoxType::Unknown)) 2796855e09eSopenharmony_ci} 2806855e09eSopenharmony_ci 2816855e09eSopenharmony_cifn box_type(input: &[u8]) -> IResult<&[u8], MP4BoxType> { 2826855e09eSopenharmony_ci alt(( 2836855e09eSopenharmony_ci map(tag("ftyp"), |_| MP4BoxType::Ftyp), 2846855e09eSopenharmony_ci map(tag("moov"), |_| MP4BoxType::Moov), 2856855e09eSopenharmony_ci map(tag("mdat"), |_| MP4BoxType::Mdat), 2866855e09eSopenharmony_ci map(tag("free"), |_| MP4BoxType::Free), 2876855e09eSopenharmony_ci map(tag("skip"), |_| MP4BoxType::Skip), 2886855e09eSopenharmony_ci map(tag("wide"), |_| MP4BoxType::Wide), 2896855e09eSopenharmony_ci unknown_box_type, 2906855e09eSopenharmony_ci ))(input) 2916855e09eSopenharmony_ci} 2926855e09eSopenharmony_ci 2936855e09eSopenharmony_ci// warning, an alt combinator with 9 branches containing a tag combinator 2946855e09eSopenharmony_ci// can make the compilation very slow. Use functions as sub parsers, 2956855e09eSopenharmony_ci// or split into multiple alt parsers if it gets slow 2966855e09eSopenharmony_cifn moov_type(input: &[u8]) -> IResult<&[u8], MP4BoxType> { 2976855e09eSopenharmony_ci alt(( 2986855e09eSopenharmony_ci map(tag("mdra"), |_| MP4BoxType::Mdra), 2996855e09eSopenharmony_ci map(tag("dref"), |_| MP4BoxType::Dref), 3006855e09eSopenharmony_ci map(tag("cmov"), |_| MP4BoxType::Cmov), 3016855e09eSopenharmony_ci map(tag("rmra"), |_| MP4BoxType::Rmra), 3026855e09eSopenharmony_ci map(tag("iods"), |_| MP4BoxType::Iods), 3036855e09eSopenharmony_ci map(tag("mvhd"), |_| MP4BoxType::Mvhd), 3046855e09eSopenharmony_ci map(tag("clip"), |_| MP4BoxType::Clip), 3056855e09eSopenharmony_ci map(tag("trak"), |_| MP4BoxType::Trak), 3066855e09eSopenharmony_ci map(tag("udta"), |_| MP4BoxType::Udta), 3076855e09eSopenharmony_ci ))(input) 3086855e09eSopenharmony_ci} 3096855e09eSopenharmony_ci 3106855e09eSopenharmony_cifn box_header(input: &[u8]) -> IResult<&[u8], MP4BoxHeader> { 3116855e09eSopenharmony_ci let (i, length) = be_u32(input)?; 3126855e09eSopenharmony_ci let (i, tag) = box_type(i)?; 3136855e09eSopenharmony_ci Ok((i, MP4BoxHeader { length, tag })) 3146855e09eSopenharmony_ci} 3156855e09eSopenharmony_ci 3166855e09eSopenharmony_cifn moov_header(input: &[u8]) -> IResult<&[u8], MP4BoxHeader> { 3176855e09eSopenharmony_ci let (i, length) = be_u32(input)?; 3186855e09eSopenharmony_ci let (i, tag) = moov_type(i)?; 3196855e09eSopenharmony_ci Ok((i, MP4BoxHeader { length, tag })) 3206855e09eSopenharmony_ci} 321