]> 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 4807a6872df8e9bfcdcb0897b6ee1f1c249e7d1d..f7bf942d9705bba31a34f2185892e660cf19c156 100644 (file)
@@ -1,66 +1,96 @@
 #include "../stdafx.h"\r
 \r
 #include "layer.h"\r
+#include "frame_producer.h"\r
+\r
+#include "../video_format.h"\r
+\r
+#include <common/concurrency/executor.h>\r
+#include <common/utility/assert.h>\r
+#include <common/utility/printable.h>\r
 \r
 #include <mixer/frame/draw_frame.h>\r
 #include <mixer/image/image_mixer.h>\r
 #include <mixer/audio/audio_mixer.h>\r
 #include <mixer/audio/audio_transform.h>\r
-#include "../producer/frame_producer.h"\r
-\r
-#include "../video_format.h"\r
 \r
-#include <common/utility/assert.h>\r
+#include <tbb/spin_mutex.h>\r
 \r
 namespace caspar { namespace core {\r
 \r
+class frame_producer_remover\r
+{\r
+       executor executor_;\r
+       tbb::atomic<int> count_;\r
+\r
+       void do_remove(safe_ptr<frame_producer>& producer)\r
+       {\r
+               auto name = producer->print();\r
+               producer = frame_producer::empty();\r
+               CASPAR_LOG(info) << name << L" Removed.";\r
+       }\r
+public:\r
+\r
+       frame_producer_remover()\r
+       {\r
+               executor_.start();\r
+               count_ = 0;\r
+       }\r
+\r
+       void remove(safe_ptr<frame_producer>&& producer)\r
+       {\r
+               CASPAR_ASSERT(producer.unique());\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
+{                              \r
+       mutable tbb::spin_mutex         printer_mutex_;\r
+       printer                                         parent_printer_;\r
+       int                                                     index_;\r
+       \r
        safe_ptr<frame_producer>        foreground_;\r
        safe_ptr<frame_producer>        background_;\r
        safe_ptr<draw_frame>            last_frame_;\r
        bool                                            is_paused_;\r
-\r
 public:\r
-       implementation() \r
-               : foreground_(frame_producer::empty())\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
        void load(const safe_ptr<frame_producer>& frame_producer, bool play_on_load)\r
-       {                       \r
+       {               \r
                background_ = frame_producer;\r
+               is_paused_ = false;\r
                if(play_on_load)\r
-                       play();                 \r
+                       play();         \r
        }\r
 \r
        void preview(const safe_ptr<frame_producer>& frame_producer)\r
        {\r
-               stop();\r
-               foreground_ = frame_producer;\r
-               background_ = frame_producer::empty();\r
-               try\r
-               {\r
-                       last_frame_ = frame_producer->receive();\r
-               }\r
-               catch(...)\r
-               {\r
-                       CASPAR_LOG_CURRENT_EXCEPTION();\r
-                       clear();\r
-               }\r
+               load(frame_producer, true);\r
+               receive();\r
+               pause();\r
        }\r
        \r
        void play()\r
        {                       \r
-               if(is_paused_)                  \r
-                       is_paused_ = false;\r
-               else\r
+               if(!is_paused_)                 \r
                {\r
                        background_->set_leading_producer(foreground_);\r
                        foreground_ = background_;\r
+                       CASPAR_LOG(info) << foreground_->print() << L" Added.";\r
                        background_ = frame_producer::empty();\r
                }\r
+               is_paused_ = false;\r
        }\r
 \r
        void pause()\r
@@ -76,9 +106,11 @@ public:
        }\r
 \r
        void clear()\r
-       {\r
-               stop();\r
+       {               \r
+               foreground_ = frame_producer::empty();\r
                background_ = frame_producer::empty();\r
+               last_frame_ = draw_frame::empty();\r
+               is_paused_ = false;\r
        }\r
        \r
        safe_ptr<draw_frame> receive()\r
@@ -98,41 +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" Added.";\r
 \r
                                last_frame_ = receive();\r
                        }\r
                }\r
                catch(...)\r
                {\r
+                       CASPAR_LOG(error) << print() << L" Unhandled Exception: ";\r
                        CASPAR_LOG_CURRENT_EXCEPTION();\r
                        stop();\r
                }\r
 \r
                return last_frame_;\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(\r
+layer::layer(int index, const printer& parent_printer)\r
 {\r
-       impl_ = new implementation();\r
-}\r
-layer::layer(layer&& other) \r
-{\r
-       impl_ = other.impl_.compare_and_swap(nullptr, other.impl_);\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_ = other.impl_.compare_and_swap(nullptr, other.impl_);\r
+       impl_ = other.impl_.fetch_and_store(nullptr);\r
        return *this;\r
 }\r
 void layer::swap(layer& other)\r
 {\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
@@ -143,4 +192,5 @@ void layer::clear(){impl_->clear();}
 safe_ptr<draw_frame> layer::receive() {return impl_->receive();}\r
 safe_ptr<frame_producer> layer::foreground() const { return impl_->foreground_;}\r
 safe_ptr<frame_producer> layer::background() const { return impl_->background_;}\r
+std::wstring layer::print() const { return impl_->print();}\r
 }}
\ No newline at end of file