]> git.sesse.net Git - casparcg/commitdiff
2.0 image_mixer: Refactored, core: Fixed destruction proxy usage.
authorRonag <Ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Wed, 24 Aug 2011 21:17:27 +0000 (21:17 +0000)
committerRonag <Ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Wed, 24 Aug 2011 21:17:27 +0000 (21:17 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@1278 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

15 files changed:
common/common.vcxproj
common/common.vcxproj.filters
common/concurrency/executor.h
common/utility/move_on_copy.h [new file with mode: 0644]
core/mixer/image/image_kernel.h
core/mixer/image/image_mixer.cpp
core/producer/frame_producer.cpp
core/producer/frame_producer.h
core/producer/stage.cpp
core/video_channel.cpp
core/video_channel.h
core/video_channel_context.cpp
core/video_channel_context.h
protocol/amcp/AMCPCommandsImpl.cpp
shell/casparcg.config

index 7fada92e263050baf517875f6d6785a22c646834..3a7700691946bb6b4a11c9a8c09b0b66b5ac7b14 100644 (file)
     <ClInclude Include="os\windows\system_info.h" />\r
     <ClInclude Include="stdafx.h" />\r
     <ClInclude Include="utility\assert.h" />\r
+    <ClInclude Include="utility\move_on_copy.h" />\r
     <ClInclude Include="utility\string.h" />\r
     <ClInclude Include="utility\timer.h" />\r
     <ClInclude Include="utility\tweener.h" />\r
index 4ebf73f0d83e0ecb1a0717d2ed8397dee64f38e3..54cce3a53fc4219395c28ca04e27ecfe0f2136df 100644 (file)
     <ClInclude Include="env.h">\r
       <Filter>source</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="utility\move_on_copy.h">\r
+      <Filter>source\utility</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
 </Project>
\ No newline at end of file
index c4ba4008f95af44af38d5601afed9a238813af0c..0687889a179a951b0d2e14d82a9162941a4d03dd 100644 (file)
@@ -21,6 +21,7 @@
 \r
 #include "../exception/win32_exception.h"\r
 #include "../utility/string.h"\r
+#include "../utility/move_on_copy.h"\r
 #include "../log/log.h"\r
 \r
 #include <tbb/atomic.h>\r
@@ -76,23 +77,6 @@ enum thread_priority
        below_normal_priority_class\r
 };\r
 \r
