codec: prefer native NVDEC over VAAPI on Linux

On multi-GPU boxes VAAPI's default render node can point at a device
with no VA driver (NVIDIA without libva-nvidia-driver), failing before
the working AMD/Intel node is ever tried; trying CUDA (NVDEC) first is
both the discrete-GPU path and sidesteps that misdirection. VAAPI stays
as the fallback for AMD/Intel-only machines.

Adds a hwcheck example printing which hw device a stream opens with and
the raw av_hwdevice_ctx_create result codes per device type.
This commit is contained in:
2026-08-30 00:31:32 +08:00
parent 197212bc46
commit 3be8c3e8fd
2 changed files with 53 additions and 2 deletions
+44
View File
@@ -0,0 +1,44 @@
// Temporary diagnostic: print the hardware decoder a video stream opens
// with (None = software fallback).
// Usage: hwcheck <mediafile> [stream_index]
use oak_codec::decoder::{CodecStream, Decoder};
use oak_codec::ffmpeg::FFmpegDecoder;
fn probe(device_type: ffmpeg_next::ffi::AVHWDeviceType, name: &str) {
let mut dev: *mut ffmpeg_next::ffi::AVBufferRef = std::ptr::null_mut();
let rc = unsafe {
ffmpeg_next::ffi::av_hwdevice_ctx_create(
&mut dev,
device_type,
std::ptr::null(),
std::ptr::null_mut(),
0,
)
};
eprintln!("{name}: av_hwdevice_ctx_create rc = {rc}");
if rc >= 0 && !dev.is_null() {
unsafe { ffmpeg_next::ffi::av_buffer_unref(&mut dev) };
}
}
fn main() {
ffmpeg_next::log::set_level(ffmpeg_next::log::Level::Debug);
probe(
ffmpeg_next::ffi::AVHWDeviceType::AV_HWDEVICE_TYPE_CUDA,
"CUDA",
);
probe(
ffmpeg_next::ffi::AVHWDeviceType::AV_HWDEVICE_TYPE_VAAPI,
"VAAPI",
);
let args: Vec<String> = std::env::args().collect();
if args.len() < 2 {
return;
}
let stream: i32 = args.get(2).and_then(|s| s.parse().ok()).unwrap_or(0);
let d = FFmpegDecoder::new();
let s = CodecStream::with_block(args[1].clone(), stream, None);
d.open(&s).expect("open video stream");
println!("hw_decoder_name = {:?}", d.hw_decoder_name());
}
+9 -2
View File
@@ -31,7 +31,7 @@
//! hardware surface.
//!
//! - **macOS**: `AV_HWDEVICE_TYPE_VIDEOTOOLBOX`
//! - **Linux**: `VAAPI`, then `CUDA` (NVDEC)
//! - **Linux**: `CUDA` (NVDEC, the discrete-GPU path), then `VAAPI`
//! - **Windows**: `D3D11VA`, then `CUDA` (NVDEC)
//!
//! Device creation can fail on machines without the device/driver (a
@@ -131,9 +131,16 @@ pub fn device_type_candidates() -> &'static [sys::AVHWDeviceType] {
}
#[cfg(all(unix, not(target_os = "macos")))]
{
// CUDA (native NVDEC) first: it is the discrete-GPU path, and on
// multi-GPU boxes VAAPI's default render node can point at a
// device with no VA driver (e.g. NVIDIA without
// libva-nvidia-driver) while the AMD/Intel node would work —
// trying NVDEC first sidesteps that misdirection. VAAPI stays as
// the fallback for AMD/Intel-only machines (CUDA device creation
// fails fast without libcuda).
&[
sys::AVHWDeviceType::AV_HWDEVICE_TYPE_VAAPI,
sys::AVHWDeviceType::AV_HWDEVICE_TYPE_CUDA,
sys::AVHWDeviceType::AV_HWDEVICE_TYPE_VAAPI,
]
}
}