]> git.sesse.net Git - casparcg/commitdiff
2.0.0.2: All pipeline stages share thread context. This is a better and simpler desig...
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Sun, 29 May 2011 16:03:41 +0000 (16:03 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Sun, 29 May 2011 16:03:41 +0000 (16:03 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@826 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

18 files changed:
common/concurrency/executor.h
core/channel.cpp
core/channel.h
core/consumer/frame_consumer_device.cpp
core/consumer/frame_consumer_device.h
core/core.vcxproj
core/core.vcxproj.filters
core/mixer/frame_mixer_device.cpp
core/mixer/frame_mixer_device.h
core/mixer/gpu/ogl_device.h
core/mixer/image/image_mixer.cpp
core/mixer/image/image_mixer.h
core/mixer/write_frame.cpp
core/mixer/write_frame.h
core/producer/frame_producer_device.cpp
core/producer/frame_producer_device.h
shell/main.cpp
shell/server.cpp

index e2d4d0243bf0c5251f5844525f5d52876a3bb869..fc8f0107995f5a23c46d2db02f0582d028501570 100644 (file)
@@ -73,7 +73,7 @@ enum priority_class
        high_priority_class,\r
        above_normal_priority_class,\r
        normal_priority_class,\r
-       below_normal_priority_clas\r
+       below_normal_priority_class\r
 };\r
 \r
 namespace internal\r
@@ -151,7 +151,7 @@ public:
                                SetThreadPriority(GetCurrentThread(), ABOVE_NORMAL_PRIORITY_CLASS);\r
                        else if(p == normal_priority_class)\r
                                SetThreadPriority(GetCurrentThread(), NORMAL_PRIORITY_CLASS);\r
-                       else if(p == below_normal_priority_clas)\r
+                       else if(p == below_normal_priority_class)\r
                                SetThreadPriority(GetCurrentThread(), BELOW_NORMAL_PRIORITY_CLASS);\r
                });\r
        }\r
