diff --git a/crates/mpeg2v/tests/common/mod.rs b/crates/mpeg2v/tests/common/mod.rs index 1b032206..7c7c3747 100644 --- a/crates/mpeg2v/tests/common/mod.rs +++ b/crates/mpeg2v/tests/common/mod.rs @@ -21,6 +21,15 @@ pub struct Spec { pub pix_fmt: &'static str, } +/// 1080i 4:2:0 (decode benchmark; Main@High). +pub const HD1080I: Spec = Spec { + name: "m2v_1080i", + lavfi: "testsrc2=size=1920x1080:rate=50,tinterlace=mode=interleave_top,setfield=tff", + frames: 25, + enc: &["-c:v", "mpeg2video", "-flags", "+ilme+ildct", "-bf", "2", "-g", "12", "-b:v", "25M", "-maxrate", "25M", "-bufsize", "9M"], + pix_fmt: "yuv420p", +}; + pub fn path(spec: &Spec) -> PathBuf { fixture_dir().join(format!("{}.{}", spec.name, if spec.enc.contains(&"mpeg1video") { "m1v" } else { "m2v" })) } diff --git a/crates/mpeg2v/tests/oracle.rs b/crates/mpeg2v/tests/oracle.rs index 975184f1..eed298c7 100644 --- a/crates/mpeg2v/tests/oracle.rs +++ b/crates/mpeg2v/tests/oracle.rs @@ -136,15 +136,6 @@ const SPECS: &[Spec] = &[ }, ]; -/// 1080i 4:2:0 (decode benchmark; Main@High). -pub const HD1080I: Spec = Spec { - name: "m2v_1080i", - lavfi: "testsrc2=size=1920x1080:rate=50,tinterlace=mode=interleave_top,setfield=tff", - frames: 25, - enc: &["-c:v", "mpeg2video", "-flags", "+ilme+ildct", "-bf", "2", "-g", "12", "-b:v", "25M", "-maxrate", "25M", "-bufsize", "9M"], - pix_fmt: "yuv420p", -}; - /// Tolerance against ffmpeg (whose integer IDCT differs from our IEEE 1180-accurate one, and the /// difference propagates through prediction): per frame max |Δ| ≤ 4 and PSNR ≥ 58 dB; overall /// at most 3 % of samples differ at all. diff --git a/crates/mpeg2v/tests/perf.rs b/crates/mpeg2v/tests/perf.rs new file mode 100644 index 00000000..44281499 --- /dev/null +++ b/crates/mpeg2v/tests/perf.rs @@ -0,0 +1,37 @@ +//! Decode speed (ignored; run with `cargo test --release -p filmcraft-mpeg2v --test perf -- +//! --ignored --nocapture`). Uses the 1080i fixture of `tests/oracle.rs` (ffmpeg-encoded, 25 Mb/s). + +mod common; + +use common::*; + +#[test] +#[ignore] +fn perf_1080i_decode_fps() { + let ff = filmcraft_testkit::require_ffmpeg!(); + let f = make(&ff, &HD1080I).expect("fixture"); + let es = std::fs::read(&f).unwrap(); + let aus = filmcraft_mpeg2v::access_units(&es); + for threads in [false, true] { + let mut best = f64::MAX; + let mut frames = 0; + for _ in 0..5 { + let mut d = filmcraft_mpeg2v::Decoder::new(); + d.set_threads(threads); + let t0 = std::time::Instant::now(); + let mut n = 0; + for (i, r) in aus.iter().enumerate() { + n += d.decode(&es[r.clone()], i as i64).unwrap().len(); + } + n += d.flush().len(); + best = best.min(t0.elapsed().as_secs_f64()); + frames = n; + } + println!( + "1080i25 MPEG-2 (4:2:0, 25 Mb/s, IBBP): {frames} frames in {:.1} ms = {:.1} fps ({})", + best * 1e3, + frames as f64 / best, + if threads { "slice rows on rayon" } else { "single thread" } + ); + } +}