record-daemon: refactor encoder detection logic
Some checks failed
record-daemon / Build, check and test (push) Failing after 11m31s

This commit is contained in:
2026-03-21 19:10:32 +01:00
parent 8e885ffc64
commit 6ac2fe9cd3

View File

@@ -300,48 +300,25 @@ pub fn detect_hardware_encoders() -> Vec<EncoderCapability> {
let mut capabilities = Vec::new(); let mut capabilities = Vec::new();
#[cfg(target_os = "linux")]
{
// Check for NVIDIA
if std::path::Path::new("/dev/nvidia0").exists() {
info!("[ENCODER_DETECT] Found NVIDIA device");
capabilities.push(EncoderCapability::Nvenc);
}
// Check for AMD
if std::path::Path::new("/sys/class/drm").exists() {
// Would check for AMD GPU
// capabilities.push(EncoderCapability::Amf);
}
}
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
{ {
// On Windows, check for NVIDIA first let gpu_vendors = detect_gpu_vendors();
// Try to load nvenc DLL
info!("[ENCODER_DETECT] Checking for NVENC...");
if is_nvenc_available() { if gpu_vendors.contains(&GpuVendor::Nvidia) {
info!("[ENCODER_DETECT] NVENC available"); info!("[ENCODER_DETECT] NVENC available");
capabilities.push(EncoderCapability::Nvenc); capabilities.push(EncoderCapability::Nvenc);
} else { } else {
info!("[ENCODER_DETECT] NVENC not available"); info!("[ENCODER_DETECT] NVENC not available");
} }
// Check for AMD AMF if gpu_vendors.contains(&GpuVendor::Amd) {
info!("[ENCODER_DETECT] Checking for AMF...");
if is_amf_available() {
info!("[ENCODER_DETECT] AMF available"); info!("[ENCODER_DETECT] AMF available");
capabilities.push(EncoderCapability::Amf); capabilities.push(EncoderCapability::Amf);
} else { } else {
info!("[ENCODER_DETECT] AMF not available"); info!("[ENCODER_DETECT] AMF not available");
} }
// Check for Intel QuickSync if gpu_vendors.contains(&GpuVendor::Intel) {
info!("[ENCODER_DETECT] Checking for QuickSync...");
if is_quicksync_available() {
info!("[ENCODER_DETECT] QuickSync available"); info!("[ENCODER_DETECT] QuickSync available");
capabilities.push(EncoderCapability::QuickSync); capabilities.push(EncoderCapability::QuickSync);
} else { } else {
@@ -349,8 +326,7 @@ pub fn detect_hardware_encoders() -> Vec<EncoderCapability> {
} }
} }
// Always available // Software encoding is always available
info!("[ENCODER_DETECT] Software encoder always available");
capabilities.push(EncoderCapability::Software); capabilities.push(EncoderCapability::Software);
info!("[ENCODER_DETECT] Detected encoders: {:?}", capabilities); info!("[ENCODER_DETECT] Detected encoders: {:?}", capabilities);
@@ -424,132 +400,6 @@ fn detect_gpu_vendors() -> Vec<GpuVendor> {
vendors vendors
} }
/// Check if NVIDIA NVENC is available.
#[cfg(target_os = "windows")]
fn is_nvenc_available() -> bool {
use tracing::info;
use winreg::enums::{HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE};
use winreg::RegKey;
// First check if NVIDIA GPU is present via registry
let vendors = detect_gpu_vendors();
if !vendors.contains(&GpuVendor::Nvidia) {
info!("[ENCODER_DETECT] No NVIDIA GPU detected via registry");
return false;
}
// NVIDIA GPU found, now check for NVENC support
// NVENC is available on most modern NVIDIA GPUs (GTX 600+ and all RTX cards)
// We can verify by checking if nvEncAPI is loadable or by checking registry
// Check for NVENC capability in registry (NVIDIA stores encoder info here)
const NVENC_REGISTRY_PATH: &str = r"SOFTWARE\NVIDIA Corporation\Global\NvEnc";
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);
// Try HKCU first
if hkcu.open_subkey(NVENC_REGISTRY_PATH).is_ok() {
info!("[ENCODER_DETECT] NVENC registry key found (HKCU)");
return true;
}
// Try HKLM
if hklm.open_subkey(NVENC_REGISTRY_PATH).is_ok() {
info!("[ENCODER_DETECT] NVENC registry key found (HKLM)");
return true;
}
// If NVIDIA GPU is present, assume NVENC is available
// Modern NVIDIA GPUs (GTX 600 series and newer) all have NVENC
// This is a reasonable fallback since the registry check might not work on all systems
info!("[ENCODER_DETECT] NVIDIA GPU detected, assuming NVENC available");
true
}
/// Check if AMD AMF is available.
#[cfg(target_os = "windows")]
fn is_amf_available() -> bool {
use tracing::info;
use winreg::enums::HKEY_LOCAL_MACHINE;
use winreg::RegKey;
// Check if AMD GPU is present via registry
let vendors = detect_gpu_vendors();
if !vendors.contains(&GpuVendor::Amd) {
info!("[ENCODER_DETECT] No AMD GPU detected via registry");
return false;
}
// AMD GPU found, check for AMF runtime
// AMF is available on modern AMD GPUs (RX 400+ and some older cards)
// Check for AMF runtime in registry
const AMF_REGISTRY_PATH: &str = r"SOFTWARE\AMD\AMF";
let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);
if hklm.open_subkey(AMF_REGISTRY_PATH).is_ok() {
info!("[ENCODER_DETECT] AMF registry key found");
return true;
}
// Fallback: check for amdocl64.dll or amfrt64.dll in system
let system32 = std::env::var("SystemRoot").unwrap_or_else(|_| "C:\\Windows".to_string());
let amdocl_path = format!("{}\\System32\\amdocl64.dll", system32);
let amfrt_path = format!("{}\\System32\\amfrt64.dll", system32);
if std::path::Path::new(&amdocl_path).exists() || std::path::Path::new(&amfrt_path).exists() {
info!("[ENCODER_DETECT] AMF DLL found");
return true;
}
// If AMD GPU is present, assume AMF is available on modern cards
info!("[ENCODER_DETECT] AMD GPU detected, assuming AMF available");
true
}
/// Check if Intel QuickSync is available.
#[cfg(target_os = "windows")]
fn is_quicksync_available() -> bool {
use tracing::info;
// Check if Intel GPU is present via registry
let vendors = detect_gpu_vendors();
if !vendors.contains(&GpuVendor::Intel) {
info!("[ENCODER_DETECT] No Intel GPU detected via registry");
return false;
}
// Intel GPU found, check for QuickSync (Intel Media SDK / oneVPL)
// QuickSync is available on Intel CPUs with integrated graphics (Sandy Bridge and newer)
// Check for Intel Media SDK or oneVPL
let system32 = std::env::var("SystemRoot").unwrap_or_else(|_| "C:\\Windows".to_string());
let mfx_path = format!("{}\\System32\\mfx64.dll", system32);
let vpl_path = format!("{}\\System32\\libmfx64.dll", system32);
if std::path::Path::new(&mfx_path).exists() || std::path::Path::new(&vpl_path).exists() {
info!("[ENCODER_DETECT] Intel Media SDK DLL found");
return true;
}
// Check for oneVPL runtime
const VPL_REGISTRY_PATH: &str = r"SOFTWARE\Intel\oneVPL";
use winreg::enums::HKEY_LOCAL_MACHINE;
use winreg::RegKey;
let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);
if hklm.open_subkey(VPL_REGISTRY_PATH).is_ok() {
info!("[ENCODER_DETECT] oneVPL registry key found");
return true;
}
// If Intel GPU is present, assume QuickSync might be available
// Note: Not all Intel GPUs have QuickSync (some low-end chips don't)
info!("[ENCODER_DETECT] Intel GPU detected, assuming QuickSync available");
true
}
/// Get the best available encoder capability. /// Get the best available encoder capability.
pub fn best_available_encoder() -> EncoderCapability { pub fn best_available_encoder() -> EncoderCapability {
let capabilities = detect_hardware_encoders(); let capabilities = detect_hardware_encoders();