87 lines
2.2 KiB
Rust
87 lines
2.2 KiB
Rust
#![cfg(feature = "mp4")]
|
|
#[macro_use]
|
|
extern crate criterion;
|
|
|
|
use std::{fs::File, io::Read, str::from_utf8};
|
|
|
|
use {
|
|
combine::{
|
|
parser::{
|
|
byte::num::be_u32,
|
|
range::{range, take},
|
|
},
|
|
stream::easy::ParseError,
|
|
*,
|
|
},
|
|
criterion::{black_box, Bencher, Criterion},
|
|
};
|
|
|
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
|
struct FileType<'a> {
|
|
major_brand: &'a str,
|
|
major_brand_version: &'a [u8],
|
|
compatible_brands: Vec<&'a str>,
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
enum MP4Box<'a> {
|
|
Ftyp(FileType<'a>),
|
|
Moov,
|
|
Mdat,
|
|
Free,
|
|
Skip,
|
|
Wide,
|
|
Unknown,
|
|
}
|
|
|
|
fn parse_mp4(data: &[u8]) -> Result<(Vec<MP4Box>, &[u8]), ParseError<&[u8]>> {
|
|
let brand_name = || take(4).and_then(from_utf8);
|
|
let filetype_box = (
|
|
range(&b"ftyp"[..]),
|
|
brand_name(),
|
|
take(4),
|
|
many(brand_name()),
|
|
)
|
|
.map(|(_, m, v, c)| {
|
|
MP4Box::Ftyp(FileType {
|
|
major_brand: m,
|
|
major_brand_version: v,
|
|
compatible_brands: c,
|
|
})
|
|
});
|
|
|
|
let mp4_box = be_u32().then(|offset| take(offset as usize - 4));
|
|
let mut box_parser = choice((
|
|
filetype_box,
|
|
range(&b"moov"[..]).map(|_| MP4Box::Moov),
|
|
range(&b"mdat"[..]).map(|_| MP4Box::Mdat),
|
|
range(&b"free"[..]).map(|_| MP4Box::Free),
|
|
range(&b"skip"[..]).map(|_| MP4Box::Skip),
|
|
range(&b"wide"[..]).map(|_| MP4Box::Wide),
|
|
value(MP4Box::Unknown),
|
|
));
|
|
let data_interpreter =
|
|
mp4_box.flat_map(|box_data| box_parser.easy_parse(box_data).map(|t| t.0));
|
|
|
|
many(data_interpreter).easy_parse(data)
|
|
}
|
|
|
|
fn run_test(b: &mut Bencher, data: &[u8]) {
|
|
b.iter(|| match parse_mp4(data) {
|
|
Ok(x) => black_box(x),
|
|
Err(err) => panic!("{}", err.map_range(|bytes| format!("{:?}", bytes))),
|
|
});
|
|
}
|
|
|
|
fn mp4_small_test(c: &mut Criterion) {
|
|
let mut mp4_small = Vec::new();
|
|
File::open("benches/small.mp4")
|
|
.and_then(|mut f| f.read_to_end(&mut mp4_small))
|
|
.expect("Unable to read benches/small.mp4");
|
|
|
|
c.bench_function("mp4_small", move |b| run_test(b, &mp4_small));
|
|
}
|
|
|
|
criterion_group!(mp4, mp4_small_test);
|
|
criterion_main!(mp4);
|