]> git.sesse.net Git - casparcg/blobdiff - core/producer/frame_producer.cpp
[frame_producer] Created workaround for bug in FFmpeg where every new thread used...
[casparcg] / core / producer / frame_producer.cpp
index e26432f97fe92637484a9037164a56d1af73c5cc..de25a488e792be9a12a95192375557188a4634e4 100644 (file)
@@ -209,6 +209,18 @@ const spl::shared_ptr<frame_producer>& frame_producer::empty()
        return producer;
 }
 
+std::shared_ptr<executor>& producer_destroyer()
+{
+       static auto destroyer = []
+       {
+               auto result = std::make_shared<executor>(L"Producer destroyer");
+               result->set_capacity(std::numeric_limits<unsigned int>::max());
+               return result;
+       }();;
+
+       return destroyer;
+}
+
 tbb::atomic<bool>& destroy_producers_in_separate_thread()
 {
        static tbb::atomic<bool> state;
@@ -219,6 +231,8 @@ tbb::atomic<bool>& 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<int> 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<frame_producer>(std::move(producer_));
-               boost::thread([=]
+
+               destroyer->begin_invoke([=]
                {
                        std::unique_ptr<spl::shared_ptr<frame_producer>> 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();}