From 06bdd05d8ec7da072de717d5e1fcb462a1d8ee56 Mon Sep 17 00:00:00 2001 From: Helge Norberg Date: Tue, 28 Feb 2017 18:14:24 +0100 Subject: [PATCH] [frame_producer] Created workaround for bug in FFmpeg where every new thread used to cleanup causes handles to leak (not sure why). Reduced the effect by using only one thread for all producer destructions. --- core/producer/frame_producer.cpp | 35 +++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/core/producer/frame_producer.cpp b/core/producer/frame_producer.cpp index e26432f97..de25a488e 100644 --- a/core/producer/frame_producer.cpp +++ b/core/producer/frame_producer.cpp @@ -209,6 +209,18 @@ const spl::shared_ptr& frame_producer::empty() return producer; } +std::shared_ptr& producer_destroyer() +{ + static auto destroyer = [] + { + auto result = std::make_shared(L"Producer destroyer"); + result->set_capacity(std::numeric_limits::max()); + return result; + }();; + + return destroyer; +} + tbb::atomic& destroy_producers_in_separate_thread() { static tbb::atomic state; @@ -219,6 +231,8 @@ tbb::atomic& destroy_producers_in_separate_thread() void destroy_producers_synchronously() { destroy_producers_in_separate_thread() = false; + // Join destroyer, executing rest of producers in queue synchronously. + producer_destroyer().reset(); } class destroy_producer_proxy : public frame_producer @@ -233,25 +247,24 @@ public: virtual ~destroy_producer_proxy() { - static tbb::atomic counter; - static std::once_flag counter_init_once; - std::call_once(counter_init_once, []{ counter = 0; }); - if(producer_ == core::frame_producer::empty() || !destroy_producers_in_separate_thread()) return; - ++counter; - CASPAR_VERIFY(counter < 8); + auto destroyer = producer_destroyer(); + + if (!destroyer) + return; + + CASPAR_VERIFY(destroyer->size() < 8); auto producer = new spl::shared_ptr(std::move(producer_)); - boost::thread([=] + + destroyer->begin_invoke([=] { std::unique_ptr> pointer_guard(producer); auto str = (*producer)->print(); try { - ensure_gpf_handler_installed_for_thread(u8(L"Destroyer: " + str).c_str()); - if (!producer->unique()) CASPAR_LOG(debug) << str << L" Not destroyed on asynchronous destruction thread: " << producer->use_count(); else @@ -268,9 +281,7 @@ public: { CASPAR_LOG_CURRENT_EXCEPTION(); } - - --counter; - }).detach(); + }); } draw_frame receive() override {return producer_->receive();} -- 2.39.2