diff --git a/plugins/nv-filters/data/locale/en-US.ini b/plugins/nv-filters/data/locale/en-US.ini index 9df63caeed30f6..ff23e23b85b884 100644 --- a/plugins/nv-filters/data/locale/en-US.ini +++ b/plugins/nv-filters/data/locale/en-US.ini @@ -5,7 +5,7 @@ Nvafx.Method="Method" Nvafx.Method.Denoiser="NVIDIA Noise Removal" Nvafx.Method.Dereverb="NVIDIA Room Echo Removal" Nvafx.Method.DenoiserPlusDereverb="NVIDIA Noise Removal + Room Echo Removal" -Nvafx.OutdatedSDK="WARNING: Please upgrade both NVIDIA Video & Audio SDK. Your current version of Audio SDK is outdated." +Nvafx.OutdatedSDK="WARNING: Please upgrade both NVIDIA Video & Audio SDK. Your current version of Audio SDK is outdated. This can break Audio FX, Video FX, or both." Nvafx.VAD="Voice Optimized" Nvvfx.Method.Greenscreen="NVIDIA Background Removal" Nvvfx.Method.Greenscreen.Mode="Mode" @@ -14,7 +14,7 @@ Nvvfx.Method.Greenscreen.Performance="Performance (lower GPU usage, good quality Nvvfx.Method.Greenscreen.Quality.Chair="Quality (higher GPU usage, better quality) + Chair removal" Nvvfx.Method.Greenscreen.Performance.Chair="Performance (lower GPU usage, good quality) + Chair removal" Nvvfx.Method.Greenscreen.Threshold="Threshold" -Nvvfx.OutdatedSDK="WARNING: Please upgrade both NVIDIA Video & Audio SDK. Your current version of Video SDK is outdated." +Nvvfx.OutdatedSDK="WARNING: Please upgrade both NVIDIA Video & Audio SDK. Your current version of Video SDK is outdated. This can break Audio FX, Video FX, or both." Nvvfx.Method.Greenscreen.Processing="Mask refresh frequency in frames" Nvvfx.Method.Greenscreen.Processing.Hint="This alleviates GPU load by generating a mask every N frames only (2 on default)." Nvvfx.Method.BlurFilter="NVIDIA Blur Filter" diff --git a/plugins/nv-filters/nv-filters.c b/plugins/nv-filters/nv-filters.c index 0a5fb44512daa6..f5055a456a8ac9 100644 --- a/plugins/nv-filters/nv-filters.c +++ b/plugins/nv-filters/nv-filters.c @@ -23,7 +23,6 @@ extern void unload_nvidia_vfx(void); bool obs_module_load(void) { #ifdef LIBNVAFX_ENABLED - /* load nvidia audio fx dll */ if (load_nvidia_afx()) obs_register_source(&nvidia_audiofx_filter); #endif diff --git a/plugins/nv-filters/nv_sdk_versions.h b/plugins/nv-filters/nv_sdk_versions.h index efdd4cb5c29d19..53911530af99e7 100644 --- a/plugins/nv-filters/nv_sdk_versions.h +++ b/plugins/nv-filters/nv_sdk_versions.h @@ -1,2 +1,7 @@ #define MIN_VFX_SDK_VERSION (0 << 24 | 7 << 16 | 6 << 8 | 0 << 0) +#define MIN_VFX_LOGGER_VERSION (0 << 24 | 7 << 16 | 6 << 8 | 0 << 0) +#define MIN_ARM_VFX_SDK_VERSION (1 << 24 | 3 << 16 | 0 << 8 | 0 << 0) + #define MIN_AFX_SDK_VERSION (1 << 24 | 6 << 16 | 1 << 8 | 2 << 0) +#define MIN_AFX_LOGGER_VERSION (1 << 24 | 6 << 16 | 1 << 8 | 2 << 0) // also gates VAD feature +#define MIN_ARM_AFX_SDK_VERSION (3 << 24 | 0 << 16 | 0 << 8 | 49 << 0) diff --git a/plugins/nv-filters/nvafx-load.h b/plugins/nv-filters/nvafx-load.h index fde85a002aec51..28dfcb9049c9c9 100644 --- a/plugins/nv-filters/nvafx-load.h +++ b/plugins/nv-filters/nvafx-load.h @@ -12,43 +12,43 @@ #ifdef LIBNVAFX_ENABLED static HMODULE nv_audiofx = NULL; +static HMODULE nv_denoiserfx = NULL; +static HMODULE nv_dereverbfx = NULL; +static HMODULE nv_dereverbdenoiserfx = NULL; /** Effects @ref NvAFX_EffectSelector */ #define NVAFX_EFFECT_DENOISER "denoiser" #define NVAFX_EFFECT_DEREVERB "dereverb" #define NVAFX_EFFECT_DEREVERB_DENOISER "dereverb_denoiser" -#define NVAFX_EFFECT_AEC "aec" -#define NVAFX_EFFECT_SUPERRES "superres" /** Model paths */ #define NVAFX_EFFECT_DENOISER_MODEL "\\models\\denoiser_48k.trtpkg" #define NVAFX_EFFECT_DEREVERB_MODEL "\\models\\dereverb_48k.trtpkg" #define NVAFX_EFFECT_DEREVERB_DENOISER_MODEL "\\models\\dereverb_denoiser_48k.trtpkg" -#define NVAFX_CHAINED_EFFECT_DENOISER_16k_SUPERRES_16k_TO_48k "denoiser16k_superres16kto48k" -#define NVAFX_CHAINED_EFFECT_DEREVERB_16k_SUPERRES_16k_TO_48k "dereverb16k_superres16kto48k" -#define NVAFX_CHAINED_EFFECT_DEREVERB_DENOISER_16k_SUPERRES_16k_TO_48k "dereverb_denoiser16k_superres16kto48k" -#define NVAFX_CHAINED_EFFECT_SUPERRES_8k_TO_16k_DENOISER_16k "superres8kto16k_denoiser16k" -#define NVAFX_CHAINED_EFFECT_SUPERRES_8k_TO_16k_DEREVERB_16k "superres8kto16k_dereverb16k" -#define NVAFX_CHAINED_EFFECT_SUPERRES_8k_TO_16k_DEREVERB_DENOISER_16k "superres8kto16k_dereverb_denoiser16k" - /** Parameter selectors */ - #define NVAFX_PARAM_NUM_STREAMS "num_streams" #define NVAFX_PARAM_USE_DEFAULT_GPU "use_default_gpu" #define NVAFX_PARAM_USER_CUDA_CONTEXT "user_cuda_context" #define NVAFX_PARAM_DISABLE_CUDA_GRAPH "disable_cuda_graph" -#define NVAFX_PARAM_ENABLE_VAD "enable_vad" + /** Effect parameters. @ref NvAFX_ParameterSelector */ #define NVAFX_PARAM_MODEL_PATH "model_path" #define NVAFX_PARAM_INPUT_SAMPLE_RATE "input_sample_rate" #define NVAFX_PARAM_OUTPUT_SAMPLE_RATE "output_sample_rate" + #define NVAFX_PARAM_NUM_INPUT_SAMPLES_PER_FRAME "num_input_samples_per_frame" #define NVAFX_PARAM_NUM_OUTPUT_SAMPLES_PER_FRAME "num_output_samples_per_frame" +/* SDK >= 3.0.0.49: replaces the 2 previous define... */ +#define NVAFX_PARAM_NUM_SAMPLES_PER_INPUT_FRAME "num_samples_per_input_frame" +#define NVAFX_PARAM_NUM_SAMPLES_PER_OUTPUT_FRAME "num_samples_per_output_frame" + #define NVAFX_PARAM_NUM_INPUT_CHANNELS "num_input_channels" #define NVAFX_PARAM_NUM_OUTPUT_CHANNELS "num_output_channels" #define NVAFX_PARAM_INTENSITY_RATIO "intensity_ratio" #define NVAFX_PARAM_ENABLE_VAD "enable_vad" +/** SDK >= 3.0.0.49: Voice activity status (boolean) is an immutable parameter. */ +#define NVAFX_PARAM_VAD_RESULT "vad_result" #pragma deprecated(NVAFX_PARAM_DENOISER_MODEL_PATH) #define NVAFX_PARAM_DENOISER_MODEL_PATH NVAFX_PARAM_MODEL_PATH @@ -90,12 +90,32 @@ typedef enum { /** Model file could not be loaded */ NVAFX_STATUS_MODEL_LOAD_FAILED = 8, - /** (32 bit SDK only) COM server was not registered, please see user manual for details */ - NVAFX_STATUS_32_SERVER_NOT_REGISTERED = 9, - /** (32 bit SDK only) COM operation failed */ - NVAFX_STATUS_32_COM_ERROR = 10, + /** Model is not loaded, it needs to be loaded for this operation */ + NVAFX_STATUS_MODEL_NOT_LOADED = 9, + /** Selected model is incompatible */ + NVAFX_STATUS_INCOMPATIBLE_MODEL = 10, /** GPU supported. The SDK requires Turing and above GPU with Tensor cores */ NVAFX_STATUS_GPU_UNSUPPORTED = 11, + /** No supported GPU found on the system */ + NVAFX_STATUS_NO_SUPPORTED_GPU_FOUND = 12, + /** Current GPU is not the one selected */ + NVAFX_STATUS_WRONG_GPU = 13, + /** Cuda operation failure */ + NVAFX_STATUS_CUDA_ERROR = 14, + /** Invalid operation performed **/ + NVAFX_STATUS_INVALID_OPERATION = 15, + /** CUDA runtime is less than supported version*/ + NVAFX_UNSUPPORTED_RUNTIME = 16, + /** (32 bit SDK only) COM server was not registered, please see user manual for details */ + NVAFX_STATUS_32_SERVER_NOT_REGISTERED = 17, + /** (32 bit SDK only) COM operation failed */ + NVAFX_STATUS_32_COM_ERROR = 18, + /** Cuda Context Failure Error */ + NVAFX_STATUS_CUDA_CONTEXT_CREATION_FAILED = 19, + /** Dynamic Load Library Error */ + NVAFX_STATUS_LIBRARY_ERROR = 20, + /** Dynamic Load Library out of memory error */ + NVAFX_STATUS_OUT_OF_MEMORY = 21, } NvAFX_Status; #define NVAFX_TRUE 1 @@ -131,30 +151,18 @@ typedef const char *NvAFX_EffectSelector; typedef const char *NvAFX_ParameterSelector; typedef void *NvAFX_Handle; -typedef NvAFX_Status NVAFX_API (*NvAFX_GetEffectList_t)(int *num_effects, NvAFX_EffectSelector *effects[]); typedef NvAFX_Status NVAFX_API (*NvAFX_CreateEffect_t)(NvAFX_EffectSelector code, NvAFX_Handle *effect); -typedef NvAFX_Status NVAFX_API (*NvAFX_CreateChainedEffect_t)(NvAFX_EffectSelector code, NvAFX_Handle *effect); typedef NvAFX_Status NVAFX_API (*NvAFX_DestroyEffect_t)(NvAFX_Handle effect); typedef NvAFX_Status NVAFX_API (*NvAFX_SetU32_t)(NvAFX_Handle effect, NvAFX_ParameterSelector param_name, unsigned int val); -typedef NvAFX_Status NVAFX_API (*NvAFX_SetU32List_t)(NvAFX_Handle effect, NvAFX_ParameterSelector param_name, - unsigned int *val, unsigned int size); typedef NvAFX_Status NVAFX_API (*NvAFX_SetString_t)(NvAFX_Handle effect, NvAFX_ParameterSelector param_name, const char *val); -typedef NvAFX_Status NVAFX_API (*NvAFX_SetStringList_t)(NvAFX_Handle effect, NvAFX_ParameterSelector param_name, - const char **val, unsigned int size); typedef NvAFX_Status NVAFX_API (*NvAFX_SetFloat_t)(NvAFX_Handle effect, NvAFX_ParameterSelector param_name, float val); -typedef NvAFX_Status NVAFX_API (*NvAFX_SetFloatList_t)(NvAFX_Handle effect, NvAFX_ParameterSelector param_name, - float *val, unsigned int size); typedef NvAFX_Status NVAFX_API (*NvAFX_GetU32_t)(NvAFX_Handle effect, NvAFX_ParameterSelector param_name, unsigned int *val); typedef NvAFX_Status NVAFX_API (*NvAFX_GetString_t)(NvAFX_Handle effect, NvAFX_ParameterSelector param_name, char *val, int max_length); -typedef NvAFX_Status NVAFX_API (*NvAFX_GetStringList_t)(NvAFX_Handle effect, NvAFX_ParameterSelector param_name, - char **val, int *max_length, unsigned int size); typedef NvAFX_Status NVAFX_API (*NvAFX_GetFloat_t)(NvAFX_Handle effect, NvAFX_ParameterSelector param_name, float *val); -typedef NvAFX_Status NVAFX_API (*NvAFX_GetFloatList_t)(NvAFX_Handle effect, NvAFX_ParameterSelector param_name, - float *val, unsigned int size); typedef NvAFX_Status NVAFX_API (*NvAFX_Load_t)(NvAFX_Handle effect); typedef NvAFX_Status NVAFX_API (*NvAFX_GetSupportedDevices_t)(NvAFX_Handle effect, int *num, int *devices); typedef NvAFX_Status NVAFX_API (*NvAFX_Run_t)(NvAFX_Handle effect, const float **input, float **output, @@ -166,21 +174,14 @@ typedef NvAFX_Status NVAFX_API (*NvAFX_InitializeLogger_t)(LoggingSeverity level const char *filename, logging_cb_t cb, void *userdata); typedef NvAFX_Status NVAFX_API (*NvAFX_UninitializeLogger_t)(); -static NvAFX_GetEffectList_t NvAFX_GetEffectList = NULL; static NvAFX_CreateEffect_t NvAFX_CreateEffect = NULL; -static NvAFX_CreateChainedEffect_t NvAFX_CreateChainedEffect = NULL; static NvAFX_DestroyEffect_t NvAFX_DestroyEffect = NULL; static NvAFX_SetU32_t NvAFX_SetU32 = NULL; -static NvAFX_SetU32List_t NvAFX_SetU32List = NULL; static NvAFX_SetString_t NvAFX_SetString = NULL; -static NvAFX_SetStringList_t NvAFX_SetStringList = NULL; static NvAFX_SetFloat_t NvAFX_SetFloat = NULL; -static NvAFX_SetFloatList_t NvAFX_SetFloatList = NULL; static NvAFX_GetU32_t NvAFX_GetU32 = NULL; static NvAFX_GetString_t NvAFX_GetString = NULL; -static NvAFX_GetStringList_t NvAFX_GetStringList = NULL; static NvAFX_GetFloat_t NvAFX_GetFloat = NULL; -static NvAFX_GetFloatList_t NvAFX_GetFloatList = NULL; static NvAFX_Load_t NvAFX_Load = NULL; static NvAFX_GetSupportedDevices_t NvAFX_GetSupportedDevices = NULL; static NvAFX_Run_t NvAFX_Run = NULL; @@ -189,23 +190,16 @@ static NvAFX_Reset_t NvAFX_Reset = NULL; static NvAFX_InitializeLogger_t NvAFX_InitializeLogger = NULL; static NvAFX_UninitializeLogger_t NvAFX_UninitializeLogger = NULL; -void release_lib(void) +static inline void release_afx_lib(void) { - NvAFX_GetEffectList = NULL; NvAFX_CreateEffect = NULL; - NvAFX_CreateChainedEffect = NULL; NvAFX_DestroyEffect = NULL; NvAFX_SetU32 = NULL; - NvAFX_SetU32List = NULL; NvAFX_SetString = NULL; - NvAFX_SetStringList = NULL; NvAFX_SetFloat = NULL; - NvAFX_SetFloatList = NULL; NvAFX_GetU32 = NULL; NvAFX_GetString = NULL; - NvAFX_GetStringList = NULL; NvAFX_GetFloat = NULL; - NvAFX_GetFloatList = NULL; NvAFX_Load = NULL; NvAFX_GetSupportedDevices = NULL; NvAFX_Run = NULL; @@ -213,16 +207,32 @@ void release_lib(void) /* SDK >= 1.6.0 */ NvAFX_InitializeLogger = NULL; NvAFX_UninitializeLogger = NULL; + if (nv_audiofx) { FreeLibrary(nv_audiofx); nv_audiofx = NULL; } + if (nv_denoiserfx) { + FreeLibrary(nv_denoiserfx); + nv_denoiserfx = NULL; + } + if (nv_dereverbfx) { + FreeLibrary(nv_dereverbfx); + nv_dereverbfx = NULL; + } + if (nv_dereverbdenoiserfx) { + FreeLibrary(nv_dereverbdenoiserfx); + nv_dereverbdenoiserfx = NULL; + } } static inline bool nvafx_get_sdk_path(char *buffer, const size_t len) { DWORD ret = GetEnvironmentVariableA("NVAFX_SDK_DIR", buffer, (DWORD)len); + if (!ret || ret >= len - 1) { + ret = GetEnvironmentVariableA("AFX_SDK_DIR", buffer, (DWORD)len); + } if (!ret || ret >= len - 1) { char path[MAX_PATH]; if (!GetEnvironmentVariableA("ProgramFiles", path, MAX_PATH)) { @@ -240,25 +250,6 @@ static inline bool nvafx_get_sdk_path(char *buffer, const size_t len) return true; } -static inline bool load_lib() -{ - char sdkPath[MAX_PATH]; - char effectsPath[MAX_PATH]; - - if (!nvafx_get_sdk_path(sdkPath, MAX_PATH)) { - return false; - } - - if (_snprintf_s(effectsPath, _countof(effectsPath), _TRUNCATE, "%s\\NVAudioEffects.dll", sdkPath) == -1) { - return false; - } - - nv_audiofx = - LoadLibraryExA(effectsPath, NULL, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); - - return !!nv_audiofx; -} - static unsigned int get_lib_version(void) { static unsigned int version = 0; @@ -287,4 +278,42 @@ static unsigned int get_lib_version(void) return version; } +static inline bool load_afx_module(HMODULE *module, const char *sdk_path, const char *filename) +{ + char path[MAX_PATH]; + + if (*module) { + return true; + } + + if (_snprintf_s(path, _countof(path), _TRUNCATE, "%s\\%s", sdk_path, filename) < 0) { + return false; + } + + *module = LoadLibraryExA(path, NULL, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); + return *module != NULL; +} + +static inline bool load_lib(unsigned int version) +{ + char sdk_path[MAX_PATH]; + + if (!nvafx_get_sdk_path(sdk_path, _countof(sdk_path))) + return false; + + if (!load_afx_module(&nv_audiofx, sdk_path, "NVAudioEffects.dll")) + return false; + + if (version < MIN_ARM_AFX_SDK_VERSION) + return true; + + if (!load_afx_module(&nv_denoiserfx, sdk_path, "nvafxdenoiser.dll") || + !load_afx_module(&nv_dereverbfx, sdk_path, "nvafxdereverb.dll") || + !load_afx_module(&nv_dereverbdenoiserfx, sdk_path, "nvafxdereverbdenoiser.dll")) { + return false; + } + + return true; +} + #endif diff --git a/plugins/nv-filters/nvidia-audiofx-filter.c b/plugins/nv-filters/nvidia-audiofx-filter.c index a9a776d13a46ba..4e2e1484de577b 100644 --- a/plugins/nv-filters/nvidia-audiofx-filter.c +++ b/plugins/nv-filters/nvidia-audiofx-filter.c @@ -49,8 +49,6 @@ #define ssize_t intptr_t #endif -bool nvafx_new_sdk = false; - struct nvidia_audio_data { obs_source_t *context; @@ -116,8 +114,9 @@ struct nvidia_audio_data { struct obs_audio_data output_audio; DARRAY(float) output_data; - /* Optimization for Voice Audio Data (VAD) ; requires SDK >= 0.7.6 */ + /* Optimization for Voice Audio Data (VAD) ; requires SDK >= 1.6.2 */ bool vad; + unsigned int sdk_version; }; static const char *nvidia_audio_name(void *unused) @@ -136,7 +135,7 @@ static void nvidia_audio_destroy(void *data) if (ng->nvidia_sdk_dir_found) pthread_mutex_lock(&ng->nvafx_mutex); - if (nvafx_new_sdk) + if (ng->sdk_version >= MIN_AFX_LOGGER_VERSION) NvAFX_UninitializeLogger(); for (size_t i = 0; i < ng->channels; i++) { @@ -180,32 +179,6 @@ bool nvidia_afx_loaded = false; #pragma warning(push) #pragma warning(disable : 4706) #endif -void release_afxlib(void) -{ - NvAFX_GetEffectList = NULL; - NvAFX_CreateEffect = NULL; - NvAFX_CreateChainedEffect = NULL; - NvAFX_DestroyEffect = NULL; - NvAFX_SetU32 = NULL; - NvAFX_SetU32List = NULL; - NvAFX_SetString = NULL; - NvAFX_SetStringList = NULL; - NvAFX_SetFloat = NULL; - NvAFX_SetFloatList = NULL; - NvAFX_GetU32 = NULL; - NvAFX_GetString = NULL; - NvAFX_GetStringList = NULL; - NvAFX_GetFloat = NULL; - NvAFX_GetFloatList = NULL; - NvAFX_Load = NULL; - NvAFX_GetSupportedDevices = NULL; - NvAFX_Run = NULL; - NvAFX_Reset = NULL; - if (nv_audiofx) { - FreeLibrary(nv_audiofx); - nv_audiofx = NULL; - } -} bool load_nvidia_afx(void) { @@ -224,9 +197,10 @@ bool load_nvidia_afx(void) (MIN_VFX_SDK_VERSION >> 16) & 0x00ff, (MIN_VFX_SDK_VERSION >> 8) & 0x0000ff); } } - if (!load_lib()) { + if (!load_lib(version)) { blog(LOG_INFO, "[NVIDIA Audio Effects:] NVIDIA denoiser disabled, redistributable not found or could not be loaded."); + release_afx_lib(); return false; } @@ -239,47 +213,24 @@ bool load_nvidia_afx(void) goto unload_everything; \ } -#define LOAD_SYM_FROM_LIB2(sym, lib, dll) \ - if (!(sym = (sym##_t)GetProcAddress(lib, #sym))) { \ - DWORD err = GetLastError(); \ - printf("[NVIDIA Audio Effects:]: Couldn't load " #sym " from " dll ": %lu (0x%lx)", err, err); \ - nvafx_new_sdk = false; \ - } else { \ - nvafx_new_sdk = true; \ - } - #define LOAD_SYM(sym) LOAD_SYM_FROM_LIB(sym, nv_audiofx, "NVAudioEffects.dll") - LOAD_SYM(NvAFX_GetEffectList); LOAD_SYM(NvAFX_CreateEffect); - LOAD_SYM(NvAFX_CreateChainedEffect); LOAD_SYM(NvAFX_DestroyEffect); LOAD_SYM(NvAFX_SetU32); - LOAD_SYM(NvAFX_SetU32List); LOAD_SYM(NvAFX_SetString); - LOAD_SYM(NvAFX_SetStringList); LOAD_SYM(NvAFX_SetFloat); - LOAD_SYM(NvAFX_SetFloatList); LOAD_SYM(NvAFX_GetU32); LOAD_SYM(NvAFX_GetString); - LOAD_SYM(NvAFX_GetStringList); LOAD_SYM(NvAFX_GetFloat); - LOAD_SYM(NvAFX_GetFloatList); LOAD_SYM(NvAFX_Load); LOAD_SYM(NvAFX_GetSupportedDevices); LOAD_SYM(NvAFX_Run); LOAD_SYM(NvAFX_Reset); -#undef LOAD_SYM -#define LOAD_SYM(sym) LOAD_SYM_FROM_LIB2(sym, nv_audiofx, "NVAudioEffects.dll") LOAD_SYM(NvAFX_InitializeLogger); - bool new_sdk = nvafx_new_sdk; LOAD_SYM(NvAFX_UninitializeLogger); - if (!nvafx_new_sdk || !new_sdk) { - blog(LOG_INFO, "[NVIDIA AUDIO FX]: SDK loaded but old redistributable detected. Please upgrade."); - nvafx_new_sdk = false; - } #undef LOAD_SYM - NvAFX_Status err; + NvAFX_Status err; NvAFX_Handle h = NULL; err = NvAFX_CreateEffect(NVAFX_EFFECT_DENOISER, &h); @@ -303,7 +254,7 @@ bool load_nvidia_afx(void) return true; unload_everything: - release_afxlib(); + release_afx_lib(); return false; } @@ -313,7 +264,7 @@ bool load_nvidia_afx(void) void unload_nvidia_afx(void) { - release_afxlib(); + release_afx_lib(); if (nvidia_afx_initializer_mutex_initialized) { pthread_mutex_destroy(&nvidia_afx_initializer_mutex); @@ -352,8 +303,9 @@ static bool nvidia_audio_initialize_internal(void *data) } // Set VAD (Voice Audio Data) - if (nvafx_new_sdk) { + if (get_lib_version() >= MIN_AFX_LOGGER_VERSION && strcmp(ng->fx, NVAFX_EFFECT_DEREVERB) != 0) { err = NvAFX_SetU32(ng->handle[i], NVAFX_PARAM_ENABLE_VAD, ng->vad); + if (err != NVAFX_STATUS_SUCCESS) { do_log(LOG_ERROR, "NvAFX_SetU32(VAD: %i) failed, error %i", ng->vad, err); goto failure; @@ -415,7 +367,10 @@ static void *nvidia_audio_initialize(void *data) do_log(LOG_ERROR, "The number of channels is not 1 in the sdk any more ==> update code"); goto failure; } - NvAFX_Status err = NvAFX_GetU32(ng->handle[0], NVAFX_PARAM_NUM_INPUT_SAMPLES_PER_FRAME, + bool updated_string = ng->sdk_version >= MIN_ARM_AFX_SDK_VERSION; + NvAFX_Status err = NvAFX_GetU32(ng->handle[0], + updated_string ? NVAFX_PARAM_NUM_SAMPLES_PER_INPUT_FRAME + : NVAFX_PARAM_NUM_INPUT_SAMPLES_PER_FRAME, &ng->num_samples_per_frame); if (err != NVAFX_STATUS_SUCCESS) { do_log(LOG_ERROR, "NvAFX_GetU32() failed to get the number of samples per frame, error %i", @@ -529,7 +484,7 @@ static void nvidia_audio_update(void *data, obs_data_t *s) pthread_mutex_unlock(&ng->nvafx_mutex); } /* updating for VAD toggled on or off */ - if (nvafx_new_sdk) { + if (ng->sdk_version >= MIN_AFX_LOGGER_VERSION && strcmp(ng->fx, NVAFX_EFFECT_DEREVERB) != 0) { if (vad != ng->vad && (strcmp(ng->fx, method) == 0)) { NvAFX_Status err; ng->vad = vad; @@ -599,7 +554,7 @@ static void *nvidia_audio_create(obs_data_t *settings, obs_source_t *filter) ng->nvafx_initialized = false; ng->nvafx_loading = false; ng->fx = NULL; - + ng->sdk_version = get_lib_version(); pthread_mutex_init(&ng->nvafx_mutex, NULL); info("NVAFX SDK redist path was found here %s", sdk_path); @@ -656,7 +611,7 @@ static void *nvidia_audio_create(obs_data_t *settings, obs_source_t *filter) nvidia_audio_update(ng, settings); /* Setup NVIDIA logger */ - if (nvafx_new_sdk) { + if (ng->sdk_version >= MIN_AFX_LOGGER_VERSION) { NvAFX_Status err = NvAFX_InitializeLogger(NVAFX_LOG_LEVEL_ERROR, LOG_TARGET_CALLBACK, NULL, &nvafx_logger_callback, ng); if (err != NVAFX_STATUS_SUCCESS) { @@ -853,10 +808,23 @@ static void nvidia_audio_defaults(obs_data_t *s) { obs_data_set_default_double(s, S_NVAFX_INTENSITY, 1.0); obs_data_set_default_string(s, S_METHOD, S_METHOD_NVAFX_DENOISER); - if (nvafx_new_sdk) + if (get_lib_version() >= MIN_AFX_LOGGER_VERSION) obs_data_set_default_bool(s, S_NVAFX_VAD, 1); } +static bool nvidia_audio_method_modified(void *data, obs_properties_t *props, obs_property_t *property, + obs_data_t *settings) +{ + const struct nvidia_audio_data *ng = data; + const char *method = obs_data_get_string(settings, S_METHOD); + + bool visible = ng->sdk_version >= MIN_AFX_LOGGER_VERSION && (strcmp(method, S_METHOD_NVAFX_DEREVERB) != 0); + obs_property_set_visible(obs_properties_get(props, S_NVAFX_VAD), visible); + + UNUSED_PARAMETER(property); + return true; +} + static obs_properties_t *nvidia_audio_properties(void *data) { obs_properties_t *ppts = obs_properties_create(); @@ -870,9 +838,8 @@ static obs_properties_t *nvidia_audio_properties(void *data) S_METHOD_NVAFX_DEREVERB_DENOISER); obs_property_t *slider = obs_properties_add_float_slider(ppts, S_NVAFX_INTENSITY, TEXT_NVAFX_INTENSITY, 0.0f, 1.0f, 0.01f); - obs_property_t *vad = obs_properties_add_bool(ppts, S_NVAFX_VAD, TEXT_NVAFX_VAD); - if (!nvafx_new_sdk) - obs_property_set_visible(vad, 0); + obs_properties_add_bool(ppts, S_NVAFX_VAD, TEXT_NVAFX_VAD); + obs_property_set_modified_callback2(method, nvidia_audio_method_modified, ng); unsigned int version = get_lib_version(); obs_property_t *warning = obs_properties_add_text(ppts, "deprecation", NULL, OBS_TEXT_INFO); diff --git a/plugins/nv-filters/nvidia-videofx-filter.c b/plugins/nv-filters/nvidia-videofx-filter.c index 15341927fe7383..24289c6567ebe7 100644 --- a/plugins/nv-filters/nvidia-videofx-filter.c +++ b/plugins/nv-filters/nvidia-videofx-filter.c @@ -48,7 +48,6 @@ enum nvvfx_fx_id { S_FX_AIGS, S_FX_BLUR, S_FX_BG_BLUR }; bool nvvfx_loaded = false; -bool nvvfx_new_sdk = false; /* clang-format off */ struct nvvfx_data { @@ -317,7 +316,6 @@ static void *nvvfx_filter_create(obs_data_t *settings, obs_source_t *context, en uint8_t minor = (filter->version >> 16) & 0x00ff; uint8_t build = (filter->version >> 8) & 0x0000ff; uint8_t revision = (filter->version >> 0) & 0x000000ff; - nvvfx_new_sdk = filter->version >= MIN_VFX_SDK_VERSION && nvvfx_new_sdk; } #endif /* 1. Create FX */ @@ -343,7 +341,7 @@ static void *nvvfx_filter_create(obs_data_t *settings, obs_source_t *context, en obs_leave_graphics(); /* 4. Allocate state for the AIGS & background blur */ - if (nvvfx_new_sdk && id != S_FX_BLUR) { + if (get_lib_version() >= MIN_VFX_LOGGER_VERSION && id != S_FX_BLUR) { vfxErr = NvVFX_AllocateState(filter->handle, &filter->stateObjectHandle); if (NVCV_SUCCESS != vfxErr) return log_nverror_destroy(filter, vfxErr); @@ -360,7 +358,7 @@ static void *nvvfx_filter_create(obs_data_t *settings, obs_source_t *context, en nvvfx_filter_update(filter, settings); /* Setup NVIDIA logger */ - if (nvvfx_new_sdk) + if (get_lib_version() >= MIN_VFX_LOGGER_VERSION) vfxErr = NvVFX_ConfigureLogger(NVCV_LOG_ERROR, NULL, &nvvfx_logger_callback, filter); return filter; @@ -1087,7 +1085,6 @@ static void nvvfx_filter_defaults(obs_data_t *settings) bool load_nvidia_vfx(void) { - bool old_sdk_loaded = false; unsigned int version = get_lib_version(); uint8_t major = (version >> 24) & 0xff; uint8_t minor = (version >> 16) & 0x00ff; @@ -1101,7 +1098,7 @@ bool load_nvidia_vfx(void) "[NVIDIA VIDEO FX]: NVIDIA VIDEO Effects SDK is outdated. Please update both audio & video SDK."); } } - if (!load_nv_vfx_libs()) { + if (!load_nv_vfx_libs(version)) { blog(LOG_INFO, "[NVIDIA VIDEO FX]: FX disabled, redistributable not found or could not be loaded."); return false; } @@ -1110,19 +1107,9 @@ bool load_nvidia_vfx(void) if (!(sym = (sym##_t)GetProcAddress(lib, #sym))) { \ DWORD err = GetLastError(); \ printf("[NVIDIA VIDEO FX]: Couldn't load " #sym " from " dll ": %lu (0x%lx)", err, err); \ - release_nv_vfx(); \ goto unload_everything; \ } -#define LOAD_SYM_FROM_LIB2(sym, lib, dll) \ - if (!(sym = (sym##_t)GetProcAddress(lib, #sym))) { \ - DWORD err = GetLastError(); \ - printf("[NVIDIA VIDEO FX]: Couldn't load " #sym " from " dll ": %lu (0x%lx)", err, err); \ - nvvfx_new_sdk = false; \ - } else { \ - nvvfx_new_sdk = true; \ - } - #define LOAD_SYM(sym) LOAD_SYM_FROM_LIB(sym, nv_videofx, "NVVideoEffects.dll") LOAD_SYM(NvVFX_GetVersion); LOAD_SYM(NvVFX_CreateEffect); @@ -1153,42 +1140,20 @@ bool load_nvidia_vfx(void) LOAD_SYM(NvVFX_AllocateState); LOAD_SYM(NvVFX_DeallocateState); LOAD_SYM(NvVFX_ResetState); - old_sdk_loaded = true; + LOAD_SYM(NvVFX_ConfigureLogger); #undef LOAD_SYM #define LOAD_SYM(sym) LOAD_SYM_FROM_LIB(sym, nv_cvimage, "NVCVImage.dll") LOAD_SYM(NvCV_GetErrorStringFromCode); LOAD_SYM(NvCVImage_Init); - LOAD_SYM(NvCVImage_InitView); LOAD_SYM(NvCVImage_Alloc); LOAD_SYM(NvCVImage_Realloc); - LOAD_SYM(NvCVImage_Dealloc); LOAD_SYM(NvCVImage_Create); LOAD_SYM(NvCVImage_Destroy); - LOAD_SYM(NvCVImage_ComponentOffsets); LOAD_SYM(NvCVImage_Transfer); - LOAD_SYM(NvCVImage_TransferRect); - LOAD_SYM(NvCVImage_TransferFromYUV); - LOAD_SYM(NvCVImage_TransferToYUV); LOAD_SYM(NvCVImage_MapResource); LOAD_SYM(NvCVImage_UnmapResource); - LOAD_SYM(NvCVImage_Composite); - LOAD_SYM(NvCVImage_CompositeRect); - LOAD_SYM(NvCVImage_CompositeOverConstant); - LOAD_SYM(NvCVImage_FlipY); - LOAD_SYM(NvCVImage_GetYUVPointers); LOAD_SYM(NvCVImage_InitFromD3D11Texture); - LOAD_SYM(NvCVImage_ToD3DFormat); - LOAD_SYM(NvCVImage_FromD3DFormat); - LOAD_SYM(NvCVImage_ToD3DColorSpace); - LOAD_SYM(NvCVImage_FromD3DColorSpace); -#undef LOAD_SYM - -#define LOAD_SYM(sym) LOAD_SYM_FROM_LIB2(sym, nv_videofx, "NVVideoEffects.dll") - LOAD_SYM(NvVFX_ConfigureLogger); - if (!nvvfx_new_sdk) { - blog(LOG_INFO, "[NVIDIA VIDEO FX]: SDK loaded but old redistributable detected. Please upgrade."); - } #undef LOAD_SYM int err; @@ -1212,13 +1177,13 @@ bool load_nvidia_vfx(void) unload_everything: nvvfx_loaded = false; blog(LOG_INFO, "[NVIDIA VIDEO FX]: disabled, redistributable not found"); - release_nv_vfx(); + release_vfx_lib(); return false; } void unload_nvidia_vfx(void) { - release_nv_vfx(); + release_vfx_lib(); } struct obs_source_info nvidia_greenscreen_filter_info = { diff --git a/plugins/nv-filters/nvvfx-load.h b/plugins/nv-filters/nvvfx-load.h index e27ad1e62afda4..04a5d7f402ad20 100644 --- a/plugins/nv-filters/nvvfx-load.h +++ b/plugins/nv-filters/nvvfx-load.h @@ -37,13 +37,11 @@ extern "C" { #endif // _WIN32 or linux #endif //NvCV_API -#define CUDARTAPI - #ifdef LIBNVVFX_ENABLED static HMODULE nv_videofx = NULL; static HMODULE nv_cvimage = NULL; -static HMODULE nv_cudart = NULL; -static HMODULE nv_cuda = NULL; +static HMODULE nv_greenscreen = NULL; +static HMODULE nv_blur = NULL; //! Status codes returned from APIs. typedef enum NvCV_Status { @@ -392,142 +390,6 @@ typedef NvCV_Status NvCV_API (*NvCVImage_FromD3DColorSpace_t)(DXGI_COLOR_SPACE_T typedef NvCV_Status NvCV_API (*NvCVImage_InitFromD3D11Texture_t)(NvCVImage *im, struct ID3D11Texture2D *tx); typedef NvCV_Status NvCV_API (*NvCVImage_InitFromD3DTexture_t)(NvCVImage *im, struct ID3D11Texture2D *tx); -/* cuda runtime */ -typedef enum cudaError { - cudaSuccess = 0, - cudaErrorInvalidValue = 1, - cudaErrorMemoryAllocation = 2, - cudaErrorInitializationError = 3, - cudaErrorCudartUnloading = 4, - cudaErrorProfilerDisabled = 5, - cudaErrorProfilerNotInitialized = 6, - cudaErrorProfilerAlreadyStarted = 7, - cudaErrorProfilerAlreadyStopped = 8, - cudaErrorInvalidConfiguration = 9, - cudaErrorInvalidPitchValue = 12, - cudaErrorInvalidSymbol = 13, - cudaErrorInvalidHostPointer = 16, - cudaErrorInvalidDevicePointer = 17, - cudaErrorInvalidTexture = 18, - cudaErrorInvalidTextureBinding = 19, - cudaErrorInvalidChannelDescriptor = 20, - cudaErrorInvalidMemcpyDirection = 21, - cudaErrorAddressOfConstant = 22, - cudaErrorTextureFetchFailed = 23, - cudaErrorTextureNotBound = 24, - cudaErrorSynchronizationError = 25, - cudaErrorInvalidFilterSetting = 26, - cudaErrorInvalidNormSetting = 27, - cudaErrorMixedDeviceExecution = 28, - cudaErrorNotYetImplemented = 31, - cudaErrorMemoryValueTooLarge = 32, - cudaErrorStubLibrary = 34, - cudaErrorInsufficientDriver = 35, - cudaErrorCallRequiresNewerDriver = 36, - cudaErrorInvalidSurface = 37, - cudaErrorDuplicateVariableName = 43, - cudaErrorDuplicateTextureName = 44, - cudaErrorDuplicateSurfaceName = 45, - cudaErrorDevicesUnavailable = 46, - cudaErrorIncompatibleDriverContext = 49, - cudaErrorMissingConfiguration = 52, - cudaErrorPriorLaunchFailure = 53, - cudaErrorLaunchMaxDepthExceeded = 65, - cudaErrorLaunchFileScopedTex = 66, - cudaErrorLaunchFileScopedSurf = 67, - cudaErrorSyncDepthExceeded = 68, - cudaErrorLaunchPendingCountExceeded = 69, - cudaErrorInvalidDeviceFunction = 98, - cudaErrorNoDevice = 100, - cudaErrorInvalidDevice = 101, - cudaErrorDeviceNotLicensed = 102, - cudaErrorSoftwareValidityNotEstablished = 103, - cudaErrorStartupFailure = 127, - cudaErrorInvalidKernelImage = 200, - cudaErrorDeviceUninitialized = 201, - cudaErrorMapBufferObjectFailed = 205, - cudaErrorUnmapBufferObjectFailed = 206, - cudaErrorArrayIsMapped = 207, - cudaErrorAlreadyMapped = 208, - cudaErrorNoKernelImageForDevice = 209, - cudaErrorAlreadyAcquired = 210, - cudaErrorNotMapped = 211, - cudaErrorNotMappedAsArray = 212, - cudaErrorNotMappedAsPointer = 213, - cudaErrorECCUncorrectable = 214, - cudaErrorUnsupportedLimit = 215, - cudaErrorDeviceAlreadyInUse = 216, - cudaErrorPeerAccessUnsupported = 217, - cudaErrorInvalidPtx = 218, - cudaErrorInvalidGraphicsContext = 219, - cudaErrorNvlinkUncorrectable = 220, - cudaErrorJitCompilerNotFound = 221, - cudaErrorUnsupportedPtxVersion = 222, - cudaErrorJitCompilationDisabled = 223, - cudaErrorInvalidSource = 300, - cudaErrorFileNotFound = 301, - cudaErrorSharedObjectSymbolNotFound = 302, - cudaErrorSharedObjectInitFailed = 303, - cudaErrorOperatingSystem = 304, - cudaErrorInvalidResourceHandle = 400, - cudaErrorIllegalState = 401, - cudaErrorSymbolNotFound = 500, - cudaErrorNotReady = 600, - cudaErrorIllegalAddress = 700, - cudaErrorLaunchOutOfResources = 701, - cudaErrorLaunchTimeout = 702, - cudaErrorLaunchIncompatibleTexturing = 703, - cudaErrorPeerAccessAlreadyEnabled = 704, - cudaErrorPeerAccessNotEnabled = 705, - cudaErrorSetOnActiveProcess = 708, - cudaErrorContextIsDestroyed = 709, - cudaErrorAssert = 710, - cudaErrorTooManyPeers = 711, - cudaErrorHostMemoryAlreadyRegistered = 712, - cudaErrorHostMemoryNotRegistered = 713, - cudaErrorHardwareStackError = 714, - cudaErrorIllegalInstruction = 715, - cudaErrorMisalignedAddress = 716, - cudaErrorInvalidAddressSpace = 717, - cudaErrorInvalidPc = 718, - cudaErrorLaunchFailure = 719, - cudaErrorCooperativeLaunchTooLarge = 720, - cudaErrorNotPermitted = 800, - cudaErrorNotSupported = 801, - cudaErrorSystemNotReady = 802, - cudaErrorSystemDriverMismatch = 803, - cudaErrorCompatNotSupportedOnDevice = 804, - cudaErrorStreamCaptureUnsupported = 900, - cudaErrorStreamCaptureInvalidated = 901, - cudaErrorStreamCaptureMerge = 902, - cudaErrorStreamCaptureUnmatched = 903, - cudaErrorStreamCaptureUnjoined = 904, - cudaErrorStreamCaptureIsolation = 905, - cudaErrorStreamCaptureImplicit = 906, - cudaErrorCapturedEvent = 907, - cudaErrorStreamCaptureWrongThread = 908, - cudaErrorTimeout = 909, - cudaErrorGraphExecUpdateFailure = 910, - cudaErrorUnknown = 999, - cudaErrorApiFailureBase = 10000 -} cudaError; - -typedef enum cudaMemcpyKind { - cudaMemcpyHostToHost = 0, /**< Host -> Host */ - cudaMemcpyHostToDevice = 1, /**< Host -> Device */ - cudaMemcpyDeviceToHost = 2, /**< Device -> Host */ - cudaMemcpyDeviceToDevice = 3, /**< Device -> Device */ - cudaMemcpyDefault = 4 -} cudaMemcpyKind; - -typedef enum cudaError cudaError_t; - -typedef cudaError_t CUDARTAPI (*cudaMalloc_t)(void **devPtr, size_t size); -typedef cudaError_t CUDARTAPI (*cudaStreamSynchronize_t)(CUstream stream); -typedef cudaError_t CUDARTAPI (*cudaFree_t)(void *devPtr); -typedef cudaError_t CUDARTAPI (*cudaMemsetAsync_t)(void *devPtr, int value, size_t count, CUstream stream); -typedef cudaError_t CUDARTAPI (*cudaMemcpy_t)(void *dst, const void *src, size_t count, enum cudaMemcpyKind kind); - /* NVVFX */ static NvVFX_GetVersion_t NvVFX_GetVersion = NULL; static NvVFX_CreateEffect_t NvVFX_CreateEffect = NULL; @@ -569,38 +431,17 @@ static NvCVImage_Init_t NvCVImage_Init = NULL; static NvCVImage_InitView_t NvCVImage_InitView = NULL; static NvCVImage_Alloc_t NvCVImage_Alloc = NULL; static NvCVImage_Realloc_t NvCVImage_Realloc = NULL; -static NvCVImage_Dealloc_t NvCVImage_Dealloc = NULL; static NvCVImage_Create_t NvCVImage_Create = NULL; static NvCVImage_Destroy_t NvCVImage_Destroy = NULL; -static NvCVImage_ComponentOffsets_t NvCVImage_ComponentOffsets = NULL; static NvCVImage_Transfer_t NvCVImage_Transfer = NULL; -static NvCVImage_TransferRect_t NvCVImage_TransferRect = NULL; -static NvCVImage_TransferFromYUV_t NvCVImage_TransferFromYUV = NULL; -static NvCVImage_TransferToYUV_t NvCVImage_TransferToYUV = NULL; static NvCVImage_MapResource_t NvCVImage_MapResource = NULL; static NvCVImage_UnmapResource_t NvCVImage_UnmapResource = NULL; -static NvCVImage_Composite_t NvCVImage_Composite = NULL; -static NvCVImage_CompositeRect_t NvCVImage_CompositeRect = NULL; -static NvCVImage_CompositeOverConstant_t NvCVImage_CompositeOverConstant = NULL; -static NvCVImage_FlipY_t NvCVImage_FlipY = NULL; -static NvCVImage_GetYUVPointers_t NvCVImage_GetYUVPointers = NULL; /* nvcvimage D3D*/ -static NvCVImage_ToD3DFormat_t NvCVImage_ToD3DFormat = NULL; -static NvCVImage_FromD3DFormat_t NvCVImage_FromD3DFormat = NULL; -static NvCVImage_ToD3DColorSpace_t NvCVImage_ToD3DColorSpace = NULL; -static NvCVImage_FromD3DColorSpace_t NvCVImage_FromD3DColorSpace = NULL; static NvCVImage_InitFromD3D11Texture_t NvCVImage_InitFromD3D11Texture = NULL; /* error codes */ static NvCV_GetErrorStringFromCode_t NvCV_GetErrorStringFromCode = NULL; -/* cuda runtime */ -static cudaMalloc_t cudaMalloc = NULL; -static cudaStreamSynchronize_t cudaStreamSynchronize = NULL; -static cudaFree_t cudaFree = NULL; -static cudaMemcpy_t cudaMemcpy = NULL; -static cudaMemsetAsync_t cudaMemsetAsync = NULL; - -static inline void release_nv_vfx() +static inline void release_vfx_lib(void) { NvVFX_CreateEffect = NULL; NvVFX_CudaStreamCreate = NULL; @@ -638,33 +479,27 @@ static inline void release_nv_vfx() nv_videofx = NULL; } NvCVImage_Alloc = NULL; - NvCVImage_ComponentOffsets = NULL; - NvCVImage_Composite = NULL; - NvCVImage_CompositeRect = NULL; - NvCVImage_CompositeOverConstant = NULL; NvCVImage_Create = NULL; - NvCVImage_Dealloc = NULL; NvCVImage_Destroy = NULL; NvCVImage_Init = NULL; NvCVImage_InitView = NULL; NvCVImage_Realloc = NULL; NvCVImage_Transfer = NULL; - NvCVImage_TransferRect = NULL; - NvCVImage_TransferFromYUV = NULL; - NvCVImage_TransferToYUV = NULL; NvCVImage_MapResource = NULL; NvCVImage_UnmapResource = NULL; NvCVImage_InitFromD3D11Texture = NULL; - NvCVImage_FlipY = NULL; - NvCVImage_GetYUVPointers = NULL; - NvCVImage_ToD3DFormat = NULL; - NvCVImage_FromD3DFormat = NULL; - NvCVImage_ToD3DColorSpace = NULL; - NvCVImage_FromD3DColorSpace = NULL; if (nv_cvimage) { FreeLibrary(nv_cvimage); nv_cvimage = NULL; } + if (nv_greenscreen) { + FreeLibrary(nv_greenscreen); + nv_greenscreen = NULL; + } + if (nv_blur) { + FreeLibrary(nv_blur); + nv_blur = NULL; + } } static inline bool nvvfx_get_sdk_path(char *buffer, const size_t len) @@ -688,31 +523,39 @@ static inline bool nvvfx_get_sdk_path(char *buffer, const size_t len) return true; } -static inline bool load_nv_vfx_libs() +static inline bool load_vfx_module(HMODULE *module, const char *sdk_path, const char *filename) { - char sdkPath[MAX_PATH]; - char effectsPath[MAX_PATH]; - char imagePath[MAX_PATH]; + char path[MAX_PATH]; - if (!nvvfx_get_sdk_path(sdkPath, MAX_PATH)) { + if (_snprintf_s(path, _countof(path), _TRUNCATE, "%s\\%s", sdk_path, filename) == -1) return false; - } - if (_snprintf_s(effectsPath, _countof(effectsPath), _TRUNCATE, "%s\\NVVideoEffects.dll", sdkPath) == -1) { + *module = LoadLibraryExA(path, NULL, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); + return *module != NULL; +} + +static inline bool load_nv_vfx_libs(unsigned int version) +{ + char sdk_path[MAX_PATH]; + + if (!nvvfx_get_sdk_path(sdk_path, MAX_PATH)) return false; - } - if (_snprintf_s(imagePath, _countof(imagePath), _TRUNCATE, "%s\\NVCVImage.dll", sdkPath) == -1) { + if (!load_vfx_module(&nv_cvimage, sdk_path, "NVCVImage.dll") || + !load_vfx_module(&nv_videofx, sdk_path, "NVVideoEffects.dll")) { + release_vfx_lib(); return false; } - nv_videofx = - LoadLibraryExA(effectsPath, NULL, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); + if (version < MIN_ARM_VFX_SDK_VERSION) + return true; - nv_cvimage = - LoadLibraryExA(imagePath, NULL, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); - - return !!nv_videofx && !!nv_cvimage; + if (!load_vfx_module(&nv_greenscreen, sdk_path, "nvVFXGreenScreen.dll") || + !load_vfx_module(&nv_blur, sdk_path, "nvVFXBackgroundBlur.dll")) { + release_vfx_lib(); + return false; + } + return true; } static unsigned int get_lib_version(void)