bframes_signals/
bframes_signals.rs1use rusty_h264_encoder::EncoderConfig;
8
9fn read_y4m(path: &str, max_frames: usize) -> (usize, usize, Vec<rusty_h264_common::types::YuvFrame>) {
10 let raw = std::fs::read(path).unwrap_or_else(|e| panic!("read {path}: {e}"));
11 let hdr_end = raw.iter().position(|&b| b == b'\n').expect("y4m header");
12 let hdr = std::str::from_utf8(&raw[..hdr_end]).expect("utf8 header");
13 let (mut w, mut h) = (0usize, 0usize);
14 for tok in hdr.split_whitespace() {
15 match tok.as_bytes().first() {
16 Some(b'W') => w = tok[1..].parse().expect("width"),
17 Some(b'H') => h = tok[1..].parse().expect("height"),
18 _ => {}
19 }
20 }
21 let (ys, cs) = (w * h, (w / 2) * (h / 2));
22 let mut frames = Vec::new();
23 let mut p = hdr_end + 1;
24 while frames.len() < max_frames {
25 let Some(rel) = raw[p..].iter().position(|&b| b == b'\n') else { break };
26 p += rel + 1;
27 if p + ys + 2 * cs > raw.len() {
28 break;
29 }
30 frames.push(rusty_h264_common::types::YuvFrame {
31 width: w,
32 height: h,
33 y: raw[p..p + ys].to_vec(),
34 u: raw[p + ys..p + ys + cs].to_vec(),
35 v: raw[p + ys + cs..p + ys + 2 * cs].to_vec(),
36 });
37 p += ys + 2 * cs;
38 }
39 (w, h, frames)
40}
41
42fn main() {
43 let mut args = std::env::args().skip(1);
44 let path = args.next().expect("clip");
45 let nframes: usize = args.next().and_then(|s| s.parse().ok()).unwrap_or(30);
46 let (w, h, frames) = read_y4m(&path, nframes);
47 let name = std::path::Path::new(&path).file_stem().unwrap().to_string_lossy().to_string();
48 let cfg = EncoderConfig::new(w, h);
49 let (bi, gmc, mg, dc, screen, grain) = rusty_h264_encoder::bframes_gate_signals(&cfg, &frames);
50 println!(
51 "{name:<24} bi={bi:>7.3} gmc={gmc:>8.3} mgain={mg:.3} dcfrac={dc:.3} screen={} grain={}",
52 screen as u8, grain as u8
53 );
54}