use std::{path::Path, process};
use avio::{HardwareAccel, VideoDecoder};
fn main() {
let mut args = std::env::args().skip(1);
let mut input = None::<String>;
let mut fps: u32 = 24;
while let Some(flag) = args.next() {
match flag.as_str() {
"--input" | "-i" => input = Some(args.next().unwrap_or_default()),
"--fps" => {
let v = args.next().unwrap_or_default();
fps = v.parse().unwrap_or(24);
}
other => {
eprintln!("Unknown flag: {other}");
process::exit(1);
}
}
}
let input = input.unwrap_or_else(|| {
eprintln!("Usage: openexr_sequence --input \"frame%04d.exr\" [--fps 24]");
process::exit(1);
});
let in_name = Path::new(&input)
.file_name()
.and_then(|n| n.to_str())
.unwrap_or(&input);
println!("Input: {in_name} fps={fps}");
println!();
let mut decoder = match VideoDecoder::open(&input)
.hardware_accel(HardwareAccel::None)
.frame_rate(fps)
.build()
{
Ok(d) => d,
Err(e) => {
eprintln!("Error opening EXR sequence: {e}");
eprintln!(
"Note: EXR decoding requires FFmpeg built with \
--enable-decoder=exr"
);
process::exit(1);
}
};
let width = decoder.width();
let height = decoder.height();
let actual_fps = decoder.frame_rate();
println!("Sequence: {width}×{height} actual_fps={actual_fps:.2}");
let mut frames: u64 = 0;
loop {
let frame = match decoder.decode_one() {
Ok(Some(f)) => f,
Ok(None) => break,
Err(e) => {
eprintln!("Decode error at frame {frames}: {e}");
process::exit(1);
}
};
if frames == 0 {
println!(
"Frame 0: format={:?} planes={}",
frame.format(),
frame.num_planes(),
);
for i in 0..frame.num_planes() {
if let Some(plane) = frame.plane(i) {
let float_count = plane.len() / 4; println!(
" plane[{i}]: {} bytes ({float_count} f32 values)",
plane.len()
);
}
}
}
frames += 1;
}
println!();
println!("Done. {frames} EXR frames decoded from '{in_name}'");
}