rd_skip_speed/
rd_skip_speed.rs1use rusty_h264_common::YuvFrame;
17use rusty_h264_encoder::{Encoder, EncoderConfig};
18
19fn synth(w: usize, h: usize, f: u64) -> YuvFrame {
20 let mut fr = YuvFrame::black(w, h);
21 for y in 0..h {
22 for x in 0..w {
23 fr.y[y * w + x] = ((x as u64 / 8 * 9 + y as u64 / 8 * 5) & 0xff) as u8;
24 }
25 }
26 for y in h / 2..h {
27 for x in 0..w {
28 let j = ((x as u64 + y as u64 * 3 + f * 7) % 3) as u8;
29 fr.y[y * w + x] = fr.y[y * w + x].saturating_add(j);
30 }
31 }
32 let (cw, ch) = (w / 2, h / 2);
33 for y in 0..ch {
34 for x in 0..cw {
35 fr.u[y * cw + x] = 110;
36 fr.v[y * cw + x] = 140;
37 }
38 }
39 fr
40}
41
42fn load(path: &str, w: usize, h: usize) -> Vec<YuvFrame> {
43 let raw = std::fs::read(path).expect("clip");
44 let fsz = w * h * 3 / 2;
45 raw.chunks_exact(fsz)
46 .take(60)
47 .map(|c| {
48 let mut fr = YuvFrame::black(w, h);
49 fr.y.copy_from_slice(&c[..w * h]);
50 fr.u.copy_from_slice(&c[w * h..w * h + w * h / 4]);
51 fr.v.copy_from_slice(&c[w * h + w * h / 4..]);
52 fr
53 })
54 .collect()
55}
56
57fn encode(frames: &[YuvFrame], w: usize, h: usize, rd_skip: bool) -> (f64, usize) {
58 let mut cfg = EncoderConfig::new(w, h);
59 cfg.qp = std::env::var("RS_QP").ok().and_then(|v| v.parse().ok()).unwrap_or(27);
60 cfg.gop_size = 30;
61 cfg.tune_rd_skip = rd_skip;
62 cfg.tune_rd_skip_fast_t = std::env::var("RS_GATE").ok().and_then(|v| v.parse().ok());
63 let mut enc = Encoder::new(cfg).expect("encoder");
64 let t = std::time::Instant::now();
65 let mut bytes = 0usize;
66 for fr in frames {
67 bytes += enc.encode(fr).len();
68 }
69 (t.elapsed().as_secs_f64(), bytes)
70}
71
72fn main() {
73 let args: Vec<String> = std::env::args().skip(1).collect();
74 let (frames, w, h, label) = if args.len() >= 2 {
75 let (w, h) = args[1].split_once('x').expect("WxH");
76 let (w, h) = (w.parse().unwrap(), h.parse().unwrap());
77 (load(&args[0], w, h), w, h, args[0].clone())
78 } else {
79 let (w, h) = (352usize, 288usize);
80 ((0..60).map(|f| synth(w, h, f)).collect(), w, h, "synthetic".into())
81 };
82
83 let mut best = [f64::MAX; 2];
84 let mut bytes = [0usize; 2];
85 for pass in 0..10 {
86 let arm = pass % 2;
87 let (t, b) = encode(&frames, w, h, arm == 1);
88 if t < best[arm] {
89 best[arm] = t;
90 }
91 bytes[arm] = b;
92 }
93
94 let px = (w * h * frames.len()) as f64;
95 println!("adaptive RD skip — encode cost ({label}, {w}x{h}, {} frames)\n", frames.len());
96 println!(" off : {:>7.1} ms {:>6.2} Mpx/s {:>8} bytes", best[0] * 1e3, px / best[0] / 1e6, bytes[0]);
97 println!(" on : {:>7.1} ms {:>6.2} Mpx/s {:>8} bytes", best[1] * 1e3, px / best[1] / 1e6, bytes[1]);
98 println!("\n speed : {:>6.3}x", best[0] / best[1]);
99 println!(" size : {:>6.2}%", 100.0 * (bytes[1] as f64 / bytes[0] as f64 - 1.0));
100}