mirror of
https://github.com/storytold/filmcraft.git
synced 2026-10-25 07:29:49 +00:00
0414a1d346
Session kept the parser's user data in a Box and later wrote through that Box, which invalidates the raw pointer the callbacks use (Stacked/Tree Borrows). Rust code now reaches the state only through the same into_raw pointer, never across the parse call, and Drop frees it after the parser is destroyed. The setting test accepts either Linux backend's decoder when NVDEC registered, and the README notes perf.stats names NVDEC for streams VA-API decodes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
57 lines
2.9 KiB
Rust
57 lines
2.9 KiB
Rust
//! Settings ▸ Playback ▸ Hardware decoding through the decoder registry and the media stack:
|
|
//! Off gives the software decoder (and no hardware frames), Auto the hardware one where the
|
|
//! system has it. Its own test binary: the switch is process-wide.
|
|
|
|
mod common;
|
|
|
|
use common::*;
|
|
use filmcraft_media::FrameRequest;
|
|
|
|
#[test]
|
|
fn off_uses_the_software_decoder() {
|
|
let ff = filmcraft_testkit::require_ffmpeg!();
|
|
let Some(path) = named(&ff, "hevc_main.mp4") else { return };
|
|
let s = read_stream(&path);
|
|
let available = filmcraft_platform::register();
|
|
assert_eq!(filmcraft_platform::register(), available, "registering twice is harmless");
|
|
|
|
filmcraft_codecs::hw::set_hardware_decoding(false);
|
|
let d = filmcraft_codecs::make_video_decoder(&s.entry).unwrap();
|
|
assert_eq!(d.name(), "FilmCraft HEVC");
|
|
let bytes: std::sync::Arc<[u8]> = std::fs::read(&path).unwrap().into();
|
|
let (g0, h0) = (filmcraft_codecs::gop_stats(), filmcraft_codecs::hw::hw_stats());
|
|
let src = filmcraft_codecs::open_bytes("hevc_main.mp4", bytes.clone()).unwrap();
|
|
let rate = src.info().frame_rate();
|
|
for i in 0..30 {
|
|
src.video_frame(FrameRequest::full(rate.tick_of(i))).unwrap();
|
|
}
|
|
assert!(filmcraft_codecs::gop_stats().frames > g0.frames, "frames counted");
|
|
assert_eq!(filmcraft_codecs::hw::hw_stats().frames, h0.frames, "Off: no hardware frames");
|
|
|
|
filmcraft_codecs::hw::set_hardware_decoding(true);
|
|
let d = filmcraft_codecs::make_video_decoder(&s.entry).unwrap();
|
|
let hw = filmcraft_platform::hardware_decoder_for(&s.entry);
|
|
if !hw {
|
|
eprintln!("SKIPPED (Auto half): no hardware decoder ({available:?})");
|
|
assert_eq!(d.name(), "FilmCraft HEVC");
|
|
return;
|
|
}
|
|
// Linux has two backends (NVDEC in front of VA-API): `register` reports the front one, but
|
|
// a stream NVDEC declines (an older GPU without HEVC) can still go to VA-API on a second GPU
|
|
let backend = match available {
|
|
filmcraft_platform::Availability::Available(name) => name,
|
|
filmcraft_platform::Availability::Unavailable(why) => panic!("a hardware decoder, but register() said {why}"),
|
|
};
|
|
let decoders: &[&str] = if backend == "NVDEC" { &["NVDEC", "VA-API"] } else { &[backend] };
|
|
assert!(decoders.iter().any(|b| d.name().starts_with(b)) && d.name().contains("HEVC"), "{} from {backend}", d.name());
|
|
assert_eq!(filmcraft_codecs::hw::hw_backend(), Some(backend), "perf.stats reports the backend");
|
|
assert!(filmcraft_platform::registered(), "register() put the factory in the registry");
|
|
let h1 = filmcraft_codecs::hw::hw_stats();
|
|
let src = filmcraft_codecs::open_bytes("hevc_main.mp4", bytes).unwrap();
|
|
for i in 0..30 {
|
|
src.video_frame(FrameRequest::full(rate.tick_of(i))).unwrap();
|
|
}
|
|
let h2 = filmcraft_codecs::hw::hw_stats();
|
|
assert!(h2.frames > h1.frames && h2.sessions > h1.sessions, "Auto: hardware frames {h1:?} → {h2:?}");
|
|
}
|