]> git.sesse.net Git - casparcg/blobdiff - core/producer/layer.cpp
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches...
[casparcg] / core / producer / layer.cpp
index 14ba9f3a9caa40879ef0cbb6cf07c6335607a701..f7bf942d9705bba31a34f2185892e660cf19c156 100644 (file)
@@ -14,7 +14,7 @@
 #include <mixer/audio/audio_mixer.h>\r
 #include <mixer/audio/audio_transform.h>\r
 \r
-#include <tbb/recursive_mutex.h>\r
+#include <tbb/spin_mutex.h>\r
 \r
 namespace caspar { namespace core {\r
 \r
@@ -27,7 +27,7 @@ class frame_producer_remover
        {\r
                auto name = producer->print();\r
                producer = frame_producer::empty();\r
-               CASPAR_LOG(info) << L"async_remover[" + boost::lexical_cast<std::wstring>(--count_) + L"] Removed: " << name << L".";\r
+               CASPAR_LOG(info) << name << L" Removed.";\r
        }\r
 public:\r
 \r
@@ -40,19 +40,19 @@ public:
        void remove(safe_ptr<frame_producer>&& producer)\r
        {\r
                CASPAR_ASSERT(producer.unique());\r
-               CASPAR_LOG(info) << L"async_remover[" + boost::lexical_cast<std::wstring>(++count_) + L"] Removing: " << producer->print() << L".";\r
                executor_.begin_invoke(std::bind(&frame_producer_remover::do_remove, this, std::move(producer)));\r
        }\r
 };\r
 \r
 frame_producer_remover g_remover;\r
 \r
+\r
 struct layer::implementation : boost::noncopyable\r
 {                              \r
-       tbb::recursive_mutex            mutex_;\r
+       mutable tbb::spin_mutex         printer_mutex_;\r
        printer                                         parent_printer_;\r
-       tbb::atomic<int>                        index_;\r
-\r
+       int                                                     index_;\r
+       \r
        safe_ptr<frame_producer>        foreground_;\r
        safe_ptr<frame_producer>        background_;\r
        safe_ptr<draw_frame>            last_frame_;\r
@@ -60,18 +60,14 @@ struct layer::implementation : boost::noncopyable
 public:\r
        implementation(int index, const printer& parent_printer) \r
                : parent_printer_(parent_printer)\r
+               , index_(index)\r
                , foreground_(frame_producer::empty())\r
                , background_(frame_producer::empty())\r
                , last_frame_(draw_frame::empty())\r
-               , is_paused_(false)\r
-       {\r
-               index_ = index;\r
-       }\r
+               , is_paused_(false){}\r
        \r
        void load(const safe_ptr<frame_producer>& frame_producer, bool play_on_load)\r
        {               \r
-               tbb::recursive_mutex::scoped_lock lock(mutex_);\r
-\r
                background_ = frame_producer;\r
                is_paused_ = false;\r
                if(play_on_load)\r
@@ -80,22 +76,18 @@ public:
 \r
        void preview(const safe_ptr<frame_producer>& frame_producer)\r
        {\r
-               tbb::recursive_mutex::scoped_lock lock(mutex_);\r
-\r
                load(frame_producer, true);\r
                receive();\r
                pause();\r
        }\r
        \r
        void play()\r
-       {               \r
-               tbb::recursive_mutex::scoped_lock lock(mutex_);\r
-       \r
+       {                       \r
                if(!is_paused_)                 \r
                {\r
                        background_->set_leading_producer(foreground_);\r
                        foreground_ = background_;\r
-                       CASPAR_LOG(info) << foreground_->print() << L" Started.";\r
+                       CASPAR_LOG(info) << foreground_->print() << L" Added.";\r
                        background_ = frame_producer::empty();\r
                }\r
                is_paused_ = false;\r
@@ -103,24 +95,18 @@ public:
 \r
        void pause()\r
        {\r
-               tbb::recursive_mutex::scoped_lock lock(mutex_);\r
-\r
                is_paused_ = true;\r
        }\r
 \r
        void stop()\r
        {\r
-               tbb::recursive_mutex::scoped_lock lock(mutex_);\r
-\r
                pause();\r
                last_frame_ = draw_frame::empty();\r
                foreground_ = frame_producer::empty();\r
        }\r
 \r
        void clear()\r
-       {\r
-               tbb::recursive_mutex::scoped_lock lock(mutex_);\r
-               \r
+       {               \r
                foreground_ = frame_producer::empty();\r
                background_ = frame_producer::empty();\r
                last_frame_ = draw_frame::empty();\r
@@ -129,8 +115,6 @@ public:
        \r
        safe_ptr<draw_frame> receive()\r
        {               \r
-               tbb::recursive_mutex::scoped_lock lock(mutex_);\r
-\r
                if(is_paused_)\r
                {\r
                        last_frame_->get_audio_transform().set_gain(0.0);\r
@@ -146,48 +130,58 @@ public:
 \r
                                auto following = foreground_->get_following_producer();\r
                                following->set_leading_producer(foreground_);\r
+                               following->set_parent_printer(boost::bind(&implementation::print, this));\r
                                g_remover.remove(std::move(foreground_));\r
                                foreground_ = following;\r
-                               CASPAR_LOG(info) << foreground_->print() << L" Started.";\r
+                               CASPAR_LOG(info) << foreground_->print() << L" Added.";\r
 \r
                                last_frame_ = receive();\r
                        }\r
                }\r
                catch(...)\r
                {\r
-                       CASPAR_LOG(error) << print() << L"Unhandled Exception: ";\r
+                       CASPAR_LOG(error) << print() << L" Unhandled Exception: ";\r
                        CASPAR_LOG_CURRENT_EXCEPTION();\r
                        stop();\r
                }\r
 \r
                return last_frame_;\r
        }\r
-       \r
-       void swap(implementation& other)\r
-       {\r
-               tbb::recursive_mutex::scoped_lock lock(mutex_);\r
-               std::swap(foreground_, other.foreground_);\r
-               std::swap(background_, other.background_);\r
-               std::swap(last_frame_, other.last_frame_);\r
-               std::swap(is_paused_, other.is_paused_);\r
-       }\r
-       \r
+               \r
        std::wstring print() const\r
        {\r
+               tbb::spin_mutex::scoped_lock lock(printer_mutex_);\r
                return (parent_printer_ ? parent_printer_() + L"/" : L"") + L"layer[" + boost::lexical_cast<std::wstring>(index_) + L"]";\r
        }\r
 };\r
 \r
-layer::layer(int index, const printer& parent_printer) : impl_(new implementation(index, parent_printer)){}\r
-layer::layer(layer&& other) : impl_(std::move(other.impl_)){}\r
+layer::layer(int index, const printer& parent_printer)\r
+{\r
+       impl_ = new implementation(index, parent_printer);\r
+}\r
+layer::~layer()\r
+{\r
+       if(!impl_)\r
+               return;\r
+\r
+       impl_->clear();\r
+       delete impl_.fetch_and_store(nullptr);\r
+}\r
+layer::layer(layer&& other)\r
+{\r
+       impl_ = other.impl_.fetch_and_store(nullptr);\r
+}\r
 layer& layer::operator=(layer&& other)\r
 {\r
-       impl_ = std::move(other.impl_);\r
+       impl_ = other.impl_.fetch_and_store(nullptr);\r
        return *this;\r
 }\r
 void layer::swap(layer& other)\r
 {\r
-       impl_->swap(*other.impl_);\r
+       impl_ = other.impl_.compare_and_swap(impl_, other.impl_);\r
+       tbb::spin_mutex::scoped_lock lock(other.impl_->printer_mutex_);\r
+       std::swap(impl_->index_, other.impl_->index_);\r
+       std::swap(impl_->parent_printer_, other.impl_->parent_printer_);\r
 }\r
 void layer::load(const safe_ptr<frame_producer>& frame_producer, bool play_on_load){return impl_->load(frame_producer, play_on_load);} \r
 void layer::preview(const safe_ptr<frame_producer>& frame_producer){return impl_->preview(frame_producer);}    \r