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