index 560b69338d078643aa694d3d577d1bd664c46022..da20af2db3b06623ef55cebd87bfac29e263470c 100644 (file)
 namespace caspar { namespace core {\r
 \r
 struct channel::implementation : boost::noncopyable\r
-{                                      \r
-       const int index_;\r
-       video_format_desc format_desc_;\r
+{\r
+       const int                                                               index_;\r
+       video_format_desc                                               format_desc_;\r
        \r
-       safe_ptr<ogl_device> ogl_;\r
+       ogl_device&                                                             ogl_;\r
+       executor                                                                context_;\r
+       executor                                                                destroy_context_;\r
 \r
        std::shared_ptr<frame_consumer_device>  consumer_;\r
        std::shared_ptr<frame_mixer_device>             mixer_;\r
        std::shared_ptr<frame_producer_device>  producer_;\r
        \r
 public:\r
-       implementation(int index, const video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl)  \r
+       implementation(int index, const video_format_desc& format_desc, ogl_device& ogl)  \r
                : index_(index)\r
                , format_desc_(format_desc)\r
                , ogl_(ogl)\r
-               , consumer_(new frame_consumer_device(format_desc, ogl))\r
-               , mixer_(new frame_mixer_device(format_desc, [=](const safe_ptr<read_frame>& frame){consumer_->send(frame);}, ogl))\r
-               , producer_(new frame_producer_device(format_desc_, [=](const std::map<int, safe_ptr<basic_frame>>& frames){mixer_->send(frames);}))    \r
-\r
+               , consumer_(new frame_consumer_device(context_, format_desc, ogl))\r
+               , mixer_(new frame_mixer_device(context_, format_desc, [=](const safe_ptr<read_frame>& frame){consumer_->send(frame);}, ogl))\r
+               , producer_(new frame_producer_device(context_, destroy_context_, format_desc_, [=](const std::map<int, safe_ptr<basic_frame>>& frames){mixer_->send(frames);}))        \r
+               , context_(print() + L"/render")\r
+               , destroy_context_(print() + L"/destroy")\r
        {\r
+               context_.set_priority_class(above_normal_priority_class);\r
+               destroy_context_.set_priority_class(below_normal_priority_class);\r
                CASPAR_LOG(info) << print() << " Successfully Initialized.";\r
        }\r
+\r
+       ~implementation()\r
+       {\r
+               // Stop context before destroying devices.\r
+               context_.stop();\r
+               context_.join();\r
+       }\r
                \r
        std::wstring print() const\r
        {\r
@@ -71,12 +83,12 @@ public:
                mixer_.reset();\r
 \r
                consumer_->set_video_format_desc(format_desc_);\r
-               mixer_ = std::make_shared<frame_mixer_device>(format_desc_, [=](const safe_ptr<read_frame>& frame){consumer_->send(frame);}, ogl_);\r
-               producer_ = std::make_shared<frame_producer_device>(format_desc_, [=](const std::map<int, safe_ptr<basic_frame>>& frames){mixer_->send(frames);});\r
+               mixer_ = std::make_shared<frame_mixer_device>(context_, format_desc_, [=](const safe_ptr<read_frame>& frame){consumer_->send(frame);}, ogl_);\r
+               producer_ = std::make_shared<frame_producer_device>(context_, destroy_context_, format_desc_, [=](const std::map<int, safe_ptr<basic_frame>>& frames){mixer_->send(frames);});\r
        }\r
 };\r
 \r
-channel::channel(int index, const video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl) : impl_(new implementation(index, format_desc, ogl)){}\r
+channel::channel(int index, const video_format_desc& format_desc, ogl_device& ogl) : impl_(new implementation(index, format_desc, ogl)){}\r
 channel::channel(channel&& other) : impl_(std::move(other.impl_)){}\r
 safe_ptr<frame_producer_device> channel::producer() { return make_safe(impl_->producer_);} \r
 safe_ptr<frame_mixer_device> channel::mixer() { return make_safe(impl_->mixer_);} \r
index a015764ab17f43c17262d433fb5be865c12f01f6..fcb6d1caefeae16d09eea6fb06cc414819127b4b 100644 (file)
@@ -35,7 +35,7 @@ class ogl_device;
 class channel : boost::noncopyable\r
 {\r
 public:\r
-       explicit channel(int index, const video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl);\r
+       explicit channel(int index, const video_format_desc& format_desc, ogl_device& ogl);\r
        channel(channel&& other);\r
 \r
        safe_ptr<frame_producer_device> producer();\r
index 7d9b5585a9cf45aca278239510f35c3b22eff40f..ac437d97e5d4aa3d1786345026caf63926edd351 100644 (file)
@@ -57,29 +57,28 @@ struct frame_consumer_device::implementation
        boost::timer frame_timer_;\r
        boost::timer tick_timer_;\r
 \r
-       safe_ptr<ogl_device> ogl_;\r
+       ogl_device& ogl_;\r
        \r
-       executor executor_;     \r
+       executor& context_;     \r
 public:\r
-       implementation( const video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl) \r
+       implementation(executor& context, const video_format_desc& format_desc, ogl_device& ogl) \r
                : format_desc_(format_desc)\r
                , diag_(diagnostics::create_graph(std::string("frame_consumer_device")))\r
                , ogl_(ogl)\r
-               , executor_(L"frame_consumer_device")\r
+               , context_(context)\r
        {               \r
                diag_->set_color("input-buffer", diagnostics::color(1.0f, 1.0f, 0.0f)); \r
                diag_->add_guide("frame-time", 0.5f);   \r
                diag_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
                diag_->set_color("tick-time", diagnostics::color(0.1f, 0.7f, 0.8f));\r
 \r
-               executor_.set_capacity(1);\r
-               executor_.set_priority_class(above_normal_priority_class);\r
+               context_.set_priority_class(above_normal_priority_class);\r
        }\r
 \r
        void add(int index, safe_ptr<frame_consumer>&& consumer)\r
        {               \r
                consumer->initialize(format_desc_);\r
-               executor_.invoke([&]\r
+               context_.invoke([&]\r
                {\r
                        buffer_.set_capacity(std::max(buffer_.capacity(), consumer->buffer_depth()));\r
 \r
@@ -91,7 +90,7 @@ public:
 \r
        void remove(int index)\r
        {\r
-               executor_.invoke([&]\r
+               context_.invoke([&]\r
                {\r
                        auto it = consumers_.find(index);\r
                        if(it != consumers_.end())\r
@@ -120,7 +119,7 @@ public:
                if(has_key_only)\r
                {\r
                        // Currently do key_only transform on cpu. Unsure if the extra 400MB/s (1080p50) overhead is worth it to do it on gpu.\r
-                       auto key_data = ogl_->create_host_buffer(frame->image_data().size(), host_buffer::write_only);                          \r
+                       auto key_data = ogl_.create_host_buffer(frame->image_data().size(), host_buffer::write_only);                           \r
                        fast_memsfhl(key_data->data(), frame->image_data().begin(), frame->image_data().size(), 0x0F0F0F0F, 0x0B0B0B0B, 0x07070707, 0x03030303);\r
                        std::vector<int16_t> audio_data(frame->audio_data().begin(), frame->audio_data().end());\r
                        return make_safe<read_frame>(std::move(key_data), std::move(audio_data));\r
@@ -131,12 +130,12 @@ public:
                                        \r
        void send(const safe_ptr<read_frame>& frame)\r
        {               \r
-               executor_.begin_invoke([=]\r
+               context_.invoke([=]\r
                {\r
                        if(!has_synchronization_clock())\r
                                timer_.tick(1.0/format_desc_.fps);\r
 \r
-                       diag_->set_value("input-buffer", static_cast<float>(executor_.size())/static_cast<float>(executor_.capacity()));\r
+                       diag_->set_value("input-buffer", static_cast<float>(context_.size())/static_cast<float>(context_.capacity()));\r
                        frame_timer_.restart();\r
                                                \r
                        buffer_.push_back(std::make_pair(frame, get_key_frame(frame)));\r
@@ -156,12 +155,12 @@ public:
                        diag_->update_value("tick-time", tick_timer_.elapsed()*format_desc_.fps*0.5);\r
                        tick_timer_.restart();\r
                });\r
-               diag_->set_value("input-buffer", static_cast<float>(executor_.size())/static_cast<float>(executor_.capacity()));\r
+               diag_->set_value("input-buffer", static_cast<float>(context_.size())/static_cast<float>(context_.capacity()));\r
        }\r
        \r
        void set_video_format_desc(const video_format_desc& format_desc)\r
        {\r
-               executor_.invoke([&]\r
+               context_.invoke([&]\r
                {\r
                        format_desc_ = format_desc;\r
                        buffer_.clear();\r
@@ -198,8 +197,8 @@ public:
        }\r
 };\r
 \r
-frame_consumer_device::frame_consumer_device(const video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl) \r
-       : impl_(new implementation(format_desc, ogl)){}\r
+frame_consumer_device::frame_consumer_device(executor& context, const video_format_desc& format_desc, ogl_device& ogl) \r
+       : impl_(new implementation(context, format_desc, ogl)){}\r
 void frame_consumer_device::add(int index, safe_ptr<frame_consumer>&& consumer){impl_->add(index, std::move(consumer));}\r
 void frame_consumer_device::remove(int index){impl_->remove(index);}\r
 void frame_consumer_device::send(const safe_ptr<read_frame>& future_frame) { impl_->send(future_frame); }\r
index cadfd545a4d2a8761727c52f497403a5fa3e1759..593c4cd6b4c4251073453dc59d957e141ecb699d 100644 (file)
 \r
 #include <boost/noncopyable.hpp>\r
 \r
-namespace caspar { namespace core {\r
+namespace caspar { \r
+       \r
+class executor;\r
+       \r
+namespace core {\r
        \r
 class basic_frame;\r
 struct video_format_desc;\r
@@ -34,7 +38,7 @@ class ogl_device;
 class frame_consumer_device : boost::noncopyable\r
 {\r
 public:\r
-       explicit frame_consumer_device(const video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl);\r
+       explicit frame_consumer_device(executor& context, const video_format_desc& format_desc, ogl_device& ogl);\r
 \r
        void add(int index, safe_ptr<frame_consumer>&& consumer);\r
        void remove(int index);\r
index 28c4de5b4273b200197d9f62f62d500eb5dcbb0f..7e4c77628fa5ae5ce24be267a21faa3bedd81316 100644 (file)
     <ClInclude Include="mixer\image\image_mixer.h" />\r
     <ClInclude Include="mixer\read_frame.h" />\r
     <ClInclude Include="mixer\write_frame.h" />\r
-    <ClInclude Include="producer\destroy_producer_proxy.h" />\r
     <ClInclude Include="producer\color\color_producer.h" />\r
     <ClInclude Include="producer\frame\audio_transform.h" />\r
     <ClInclude Include="producer\frame\basic_frame.h" />\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
-    <ClCompile Include="producer\destroy_producer_proxy.cpp">\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
-    </ClCompile>\r
     <ClCompile Include="producer\color\color_producer.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
index 72bd0b4a7d93ed774db4b41e4b36ae6b0163babe..3ae4332ea4e1ad5b02152cbbcf6b1b7164133eef 100644 (file)
     <ClInclude Include="mixer\frame_mixer_device.h">\r
       <Filter>mixer</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="producer\destroy_producer_proxy.h">\r
-      <Filter>producer</Filter>\r
-    </ClInclude>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClCompile Include="producer\transition\transition_producer.cpp">\r
     <ClCompile Include="mixer\write_frame.cpp">\r
       <Filter>mixer</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="producer\destroy_producer_proxy.cpp">\r
-      <Filter>producer</Filter>\r
-    </ClCompile>\r
   </ItemGroup>\r
 </Project>
\ No newline at end of file
index e7bf452fd5f396131981f26cbdc43fde8c934e6a..953bfa20ed1f48d8f4a926dc78fda95b69bc9834 100644 (file)
@@ -104,26 +104,21 @@ struct frame_mixer_device::implementation : boost::noncopyable
        \r
        boost::fusion::map<boost::fusion::pair<core::image_transform, tweened_transform<core::image_transform>>,\r
                                        boost::fusion::pair<core::audio_transform, tweened_transform<core::audio_transform>>> root_transforms_;\r
-\r
-       safe_ptr<ogl_device> ogl_;\r
-\r
-       executor executor_;\r
+       \r
+       executor& context_;\r
 public:\r
-       implementation(const core::video_format_desc& format_desc, const output_t& output, const safe_ptr<ogl_device>& ogl) \r
+       implementation(executor& context, const core::video_format_desc& format_desc, const output_t& output, ogl_device& ogl) \r
                : format_desc_(format_desc)\r
                , diag_(diagnostics::create_graph(narrow(print())))\r
                , image_mixer_(format_desc, ogl)\r
                , output_(output)\r
-               , ogl_(ogl)\r
-               , executor_(L"frame_mixer_device")\r
+               , context_(context)\r
        {\r
                diag_->add_guide("frame-time", 0.5f);   \r
                diag_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
                diag_->set_color("tick-time", diagnostics::color(0.1f, 0.7f, 0.8f));\r
                diag_->set_color("input-buffer", diagnostics::color(1.0f, 1.0f, 0.0f)); \r
-               executor_.set_capacity(1);      \r
-               executor_.set_priority_class(above_normal_priority_class);\r
-\r
+       \r
                CASPAR_LOG(info) << print() << L" Successfully initialized.";   \r
        }\r
        \r
@@ -181,22 +176,22 @@ public:
                \r
        void send(const std::map<int, safe_ptr<core::basic_frame>>& frames)\r
        {                       \r
-               executor_.invoke([=]\r
+               context_.invoke([=]\r
                {               \r
-                       diag_->set_value("input-buffer", static_cast<float>(executor_.size())/static_cast<float>(executor_.capacity()));        \r
+                       diag_->set_value("input-buffer", static_cast<float>(context_.size())/static_cast<float>(context_.capacity()));  \r
                        frame_timer_.restart();\r
 \r
                        auto image = mix_image(frames);\r
                        auto audio = mix_audio(frames);\r
                        \r
-                       diag_->update_value("frame-time", static_cast<float>(frame_timer_.elapsed()*format_desc_.fps*0.5));\r
+                       diag_->update_value("frame-time", frame_timer_.elapsed()*format_desc_.fps*0.5);\r
 \r
                        output_(make_safe<read_frame>(std::move(image), std::move(audio)));\r
 \r
-                       diag_->update_value("tick-time", static_cast<float>(tick_timer_.elapsed()*format_desc_.fps*0.5));\r
+                       diag_->update_value("tick-time", tick_timer_.elapsed()*format_desc_.fps*0.5);\r
                        tick_timer_.restart();\r
                });\r
-               diag_->set_value("input-buffer", static_cast<float>(executor_.size())/static_cast<float>(executor_.capacity()));\r
+               diag_->set_value("input-buffer", static_cast<float>(context_.size())/static_cast<float>(context_.capacity()));\r
        }\r
                \r
        safe_ptr<core::write_frame> create_frame(void* tag, const core::pixel_format_desc& desc)\r
@@ -207,7 +202,7 @@ public:
        template<typename T>    \r
        void set_transform(const T& transform, unsigned int mix_duration, const std::wstring& tween)\r
        {\r
-               executor_.invoke([&]\r
+               context_.invoke([&]\r
                {\r
                        auto& root = boost::fusion::at_key<T>(root_transforms_);\r
 \r
@@ -220,7 +215,7 @@ public:
        template<typename T>\r
        void set_transform(int index, const T& transform, unsigned int mix_duration, const std::wstring& tween)\r
        {\r
-               executor_.invoke([&]\r
+               context_.invoke([&]\r
                {\r
                        auto& transforms = boost::fusion::at_key<T>(transforms_);\r
 \r
@@ -233,7 +228,7 @@ public:
        template<typename T>\r
        void apply_transform(const std::function<T(const T&)>& transform, unsigned int mix_duration, const std::wstring& tween)\r
        {\r
-               return executor_.invoke([&]\r
+               return context_.invoke([&]\r
                {\r
                        auto& root = boost::fusion::at_key<T>(root_transforms_);\r
 \r
@@ -246,7 +241,7 @@ public:
        template<typename T>\r
        void apply_transform(int index, const std::function<T(T)>& transform, unsigned int mix_duration, const std::wstring& tween)\r
        {\r
-               executor_.invoke([&]\r
+               context_.invoke([&]\r
                {\r
                        auto& transforms = boost::fusion::at_key<T>(transforms_);\r
 \r
@@ -259,7 +254,7 @@ public:
        template<typename T>\r
        void reset_transform(unsigned int mix_duration, const std::wstring& tween)\r
        {\r
-               executor_.invoke([&]\r
+               context_.invoke([&]\r
                {\r
                        auto& transforms = boost::fusion::at_key<T>(transforms_);\r
 \r
@@ -272,7 +267,7 @@ public:
        template<typename T>\r
        void reset_transform(int index, unsigned int mix_duration, const std::wstring& tween)\r
        {\r
-               executor_.invoke([&]\r
+               context_.invoke([&]\r
                {               \r
                        set_transform(T(), mix_duration, tween);\r
                });\r
@@ -284,9 +279,8 @@ public:
        }\r
 };\r
        \r
-frame_mixer_device::frame_mixer_device(const core::video_format_desc& format_desc, const output_t& output, const safe_ptr<ogl_device>& ogl)\r
-       : impl_(new implementation(format_desc, output, ogl)){}\r
-frame_mixer_device::frame_mixer_device(frame_mixer_device&& other) : impl_(std::move(other.impl_)){}\r
+frame_mixer_device::frame_mixer_device(executor& context, const core::video_format_desc& format_desc, const output_t& output, ogl_device& ogl)\r
+       : impl_(new implementation(context, format_desc, output, ogl)){}\r
 void frame_mixer_device::send(const std::map<int, safe_ptr<core::basic_frame>>& frames){impl_->send(frames);}\r
 const core::video_format_desc& frame_mixer_device::get_video_format_desc() const { return impl_->format_desc_; }\r
 safe_ptr<core::write_frame> frame_mixer_device::create_frame(void* tag, const core::pixel_format_desc& desc){ return impl_->create_frame(tag, desc); }         \r
index e2992a76845d4988557d4741253f5bc06c09d493..b6d58be5a6370c1171ca254093628277cc5e193b 100644 (file)
@@ -28,6 +28,8 @@
 #include <map>\r
 \r
 namespace caspar { \r
+\r
+class executor;\r
        \r
 namespace core {\r
 \r
@@ -43,8 +45,7 @@ class frame_mixer_device : public core::frame_factory
 public:        \r
        typedef std::function<void(const safe_ptr<core::read_frame>&)> output_t;\r
 \r
-       frame_mixer_device(const core::video_format_desc& format_desc, const output_t& output, const safe_ptr<ogl_device>& ogl);\r
-       frame_mixer_device(frame_mixer_device&& other); // nothrow\r
+       frame_mixer_device(executor& context, const core::video_format_desc& format_desc, const output_t& output, ogl_device& ogl);\r
                \r
        void send(const std::map<int, safe_ptr<core::basic_frame>>& frames); // nothrow\r
                \r
index 032bf0dfae433e4db4522ec8afffc09752825c7f..db9354ee61091ec66cee6c7a81968f2b1fed6af8 100644 (file)
@@ -28,6 +28,7 @@
 #include <tbb/concurrent_unordered_map.h>\r
 #include <tbb/concurrent_queue.h>\r
 \r
+#include <boost/noncopyable.hpp>\r
 #include <boost/thread/future.hpp>\r
 \r
 #include <array>\r
@@ -36,7 +37,7 @@
 \r
 namespace caspar { namespace core {\r
 \r
-class ogl_device\r
+class ogl_device : boost::noncopyable\r
 {      \r
        std::unique_ptr<sf::Context> context_;\r
        \r
index 9b01935ec4e5456884c105aa0456ae2f9e996104..87070755f914a0740f68f80e10bcfac8a348863e 100644 (file)
@@ -61,7 +61,7 @@ struct image_mixer::implementation : boost::noncopyable
        \r
        image_kernel kernel_;\r
        \r
-       safe_ptr<ogl_device> ogl_;\r
+       ogl_device& ogl_;\r
        \r
        safe_ptr<host_buffer>   read_buffer_;\r
        safe_ptr<device_buffer> draw_buffer_;\r
@@ -74,14 +74,14 @@ struct image_mixer::implementation : boost::noncopyable
        bool layer_key_;\r
        \r
 public:\r
-       implementation(const core::video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl) \r
+       implementation(const core::video_format_desc& format_desc, ogl_device& ogl) \r
                : format_desc_(format_desc)\r
                , ogl_(ogl)\r
-               , read_buffer_(ogl_->create_host_buffer(format_desc_.size, host_buffer::read_only))\r
-               , draw_buffer_(ogl_->create_device_buffer(format_desc.width, format_desc.height, 4))\r
-               , write_buffer_ (ogl_->create_device_buffer(format_desc.width, format_desc.height, 4))\r
-               , local_key_buffer_(ogl_->create_device_buffer(format_desc.width, format_desc.height, 1))\r
-               , layer_key_buffer_(ogl_->create_device_buffer(format_desc.width, format_desc.height, 1))\r
+               , read_buffer_(ogl_.create_host_buffer(format_desc_.size, host_buffer::read_only))\r
+               , draw_buffer_(ogl_.create_device_buffer(format_desc.width, format_desc.height, 4))\r
+               , write_buffer_ (ogl_.create_device_buffer(format_desc.width, format_desc.height, 4))\r
+               , local_key_buffer_(ogl_.create_device_buffer(format_desc.width, format_desc.height, 1))\r
+               , layer_key_buffer_(ogl_.create_device_buffer(format_desc.width, format_desc.height, 1))\r
                , local_key_(false)\r
                , layer_key_(false)\r
        {\r
@@ -116,7 +116,7 @@ public:
        boost::unique_future<safe_ptr<host_buffer>> render()\r
        {               \r
                auto read_buffer = read_buffer_;\r
-               auto result = ogl_->begin_invoke([=]()  -> safe_ptr<host_buffer>\r
+               auto result = ogl_.begin_invoke([=]()  -> safe_ptr<host_buffer>\r
                {\r
                        read_buffer->map();\r
                        return read_buffer;\r
@@ -124,7 +124,7 @@ public:
 \r
                auto render_queue = std::move(render_queue_);\r
 \r
-               ogl_->begin_invoke([=]() mutable\r
+               ogl_.begin_invoke([=]() mutable\r
                {\r
                        local_key_ = false;\r
                        layer_key_ = false;\r
@@ -147,7 +147,7 @@ public:
                                {\r
                                        draw(layer.front());\r
                                        layer.pop();\r
-                                       ogl_->yield(); // Allow quick buffer allocation to execute.\r
+                                       ogl_.yield(); // Allow quick buffer allocation to execute.\r
                                }\r
 \r
                                layer_key_ = local_key_; // If there was only key in last layer then use it as key for the entire next layer.\r
@@ -159,7 +159,7 @@ public:
                        std::swap(draw_buffer_, write_buffer_);\r
 \r
                        // Start transfer from device to host.  \r
-                       read_buffer_ = ogl_->create_host_buffer(format_desc_.size, host_buffer::read_only);                                     \r
+                       read_buffer_ = ogl_.create_host_buffer(format_desc_.size, host_buffer::read_only);                                      \r
                        write_buffer_->write(*read_buffer_);\r
                });\r
 \r
@@ -210,25 +210,11 @@ public:
                        \r
        safe_ptr<write_frame> create_frame(void* tag, const core::pixel_format_desc& desc)\r
        {\r
-               std::vector<safe_ptr<host_buffer>> buffers;\r
-               std::vector<safe_ptr<device_buffer>> textures;\r
-               ogl_->invoke([&]\r
-               {\r
-                       std::transform(desc.planes.begin(), desc.planes.end(), std::back_inserter(buffers), [&](const core::pixel_format_desc::plane& plane)\r
-                       {\r
-                               return ogl_->create_host_buffer(plane.size, host_buffer::write_only);\r
-                       });\r
-                       std::transform(desc.planes.begin(), desc.planes.end(), std::back_inserter(textures), [&](const core::pixel_format_desc::plane& plane)\r
-                       {\r
-                               return ogl_->create_device_buffer(plane.width, plane.height, plane.channels);\r
-                       });\r
-               });\r
-\r
-               return make_safe<write_frame>(reinterpret_cast<int>(tag), desc, buffers, textures, ogl_);\r
+               return make_safe<write_frame>(ogl_, reinterpret_cast<int>(tag), desc);\r
        }\r
 };\r
 \r
-image_mixer::image_mixer(const core::video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl) : impl_(new implementation(format_desc, ogl)){}\r
+image_mixer::image_mixer(const core::video_format_desc& format_desc, ogl_device& ogl) : impl_(new implementation(format_desc, ogl)){}\r
 void image_mixer::begin(const core::basic_frame& frame){impl_->begin(frame);}\r
 void image_mixer::visit(core::write_frame& frame){impl_->visit(frame);}\r
 void image_mixer::end(){impl_->end();}\r
index e6589df2cc9753718dd700c1177908bab3e9b974..6cf7a19d536922e28c945f5e2a42d1585cd3e4a9 100644 (file)
 */\r
 #pragma once\r
 \r
-#include "../write_frame.h"\r
-\r
 #include <common/memory/safe_ptr.h>\r
 \r
 #include <core/video_format.h>\r
 #include <core/producer/frame/frame_visitor.h>\r
 #include <core/producer/frame/pixel_format.h>\r
 \r
-#include "../gpu/host_buffer.h"\r
-\r
 #include <boost/noncopyable.hpp>\r
 #include <boost/thread/future.hpp>\r
 \r
-#include <vector>\r
-\r
 namespace caspar { namespace core {\r
-       \r
+\r
+class write_frame;\r
+class host_buffer;\r
 class ogl_device;\r
 \r
 class image_mixer : public core::frame_visitor, boost::noncopyable\r
 {\r
 public:\r
-       image_mixer(const core::video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl);\r
+       image_mixer(const core::video_format_desc& format_desc, ogl_device& ogl);\r
        \r
        virtual void begin(const core::basic_frame& frame);\r
        virtual void visit(core::write_frame& frame);\r
index 4dbb43cde685928306784d0aec8ca8f141aede11..2d7a70775479bc36a4036e70d4e777469e3b719e 100644 (file)
@@ -32,21 +32,31 @@ namespace caspar { namespace core {
                                                                                                                                                                                                                                                                                                                        \r
 struct write_frame::implementation : boost::noncopyable\r
 {                              \r
-       safe_ptr<ogl_device> ogl_;\r
-       std::vector<safe_ptr<host_buffer>> buffers_;\r
-       std::vector<safe_ptr<device_buffer>> textures_;\r
-       std::vector<int16_t> audio_data_;\r
-       const core::pixel_format_desc desc_;\r
-       int32_t tag_;\r
+       ogl_device&                                                             ogl_;\r
+       std::vector<safe_ptr<host_buffer>>              buffers_;\r
+       std::vector<safe_ptr<device_buffer>>    textures_;\r
+       std::vector<int16_t>                                    audio_data_;\r
+       const core::pixel_format_desc                   desc_;\r
+       int32_t                                                                 tag_;\r
 \r
 public:\r
-       implementation(int32_t tag, const core::pixel_format_desc& desc, const std::vector<safe_ptr<host_buffer>>& buffers, const std::vector<safe_ptr<device_buffer>>& textures, const safe_ptr<ogl_device> ogl\r
+       implementation(ogl_device& ogl, int32_t tag, const core::pixel_format_desc& desc\r
                : ogl_(ogl)\r
-               , buffers_(buffers)\r
-               , textures_(textures)\r
                , desc_(desc)\r
                , tag_(tag)\r
-       {}\r
+       {\r
+               ogl_.invoke([&]\r
+               {\r
+                       std::transform(desc.planes.begin(), desc.planes.end(), std::back_inserter(buffers_), [&](const core::pixel_format_desc::plane& plane)\r
+                       {\r
+                               return ogl_.create_host_buffer(plane.size, host_buffer::write_only);\r
+                       });\r
+                       std::transform(desc.planes.begin(), desc.planes.end(), std::back_inserter(textures_), [&](const core::pixel_format_desc::plane& plane)\r
+                       {\r
+                               return ogl_.create_device_buffer(plane.width, plane.height, plane.channels);\r
+                       });\r
+               });\r
+       }\r
        \r
        void accept(write_frame& self, core::frame_visitor& visitor)\r
        {\r
@@ -85,15 +95,15 @@ public:
                auto texture = textures_[plane_index];\r
                auto buffer = std::move(buffers_[plane_index]); // Release buffer once done.\r
 \r
-               ogl_->begin_invoke([=]\r
+               ogl_.begin_invoke([=]\r
                {\r
                        texture->read(*buffer);\r
                });\r
        }\r
 };\r
        \r
-write_frame::write_frame(int32_t tag, const core::pixel_format_desc& desc, const std::vector<safe_ptr<host_buffer>>& buffers, const std::vector<safe_ptr<device_buffer>>& textures, const safe_ptr<ogl_device>& ogl\r
-       : impl_(new implementation(tag, desc, buffers, textures, ogl)){}\r
+write_frame::write_frame(ogl_device& ogl, int32_t tag, const core::pixel_format_desc& desc\r
+       : impl_(new implementation(ogl, tag, desc)){}\r
 void write_frame::accept(core::frame_visitor& visitor){impl_->accept(*this, visitor);}\r
 \r
 boost::iterator_range<uint8_t*> write_frame::image_data(size_t index){return impl_->image_data(index);}\r
index 0619fe0655b166fbf09e76f9885e558c63e10f3d..05f0204ace40a716d209934436e031f7aa93c9e9 100644 (file)
@@ -41,7 +41,7 @@ class ogl_device;
 class write_frame : public core::basic_frame, boost::noncopyable\r
 {\r
 public:        \r
-       explicit write_frame(int tag, const core::pixel_format_desc& desc, const std::vector<safe_ptr<host_buffer>>& buffers, const std::vector<safe_ptr<device_buffer>>& textures, const safe_ptr<ogl_device>& ogl);\r
+       explicit write_frame(ogl_device& ogl, int tag, const core::pixel_format_desc& desc);\r
                        \r
        virtual boost::iterator_range<uint8_t*> image_data(size_t plane_index = 0);     \r
        virtual std::vector<int16_t>& audio_data();\r
index d35abdbdc87ec767656a88ece2700d29a175942c..a788a30b2a7ae132d394ab6674c5238ecbeb068a 100644 (file)
@@ -23,7 +23,6 @@
 #include "frame_producer_device.h"\r
 \r
 #include "layer.h"\r
-#include "destroy_producer_proxy.h"\r
 \r
 #include <core/producer/frame/basic_frame.h>\r
 #include <core/producer/frame/frame_factory.h>\r
 #include <map>\r
 \r
 namespace caspar { namespace core {\r
+               \r
+void destroy_producer(safe_ptr<frame_producer>& producer)\r
+{\r
+       if(!producer.unique())\r
+               CASPAR_LOG(warning) << producer->print() << L" Not destroyed on safe asynchronous destruction thread.";\r
+               \r
+       producer = frame_producer::empty();\r
+}\r
+\r
+class destroy_producer_proxy : public frame_producer\r
+{\r
+       safe_ptr<frame_producer> producer_;\r
+       executor& destroy_context_;\r
+public:\r
+       destroy_producer_proxy(executor& destroy_context, const safe_ptr<frame_producer>& producer) \r
+               : producer_(producer)\r
+               , destroy_context_(destroy_context){}\r
+\r
+       ~destroy_producer_proxy()\r
+       {               \r
+               if(destroy_context_.size() > 4)\r
+                       CASPAR_LOG(error) << L" Potential destroyer deadlock.";\r
+\r
+               destroy_context_.begin_invoke(std::bind(&destroy_producer, std::move(producer_)));\r
+       }\r
+\r
+       virtual safe_ptr<basic_frame>           receive()                                                                                                               {return core::receive(producer_);}\r
+       virtual std::wstring                            print() const                                                                                                   {return producer_->print();}\r
+       virtual void                                            param(const std::wstring& str)                                                                  {producer_->param(str);}\r
+       virtual safe_ptr<frame_producer>        get_following_producer() const                                                                  {return producer_->get_following_producer();}\r
+       virtual void                                            set_leading_producer(const safe_ptr<frame_producer>& producer)  {producer_->set_leading_producer(producer);}\r
+};\r
 \r
 struct frame_producer_device::implementation : boost::noncopyable\r
 {              \r
@@ -50,12 +81,14 @@ struct frame_producer_device::implementation : boost::noncopyable
        boost::timer                             tick_timer_;\r
        boost::timer                             output_timer_;\r
        \r
-       executor                                        executor_;\r
+       executor&                                        context_;\r
+       executor&                                        destroy_context_;\r
 public:\r
-       implementation(const video_format_desc& format_desc, const output_t& output)  \r
+       implementation(executor& context, executor& destroy_context, const video_format_desc& format_desc, const output_t& output)  \r
                : format_desc_(format_desc)\r
                , diag_(diagnostics::create_graph(std::string("frame_producer_device")))\r
-               , executor_(L"frame_producer_device")\r
+               , context_(context)\r
+               , destroy_context_(destroy_context)\r
                , output_(output)\r
        {\r
                diag_->add_guide("frame-time", 0.5f);   \r
@@ -63,8 +96,7 @@ public:
                diag_->set_color("tick-time", diagnostics::color(0.1f, 0.7f, 0.8f));\r
                diag_->set_color("output-time", diagnostics::color(0.5f, 1.0f, 0.2f));\r
 \r
-               executor_.set_priority_class(above_normal_priority_class);\r
-               executor_.begin_invoke([=]{tick();});           \r
+               context_.begin_invoke([=]{tick();});            \r
        }\r
                        \r
        void tick()\r
@@ -81,7 +113,7 @@ public:
                        CASPAR_LOG_CURRENT_EXCEPTION();\r
                }\r
 \r
-               executor_.begin_invoke([=]{tick();});\r
+               context_.begin_invoke([=]{tick();});\r
        }\r
                        \r
        std::map<int, safe_ptr<basic_frame>> render()\r
@@ -107,37 +139,37 @@ public:
 \r
        void load(int index, const safe_ptr<frame_producer>& producer, bool preview)\r
        {\r
-               executor_.invoke([&]{layers_[index].load(make_safe<destroy_producer_proxy>(producer), preview);});\r
+               context_.invoke([&]{layers_[index].load(make_safe<destroy_producer_proxy>(destroy_context_, producer), preview);});\r
        }\r
 \r
        void pause(int index)\r
        {               \r
-               executor_.invoke([&]{layers_[index].pause();});\r
+               context_.invoke([&]{layers_[index].pause();});\r
        }\r
 \r
        void play(int index)\r
        {               \r
-               executor_.invoke([&]{layers_[index].play();});\r
+               context_.invoke([&]{layers_[index].play();});\r
        }\r
 \r
        void stop(int index)\r
        {               \r
-               executor_.invoke([&]{layers_[index].stop();});\r
+               context_.invoke([&]{layers_[index].stop();});\r
        }\r
 \r
        void clear(int index)\r
        {\r
-               executor_.invoke([&]{layers_.erase(index);});\r
+               context_.invoke([&]{layers_.erase(index);});\r
        }\r
                \r
        void clear()\r
        {\r
-               executor_.invoke([&]{layers_.clear();});\r
+               context_.invoke([&]{layers_.clear();});\r
        }       \r
        \r
        void swap_layer(int index, size_t other_index)\r
        {\r
-               executor_.invoke([&]{layers_[index].swap(layers_[other_index]);});\r
+               context_.invoke([&]{layers_[index].swap(layers_[other_index]);});\r
        }\r
 \r
        void swap_layer(int index, size_t other_index, frame_producer_device& other)\r
@@ -151,7 +183,7 @@ public:
 \r
                        auto func = [&]{layers_[index].swap(other.impl_->layers_[other_index]);};\r
                \r
-                       executor_.invoke([&]{other.impl_->executor_.invoke(func);});\r
+                       context_.invoke([&]{other.impl_->context_.invoke(func);});\r
                }\r
        }\r
 \r
@@ -178,21 +210,22 @@ public:
                        });                                     \r
                };\r
                \r
-               executor_.invoke([&]{other.impl_->executor_.invoke(func);});\r
+               context_.invoke([&]{other.impl_->context_.invoke(func);});\r
        }\r
        \r
        boost::unique_future<safe_ptr<frame_producer>> foreground(int index)\r
        {\r
-               return executor_.begin_invoke([=]{return layers_[index].foreground();});\r
+               return context_.begin_invoke([=]{return layers_[index].foreground();});\r
        }\r
        \r
        boost::unique_future<safe_ptr<frame_producer>> background(int index)\r
        {\r
-               return executor_.begin_invoke([=]{return layers_[index].background();});\r
+               return context_.begin_invoke([=]{return layers_[index].background();});\r
        }\r
 };\r
 \r
-frame_producer_device::frame_producer_device(const video_format_desc& format_desc, const output_t& output) : impl_(new implementation(format_desc, output)){}\r
+frame_producer_device::frame_producer_device(executor& context, executor& destroy_context, const video_format_desc& format_desc, const output_t& output)\r
+       : impl_(new implementation(context, destroy_context, format_desc, output)){}\r
 frame_producer_device::frame_producer_device(frame_producer_device&& other) : impl_(std::move(other.impl_)){}\r
 void frame_producer_device::swap(frame_producer_device& other){impl_->swap(other);}\r
 void frame_producer_device::load(int index, const safe_ptr<frame_producer>& producer, bool preview){impl_->load(index, producer, preview);}\r
index d8d9ca3b30217c06c4c54013b5a4002319662165..ff27c282b7861d1d9ee84b17b6ab9746f634d833 100644 (file)
 \r
 #include <functional>\r
 \r
-namespace caspar { namespace core {\r
+namespace caspar { \r
+       \r
+class executor;\r
+\r
+namespace core {\r
 \r
 struct video_format_desc;\r
 \r
@@ -38,7 +42,7 @@ class frame_producer_device : boost::noncopyable
 public:\r
        typedef std::function<void(const std::map<int, safe_ptr<basic_frame>>&)> output_t;\r
 \r
-       explicit frame_producer_device(const video_format_desc& format_desc, const output_t& output);\r
+       explicit frame_producer_device(executor& context, executor& destroy_context, const video_format_desc& format_desc, const output_t& output);\r
        frame_producer_device(frame_producer_device&& other);\r
 \r
        void swap(frame_producer_device& other);\r
index aa8edf040b6eec3652c2d6f508b599ea87689c35..1eb540b125ead5ebcda2607fb1c4d88112f585ad 100644 (file)
@@ -227,7 +227,7 @@ int main(int argc, wchar_t* argv[])
                                wcmd = L"MIXER 1 VIDEO GRID " + boost::lexical_cast<std::wstring>(n);\r
 \r
                                for(int i = 1; i <= num; ++i)\r
-                                       wcmd += L"\r\nPLAY 1-" + boost::lexical_cast<std::wstring>(i) + L" " + file + L" SLIDE 100 LOOP";\r
+                                       wcmd += L"\r\nPLAY 1-" + boost::lexical_cast<std::wstring>(i) + L" " + file + L" LOOP";// + L" SLIDE 100 LOOP";\r
                        }\r
 \r
                        wcmd += L"\r\n";\r
index 204e54dd33d5d94152edbc5181cd5f95b9f69b80..c83565b208ec82ad1aecfea2fbfdaa669e911f00 100644 (file)
@@ -64,7 +64,7 @@ struct server::implementation : boost::noncopyable
 {\r
        std::vector<safe_ptr<IO::AsyncEventServer>> async_servers_;     \r
        std::vector<safe_ptr<channel>>                          channels_;\r
-       safe_ptr<ogl_device>                                            ogl_;\r
+       ogl_device                                                                      ogl_;\r
 \r
        implementation()                                                                                                \r
        {                       \r