X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fffmpeg%2Fffmpeg.cpp;h=ab500c3e050240558ef1f511dd7689283cfaa1dc;hb=726897adbf881d3b75f171fff24f2b917ba5f05a;hp=871d984b2c9ca3204af86b037e1c1eb1c2e77af5;hpb=33b7310a5c59c164330564739eaad8c93f046ff6;p=casparcg diff --git a/modules/ffmpeg/ffmpeg.cpp b/modules/ffmpeg/ffmpeg.cpp index 871d984b2..ab500c3e0 100644 --- a/modules/ffmpeg/ffmpeg.cpp +++ b/modules/ffmpeg/ffmpeg.cpp @@ -24,18 +24,23 @@ #include "ffmpeg.h" #include "consumer/ffmpeg_consumer.h" +#include "consumer/streaming_consumer.h" #include "producer/ffmpeg_producer.h" #include "producer/util/util.h" #include +#include #include +#include #include #include #include #include #include +#include +#include #include @@ -45,7 +50,7 @@ #pragma warning (disable : 4996) #endif -extern "C" +extern "C" { #define __STDC_CONSTANT_MACROS #define __STDC_LIMIT_MACROS @@ -53,45 +58,45 @@ extern "C" #include #include #include + #include } namespace caspar { namespace ffmpeg { - -int ffmpeg_lock_callback(void **mutex, enum AVLockOp op) -{ +int ffmpeg_lock_callback(void **mutex, enum AVLockOp op) +{ if(!mutex) return 0; auto my_mutex = reinterpret_cast(*mutex); - - switch(op) - { - case AV_LOCK_CREATE: - { - *mutex = new tbb::recursive_mutex(); - break; - } - case AV_LOCK_OBTAIN: - { + + switch(op) + { + case AV_LOCK_CREATE: + { + *mutex = new tbb::recursive_mutex(); + break; + } + case AV_LOCK_OBTAIN: + { if(my_mutex) - my_mutex->lock(); - break; - } - case AV_LOCK_RELEASE: - { + my_mutex->lock(); + break; + } + case AV_LOCK_RELEASE: + { if(my_mutex) - my_mutex->unlock(); - break; - } - case AV_LOCK_DESTROY: - { + my_mutex->unlock(); + break; + } + case AV_LOCK_DESTROY: + { delete my_mutex; *mutex = nullptr; - break; - } - } - return 0; -} + break; + } + } + return 0; +} static void sanitize(uint8_t *line) { @@ -114,15 +119,15 @@ void log_callback(void* ptr, int level, const char* fmt, va_list vl) if(level > av_log_get_level()) return; line[0]=0; - + #undef fprintf - if(print_prefix && avc) + if(print_prefix && avc) { - if (avc->parent_log_context_offset) + if (avc->parent_log_context_offset) { AVClass** parent= *(AVClass***)(((uint8_t*)ptr) + avc->parent_log_context_offset); if(parent && *parent) - std::sprintf(line, "[%s @ %p] ", (*parent)->item_name(parent), parent); + std::sprintf(line, "[%s @ %p] ", (*parent)->item_name(parent), parent); } std::sprintf(line + strlen(line), "[%s @ %p] ", avc->item_name(ptr), ptr); } @@ -130,7 +135,7 @@ void log_callback(void* ptr, int level, const char* fmt, va_list vl) std::vsprintf(line + strlen(line), fmt, vl); print_prefix = strlen(line) && line[strlen(line)-1] == '\n'; - + //if(print_prefix && !strcmp(line, prev)){ // count++; // if(is_atty==1) @@ -147,7 +152,7 @@ void log_callback(void* ptr, int level, const char* fmt, va_list vl) auto len = strlen(line); if(len > 0) line[len-1] = 0; - + if(level == AV_LOG_DEBUG) CASPAR_LOG(debug) << L"[ffmpeg] " << line; else if(level == AV_LOG_INFO) @@ -234,43 +239,92 @@ std::wstring swscale_version() { return make_version(::swscale_version()); } +bool& get_quiet_logging_for_thread() +{ + static boost::thread_specific_ptr quiet_logging_for_thread; + + auto local = quiet_logging_for_thread.get(); + + if (!local) + { + local = new bool(false); + quiet_logging_for_thread.reset(local); + } + + return *local; +} + +void enable_quiet_logging_for_thread() +{ + get_quiet_logging_for_thread() = true; +} -void init( - const spl::shared_ptr& media_info_repo, - const spl::shared_ptr& system_info_repo) +bool is_logging_quiet_for_thread() +{ + return get_quiet_logging_for_thread(); +} + +std::shared_ptr temporary_enable_quiet_logging_for_thread(bool enable) +{ + if (!enable || is_logging_quiet_for_thread()) + return std::shared_ptr(); + + get_quiet_logging_for_thread() = true; + + return std::shared_ptr(nullptr, [](void*) + { + get_quiet_logging_for_thread() = false; // Only works correctly if destructed in same thread as original caller. + }); +} + +void log_for_thread(void* ptr, int level, const char* fmt, va_list vl) +{ + ensure_gpf_handler_installed_for_thread("ffmpeg-thread"); + + int min_level = is_logging_quiet_for_thread() ? AV_LOG_DEBUG : AV_LOG_FATAL; + + log_callback(ptr, std::max(level, min_level), fmt, vl); +} + +void init(core::module_dependencies dependencies) { av_lockmgr_register(ffmpeg_lock_callback); - av_log_set_callback(log_callback); + av_log_set_callback(log_for_thread); avfilter_register_all(); //fix_yadif_filter_format_query(); av_register_all(); avformat_network_init(); avcodec_register_all(); - - core::register_consumer_factory(create_consumer); - core::register_preconfigured_consumer_factory(L"file", create_preconfigured_consumer); - core::register_producer_factory(create_producer); - - media_info_repo->register_extractor( + avdevice_register_all(); + + auto info_repo = dependencies.media_info_repo; + + dependencies.consumer_registry->register_consumer_factory(L"FFmpeg Consumer", create_consumer, describe_consumer); + dependencies.consumer_registry->register_consumer_factory(L"Streaming Consumer", create_streaming_consumer, describe_streaming_consumer); + dependencies.consumer_registry->register_preconfigured_consumer_factory(L"file", create_preconfigured_consumer); + dependencies.consumer_registry->register_preconfigured_consumer_factory(L"stream", create_preconfigured_streaming_consumer); + dependencies.producer_registry->register_producer_factory(L"FFmpeg Producer", boost::bind(&create_producer, _1, _2, info_repo), describe_producer); + dependencies.producer_registry->register_thumbnail_producer(boost::bind(&create_thumbnail_frame, _1, _2, info_repo)); + + info_repo->register_extractor( [](const std::wstring& file, const std::wstring& extension, core::media_info& info) -> bool { - // TODO: merge thumbnail generation from 2.0 - //auto disable_logging = temporary_disable_logging_for_thread(true); + auto quiet_logging = temporary_enable_quiet_logging_for_thread(true); if (extension == L".WAV" || extension == L".MP3") { info.clip_type = L"AUDIO"; return true; } - if (!is_valid_file(file)) + if (!is_valid_file(file, true)) return false; info.clip_type = L"MOVIE"; return try_get_duration(file, info.duration, info.time_base); }); - system_info_repo->register_system_info_provider([](boost::property_tree::wptree& info) + dependencies.system_info_provider_repo->register_system_info_provider([](boost::property_tree::wptree& info) { info.add(L"system.ffmpeg.avcodec", avcodec_version()); info.add(L"system.ffmpeg.avformat", avformat_version()); @@ -286,5 +340,4 @@ void uninit() avformat_network_deinit(); av_lockmgr_register(nullptr); } - -}} \ No newline at end of file +}}