Skip to content

Commit

Permalink
obs-ffmpeg: Replace NVENC FFmpeg fallback with native encoder
Browse files Browse the repository at this point in the history
  • Loading branch information
derrod committed Jan 21, 2024
1 parent fb8d228 commit 53c8b5e
Show file tree
Hide file tree
Showing 3 changed files with 455 additions and 75 deletions.
72 changes: 68 additions & 4 deletions plugins/obs-ffmpeg/obs-nvenc-helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
#include <util/pipe.h>

static void *nvenc_lib = NULL;
static void *cuda_lib = NULL;
static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
NV_ENCODE_API_FUNCTION_LIST nv = {NV_ENCODE_API_FUNCTION_LIST_VER};
NV_CREATE_INSTANCE_FUNC nv_create_instance = NULL;
CudaFunctions *cu = NULL;

#define error(format, ...) blog(LOG_ERROR, "[obs-nvenc] " format, ##__VA_ARGS__)

Expand Down Expand Up @@ -113,6 +115,21 @@ static void *load_nv_func(const char *func)
return func_ptr;
}

bool load_cuda_lib(void)
{
cuda_lib = os_dlopen("nvcuda.dll");
return cuda_lib != NULL;
}

static void *load_cuda_func(const char *func)
{
void *func_ptr = os_dlsym(cuda_lib, func);
if (!func_ptr) {
error("Could not load function: %s", func);
}
return func_ptr;
}

typedef NVENCSTATUS(NVENCAPI *NV_MAX_VER_FUNC)(uint32_t *);

uint32_t get_nvenc_ver(void)
Expand Down Expand Up @@ -227,6 +244,32 @@ static inline bool init_nvenc_internal(obs_encoder_t *encoder)
return true;
}

static inline bool init_cuda_internal(obs_encoder_t *encoder)
{
static bool initialized = false;
static bool success = false;

if (initialized)
return success;
initialized = true;

if (!load_cuda_lib()) {
obs_encoder_set_last_error(encoder,
"Loading CUDA library failed.");
return false;
}

cu = bzalloc(sizeof(CudaFunctions));
cu->cuInit = (tcuInit *)load_cuda_func("cuInit");
cu->cuDeviceGetCount = (tcuDeviceGetCount *)load_cuda_func("cuDeviceGetCount");
cu->cuDeviceGet = (tcuDeviceGet *)load_cuda_func("cuDeviceGet");
cu->cuCtxCreate = (tcuCtxCreate_v2 *)load_cuda_func("cuCtxCreate_v2");
cu->cuCtxDestroy = (tcuCtxDestroy_v2 *)load_cuda_func("cuCtxDestroy_v2");

success = true;
return true;
}

bool init_nvenc(obs_encoder_t *encoder)
{
bool success;
Expand All @@ -238,11 +281,25 @@ bool init_nvenc(obs_encoder_t *encoder)
return success;
}

bool init_cuda(obs_encoder_t *encoder)
{
bool success;

pthread_mutex_lock(&init_mutex);
success = init_cuda_internal(encoder);
pthread_mutex_unlock(&init_mutex);

return success;
}

extern struct obs_encoder_info h264_nvenc_info;
extern struct obs_encoder_info h264_nvenc_soft_info;
#ifdef ENABLE_HEVC
extern struct obs_encoder_info hevc_nvenc_info;
extern struct obs_encoder_info hevc_nvenc_soft_info;
#endif
extern struct obs_encoder_info av1_nvenc_info;
extern struct obs_encoder_info av1_nvenc_soft_info;

static bool enum_luids(void *param, uint32_t idx, uint64_t luid)
{
Expand Down Expand Up @@ -323,19 +380,26 @@ static bool av1_supported(void)
void obs_nvenc_load(bool h264, bool hevc, bool av1)
{
pthread_mutex_init(&init_mutex, NULL);
if (h264)
if (h264) {
obs_register_encoder(&h264_nvenc_info);
obs_register_encoder(&h264_nvenc_soft_info);
}
#ifdef ENABLE_HEVC
if (hevc)
if (hevc) {
obs_register_encoder(&hevc_nvenc_info);
obs_register_encoder(&hevc_nvenc_soft_info);
}
#endif
if (av1 && av1_supported())
if (av1 && av1_supported()) {
obs_register_encoder(&av1_nvenc_info);
else
obs_register_encoder(&av1_nvenc_soft_info);
} else {
blog(LOG_WARNING, "[NVENC] AV1 is not supported");
}
}

void obs_nvenc_unload(void)
{
bfree(cu);
pthread_mutex_destroy(&init_mutex);
}
Loading

0 comments on commit 53c8b5e

Please sign in to comment.