Files
craft-libs/crates/video/examples/vp8_vp8dec.rs
el-j 9f10d434d9 craft-video: clean-room video codecs, one feature per codec (#702–#708)
The eight-part craft-video series landed as one commit, because each part's branch contains the parts before it.

- #702 dnx: DNxHD/DNxHR decoder and encoder
- #703 vp8: VP8 decoder
- #704 prores: ProRes decoder and encoder
- #705 h264: H.264 encoder
- #706 hevc: HEVC encoder
- #707 vp9: VP9 encoder
- #708 av1: AV1 encoder
2026-11-11 08:25:23 -05:00

41 lines
1.5 KiB
Rust

//! Decode an IVF file to raw I420 (`vp8dec in.ivf out.yuv`), for comparison with other decoders.
//! With `VP8DEC_SIZES` set, prints the size of each picture.
use std::io::Write;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<String> = std::env::args().collect();
let [_, input, output] = args.as_slice() else {
return Err("usage: vp8dec in.ivf out.yuv".into());
};
let data = std::fs::read(input)?;
let hdr_len = usize::from(u16::from_le_bytes([data[6], data[7]]));
let mut pos = hdr_len;
let mut out = std::io::BufWriter::new(std::fs::File::create(output)?);
let mut dec = craft_video::vp8::Decoder::new();
let mut n = 0;
let t = std::time::Instant::now();
while pos + 12 <= data.len() {
let size = u32::from_le_bytes(data[pos..pos + 4].try_into()?) as usize;
let pts = i64::from_le_bytes(data[pos + 4..pos + 12].try_into()?);
pos += 12;
let frame = &data[pos..(pos + size).min(data.len())];
pos += size;
match dec.decode(frame, pts) {
Ok(Some(p)) => {
if std::env::var_os("VP8DEC_SIZES").is_some() {
println!("{} {}", p.width, p.height);
}
out.write_all(&p.y)?;
out.write_all(&p.u)?;
out.write_all(&p.v)?;
n += 1;
}
Ok(None) => {}
Err(e) => eprintln!("frame at pts {pts}: {e}"),
}
}
eprintln!("{n} pictures in {:.2}s; {:?}", t.elapsed().as_secs_f64(), dec.stats());
Ok(())
}