filmcraft/crates/codecs/tests/pool_bitexact.rs

64 lines
2.4 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! Decoded pictures are written into recycled plane buffers (`filmcraft_frame::pool`). A recycled
//! buffer still holds an old picture, so the decoder must overwrite every byte: here the pool is
//! primed with buffers full of 0xAA before decoding, and every frame must still match ffmpeg bit
//! for bit. (Its own process: the pool is global.)
mod common;
use std::sync::Arc;
use common::*;
use filmcraft_frame::{Chroma, PixelData, VideoFrame};
use filmcraft_media::FrameRequest;
#[test]
fn dirty_recycled_planes_decode_bit_exact() {
let ff = filmcraft_testkit::require_ffmpeg!();
// 640×480: luma and chroma planes are both large enough to be pooled
let Some(file) = fixture(
&ff,
"pool_h264.mp4",
&[
"-f",
"lavfi",
"-i",
"testsrc2=s=640x480:r=24:d=1,noise=alls=10:allf=t",
"-c:v",
"libx264",
"-preset",
"fast",
"-x264-params",
"bframes=2:keyint=12",
"-pix_fmt",
"yuv420p",
],
) else {
return;
};
let (w, h) = (640usize, 480usize);
let raw = ffmpeg_frames(&ff, &file, "yuv420p");
let fsize = w * h * 3 / 2;
let n = raw.len() / fsize;
assert!(n >= 20, "{n} frames");
let reference = |i: usize| raw_planes(&raw[i * fsize..(i + 1) * fsize], w, h, w / 2, h / 2, 1);
// prime the pool with dirty buffers of exactly the plane sizes the decoder asks for
for _ in 0..8 {
let dirty = |len: usize| Arc::new(vec![0xAAu8; len]);
let f = VideoFrame {
data: PixelData::Yuv8 { planes: [dirty(w * h), dirty(w * h / 4), dirty(w * h / 4)], chroma: Chroma::C420, alpha: None },
..VideoFrame::rgba8(w as u32, h as u32, vec![0; w * h * 4])
};
filmcraft_frame::pool::recycle(Arc::new(f));
}
let reused_before = filmcraft_frame::pool::stats().reused;
let src = filmcraft_codecs::open_bytes("pool_h264.mp4", bytes(&file)).expect("open");
let rate = src.info().frame_rate();
for i in 0..n {
let f = src.video_frame(FrameRequest::full(rate.tick_of(i as i64))).expect("frame");
assert_eq!(max_diff(&planes(&f), &reference(i)), 0, "frame {i} decoded into a recycled buffer");
}
assert!(filmcraft_frame::pool::stats().reused > reused_before, "the decoder took the dirty pooled buffers");
}