From 617086b040886fab40b64f584f563e9cd186e225 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Tue, 9 Jul 2019 08:44:04 -0700 Subject: [PATCH] obs-ffmpeg: Separate logging code Cleans up obs-ffmpeg.c and separates all the logging code to a different file, which can be enabled with ENABLE_FFMPEG_LOGGING. --- plugins/obs-ffmpeg/CMakeLists.txt | 16 +++ plugins/obs-ffmpeg/obs-ffmpeg-config.h.in | 17 +++ plugins/obs-ffmpeg/obs-ffmpeg-logging.c | 138 ++++++++++++++++++++++ plugins/obs-ffmpeg/obs-ffmpeg.c | 135 ++------------------- 4 files changed, 184 insertions(+), 122 deletions(-) create mode 100644 plugins/obs-ffmpeg/obs-ffmpeg-config.h.in create mode 100644 plugins/obs-ffmpeg/obs-ffmpeg-logging.c diff --git a/plugins/obs-ffmpeg/CMakeLists.txt b/plugins/obs-ffmpeg/CMakeLists.txt index 34d08b005..17365ef69 100644 --- a/plugins/obs-ffmpeg/CMakeLists.txt +++ b/plugins/obs-ffmpeg/CMakeLists.txt @@ -5,10 +5,20 @@ if(MSVC) w32-pthreads) endif() +option(ENABLE_FFMPEG_LOGGING "Enables obs-ffmpeg logging" OFF) + find_package(FFmpeg REQUIRED COMPONENTS avcodec avfilter avdevice avutil swscale avformat swresample) include_directories(${FFMPEG_INCLUDE_DIRS}) +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/obs-ffmpeg-config.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/obs-ffmpeg-config.h") +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +set(obs-ffmpeg_config_HEADERS + "${CMAKE_CURRENT_BINARY_DIR}/obs-ffmpeg-config.h") + set(obs-ffmpeg_HEADERS obs-ffmpeg-formats.h obs-ffmpeg-compat.h @@ -29,6 +39,11 @@ if(UNIX AND NOT APPLE) ${LIBVA_LBRARIES}) endif() +if(ENABLE_FFMPEG_LOGGING) + list(APPEND obs-ffmpeg_SOURCES + obs-ffmpeg-logging.c) +endif() + if(WIN32) list(APPEND obs-ffmpeg_SOURCES jim-nvenc.c @@ -38,6 +53,7 @@ if(WIN32) endif() add_library(obs-ffmpeg MODULE + ${obs-ffmpeg_config_HEADERS} ${obs-ffmpeg_HEADERS} ${obs-ffmpeg_SOURCES}) target_link_libraries(obs-ffmpeg diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-config.h.in b/plugins/obs-ffmpeg/obs-ffmpeg-config.h.in new file mode 100644 index 000000000..8f528b10a --- /dev/null +++ b/plugins/obs-ffmpeg/obs-ffmpeg-config.h.in @@ -0,0 +1,17 @@ +#ifndef ON +#define ON 1 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef OFF +#define OFF 0 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define ENABLE_FFMPEG_LOGGING @ENABLE_FFMPEG_LOGGING@ diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-logging.c b/plugins/obs-ffmpeg/obs-ffmpeg-logging.c new file mode 100644 index 000000000..4a45a1283 --- /dev/null +++ b/plugins/obs-ffmpeg/obs-ffmpeg-logging.c @@ -0,0 +1,138 @@ +#include +#include +#include +#include + +static DARRAY(struct log_context { + void *context; + char str[4096]; + int print_prefix; +} *) active_log_contexts; +static DARRAY(struct log_context *) cached_log_contexts; +pthread_mutex_t log_contexts_mutex = PTHREAD_MUTEX_INITIALIZER; + +static struct log_context *create_or_fetch_log_context(void *context) +{ + pthread_mutex_lock(&log_contexts_mutex); + for (size_t i = 0; i < active_log_contexts.num; i++) { + if (context == active_log_contexts.array[i]->context) { + pthread_mutex_unlock(&log_contexts_mutex); + return active_log_contexts.array[i]; + } + } + + struct log_context *new_log_context = NULL; + + size_t cnt = cached_log_contexts.num; + if (!!cnt) { + new_log_context = cached_log_contexts.array[cnt - 1]; + da_pop_back(cached_log_contexts); + } + + if (!new_log_context) + new_log_context = bzalloc(sizeof(struct log_context)); + + new_log_context->context = context; + new_log_context->str[0] = '\0'; + new_log_context->print_prefix = 1; + + da_push_back(active_log_contexts, &new_log_context); + + pthread_mutex_unlock(&log_contexts_mutex); + + return new_log_context; +} + +static void destroy_log_context(struct log_context *log_context) +{ + pthread_mutex_lock(&log_contexts_mutex); + da_erase_item(active_log_contexts, &log_context); + da_push_back(cached_log_contexts, &log_context); + pthread_mutex_unlock(&log_contexts_mutex); +} + +static void ffmpeg_log_callback(void *context, int level, const char *format, + va_list args) +{ + if (format == NULL) + return; + + struct log_context *log_context = create_or_fetch_log_context(context); + + char *str = log_context->str; + + av_log_format_line(context, level, format, args, str + strlen(str), + (int)(sizeof(log_context->str) - strlen(str)), + &log_context->print_prefix); + + int obs_level; + switch (level) { + case AV_LOG_PANIC: + case AV_LOG_FATAL: + obs_level = LOG_ERROR; + break; + case AV_LOG_ERROR: + case AV_LOG_WARNING: + obs_level = LOG_WARNING; + break; + case AV_LOG_INFO: + case AV_LOG_VERBOSE: + obs_level = LOG_INFO; + break; + case AV_LOG_DEBUG: + default: + obs_level = LOG_DEBUG; + } + + if (!log_context->print_prefix) + return; + + char *str_end = str + strlen(str) - 1; + while (str < str_end) { + if (*str_end != '\n') + break; + *str_end-- = '\0'; + } + + if (str_end <= str) + goto cleanup; + + blog(obs_level, "[ffmpeg] %s", str); + +cleanup: + destroy_log_context(log_context); +} + +static bool logging_initialized = false; + +void obs_ffmpeg_load_logging(void) +{ + da_init(active_log_contexts); + da_init(cached_log_contexts); + + if (pthread_mutex_init(&log_contexts_mutex, NULL) == 0) { + av_log_set_callback(ffmpeg_log_callback); + logging_initialized = true; + } +} + +void obs_ffmpeg_unload_logging(void) +{ + if (!logging_initialized) + return; + + logging_initialized = false; + + av_log_set_callback(av_log_default_callback); + pthread_mutex_destroy(&log_contexts_mutex); + + for (size_t i = 0; i < active_log_contexts.num; i++) { + bfree(active_log_contexts.array[i]); + } + for (size_t i = 0; i < cached_log_contexts.num; i++) { + bfree(cached_log_contexts.array[i]); + } + + da_free(active_log_contexts); + da_free(cached_log_contexts); +} diff --git a/plugins/obs-ffmpeg/obs-ffmpeg.c b/plugins/obs-ffmpeg/obs-ffmpeg.c index eef8da2d2..6f850297c 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg.c +++ b/plugins/obs-ffmpeg/obs-ffmpeg.c @@ -1,11 +1,10 @@ #include -#include #include -#include #include #include #include -#include + +#include "obs-ffmpeg-config.h" #ifdef _WIN32 #include @@ -36,106 +35,6 @@ extern struct obs_encoder_info nvenc_encoder_info; extern struct obs_encoder_info vaapi_encoder_info; #endif -static DARRAY(struct log_context { - void *context; - char str[4096]; - int print_prefix; -} *) active_log_contexts; -static DARRAY(struct log_context *) cached_log_contexts; -pthread_mutex_t log_contexts_mutex = PTHREAD_MUTEX_INITIALIZER; - -static struct log_context *create_or_fetch_log_context(void *context) -{ - pthread_mutex_lock(&log_contexts_mutex); - for (size_t i = 0; i < active_log_contexts.num; i++) { - if (context == active_log_contexts.array[i]->context) { - pthread_mutex_unlock(&log_contexts_mutex); - return active_log_contexts.array[i]; - } - } - - struct log_context *new_log_context = NULL; - - size_t cnt = cached_log_contexts.num; - if (!!cnt) { - new_log_context = cached_log_contexts.array[cnt - 1]; - da_pop_back(cached_log_contexts); - } - - if (!new_log_context) - new_log_context = bzalloc(sizeof(struct log_context)); - - new_log_context->context = context; - new_log_context->str[0] = '\0'; - new_log_context->print_prefix = 1; - - da_push_back(active_log_contexts, &new_log_context); - - pthread_mutex_unlock(&log_contexts_mutex); - - return new_log_context; -} - -static void destroy_log_context(struct log_context *log_context) -{ - pthread_mutex_lock(&log_contexts_mutex); - da_erase_item(active_log_contexts, &log_context); - da_push_back(cached_log_contexts, &log_context); - pthread_mutex_unlock(&log_contexts_mutex); -} - -static void ffmpeg_log_callback(void *context, int level, const char *format, - va_list args) -{ - if (format == NULL) - return; - - struct log_context *log_context = create_or_fetch_log_context(context); - - char *str = log_context->str; - - av_log_format_line(context, level, format, args, str + strlen(str), - (int)(sizeof(log_context->str) - strlen(str)), - &log_context->print_prefix); - - int obs_level; - switch (level) { - case AV_LOG_PANIC: - case AV_LOG_FATAL: - obs_level = LOG_ERROR; - break; - case AV_LOG_ERROR: - case AV_LOG_WARNING: - obs_level = LOG_WARNING; - break; - case AV_LOG_INFO: - case AV_LOG_VERBOSE: - obs_level = LOG_INFO; - break; - case AV_LOG_DEBUG: - default: - obs_level = LOG_DEBUG; - } - - if (!log_context->print_prefix) - return; - - char *str_end = str + strlen(str) - 1; - while (str < str_end) { - if (*str_end != '\n') - break; - *str_end-- = '\0'; - } - - if (str_end <= str) - goto cleanup; - - blog(obs_level, "[ffmpeg] %s", str); - -cleanup: - destroy_log_context(log_context); -} - #ifndef __APPLE__ static const char *nvenc_check_name = "nvenc_check"; @@ -301,13 +200,13 @@ extern void jim_nvenc_load(void); extern void jim_nvenc_unload(void); #endif +#if ENABLE_FFMPEG_LOGGING +extern void obs_ffmpeg_load_logging(void); +extern void obs_ffmpeg_unload_logging(void); +#endif + bool obs_module_load(void) { - da_init(active_log_contexts); - da_init(cached_log_contexts); - - //av_log_set_callback(ffmpeg_log_callback); - obs_register_source(&ffmpeg_source); obs_register_output(&ffmpeg_output); obs_register_output(&ffmpeg_muxer); @@ -330,28 +229,20 @@ bool obs_module_load(void) obs_register_encoder(&vaapi_encoder_info); } #endif +#endif + +#if ENABLE_FFMPEG_LOGGING + obs_ffmpeg_load_logging(); #endif return true; } void obs_module_unload(void) { - av_log_set_callback(av_log_default_callback); - -#ifdef _WIN32 - pthread_mutex_destroy(&log_contexts_mutex); +#if ENABLE_FFMPEG_LOGGING + obs_ffmpeg_unload_logging(); #endif - for (size_t i = 0; i < active_log_contexts.num; i++) { - bfree(active_log_contexts.array[i]); - } - for (size_t i = 0; i < cached_log_contexts.num; i++) { - bfree(cached_log_contexts.array[i]); - } - - da_free(active_log_contexts); - da_free(cached_log_contexts); - #ifdef _WIN32 jim_nvenc_unload(); #endif