mirror of
https://github.com/storytold/filmcraft.git
synced 2026-10-28 20:17:58 -06:00
- frame-level parallelism: the calling thread handles headers, POC, DPB and reference lists; each picture decodes as a job on a rayon pool (feature 'threads') and publishes deblocked macroblock rows into a shared Frame; motion compensation and co-located lookups block per row on references still being decoded (safe Rust, OnceLock per MB row); outputs are handed out once their job has finished - row-pipelined deblocking inside a picture (row r filtered after row r+1 is reconstructed), picture buffer recycling, panic/error isolation per job - faster luma/chroma interpolation (row-wise filters, window fetch), direct interpolation into the picture for unweighted single-list blocks, merged motion compensation for uniform direct macroblocks, 8x8 direct derivation with direct_8x8_inference, vectorisable weighted prediction, deblocking with per-edge parameters and cached reference identities - conformance tests now decode every fixture single- and multi-threaded and check pts/POC output order; ignored perf test (1080p High CRF20, 120 frames) 1080p: ~100 fps single-threaded, ~600 fps with 14 threads (M4 Pro, heavily loaded machine). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
35 lines
1.2 KiB
Rust
35 lines
1.2 KiB
Rust
//! Decode speed on a 1080p High-profile stream (ignored by default; run with
|
|
//! `cargo test --release -p filmcraft-h264 --test perf -- --ignored --nocapture`).
|
|
|
|
mod common;
|
|
|
|
use filmcraft_h264::Decoder;
|
|
use std::time::Instant;
|
|
|
|
fn bench(data: &[u8], threads: usize, iters: usize) -> (usize, f64) {
|
|
let mut best = f64::MAX;
|
|
let mut frames = 0;
|
|
for _ in 0..iters {
|
|
let mut dec = Decoder::with_threads(threads);
|
|
let t0 = Instant::now();
|
|
frames = dec.decode(data, 0).expect("decode").len() + dec.flush().len();
|
|
best = best.min(t0.elapsed().as_secs_f64());
|
|
}
|
|
(frames, best)
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn perf_1080p() {
|
|
let f = common::fixture("bench_1080p");
|
|
let Some((h264, _)) = common::ensure(f) else { return };
|
|
// correctness first
|
|
common::check_fixture("bench_1080p").unwrap();
|
|
let data = std::fs::read(h264).unwrap();
|
|
let cores = std::thread::available_parallelism().map(|n| n.get()).unwrap_or(1);
|
|
for threads in [1, cores.min(16)] {
|
|
let (frames, secs) = bench(&data, threads, 5);
|
|
println!("1080p High CRF20 ({} KB): {threads} thread(s): {frames} frames in {secs:.3}s = {:.1} fps", data.len() / 1024, frames as f64 / secs);
|
|
}
|
|
}
|