record-daemon: refactor encoder detection logic
Some checks failed
record-daemon / Build, check and test (push) Failing after 11m31s
Some checks failed
record-daemon / Build, check and test (push) Failing after 11m31s
This commit is contained in:
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user