thread_bench/
thread_bench.rs1use rusty_h264_common::types::YuvFrame;
5use rusty_h264_encoder::{Encoder, EncoderConfig, Preset};
6
7fn read_y4m(path: &str, max: usize) -> (usize, usize, Vec<YuvFrame>) {
8 let raw = std::fs::read(path).unwrap();
9 let e = raw.iter().position(|&b| b == b'\n').unwrap();
10 let hdr = std::str::from_utf8(&raw[..e]).unwrap();
11 let (mut w, mut h) = (0usize, 0usize);
12 for t in hdr.split_whitespace() {
13 match t.as_bytes().first() {
14 Some(b'W') => w = t[1..].parse().unwrap(),
15 Some(b'H') => h = t[1..].parse().unwrap(),
16 _ => {}
17 }
18 }
19 let (ys, cs) = (w * h, (w / 2) * (h / 2));
20 let (mut f, mut p) = (Vec::new(), e + 1);
21 while f.len() < max {
22 let Some(r) = raw[p..].iter().position(|&b| b == b'\n') else { break };
23 p += r + 1;
24 if p + ys + 2 * cs > raw.len() { break }
25 f.push(YuvFrame { width: w, height: h, y: raw[p..p+ys].to_vec(), u: raw[p+ys..p+ys+cs].to_vec(), v: raw[p+ys+cs..p+ys+2*cs].to_vec() });
26 p += ys + 2 * cs;
27 }
28 (w, h, f)
29}
30
31fn main() {
32 let path = std::env::args().nth(1).unwrap();
33 let n: usize = std::env::var("TB_FRAMES").ok().and_then(|v| v.parse().ok()).unwrap_or(240);
34 let gop: u32 = std::env::var("TB_GOP").ok().and_then(|v| v.parse().ok()).unwrap_or(30);
35 let (w, h, frames) = read_y4m(&path, n);
36 for (pn, preset) in [("balanced", Preset::Balanced), ("quality", Preset::Quality)] {
37 let mut cfg = EncoderConfig::new(w, h);
38 cfg.qp = 27; cfg.gop_size = gop; cfg.preset = preset;
39 let mut seq_ms = f64::MAX; let mut seq_out = Vec::new();
41 for _ in 0..3 {
42 let mut enc = Encoder::new(cfg.clone()).unwrap();
43 let t = std::time::Instant::now();
44 let mut o = Vec::new();
45 for f in &frames { o.extend_from_slice(&enc.encode(f)); }
46 seq_ms = seq_ms.min(t.elapsed().as_secs_f64() * 1e3);
47 seq_out = o;
48 }
49 let mut par_ms = f64::MAX; let mut par_out = Vec::new();
50 for _ in 0..3 {
51 let enc = Encoder::new(cfg.clone()).unwrap();
52 let t = std::time::Instant::now();
53 let o: Vec<u8> = enc.encode_all(&frames).unwrap().concat();
54 par_ms = par_ms.min(t.elapsed().as_secs_f64() * 1e3);
55 par_out = o;
56 }
57 assert_eq!(seq_out, par_out, "seq != parallel — compression WOULD be compromised");
58 println!("{pn:<9} x{} gop{gop}: seq {seq_ms:.0} ms parallel {par_ms:.0} ms speedup {:.2}x (byte-identical ✓)", frames.len(), seq_ms / par_ms);
59 }
60}