]> git.sesse.net Git - casparcg/blobdiff - modules/ffmpeg/ffmpeg.cpp
- Added support for multiple streaming_consumers on the same channel
[casparcg] / modules / ffmpeg / ffmpeg.cpp
index c11babbd1c6371bbd610f83e96bab675268a9c14..287288775b4cab5d240937177464dafc7c633db8 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
-* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+* Copyright 2013 Sveriges Television AB http://casparcg.com/\r
 *\r
 * This file is part of CasparCG (www.casparcg.com).\r
 *\r
 #include "StdAfx.h"\r
 \r
 #include "consumer/ffmpeg_consumer.h"\r
+#include "consumer/streaming_consumer.h"\r
 #include "producer/ffmpeg_producer.h"\r
+#include "producer/util/util.h"\r
 \r
 #include <common/log/log.h>\r
+#include <common/exception/win32_exception.h>\r
 \r
+#include <core/parameters/parameters.h>\r
 #include <core/consumer/frame_consumer.h>\r
 #include <core/producer/frame_producer.h>\r
+#include <core/producer/media_info/media_info.h>\r
+#include <core/producer/media_info/media_info_repository.h>\r
 \r
 #include <tbb/recursive_mutex.h>\r
 \r
+#include <boost/thread.hpp>\r
+\r
 #if defined(_MSC_VER)\r
 #pragma warning (disable : 4244)\r
 #pragma warning (disable : 4603)\r
@@ -45,12 +53,14 @@ extern "C"
        #include <libswscale/swscale.h>\r
        #include <libavutil/avutil.h>\r
        #include <libavfilter/avfilter.h>\r
+       #include <libavdevice/avdevice.h>\r
 }\r
 \r
 namespace caspar { namespace ffmpeg {\r
        \r
 int ffmpeg_lock_callback(void **mutex, enum AVLockOp op) \r
 { \r
+       win32_exception::ensure_handler_installed_for_thread("ffmpeg-thread");\r
        if(!mutex)\r
                return 0;\r
 \r
@@ -156,6 +166,44 @@ void log_callback(void* ptr, int level, const char* fmt, va_list vl)
     //colored_fputs(av_clip(level>>3, 0, 6), line);\r
 }\r
 \r
+boost::thread_specific_ptr<bool>& get_disable_logging_for_thread()\r
+{\r
+       static boost::thread_specific_ptr<bool> disable_logging_for_thread;\r
+\r
+       return disable_logging_for_thread;\r
+}\r
+\r
+void disable_logging_for_thread()\r
+{\r
+       if (get_disable_logging_for_thread().get() == nullptr)\r
+               get_disable_logging_for_thread().reset(new bool); // bool value does not matter\r
+}\r
+\r
+bool is_logging_already_disabled_for_thread()\r
+{\r
+       return get_disable_logging_for_thread().get() != nullptr;\r
+}\r
+\r
+std::shared_ptr<void> temporary_disable_logging_for_thread(bool disable)\r
+{\r
+       if (!disable || is_logging_already_disabled_for_thread())\r
+               return std::shared_ptr<void>();\r
+\r
+       disable_logging_for_thread();\r
+\r
+       return std::shared_ptr<void>(nullptr, [] (void*)\r
+       {\r
+               get_disable_logging_for_thread().release(); // Only works correctly if destructed in same thread as original caller.\r
+       });\r
+}\r
+\r
+void log_for_thread(void* ptr, int level, const char* fmt, va_list vl)\r
+{\r
+       win32_exception::ensure_handler_installed_for_thread("ffmpeg-thread");\r
+       if (get_disable_logging_for_thread().get() == nullptr) // It does not matter what the value of the bool is\r
+               log_callback(ptr, level, fmt, vl);\r
+}\r
+\r
 //static int query_yadif_formats(AVFilterContext *ctx)\r
 //{\r
 //    static const int pix_fmts[] = {\r
@@ -195,20 +243,29 @@ void log_callback(void* ptr, int level, const char* fmt, va_list vl)
 //}\r
 //#pragma warning (pop)\r
 \r
-void init()\r
+void init(const safe_ptr<core::media_info_repository>& media_info_repo)\r
 {\r
        av_lockmgr_register(ffmpeg_lock_callback);\r
-       av_log_set_callback(log_callback);\r
-\r
+       av_log_set_callback(log_for_thread);\r
+               \r
+    avcodec_register_all();    \r
+    avdevice_register_all();\r
     avfilter_register_all();\r
-       //fix_yadif_filter_format_query();\r
-       av_register_all();\r
+    av_register_all();\r
     avformat_network_init();\r
-       avcodec_init();\r
-    avcodec_register_all();\r
        \r
-       core::register_consumer_factory([](const std::vector<std::wstring>& params){return create_consumer(params);});\r
+       core::register_consumer_factory([](const core::parameters& params){return ffmpeg::create_consumer(params);});\r
+       core::register_consumer_factory([](const core::parameters& params){return ffmpeg::create_streaming_consumer(params);});\r
        core::register_producer_factory(create_producer);\r
+       core::register_thumbnail_producer_factory(create_thumbnail_producer);\r
+\r
+       media_info_repo->register_extractor(\r
+                       [](const std::wstring& file, core::media_info& info) -> bool\r
+                       {\r
+                               auto disable_logging = temporary_disable_logging_for_thread(true);\r
+\r
+                               return is_valid_file(file) && try_get_duration(file, info.duration, info.time_base);\r
+                       });\r
 }\r
 \r
 void uninit()\r