-namespace internal\r
-{\r
-       template<typename T>\r
-       struct move_on_copy\r
-       {\r
-               move_on_copy(const move_on_copy<T>& other) : value(std::move(other.value)){}\r
-               move_on_copy(T&& value) : value(std::move(value)){}\r
-               mutable T value;\r
-       };\r
-\r
-       template<typename T>\r
-       move_on_copy<T> make_move_on_copy(T&& value)\r
-       {\r
-               return move_on_copy<T>(std::move(value));\r
-       }\r
-}\r
-\r
 class executor : boost::noncopyable\r
 {\r
        const std::string name_;\r
@@ -133,6 +117,7 @@ public:
        virtual ~executor() // noexcept\r
        {\r
                stop();\r
+               execution_queue_[normal_priority].try_push([]{}); // Wake the execution thread.\r
                join();\r
        }\r
 \r
@@ -159,7 +144,6 @@ public:
        void stop() // noexcept\r
        {\r
                is_running_ = false;    \r
-               execution_queue_[normal_priority].try_push([]{}); // Wake the execution thread.\r
        }\r
 \r
        void wait() // noexcept\r
@@ -177,7 +161,7 @@ public:
        auto begin_invoke(Func&& func, task_priority priority = normal_priority) -> boost::unique_future<decltype(func())> // noexcept\r
        {       \r
                // Create a move on copy adaptor to avoid copying the functor into the queue, tbb::concurrent_queue does not support move semantics.\r
-               auto task_adaptor = internal::make_move_on_copy(create_task(func));\r
+               auto task_adaptor = make_move_on_copy(create_task(func));\r
 \r
                auto future = task_adaptor.value.get_future();\r
 \r
@@ -198,7 +182,7 @@ public:
        auto try_begin_invoke(Func&& func, task_priority priority = normal_priority) -> boost::unique_future<decltype(func())> // noexcept\r
        {\r
                // Create a move on copy adaptor to avoid copying the functor into the queue, tbb::concurrent_queue does not support move semantics.\r
-               auto task_adaptor = internal::make_move_on_copy(create_task(func));\r
+               auto task_adaptor = make_move_on_copy(create_task(func));\r
                \r
                auto future = task_adaptor.value.get_future();\r
 \r
diff --git a/common/utility/move_on_copy.h b/common/utility/move_on_copy.h
new file mode 100644 (file)
index 0000000..99774d1
--- /dev/null
@@ -0,0 +1,19 @@
+#pragma once\r
+\r
+namespace caspar {\r
+               \r
+template<typename T>\r
+struct move_on_copy\r
+{\r
+       move_on_copy(const move_on_copy<T>& other) : value(std::move(other.value)){}\r
+       move_on_copy(T&& value) : value(std::move(value)){}\r
+       mutable T value;\r
+};\r
+\r
+template<typename T>\r
+move_on_copy<T> make_move_on_copy(T&& value)\r
+{\r
+       return move_on_copy<T>(std::move(value));\r
+}\r
+\r
+}
\ No newline at end of file
index 2e6051fef2880b211d98a4bf10548933a5ed2d12..2af0d5bcf60bb4326bf2f18809bc0e3b5484acf6 100644 (file)
@@ -39,6 +39,8 @@ struct render_item
        std::vector<safe_ptr<device_buffer>>    textures;\r
        frame_transform                                                 transform;\r
        blend_mode::type                                                blend_mode;\r
+\r
+       render_item() : blend_mode(blend_mode::normal){}\r
 };\r
 \r
 bool operator==(const render_item& lhs, const render_item& rhs);\r
index eda73da2f3af2a2ed7eb612998ab1057a155a3ba..941e28d6c58fbbe18dd1c16af9671678bc07b915 100644 (file)
@@ -30,6 +30,7 @@
 \r
 #include <common/exception/exceptions.h>\r
 #include <common/gl/gl_check.h>\r
+#include <common/utility/move_on_copy.h>\r
 \r
 #include <core/producer/frame/frame_transform.h>\r
 #include <core/producer/frame/pixel_format.h>\r
@@ -46,7 +47,15 @@ using namespace boost::assign;
 \r
 namespace caspar { namespace core {\r
        \r
-typedef std::deque<render_item>                                layer;\r
+struct layer\r
+{\r
+       std::vector<render_item> items;\r
+       blend_mode::type                 blend_mode;\r
+\r
+       layer(blend_mode::type blend_mode) : blend_mode(blend_mode)\r
+       {\r
+       }\r
+};\r
 \r
 class image_renderer\r
 {\r
@@ -59,17 +68,17 @@ public:
        {\r
        }\r
        \r
-       boost::unique_future<safe_ptr<host_buffer>> render(std::deque<layer>&& layers)\r
+       boost::unique_future<safe_ptr<host_buffer>> render(std::vector<layer>&& layers)\r
        {               \r
-               auto layers2 = std::move(layers);\r
-               return channel_.ogl().begin_invoke([=]() mutable\r
+               auto layers2 = make_move_on_copy(std::move(layers));\r
+               return channel_.ogl().begin_invoke([=]\r
                {\r
-                       return do_render(std::move(layers2));\r
+                       return do_render(std::move(layers2.value));\r
                });\r
        }\r
        \r
 private:\r
-       safe_ptr<host_buffer> do_render(std::deque<layer>&& layers)\r
+       safe_ptr<host_buffer> do_render(std::vector<layer>&& layers)\r
        {\r
                std::shared_ptr<device_buffer> layer_key_buffer;\r
 \r
@@ -91,34 +100,30 @@ private:
 \r
        void draw_layer(layer&& layer, const safe_ptr<device_buffer>& draw_buffer, std::shared_ptr<device_buffer>& layer_key_buffer)\r
        {                               \r
-               if(layer.empty())\r
+               if(layer.items.empty())\r
                        return;\r
 \r
                std::pair<int, std::shared_ptr<device_buffer>> local_key_buffer = std::make_pair(0, nullptr); // int is fields flag\r
                                \r
-               if(layer.front().blend_mode != blend_mode::normal && has_overlapping_items(layer))\r
+               if(layer.blend_mode != blend_mode::normal && has_overlapping_items(layer))\r
                {\r
                        auto layer_draw_buffer = create_device_buffer(4); // int is fields flag\r
-                       auto layer_blend_mode = layer.front().blend_mode;\r
 \r
-                       BOOST_FOREACH(auto& item, layer)\r
-                       {\r
-                               item.blend_mode = blend_mode::normal; // Disable blending and just merge.\r
+                       BOOST_FOREACH(auto& item, layer.items)\r
                                draw_item(std::move(item), *layer_draw_buffer, local_key_buffer, layer_key_buffer);             \r
-                       }\r
-                       \r
+                                               \r
                        render_item item;\r
                        item.pix_desc.pix_fmt   = pixel_format::bgra;\r
                        item.pix_desc.planes    = list_of(pixel_format_desc::plane(channel_.get_format_desc().width, channel_.get_format_desc().height, 4));\r
                        item.textures                   = list_of(layer_draw_buffer);\r
                        item.transform                  = frame_transform();\r
-                       item.blend_mode                 = layer_blend_mode;\r
+                       item.blend_mode                 = layer.blend_mode;\r
 \r
                        kernel_.draw(channel_.ogl(), std::move(item), *draw_buffer, nullptr, nullptr);\r
                }\r
                else // fast path\r
                {\r
-                       BOOST_FOREACH(auto& item, layer)                \r
+                       BOOST_FOREACH(auto& item, layer.items)          \r
                                draw_item(std::move(item), *draw_buffer, local_key_buffer, layer_key_buffer);           \r
                }                                       \r
 \r
@@ -158,12 +163,12 @@ private:
 \r
        bool has_overlapping_items(const layer& layer)\r
        {               \r
-               auto upper_count = boost::range::count_if(layer, [&](const render_item& item)\r
+               auto upper_count = boost::range::count_if(layer.items, [&](const render_item& item)\r
                {\r
                        return !item.transform.is_key && (item.transform.field_mode & field_mode::upper);\r
                });\r
 \r
-               auto lower_count = boost::range::count_if(layer, [&](const render_item& item)\r
+               auto lower_count = boost::range::count_if(layer.items, [&](const render_item& item)\r
                {\r
                        return  !item.transform.is_key && (item.transform.field_mode & field_mode::lower);\r
                });\r
@@ -182,24 +187,21 @@ private:
                \r
 struct image_mixer::implementation : boost::noncopyable\r
 {      \r
-       ogl_device&                                                             ogl_;\r
-       image_renderer                                                  renderer_;\r
-       std::vector<frame_transform>                    transform_stack_;\r
-       blend_mode::type                                                active_blend_mode_;\r
-       std::deque<std::deque<render_item>>             layers_; // layer/stream/items\r
+       ogl_device&                                             ogl_;\r
+       image_renderer                                  renderer_;\r
+       std::vector<frame_transform>    transform_stack_;\r
+       std::vector<layer>                              layers_; // layer/stream/items\r
 public:\r
        implementation(video_channel_context& video_channel) \r
                : ogl_(video_channel.ogl())\r
                , renderer_(video_channel)\r
-               , transform_stack_(1)\r
-               , active_blend_mode_(blend_mode::normal)                \r
+               , transform_stack_(1)   \r
        {\r
        }\r
 \r
        void begin_layer(blend_mode::type blend_mode)\r
        {\r
-               active_blend_mode_ = blend_mode;\r
-               layers_ += layer();\r
+               layers_.push_back(layer(blend_mode));\r
        }\r
                \r
        void begin(core::basic_frame& frame)\r
@@ -216,9 +218,8 @@ public:
                item.pix_desc   = frame.get_pixel_format_desc();\r
                item.textures   = frame.get_textures();\r
                item.transform  = transform_stack_.back();\r
-               item.blend_mode = active_blend_mode_;   \r
 \r
-               layers_.back() += item;\r
+               layers_.back().items.push_back(item);\r
        }\r
 \r
        void end()\r
index f881d2adbb6d36353912b8cfb8b56b3c12e23335..a17fa10ba673003985e0392b23a8eafe211abfbf 100644 (file)
 #include "separated/separated_producer.h"\r
 \r
 #include <common/memory/safe_ptr.h>\r
+#include <common/concurrency/executor.h>\r
 #include <common/exception/exceptions.h>\r
+#include <common/utility/move_on_copy.h>\r
 \r
 namespace caspar { namespace core {\r
        \r
 std::vector<const producer_factory_t> g_factories;\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
+               // Hacks to bypass compiler bugs.\r
+               auto mov_producer = make_move_on_copy<safe_ptr<frame_producer>>(std::move(producer_));\r
+               auto empty_producer = frame_producer::empty();\r
+               destroy_context_.begin_invoke([=]\r
+               {                       \r
+                       if(!mov_producer.value.unique())\r
+                               CASPAR_LOG(debug) << mov_producer.value->print() << L" Not destroyed on safe asynchronous destruction thread.";\r
+                       else\r
+                               CASPAR_LOG(debug) << mov_producer.value->print() << L" Destroying on safe asynchronous destruction thread.";\r
+       \r
+                       mov_producer.value = empty_producer;\r
+               });\r
+       }\r
+\r
+       virtual safe_ptr<basic_frame>           receive(int hints)                                                                                              {return producer_->receive(hints);}\r
+       virtual safe_ptr<basic_frame>           last_frame() const                                                                                              {return producer_->last_frame();}\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
+       virtual int64_t                                         nb_frames() const                                                                                               {return producer_->nb_frames();}\r
+};\r
+\r
+safe_ptr<core::frame_producer> create_destroy_producer_proxy(executor& destroy_context, const safe_ptr<frame_producer>& producer)\r
+{\r
+       return make_safe<destroy_producer_proxy>(destroy_context, producer);\r
+}\r
 \r
 class last_frame_producer : public frame_producer\r
 {\r
index d2b1becdf9f83ba04bb4d35aa1941feabe03a203..830461d5b9841ca7a31c73bc28e0285033b1c88a 100644 (file)
 #include <stdint.h>\r
 #include <numeric>\r
 \r
-namespace caspar { namespace core {\r
+namespace caspar { \r
+       \r
+class executor;\r
+       \r
+namespace core {\r
 \r
 class basic_frame;\r
 struct frame_factory;\r
@@ -66,5 +70,6 @@ typedef std::function<safe_ptr<core::frame_producer>(const safe_ptr<frame_factor
 void register_producer_factory(const producer_factory_t& factory); // Not thread-safe.\r
 safe_ptr<core::frame_producer> create_producer(const safe_ptr<frame_factory>&, const std::vector<std::wstring>& params);\r
 \r
+safe_ptr<core::frame_producer> create_destroy_producer_proxy(executor& destroy_context, const safe_ptr<frame_producer>& producer);\r
 \r
 }}\r
index 6c7816ba91d345de3c42f583f86efb1fcf3e0759..9fe30bbd45b917d03a901138cba211c987a16e9f 100644 (file)
@@ -30,6 +30,7 @@
 #include <core/producer/frame/frame_factory.h>\r
 \r
 #include <common/concurrency/executor.h>\r
+#include <common/utility/move_on_copy.h>\r
 \r
 #include <boost/foreach.hpp>\r
 \r
 #include <set>\r
 \r
 namespace caspar { namespace core {\r
-       \r
-void destroy_producer(safe_ptr<frame_producer>& producer)\r
-{\r
-       if(!producer.unique())\r
-               CASPAR_LOG(debug) << 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(int hints)                                                                                              {return producer_->receive(hints);}\r
-       virtual safe_ptr<basic_frame>           last_frame() const                                                                                              {return producer_->last_frame();}\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
-       virtual int64_t                                         nb_frames() const                                                                                               {return producer_->nb_frames();}\r
-};\r
 \r
 struct stage::implementation : boost::noncopyable\r
 {              \r
@@ -111,7 +78,7 @@ public:
        {\r
                channel_.execution().invoke([&]\r
                {\r
-                       layers_[index].load(make_safe<destroy_producer_proxy>(channel_.destruction(), producer), preview, auto_play_delta);\r
+                       layers_[index].load(create_destroy_producer_proxy(channel_.destruction(), producer), preview, auto_play_delta);\r
                }, high_priority);\r
        }\r
 \r
index c1a37a78fe2c51814a73be1d0bc5ec8446562b92..267a821dbd50723cbc53edddbb2e18bdb2a5c2ae 100644 (file)
@@ -32,6 +32,8 @@
 #include <common/concurrency/executor.h>\r
 #include <common/diagnostics/graph.h>\r
 \r
+#include "mixer/gpu/ogl_device.h"\r
+\r
 #include <boost/timer.hpp>\r
 \r
 #ifdef _MSC_VER\r
@@ -151,5 +153,6 @@ safe_ptr<output> video_channel::output() { return impl_->output_;}
 video_format_desc video_channel::get_video_format_desc() const{return impl_->context_.get_format_desc();}\r
 void video_channel::set_video_format_desc(const video_format_desc& format_desc){impl_->set_video_format_desc(format_desc);}\r
 std::wstring video_channel::print() const { return impl_->print();}\r
+video_channel_context& video_channel::context(){return impl_->context_;}\r
 \r
 }}
\ No newline at end of file
index 2ca9c674c77ff927af3aee67ce9a5c4fc3e79ef7..7a0225b6b0395d99281ebd3a558b2564b5da654c 100644 (file)
@@ -31,6 +31,7 @@ class mixer;
 class output;\r
 class ogl_device;\r
 struct video_format_desc;\r
+class video_channel_context;\r
 \r
 class video_channel : boost::noncopyable\r
 {\r
@@ -42,6 +43,8 @@ public:
        safe_ptr<mixer> mixer();\r
        safe_ptr<output> output();\r
 \r
+       video_channel_context& context();\r
+\r
        video_format_desc get_video_format_desc() const;\r
        void set_video_format_desc(const video_format_desc& format_desc);\r
 \r
index 677c1180e9696daddd86c3c9a33587aee8f9d07a..84806b2a3c8db3705a0aa7713026415c5fc90f10 100644 (file)
@@ -4,38 +4,58 @@
 \r
 namespace caspar { namespace core {\r
 \r
+struct video_channel_context::implementation\r
+{              \r
+       mutable tbb::spin_rw_mutex      mutex_;\r
+       const int                                       index_;\r
+       video_format_desc                       format_desc_;\r
+       executor                                        execution_;\r
+       executor                                        destruction_;\r
+       ogl_device&                                     ogl_;\r
+\r
+       implementation(int index, ogl_device& ogl, const video_format_desc& format_desc)\r
+               : index_(index)\r
+               , format_desc_(format_desc)\r
+               , execution_(print() + L"/execution")\r
+               , destruction_(print() + L"/destruction")\r
+               , ogl_(ogl)\r
+       {\r
+               execution_.set_priority_class(above_normal_priority_class);\r
+               destruction_.set_priority_class(below_normal_priority_class);\r
+       }\r
+\r
+       std::wstring print() const\r
+       {\r
+               return L"video_channel[" + boost::lexical_cast<std::wstring>(index_+1) + L"|" +  format_desc_.name + L"]";\r
+       }\r
+};\r
+\r
 video_channel_context::video_channel_context(int index, ogl_device& ogl, const video_format_desc& format_desc) \r
-       : index_(index)\r
-       , format_desc_(format_desc)\r
-       , execution_(print() + L"/execution")\r
-       , destruction_(print() + L"/destruction")\r
-       , ogl_(ogl)\r
+       : impl_(new implementation(index, ogl, format_desc))\r
 {\r
-       execution_.set_priority_class(above_normal_priority_class);\r
-       destruction_.set_priority_class(below_normal_priority_class);\r
 }\r
 \r
-const int video_channel_context::index() const {return index_;}\r
+const int video_channel_context::index() const {return impl_->index_;}\r
 \r
 video_format_desc video_channel_context::get_format_desc()\r
 {\r
-       tbb::spin_rw_mutex::scoped_lock lock(mutex_, false);\r
-       return format_desc_;\r
+       tbb::spin_rw_mutex::scoped_lock lock(impl_->mutex_, false);\r
+       return impl_->format_desc_;\r
 }\r
 \r
 void video_channel_context::set_format_desc(const video_format_desc& format_desc)\r
 {\r
-       tbb::spin_rw_mutex::scoped_lock lock(mutex_, true);\r
-       format_desc_ = format_desc;\r
+       tbb::spin_rw_mutex::scoped_lock lock(impl_->mutex_, true);\r
+       impl_->format_desc_ = format_desc;\r
 }\r
 \r
-executor& video_channel_context::execution() {return execution_;}\r
-executor& video_channel_context::destruction() {return destruction_;}\r
-ogl_device& video_channel_context::ogl() { return ogl_;}\r
+executor& video_channel_context::execution() {return impl_->execution_;}\r
+executor& video_channel_context::destruction() {return impl_->destruction_;}\r
+ogl_device& video_channel_context::ogl() { return impl_->ogl_;}\r
 \r
 std::wstring video_channel_context::print() const\r
 {\r
-       return L"video_channel[" + boost::lexical_cast<std::wstring>(index_+1) + L"|" +  format_desc_.name + L"]";\r
+       return impl_->print();\r
 }\r
 \r
 }}
\ No newline at end of file
index f30799147c047ad7595dd07c0c51f54cb28fa376..4c06e3a9f3801dd9fafee0c48bd8232bec31d2c3 100644 (file)
@@ -2,7 +2,6 @@
 \r
 #include <common/concurrency/executor.h>\r
 \r
-#include <core/mixer/gpu/ogl_device.h>\r
 #include <core/video_format.h>\r
 \r
 #include <tbb/spin_rw_mutex.h>\r
 \r
 #include <string>\r
 \r
-namespace caspar { namespace core {\r
+namespace caspar { \r
+\r
+class executor;\r
+\r
+namespace core {\r
+\r
+class ogl_device;\r
 \r
 class video_channel_context\r
 {\r
-       mutable tbb::spin_rw_mutex      mutex_;\r
-       const int                                       index_;\r
-       video_format_desc                       format_desc_;\r
-       executor                                        execution_;\r
-       executor                                        destruction_;\r
-       ogl_device&                                     ogl_;\r
 \r
 public:\r
        video_channel_context(int index, ogl_device& ogl, const video_format_desc& format_desc);\r
@@ -33,6 +32,9 @@ public:
        executor&                       destruction();\r
        ogl_device&                     ogl();\r
        std::wstring            print() const;\r
+private:\r
+       struct implementation;\r
+       std::shared_ptr<implementation> impl_;\r
 };\r
        \r
 }}
\ No newline at end of file
index 5eedd32f13a8d1fcb72b9c5666903bd4badf9a99..a5e1d837743262216a9149f23690febb9b7df0bf 100644 (file)
@@ -33,6 +33,7 @@
 \r
 #include <core/producer/frame_producer.h>\r
 #include <core/video_format.h>\r
+#include <core/video_channel_context.h>\r
 #include <core/producer/transition/transition_producer.h>\r
 #include <core/producer/frame/frame_transform.h>\r
 #include <core/producer/stage.h>\r
@@ -649,7 +650,7 @@ bool LoadbgCommand::DoExecute()
 \r
                bool auto_play = std::find(_parameters.begin(), _parameters.end(), L"AUTO") != _parameters.end();\r
 \r
-               auto pFP2 = create_transition_producer(GetChannel()->get_video_format_desc().field_mode, pFP, transitionInfo);\r
+               auto pFP2 = create_transition_producer(GetChannel()->get_video_format_desc().field_mode, create_destroy_producer_proxy(GetChannel()->context().destruction(), pFP), transitionInfo);\r
                GetChannel()->stage()->load(GetLayerIndex(), pFP2, false, auto_play ? transitionInfo.duration : -1); // TODO: LOOP\r
        \r
                CASPAR_LOG(info) << "Loaded " << _parameters[0] << TEXT(" successfully to background");\r
index 8e02dace41a604f7236915fd9c58bbd8bb634006..ed235ac3cfb90aca97dee76b4477219c2f37a4b0 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>\r
 <configuration>\r
   <paths>\r
-    <media-path>L:\casparcg\_media\</media-path>\r
+    <media-path>C:\Lokala Filer\server\branches\2.0.0.2\bin\_media\</media-path>\r
     <log-path>L:\casparcg\_log\</log-path>\r
     <data-path>L:\casparcg\_data\</data-path>\r
     <template-path>L:\casparcg\_templates\</template-path>\r
   </producers>\r
   <channels>\r
     <channel>\r
-      <video-mode>720p5000</video-mode>\r
+      <video-mode>PAL</video-mode>\r
       <consumers>\r
-        <decklink>\r
-          <device>1</device>\r
-          <embedded-audio>true</embedded-audio>\r
-        </decklink>\r
         <screen>\r
-          <device>1</device>\r
         </screen>\r
       </consumers>\r
     </channel>\r