]> git.sesse.net Git - casparcg/commitdiff
2.0.0.2: Fixed SWAP command. Now swaps video-layers in producer_device instead of...
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Wed, 19 Jan 2011 20:15:10 +0000 (20:15 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Wed, 19 Jan 2011 20:15:10 +0000 (20:15 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@384 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

core/mixer/gpu/ogl_device.h
core/mixer/image/image_mixer.cpp
core/producer/flash/cg_producer.h
core/producer/frame_producer_device.cpp
core/producer/frame_producer_device.h
core/producer/layer.cpp
core/producer/layer.h
protocol/amcp/AMCPCommandsImpl.cpp

index 94c1e5483b2ed6075033c4f542920b9d7a1bd481..a41ee9667a336a8c7d585b590d77c0e459d35df0 100644 (file)
@@ -17,8 +17,13 @@ namespace caspar { namespace core {
 \r
 class ogl_device\r
 {      \r
-public:        \r
        ogl_device();\r
+public:        \r
+       static safe_ptr<ogl_device> create()\r
+       {\r
+               static safe_ptr<ogl_device> instance(new ogl_device());\r
+               return instance;\r
+       }\r
 \r
        template<typename Func>\r
        auto begin_invoke(Func&& func) -> boost::unique_future<decltype(func())> // noexcept\r
index d648f77f40b219966a007467f95fe6a0a79dde5b..aa5b2ec73989ed12619b52c7d200a2af8e652f8c 100644 (file)
@@ -122,13 +122,14 @@ struct image_mixer::implementation : boost::noncopyable
 \r
        image_kernel kernel_;\r
 \r
-       ogl_device context_;\r
+       safe_ptr<ogl_device> context_;\r
 \r
 public:\r
        implementation(const video_format_desc& format_desc) \r
                : format_desc_(format_desc)\r
+               , context_(ogl_device::create())\r
        {\r
-               context_.begin_invoke([=]\r
+               context_->begin_invoke([=]\r
                {\r
                        transform_stack_.push(image_transform());\r
                        transform_stack_.top().set_mode(video_mode::progressive);\r
@@ -137,14 +138,14 @@ public:
                        GL(glEnable(GL_TEXTURE_2D));\r
                        GL(glDisable(GL_DEPTH_TEST));           \r
 \r
-                       render_targets_[0] = context_.create_device_buffer(format_desc.width, format_desc.height, 4);\r
-                       render_targets_[1] = context_.create_device_buffer(format_desc.width, format_desc.height, 4);\r
+                       render_targets_[0] = context_->create_device_buffer(format_desc.width, format_desc.height, 4);\r
+                       render_targets_[1] = context_->create_device_buffer(format_desc.width, format_desc.height, 4);\r
                        \r
                        GL(glGenFramebuffers(1, &fbo_));                \r
                        GL(glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo_));\r
                        GL(glReadBuffer(GL_COLOR_ATTACHMENT0_EXT));\r
 \r
-                       reading_ = context_.create_host_buffer(format_desc_.size, host_buffer::read_only);\r
+                       reading_ = context_->create_host_buffer(format_desc_.size, host_buffer::read_only);\r
                });\r
        }\r
 \r
@@ -161,7 +162,7 @@ public:
        void render(const pixel_format_desc& desc, std::vector<safe_ptr<host_buffer>>& buffers)\r
        {\r
                auto transform = transform_stack_.top();\r
-               context_.begin_invoke([=]\r
+               context_->begin_invoke([=]\r
                {\r
                        GL(glLoadIdentity());\r
                        GL(glTranslated(transform.get_position()[0]*2.0, transform.get_position()[1]*2.0, 0.0));\r
@@ -172,7 +173,7 @@ public:
                        std::vector<safe_ptr<device_buffer>> device_buffers;\r
                        for(size_t n = 0; n < buffers.size(); ++n)\r
                        {\r
-                               auto texture = context_.create_device_buffer(desc.planes[n].width, desc.planes[n].height, desc.planes[n].channels);\r
+                               auto texture = context_->create_device_buffer(desc.planes[n].width, desc.planes[n].height, desc.planes[n].channels);\r
                                texture->read(*buffers[n]);\r
                                device_buffers.push_back(texture);\r
                        }\r
@@ -200,7 +201,7 @@ public:
 \r
        boost::unique_future<safe_ptr<const host_buffer>> begin_pass()\r
        {\r
-               return context_.begin_invoke([=]() -> safe_ptr<const host_buffer>\r
+               return context_->begin_invoke([=]() -> safe_ptr<const host_buffer>\r
                {\r
                        reading_->map();\r
                        render_targets_[0]->attach(0);\r
@@ -211,9 +212,9 @@ public:
 \r
        void end_pass()\r
        {\r
-               context_.begin_invoke([=]\r
+               context_->begin_invoke([=]\r
                {\r
-                       reading_ = context_.create_host_buffer(format_desc_.size, host_buffer::read_only);\r
+                       reading_ = context_->create_host_buffer(format_desc_.size, host_buffer::read_only);\r
                        render_targets_[0]->write(*reading_);\r
                        std::rotate(render_targets_.begin(), render_targets_.begin() + 1, render_targets_.end());\r
                });\r
@@ -224,7 +225,7 @@ public:
                std::vector<safe_ptr<host_buffer>> buffers;\r
                std::transform(format.planes.begin(), format.planes.end(), std::back_inserter(buffers), [&](const pixel_format_desc::plane& plane) -> safe_ptr<host_buffer>\r
                {\r
-                       return context_.create_host_buffer(plane.size, host_buffer::write_only);\r
+                       return context_->create_host_buffer(plane.size, host_buffer::write_only);\r
                });\r
                return buffers;\r
        }\r
index 98fbade11f77c628c6b708d9fdcce518bee2734c..1a21e7eb1fb35f5b0e0c44b50bb7c9598f272c36 100644 (file)
@@ -1,6 +1,7 @@
 #pragma once\r
 \r
 #include "../frame_producer.h"\r
+#include "../frame_producer_device.h"\r
 #include "../../video_format.h"\r
 #include "../../channel.h"\r
 \r
@@ -9,7 +10,7 @@ namespace caspar { namespace core { namespace flash{
 class cg_producer : public frame_producer\r
 {\r
 public:\r
-       static const unsigned int DEFAULT_LAYER = 5000;\r
+       static const unsigned int DEFAULT_LAYER = frame_producer_device::MAX_LAYER;\r
 \r
        explicit cg_producer();\r
        cg_producer(cg_producer&& other);\r
index 21c8026aec571e0284a298af5ee6d46317c5aa7b..fed13e9326323dec6623a893299a38dc89eb3c9d 100644 (file)
 #include <common/concurrency/executor.h>\r
 \r
 #include <boost/range/algorithm_ext/erase.hpp>\r
+#include <boost/lexical_cast.hpp>\r
 \r
 #include <tbb/parallel_for.h>\r
 \r
-#include <map>\r
+#include <array>\r
 #include <memory>\r
 \r
 namespace caspar { namespace core {\r
 \r
 struct frame_producer_device::implementation : boost::noncopyable\r
 {              \r
-       std::map<int, layer> layers_;           \r
+       std::array<layer, frame_producer_device::MAX_LAYER> layers_;            \r
 \r
        const output_func output_;\r
        const safe_ptr<frame_factory> factory_;\r
@@ -53,101 +54,128 @@ public:
                tbb::parallel_for(tbb::blocked_range<size_t>(0, frames.size()), \r
                [&](const tbb::blocked_range<size_t>& r)\r
                {\r
-                       auto it = layers_.begin();\r
-                       std::advance(it, r.begin());\r
-                       for(size_t i = r.begin(); i != r.end(); ++i, ++it)\r
-                               frames[i] = it->second.receive();\r
+                       for(size_t i = r.begin(); i != r.end(); ++i)\r
+                               frames[i] = layers_[i].receive();\r
                });             \r
                boost::range::remove_erase(frames, draw_frame::eof());\r
                boost::range::remove_erase(frames, draw_frame::empty());\r
                return frames;\r
        }\r
 \r
-       void load(int index, const safe_ptr<frame_producer>& producer, bool play_on_load)\r
+       void load(size_t index, const safe_ptr<frame_producer>& producer, bool play_on_load)\r
        {\r
+               check_bounds(index);\r
                producer->initialize(factory_);\r
-               executor_.begin_invoke([=]\r
+               executor_.invoke([&]\r
                {\r
-                       auto it = layers_.insert(std::make_pair(index, layer(index))).first;\r
-                       it->second.load(producer, play_on_load);\r
+                       layers_[index] = layer(index);\r
+                       layers_[index].load(producer, play_on_load);\r
                });\r
        }\r
                        \r
-       void preview(int index, const safe_ptr<frame_producer>& producer)\r
+       void preview(size_t index, const safe_ptr<frame_producer>& producer)\r
        {\r
+               check_bounds(index);\r
                producer->initialize(factory_);\r
-               executor_.begin_invoke([=]\r
-               {\r
-                       auto it = layers_.insert(std::make_pair(index, layer(index))).first;\r
-                       it->second.preview(producer);\r
+               executor_.invoke([&]\r
+               {                       \r
+                       layers_[index] = layer(index);\r
+                       layers_[index].preview(producer);\r
                });\r
        }\r
 \r
-       void pause(int index)\r
+       void pause(size_t index)\r
        {               \r
-               begin_invoke_layer(index, std::mem_fn(&layer::pause));\r
+               check_bounds(index);\r
+               executor_.invoke([&]\r
+               {\r
+                       layers_[index].pause();\r
+               });\r
        }\r
 \r
-       void play(int index)\r
+       void play(size_t index)\r
        {               \r
-               begin_invoke_layer(index, std::mem_fn(&layer::play));\r
+               check_bounds(index);\r
+               executor_.invoke([&]\r
+               {\r
+                       layers_[index].play();\r
+               });\r
        }\r
 \r
-       void stop(int index)\r
+       void stop(size_t index)\r
        {               \r
-               begin_invoke_layer(index, std::mem_fn(&layer::stop));\r
+               check_bounds(index);\r
+               executor_.invoke([&]\r
+               {\r
+                       layers_[index].stop();\r
+               });\r
        }\r
 \r
-       void clear(int index)\r
+       void clear(size_t index)\r
        {\r
-               executor_.begin_invoke([=]\r
-               {                       \r
-                       auto it = layers_.find(index);\r
-                       if(it != layers_.end())\r
-                       {\r
-                               it->second.clear();             \r
-                               layers_.erase(it);\r
-                       }\r
+               check_bounds(index);\r
+               executor_.invoke([&]\r
+               {\r
+                       layers_[index] = std::move(layer());\r
                });\r
        }\r
                \r
        void clear()\r
        {\r
-               executor_.begin_invoke([=]\r
-               {                       \r
-                       layers_.clear();\r
+               executor_.invoke([&]\r
+               {\r
+                       for(auto it = layers_.begin(); it != layers_.end(); ++it)\r
+                               *it = std::move(layer());\r
                });\r
-       }               \r
+       }       \r
+       \r
+       void swap(size_t index, size_t other_index)\r
+       {\r
+               check_bounds(index);\r
+               check_bounds(other_index);\r
 \r
-       template<typename F>\r
-       void begin_invoke_layer(int index, F&& func)\r
+               executor_.invoke([&]\r
+               {\r
+                       layers_[index].swap(layers_[other_index]);\r
+               });\r
+       }\r
+\r
+       void swap(size_t index, size_t other_index, frame_producer_device& other)\r
        {\r
-               executor_.begin_invoke([=]\r
+               check_bounds(index);\r
+               check_bounds(other_index);\r
+\r
+               executor_.invoke([&]\r
                {\r
-                       auto it = layers_.find(index);\r
-                       if(it != layers_.end())\r
-                               func(it->second);       \r
+                       layers_[index].swap(other.impl_->layers_[other_index]);\r
                });\r
        }\r
 \r
-       boost::unique_future<safe_ptr<frame_producer>> foreground(int index) const\r
+       void check_bounds(size_t index)\r
+       {\r
+               if(index < 0 || index >= frame_producer_device::MAX_LAYER)\r
+                       BOOST_THROW_EXCEPTION(out_of_range() << msg_info("Valid range is [0..100]") << arg_name_info("index") << arg_value_info(boost::lexical_cast<std::string>(index)));\r
+       }\r
+       \r
+       boost::unique_future<safe_ptr<frame_producer>> foreground(size_t index) const\r
        {\r
                return executor_.begin_invoke([=]() -> safe_ptr<frame_producer>\r
                {                       \r
-                       auto it = layers_.find(index);\r
-                       return it != layers_.end() ? it->second.foreground() : frame_producer::empty();\r
+                       return layers_[index].foreground();\r
                });\r
        }\r
 };\r
 \r
 frame_producer_device::frame_producer_device(const safe_ptr<frame_factory>& factory, const output_func& output) : impl_(new implementation(factory, output)){}\r
 frame_producer_device::frame_producer_device(frame_producer_device&& other) : impl_(std::move(other.impl_)){}\r
-void frame_producer_device::load(int index, const safe_ptr<frame_producer>& producer, bool play_on_load){impl_->load(index, producer, play_on_load);}\r
-void frame_producer_device::preview(int index, const safe_ptr<frame_producer>& producer){impl_->preview(index, producer);}\r
-void frame_producer_device::pause(int index){impl_->pause(index);}\r
-void frame_producer_device::play(int index){impl_->play(index);}\r
-void frame_producer_device::stop(int index){impl_->stop(index);}\r
-void frame_producer_device::clear(int index){impl_->clear(index);}\r
+void frame_producer_device::load(size_t index, const safe_ptr<frame_producer>& producer, bool play_on_load){impl_->load(index, producer, play_on_load);}\r
+void frame_producer_device::preview(size_t index, const safe_ptr<frame_producer>& producer){impl_->preview(index, producer);}\r
+void frame_producer_device::pause(size_t index){impl_->pause(index);}\r
+void frame_producer_device::play(size_t index){impl_->play(index);}\r
+void frame_producer_device::stop(size_t index){impl_->stop(index);}\r
+void frame_producer_device::clear(size_t index){impl_->clear(index);}\r
 void frame_producer_device::clear(){impl_->clear();}\r
-boost::unique_future<safe_ptr<frame_producer>> frame_producer_device::foreground(int index) const{     return impl_->foreground(index);}\r
+void frame_producer_device::swap(size_t index, size_t other_index){impl_->swap(index, other_index);}\r
+void frame_producer_device::swap(size_t index, size_t other_index, frame_producer_device& other){impl_->swap(index, other_index, other);}\r
+boost::unique_future<safe_ptr<frame_producer>> frame_producer_device::foreground(size_t index) const{  return impl_->foreground(index);}\r
 }}
\ No newline at end of file
index 54d80b1c455f2274a11e4fefb36d6ecba11f62b4..7f466bb591969a91ba8d2d6d8ff9bcb38d34a623 100644 (file)
@@ -25,19 +25,23 @@ namespace caspar { namespace core {
 class frame_producer_device : boost::noncopyable\r
 {\r
 public:\r
+       static const int MAX_LAYER = 101;\r
+\r
        typedef std::function<void(const std::vector<safe_ptr<draw_frame>>&)> output_func;\r
 \r
        explicit frame_producer_device(const safe_ptr<frame_factory>& factory, const output_func& output);\r
        frame_producer_device(frame_producer_device&& other);\r
                \r
-       void load(int index, const safe_ptr<frame_producer>& producer, bool play_on_load = false);\r
-       void preview(int index, const safe_ptr<frame_producer>& producer);\r
-       void pause(int index);\r
-       void play(int index);\r
-       void stop(int index);\r
-       void clear(int index);\r
+       void load(size_t index, const safe_ptr<frame_producer>& producer, bool play_on_load = false);\r
+       void preview(size_t index, const safe_ptr<frame_producer>& producer);\r
+       void pause(size_t index);\r
+       void play(size_t index);\r
+       void stop(size_t index);\r
+       void clear(size_t index);\r
        void clear();   \r
-       boost::unique_future<safe_ptr<frame_producer>> foreground(int index) const;\r
+       void swap(size_t index, size_t other_index);\r
+       void swap(size_t index, size_t other_index, frame_producer_device& other);\r
+       boost::unique_future<safe_ptr<frame_producer>> foreground(size_t index) const;\r
 \r
 private:\r
        struct implementation;\r
index ab32c18885a0fff7aadc5ba5b9ba24861f733d86..66fda5c9e61f8970869b51a5d8139a8d732454b9 100644 (file)
@@ -119,14 +119,25 @@ public:
        std::wstring print() const { return L"layer[" + boost::lexical_cast<std::wstring>(index_) + L"]"; }\r
 };\r
 \r
-layer::layer(int index) : impl_(new implementation(index)){}\r
+layer::layer(int index) \r
+{\r
+       impl_ = new implementation(index);\r
+}\r
 layer::layer(layer&& other) : impl_(std::move(other.impl_)){other.impl_ = nullptr;}\r
+layer::~layer()\r
+{\r
+       delete impl_.fetch_and_store(nullptr);\r
+}\r
 layer& layer::operator=(layer&& other)\r
 {\r
        impl_ = std::move(other.impl_); \r
        other.impl_ = nullptr;\r
        return *this;\r
 }\r
+void layer::swap(layer& other)\r
+{\r
+       impl_ = other.impl_.compare_and_swap(impl_, other.impl_);\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
 void layer::play(){impl_->play();}\r
index 897a21706aa578fd0ac7da2018d683246bcc8271..2671d9049ff521753c37564db0ee4ecbc6e64b6b 100644 (file)
@@ -4,6 +4,8 @@
 \r
 #include <boost/noncopyable.hpp>\r
 \r
+#include <tbb/atomic.h>\r
+\r
 namespace caspar { namespace core {\r
 \r
 class frame_producer;\r
@@ -14,7 +16,11 @@ class layer : boost::noncopyable
 public:\r
        layer(int index = -1); // nothrow\r
        layer(layer&& other); // nothrow\r
+       ~layer();\r
        layer& operator=(layer&& other); // nothrow\r
+\r
+       //NOTE: swap is thread-safe on "other", NOT on "this".\r
+       void swap(layer& other); // nothrow \r
                \r
        void load(const safe_ptr<frame_producer>& producer, bool play_on_load = false); // nothrow\r
        void preview(const safe_ptr<frame_producer>& producer); // nothrow\r
@@ -29,7 +35,7 @@ public:
        safe_ptr<draw_frame> receive(); // nothrow\r
 private:\r
        struct implementation;\r
-       std::shared_ptr<implementation> impl_;\r
+       tbb::atomic<implementation*> impl_;\r
 };\r
 \r
 }}
\ No newline at end of file
index e1334bde1829ffe08c33cda609561de0535b2d2d..a3b335409ba1cd926f8f1a22bd73ee40579fce71 100644 (file)
@@ -229,23 +229,20 @@ bool SwapCommand::DoExecute()
        //Perform loading of the clip\r
        try\r
        {\r
-               //std::vector<std::string> strs;\r
-               //boost::split(strs, _parameters[0], boost::is_any_of("-"));\r
-               //      \r
-               //auto ch1 = GetChannel();\r
-               //auto ch2 = GetChannels().at(boost::lexical_cast<int>(strs.at(0))-1);\r
-\r
-               //int l1 = GetLayerIndex();\r
-               //int l2 = boost::lexical_cast<int>(strs.at(1));\r
-               //\r
-               //auto c1 = ch1->consumer().get(l1);\r
-               //auto c2 = ch2->consumer().get(l2);\r
-\r
-               //ch2->consumer().add(l1, c1);\r
-               //ch1->consumer().add(l2, c2);\r
-               //CASPAR_LOG(info) << "Swapped successfully";\r
-\r
-               SetReplyString(TEXT("600 SWAP NOT IMPLEMENTED\r\n"));\r
+               std::vector<std::string> strs;\r
+               boost::split(strs, _parameters[0], boost::is_any_of("-"));\r
+                       \r
+               auto ch1 = GetChannel();\r
+               auto ch2 = GetChannels().at(boost::lexical_cast<int>(strs.at(0))-1);\r
+\r
+               int l1 = GetLayerIndex();\r
+               int l2 = boost::lexical_cast<int>(strs.at(1));\r
+\r
+               ch1->producer().swap(l1, l2, ch2->producer());\r
+\r
+               CASPAR_LOG(info) << "Swapped successfully";\r
+\r
+               SetReplyString(TEXT("202 SWAP OK\r\n"));\r
 \r
                return false;\r
        }\r