]> git.sesse.net Git - casparcg/commitdiff
- more gpu refactoring.
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Sat, 21 Jan 2012 01:22:19 +0000 (01:22 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Sat, 21 Jan 2012 01:22:19 +0000 (01:22 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.1.0@2139 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

42 files changed:
common/scope_guard.h [new file with mode: 0644]
core/consumer/frame_consumer.cpp
core/consumer/frame_consumer.h
core/consumer/output.cpp
core/consumer/output.h
core/core.vcxproj
core/core.vcxproj.filters
core/mixer/audio/audio_mixer.cpp
core/mixer/audio/audio_mixer.h
core/mixer/data_frame.cpp [moved from core/mixer/read_frame.cpp with 89% similarity]
core/mixer/data_frame.h [moved from core/mixer/read_frame.h with 88% similarity]
core/mixer/device_frame.cpp [new file with mode: 0644]
core/mixer/device_frame.h [moved from core/mixer/write_frame.h with 65% similarity]
core/mixer/gpu/host_buffer.h
core/mixer/gpu/ogl_device.cpp
core/mixer/gpu/ogl_device.h
core/mixer/image/image_mixer.cpp
core/mixer/image/image_mixer.h
core/mixer/mixer.cpp
core/mixer/mixer.h
core/mixer/write_frame.cpp [deleted file]
core/producer/channel/channel_producer.cpp
core/producer/color/color_producer.cpp
core/producer/color/color_producer.h
core/producer/frame/frame_factory.h
core/producer/frame/frame_visitor.h
core/video_channel.cpp
modules/bluefish/consumer/bluefish_consumer.cpp
modules/decklink/consumer/decklink_consumer.cpp
modules/decklink/producer/decklink_producer.cpp
modules/ffmpeg/consumer/ffmpeg_consumer.cpp
modules/ffmpeg/producer/muxer/frame_muxer.cpp
modules/ffmpeg/producer/muxer/frame_muxer.h
modules/ffmpeg/producer/util/util.cpp
modules/ffmpeg/producer/util/util.h
modules/ffmpeg/producer/video/video_decoder.h
modules/flash/producer/flash_producer.cpp
modules/image/consumer/image_consumer.cpp
modules/image/producer/image_producer.cpp
modules/image/producer/image_scroll_producer.cpp
modules/oal/consumer/oal_consumer.cpp
modules/ogl/consumer/ogl_consumer.cpp

diff --git a/common/scope_guard.h b/common/scope_guard.h
new file mode 100644 (file)
index 0000000..4966445
--- /dev/null
@@ -0,0 +1,29 @@
+#pragma once\r
+\r
+namespace caspar {\r
+\r
+template<typename F>\r
+class scope_guard\r
+{\r
+       F func_;\r
+public:\r
+\r
+       template<typename U>\r
+       scope_guard(U&& func)\r
+               : func_(std::forward<U>(func))\r
+       {\r
+       }\r
+\r
+       ~scope_guard()\r
+       {\r
+               func_();\r
+       }\r
+};\r
+\r
+template<typename F>\r
+scope_guard<F> make_scope_guard(F&& func)\r
+{\r
+       return scope_guard<F>(std::forward<F>(func));\r
+}\r
+\r
+}
\ No newline at end of file
index 4e40c513ec44e756c29170f11290051ed2451306..397a8aff30b2a1a0ce92e1025ac7e780f1f66b6e 100644 (file)
@@ -27,7 +27,7 @@
 #include <common/memory/safe_ptr.h>\r
 #include <common/exception/exceptions.h>\r
 #include <core/video_format.h>\r
-#include <core/mixer/read_frame.h>\r
+#include <core/mixer/data_frame.h>\r
 \r
 #include <boost/circular_buffer.hpp>\r
 \r
@@ -84,7 +84,7 @@ public:
                consumer_->initialize(format_desc, channel_index);\r
        }\r
 \r
-       virtual bool send(const safe_ptr<read_frame>& frame) override\r
+       virtual bool send(const safe_ptr<data_frame>& frame) override\r
        {               \r
                if(audio_cadence_.size() == 1)\r
                        return consumer_->send(frame);\r
@@ -140,7 +140,7 @@ const safe_ptr<frame_consumer>& frame_consumer::empty()
 {\r
        struct empty_frame_consumer : public frame_consumer\r
        {\r
-               virtual bool send(const safe_ptr<read_frame>&) override {return false;}\r
+               virtual bool send(const safe_ptr<data_frame>&) override {return false;}\r
                virtual void initialize(const video_format_desc&, int) override{}\r
                virtual std::wstring print() const override {return L"empty";}\r
                virtual bool has_synchronization_clock() const override {return false;}\r
index 68b3e8ac99bbec5a3011c19dfee20149e85dc2c0..800e47517c8008cf0f3ffa4d67d52b98f42319d8 100644 (file)
@@ -37,7 +37,7 @@ struct frame_consumer : boost::noncopyable
        frame_consumer(){}\r
        virtual ~frame_consumer() {}\r
        \r
-       virtual bool send(const safe_ptr<class read_frame>& frame) = 0;\r
+       virtual bool send(const safe_ptr<class data_frame>& frame) = 0;\r
        virtual void initialize(const struct video_format_desc& format_desc, int channel_index) = 0;\r
        virtual std::wstring print() const = 0;\r
        virtual boost::property_tree::wptree info() const = 0;\r
index b690472de40237ddb12f466cf76d4ab50759d788..ea10fd7bf9522ded06b9387374b8dd2a61a440f2 100644 (file)
@@ -31,7 +31,7 @@
 \r
 #include "../video_format.h"\r
 #include "../mixer/gpu/ogl_device.h"\r
-#include "../mixer/read_frame.h"\r
+#include "../mixer/data_frame.h"\r
 \r
 #include <common/concurrency/executor.h>\r
 #include <common/diagnostics/graph.h>\r
@@ -60,7 +60,7 @@ struct output::impl
        \r
        prec_timer                                                                              sync_timer_;\r
 \r
-       boost::circular_buffer<safe_ptr<read_frame>>    frames_;\r
+       boost::circular_buffer<safe_ptr<data_frame>>    frames_;\r
 \r
        executor                                                                                executor_;\r
                \r
@@ -164,7 +164,7 @@ public:
                return boost::range::count_if(consumers_ | boost::adaptors::map_values, [](const safe_ptr<frame_consumer>& x){return x->has_synchronization_clock();}) > 0;\r
        }\r
 \r
-       void send(const std::pair<safe_ptr<read_frame>, std::shared_ptr<void>>& packet)\r
+       void send(const std::pair<safe_ptr<data_frame>, std::shared_ptr<void>>& packet)\r
        {\r
                executor_.begin_invoke([=]\r
                {\r
@@ -264,7 +264,7 @@ void output::add(int index, const safe_ptr<frame_consumer>& consumer){impl_->add
 void output::add(const safe_ptr<frame_consumer>& consumer){impl_->add(consumer);}\r
 void output::remove(int index){impl_->remove(index);}\r
 void output::remove(const safe_ptr<frame_consumer>& consumer){impl_->remove(consumer);}\r
-void output::send(const std::pair<safe_ptr<read_frame>, std::shared_ptr<void>>& frame) {impl_->send(frame); }\r
+void output::send(const std::pair<safe_ptr<data_frame>, std::shared_ptr<void>>& frame) {impl_->send(frame); }\r
 void output::set_video_format_desc(const video_format_desc& format_desc){impl_->set_video_format_desc(format_desc);}\r
 boost::unique_future<boost::property_tree::wptree> output::info() const{return impl_->info();}\r
 }}
\ No newline at end of file
index 2fdc33aef1af36ace82bf8ca5d52e901a5dbe193..72c40b76b3b5012f004ba49738fc4f1b2e1f0dea 100644 (file)
@@ -33,7 +33,7 @@ FORWARD2(caspar, diagnostics, class graph);
 \r
 namespace caspar { namespace core {\r
        \r
-class output sealed : public target<std::pair<safe_ptr<class read_frame>, std::shared_ptr<void>>>\r
+class output sealed : public target<std::pair<safe_ptr<class data_frame>, std::shared_ptr<void>>>\r
                                        , boost::noncopyable\r
 {\r
 public:\r
@@ -41,7 +41,7 @@ public:
 \r
        // target\r
        \r
-       virtual void send(const std::pair<safe_ptr<class read_frame>, std::shared_ptr<void>>& frame) override;\r
+       virtual void send(const std::pair<safe_ptr<class data_frame>, std::shared_ptr<void>>& frame) override;\r
 \r
        // output\r
        \r
index 78315559873f6805fc1d28ac6c46e867bc225fe5..69176e32b238cc77e33967644ceadd10a805490a 100644 (file)
     <ClInclude Include="mixer\gpu\ogl_device.h" />\r
     <ClInclude Include="mixer\image\image_kernel.h" />\r
     <ClInclude Include="mixer\image\image_mixer.h" />\r
-    <ClInclude Include="mixer\read_frame.h" />\r
-    <ClInclude Include="mixer\write_frame.h" />\r
+    <ClInclude Include="mixer\data_frame.h" />\r
+    <ClInclude Include="mixer\device_frame.h" />\r
     <ClInclude Include="producer\color\color_producer.h" />\r
     <ClInclude Include="producer\frame\basic_frame.h" />\r
     <ClInclude Include="producer\frame\frame_factory.h" />\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
-    <ClCompile Include="mixer\read_frame.cpp">\r
+    <ClCompile Include="mixer\data_frame.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
-    <ClCompile Include="mixer\write_frame.cpp">\r
+    <ClCompile Include="mixer\device_frame.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
index fdd9b6c74b204508e4857acb32120249223e5d81..fad1f823653c220639795f5f499b3f9aacc3a728 100644 (file)
     <ClInclude Include="mixer\audio\audio_mixer.h">\r
       <Filter>source\mixer\audio</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="mixer\read_frame.h">\r
-      <Filter>source\mixer</Filter>\r
-    </ClInclude>\r
-    <ClInclude Include="mixer\write_frame.h">\r
-      <Filter>source\mixer</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="StdAfx.h" />\r
     <ClInclude Include="mixer\mixer.h">\r
       <Filter>source\mixer</Filter>\r
     <ClInclude Include="producer\separated\separated_producer.h">\r
       <Filter>source\producer\separated</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="mixer\device_frame.h">\r
+      <Filter>source\mixer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="mixer\data_frame.h">\r
+      <Filter>source\mixer</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClCompile Include="producer\transition\transition_producer.cpp">\r
     <ClCompile Include="producer\separated\separated_producer.cpp">\r
       <Filter>source\producer\separated</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="mixer\read_frame.cpp">\r
-      <Filter>source\mixer</Filter>\r
-    </ClCompile>\r
-    <ClCompile Include="mixer\write_frame.cpp">\r
-      <Filter>source\mixer</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="StdAfx.cpp" />\r
     <ClCompile Include="mixer\mixer.cpp">\r
       <Filter>source\mixer</Filter>\r
     <ClCompile Include="producer\channel\channel_producer.cpp">\r
       <Filter>source\producer\channel</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="mixer\device_frame.cpp">\r
+      <Filter>source\mixer</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\data_frame.cpp">\r
+      <Filter>source\mixer</Filter>\r
+    </ClCompile>\r
   </ItemGroup>\r
 </Project>
\ No newline at end of file
index 99020283474ff17281fc2b58f80fb3c4134e03c3..8dac9a516bff96dfb51fa1033a2f03b35e5c1e9d 100644 (file)
@@ -23,7 +23,7 @@
 \r
 #include "audio_mixer.h"\r
 \r
-#include <core/mixer/write_frame.h>\r
+#include <core/mixer/device_frame.h>\r
 #include <core/producer/frame/frame_transform.h>\r
 #include <common/diagnostics/graph.h>\r
 \r
@@ -84,7 +84,7 @@ public:
                transform_stack_.push(transform_stack_.top()*frame.get_frame_transform());\r
        }\r
 \r
-       void visit(core::write_frame& frame)\r
+       void visit(core::device_frame& frame)\r
        {\r
                if(transform_stack_.top().volume < 0.002 || frame.audio_data().empty())\r
                        return;\r
@@ -193,7 +193,7 @@ public:
 \r
 audio_mixer::audio_mixer(const safe_ptr<diagnostics::graph>& graph) : impl_(new impl(graph)){}\r
 void audio_mixer::begin(core::basic_frame& frame){impl_->begin(frame);}\r
-void audio_mixer::visit(core::write_frame& frame){impl_->visit(frame);}\r
+void audio_mixer::visit(core::device_frame& frame){impl_->visit(frame);}\r
 void audio_mixer::end(){impl_->end();}\r
 audio_buffer audio_mixer::operator()(const video_format_desc& format_desc){return impl_->mix(format_desc);}\r
 \r
index 8cb13876623ad8af18cd0fc88c467f640b6620ca..87cda96726986aa9deeade8ad9715a44bf1f7f79 100644 (file)
@@ -42,7 +42,7 @@ public:
        audio_mixer(const safe_ptr<diagnostics::graph>& graph);\r
 \r
        virtual void begin(core::basic_frame& frame);\r
-       virtual void visit(core::write_frame& frame);\r
+       virtual void visit(core::device_frame& frame);\r
        virtual void end();\r
 \r
        audio_buffer operator()(const struct video_format_desc& format_desc);\r
similarity index 89%
rename from core/mixer/read_frame.cpp
rename to core/mixer/data_frame.cpp
index 372641910c31124e9e51c3477f4c33d506d1f35b..760e69693e61a07fc016351a5511833ac037c732 100644 (file)
@@ -21,7 +21,7 @@
 \r
 #include "../stdafx.h"\r
 \r
-#include "read_frame.h"\r
+#include "data_frame.h"\r
 \r
 #include "gpu/fence.h"\r
 #include "gpu/host_buffer.h"   \r
@@ -31,7 +31,7 @@
 \r
 namespace caspar { namespace core {\r
                                                                                                                                                                                                                                                                                                                        \r
-struct read_frame::impl : boost::noncopyable\r
+struct data_frame::impl : boost::noncopyable\r
 {\r
        int                                                                                     width_;\r
        int                                                                                     height_;\r
@@ -56,21 +56,21 @@ public:
        }\r
 };\r
 \r
-read_frame::read_frame(int width, int height, boost::unique_future<safe_ptr<host_buffer>>&& image_data, audio_buffer&& audio_data) \r
+data_frame::data_frame(int width, int height, boost::unique_future<safe_ptr<host_buffer>>&& image_data, audio_buffer&& audio_data) \r
        : impl_(new impl(width, height, std::move(image_data), std::move(audio_data))){}\r
-read_frame::read_frame(){}\r
-const boost::iterator_range<const uint8_t*> read_frame::image_data()\r
+data_frame::data_frame(){}\r
+const boost::iterator_range<const uint8_t*> data_frame::image_data()\r
 {\r
        return impl_ ? impl_->image_data() : boost::iterator_range<const uint8_t*>();\r
 }\r
 \r
-const boost::iterator_range<const int32_t*> read_frame::audio_data()\r
+const boost::iterator_range<const int32_t*> data_frame::audio_data()\r
 {\r
        return impl_ ? impl_->audio_data() : boost::iterator_range<const int32_t*>();\r
 }\r
 \r
-int read_frame::width() const{return impl_ ? impl_->width_ : 0;}\r
-int read_frame::height() const{return impl_ ? impl_->height_ : 0;}\r
+int data_frame::width() const{return impl_ ? impl_->width_ : 0;}\r
+int data_frame::height() const{return impl_ ? impl_->height_ : 0;}\r
 \r
 //#include <tbb/scalable_allocator.h>\r
 //#include <tbb/parallel_for.h>\r
@@ -87,7 +87,7 @@ int read_frame::height() const{return impl_ ? impl_->height_ : 0;}
 //\r
 //void CopyFrame( void * pSrc, void * pDest, UINT width, UINT height, UINT pitch );\r
 //\r
-//void* copy_frame(void* dest, const safe_ptr<read_frame>& frame)\r
+//void* copy_frame(void* dest, const safe_ptr<data_frame>& frame)\r
 //{\r
 //     auto src                = frame->image_data().begin();\r
 //     auto height             = 720;\r
similarity index 88%
rename from core/mixer/read_frame.h
rename to core/mixer/data_frame.h
index 36b56dd4a9ff492752f9c5ee572716f2bd2262ab..3e70183d88b40057222172519ce6c322d4aa43bc 100644 (file)
@@ -37,11 +37,11 @@ FORWARD1(boost, template<typename> class unique_future);
 \r
 namespace caspar { namespace core {\r
        \r
-class read_frame sealed : boost::noncopyable\r
+class data_frame sealed : boost::noncopyable\r
 {\r
 public:\r
-       read_frame();\r
-       read_frame(int width, int height, boost::unique_future<safe_ptr<class host_buffer>>&& image_data, audio_buffer&& audio_data);\r
+       data_frame();\r
+       data_frame(int width, int height, boost::unique_future<safe_ptr<class host_buffer>>&& image_data, audio_buffer&& audio_data);\r
 \r
        const boost::iterator_range<const uint8_t*> image_data();\r
        const boost::iterator_range<const int32_t*> audio_data();\r
diff --git a/core/mixer/device_frame.cpp b/core/mixer/device_frame.cpp
new file mode 100644 (file)
index 0000000..6f15710
--- /dev/null
@@ -0,0 +1,99 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../stdafx.h"\r
+\r
+#include "device_frame.h"\r
+\r
+#include "gpu/ogl_device.h"\r
+#include "gpu/host_buffer.h"\r
+#include "gpu/device_buffer.h"\r
+\r
+#include <core/producer/frame/frame_visitor.h>\r
+#include <core/producer/frame/pixel_format.h>\r
+#include <common/scope_guard.h>\r
+#include <common/gl/gl_check.h>\r
+\r
+#include <boost/lexical_cast.hpp>\r
+\r
+namespace caspar { namespace core {\r
+                                                                                                                                                                                                                                                                                                                       \r
+struct device_frame::impl : boost::noncopyable\r
+{                      \r
+       std::vector<boost::shared_future<safe_ptr<device_buffer>>>      textures_;\r
+       audio_buffer                                                                                            audio_data_;\r
+       const core::pixel_format_desc                                                           desc_;\r
+       const void*                                                                                                     tag_;\r
+       core::field_mode                                                                                        mode_;\r
+\r
+       impl(const void* tag)\r
+               : tag_(tag)\r
+               , mode_(core::field_mode::empty)\r
+       {\r
+       }\r
+\r
+       impl(std::vector<boost::unique_future<safe_ptr<device_buffer>>>&& textures, const void* tag, const core::pixel_format_desc& desc, field_mode type) \r
+               : desc_(desc)\r
+               , tag_(tag)\r
+               , mode_(type)\r
+       {\r
+               BOOST_FOREACH(auto& texture, textures)\r
+                       textures_.push_back(std::move(texture));\r
+       }\r
+\r
+       impl(boost::unique_future<safe_ptr<device_buffer>>&& texture, const void* tag, const core::pixel_format_desc& desc, field_mode type) \r
+               : desc_(desc)\r
+               , tag_(tag)\r
+               , mode_(type)\r
+       {\r
+               textures_.push_back(std::move(texture));\r
+       }\r
+                       \r
+       void accept(device_frame& self, core::frame_visitor& visitor)\r
+       {\r
+               visitor.begin(self);\r
+               visitor.visit(self);\r
+               visitor.end();\r
+       }\r
+};\r
+       \r
+\r
+device_frame::device_frame(const void* tag) : impl_(new impl(tag)){}\r
+device_frame::device_frame(std::vector<future_texture>&& textures, const void* tag, const struct pixel_format_desc& desc, field_mode type)\r
+       : impl_(new impl(std::move(textures), tag, desc, type)){}\r
+device_frame::device_frame(future_texture&& texture, const void* tag, const struct pixel_format_desc& desc, field_mode type)\r
+       : impl_(new impl(std::move(texture), tag, desc, type)){}\r
+device_frame::device_frame(device_frame&& other) : impl_(std::move(other.impl_)){}\r
+device_frame& device_frame::operator=(device_frame&& other)\r
+{\r
+       device_frame temp(std::move(other));\r
+       temp.swap(*this);\r
+       return *this;\r
+}\r
+void device_frame::swap(device_frame& other){impl_.swap(other.impl_);}\r
+audio_buffer& device_frame::audio_data() { return impl_->audio_data_; }\r
+const void* device_frame::tag() const {return impl_->tag_;}\r
+const core::pixel_format_desc& device_frame::get_pixel_format_desc() const{return impl_->desc_;}\r
+const std::vector<boost::shared_future<safe_ptr<device_buffer>>>& device_frame::get_textures() const{return impl_->textures_;}\r
+core::field_mode device_frame::get_type() const{return impl_->mode_;}\r
+void device_frame::accept(core::frame_visitor& visitor){impl_->accept(*this, visitor);}\r
+\r
+}}
\ No newline at end of file
similarity index 65%
rename from core/mixer/write_frame.h
rename to core/mixer/device_frame.h
index 77be16af3f338dc14e131a766bb6a263054546fe..204e310d720eb0f19a7f02cf0ade41a9833363ad 100644 (file)
 #include <core/mixer/audio/audio_mixer.h>\r
 \r
 #include <boost/range/iterator_range.hpp>\r
+#include <boost/thread/future.hpp>\r
 \r
 #include <stdint.h>\r
 #include <vector>\r
 \r
 namespace caspar { namespace core {\r
        \r
-class write_frame sealed : public core::basic_frame\r
+class device_frame sealed : public core::basic_frame\r
 {\r
 public:        \r
-       explicit write_frame(const void* tag);\r
-       explicit write_frame(const safe_ptr<class ogl_device>& ogl, const void* tag, const struct pixel_format_desc& desc);\r
+       typedef boost::unique_future<safe_ptr<class device_buffer>> future_texture;\r
 \r
-       write_frame(write_frame&& other);\r
-       write_frame& operator=(write_frame&& other);\r
+       explicit device_frame(const void* tag);\r
+       explicit device_frame(std::vector<future_texture>&& textures, const void* tag, const struct pixel_format_desc& desc, field_mode type);\r
+       explicit device_frame(future_texture&& texture, const void* tag, const struct pixel_format_desc& desc, field_mode type);\r
+\r
+       device_frame(device_frame&& other);\r
+       device_frame& operator=(device_frame&& other);\r
                        \r
        // basic_frame\r
 \r
@@ -49,15 +53,10 @@ public:
 \r
        // write _frame\r
 \r
-       void swap(write_frame& other);\r
+       void swap(device_frame& other);\r
                        \r
-       boost::iterator_range<uint8_t*> image_data(int plane_index = 0);        \r
        audio_buffer& audio_data();\r
-       \r
-       void commit(int plane_index);\r
-       void commit();\r
-       \r
-       void set_type(const field_mode& mode);\r
+               \r
        field_mode get_type() const;\r
        \r
        const void* tag() const;\r
@@ -67,7 +66,7 @@ public:
 private:\r
        friend class image_mixer;\r
        \r
-       const std::vector<safe_ptr<class device_buffer>>& get_textures() const;\r
+       const std::vector<boost::shared_future<safe_ptr<class device_buffer>>>& get_textures() const;\r
 \r
        struct impl;\r
        safe_ptr<impl> impl_;\r
index d5e39ba2ef25a1601eaffb15aa6fbe1b2f0157e4..555e7b1bbd7d6c057210e6f5b65922630da040e3 100644 (file)
@@ -38,16 +38,16 @@ public:
        \r
        const void* data() const;\r
        void* data();\r
-       int size() const;       \r
+       int size() const;\r
        \r
-       void bind();\r
-       void unbind();\r
-\r
-       void map();\r
-       void unmap();\r
 private:\r
        friend class ogl_device;\r
        host_buffer(int size, usage_t usage);\r
+               \r
+       void map();\r
+       void bind();\r
+       void unbind();\r
+       void unmap();\r
 \r
        struct impl;\r
        safe_ptr<impl> impl_;\r
index f7bd780ce25b0f44f44278972a097cc5dc57f8b2..d771df013d11b81f5f42dadd3623940157274515 100644 (file)
@@ -385,7 +385,7 @@ void ogl_device::attach(GLint id)
        }\r
 }\r
 \r
-void ogl_device::attach(device_buffer& texture)\r
+void ogl_device::attach(const device_buffer& texture)\r
 {      \r
        attach(texture.id());\r
 }\r
@@ -399,7 +399,7 @@ void ogl_device::bind(GLint id, int index)
        }\r
 }\r
 \r
-void ogl_device::bind(device_buffer& texture, int index)\r
+void ogl_device::bind(const device_buffer& texture, int index)\r
 {\r
        //while(true)\r
        //{\r
@@ -433,7 +433,7 @@ void ogl_device::use(GLint id)
        }\r
 }\r
 \r
-void ogl_device::use(shader& shader)\r
+void ogl_device::use(const shader& shader)\r
 {\r
        use(shader.id());\r
 }\r
@@ -475,7 +475,6 @@ boost::unique_future<safe_ptr<host_buffer>> ogl_device::transfer(const safe_ptr<
 \r
                attach(*source);\r
        \r
-               dest->unmap();\r
                dest->bind();\r
                GL(glReadPixels(0, 0, source->width(), source->height(), format(source->stride()), GL_UNSIGNED_BYTE, NULL));\r
                dest->unbind();\r
@@ -503,6 +502,29 @@ boost::unique_future<safe_ptr<host_buffer>> ogl_device::transfer(const safe_ptr<
        });\r
 }\r
 \r
+boost::unique_future<safe_ptr<device_buffer>> ogl_device::transfer(const safe_ptr<host_buffer>& source, int width, int height, int stride)\r
+{              \r
+       return begin_invoke([=]() -> safe_ptr<device_buffer>\r
+       {\r
+               push_state();\r
+               auto restore_state = make_scope_guard([&]\r
+               {\r
+                       pop_state();\r
+               });\r
+               \r
+               auto dest = create_device_buffer(width, height, stride);\r
+\r
+               source->unmap();\r
+               source->bind();\r
+                       \r
+               const_cast<ogl_device*>(this)->bind(*dest, 0); // WORKAROUND: const-cast needed due to compiler bug?\r
+               GL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, dest->width(), dest->height(), format(dest->stride()), GL_UNSIGNED_BYTE, NULL));\r
+                       \r
+               source->unbind();\r
+\r
+               return dest;\r
+       });\r
+}\r
 \r
 }}\r
 \r
index 5e080c4d8bfa53314cc9fb0c4dfd119e745ff3d6..368c8490c248dfbb06cfc0a7b72411b5d9f229ff 100644 (file)
@@ -105,14 +105,15 @@ class ogl_device : public std::enable_shared_from_this<ogl_device>
 \r
        void use(GLint id);\r
        void attach(GLint id);\r
-       void bind(GLint id, int index);\r
+       void bind(GLint id, int index); \r
+       void push_state();\r
+       void pop_state();\r
+       void flush();\r
 \r
 public:                \r
        static safe_ptr<ogl_device> create();\r
        ~ogl_device();\r
 \r
-       void push_state();\r
-       void pop_state();\r
 \r
        // Not thread-safe, must be called inside of context\r
        void viewport(int x, int y, int width, int height);\r
@@ -124,13 +125,12 @@ public:
        void blend_func(int c1, int c2, int a1, int a2);\r
        void blend_func(int c1, int c2);\r
        \r
-       void use(shader& shader);\r
+       void use(const shader& shader);\r
 \r
-       void attach(device_buffer& texture);\r
+       void attach(const device_buffer& texture);\r
 \r
-       void bind(device_buffer& texture, int index);\r
+       void bind(const device_buffer& texture, int index);\r
 \r
-       void flush();\r
 \r
        // thread-afe\r
        template<typename Func>\r
@@ -147,7 +147,9 @@ public:
                \r
        safe_ptr<device_buffer> create_device_buffer(int width, int height, int stride);\r
        safe_ptr<host_buffer> create_host_buffer(int size, host_buffer::usage_t usage);\r
+\r
        boost::unique_future<safe_ptr<host_buffer>> transfer(const safe_ptr<device_buffer>& source);\r
+       boost::unique_future<safe_ptr<device_buffer>> transfer(const safe_ptr<host_buffer>& source, int width, int height, int stride);\r
        \r
        void yield();\r
        boost::unique_future<void> gc();\r
index e030799f2e72b07e20ea49d362fdf3ba7a0cf2e0..42c0ad63e30280ed8b5045649e015dfa9072cb4a 100644 (file)
@@ -24,7 +24,7 @@
 #include "image_mixer.h"\r
 \r
 #include "image_kernel.h"\r
-#include "../write_frame.h"\r
+#include "../device_frame.h"\r
 #include "../gpu/ogl_device.h"\r
 #include "../gpu/host_buffer.h"\r
 #include "../gpu/device_buffer.h"\r
@@ -35,8 +35,6 @@
 #include <core/producer/frame/pixel_format.h>\r
 #include <core/video_format.h>\r
 \r
-#include <gl/glew.h>\r
-\r
 #include <boost/foreach.hpp>\r
 #include <boost/range/algorithm_ext/erase.hpp>\r
 #include <boost/thread/future.hpp>\r
@@ -50,9 +48,9 @@ namespace caspar { namespace core {
        \r
 struct item\r
 {\r
-       pixel_format_desc                                               pix_desc;\r
-       std::vector<safe_ptr<device_buffer>>    textures;\r
-       frame_transform                                                 transform;\r
+       pixel_format_desc                                                                                       pix_desc;\r
+       std::vector<boost::shared_future<safe_ptr<device_buffer>>>      textures;\r
+       frame_transform                                                                                         transform;\r
 };\r
 \r
 typedef std::pair<blend_mode, std::vector<item>> layer;\r
@@ -155,7 +153,10 @@ private:
        {                       \r
                draw_params draw_params;\r
                draw_params.pix_desc                            = std::move(item.pix_desc);\r
-               draw_params.textures                            = std::move(item.textures);\r
+\r
+               BOOST_FOREACH(auto& tex, item.textures)\r
+                       draw_params.textures.push_back(tex.get());\r
+\r
                draw_params.transform                           = std::move(item.transform);\r
 \r
                if(item.transform.is_key)\r
@@ -242,7 +243,7 @@ public:
                transform_stack_.push_back(transform_stack_.back()*frame.get_frame_transform());\r
        }\r
                \r
-       void visit(write_frame& frame)\r
+       void visit(device_frame& frame)\r
        {                       \r
                item item;\r
                item.pix_desc   = frame.get_pixel_format_desc();\r
@@ -271,7 +272,7 @@ public:
 \r
 image_mixer::image_mixer(const safe_ptr<ogl_device>& ogl) : impl_(new impl(ogl)){}\r
 void image_mixer::begin(basic_frame& frame){impl_->begin(frame);}\r
-void image_mixer::visit(write_frame& frame){impl_->visit(frame);}\r
+void image_mixer::visit(device_frame& frame){impl_->visit(frame);}\r
 void image_mixer::end(){impl_->end();}\r
 boost::unique_future<safe_ptr<host_buffer>> image_mixer::operator()(const video_format_desc& format_desc){return impl_->render(format_desc);}\r
 void image_mixer::begin_layer(blend_mode blend_mode){impl_->begin_layer(blend_mode);}\r
index 2b950971c4e7bb66898e59c6101575e40f35b752..ebad17d7cef9f3c708e81d813141fc75ff084722 100644 (file)
@@ -38,7 +38,7 @@ public:
        image_mixer(const safe_ptr<class ogl_device>& ogl);\r
        \r
        virtual void begin(class basic_frame& frame);\r
-       virtual void visit(class write_frame& frame);\r
+       virtual void visit(class device_frame& frame);\r
        virtual void end();\r
 \r
        void begin_layer(blend_mode blend_mode);\r
index 39f2f3a947535796036eb23b84c1fd919e347a33..ece1927285e352095de3133e1fc55f491be15f59 100644 (file)
@@ -23,8 +23,8 @@
 \r
 #include "mixer.h"\r
 \r
-#include "read_frame.h"\r
-#include "write_frame.h"\r
+#include "data_frame.h"\r
+#include "device_frame.h"\r
 \r
 #include "audio/audio_mixer.h"\r
 #include "image/image_mixer.h"\r
@@ -36,8 +36,8 @@
 #include <common/gl/gl_check.h>\r
 #include <common/utility/tweener.h>\r
 \r
-#include <core/mixer/read_frame.h>\r
-#include <core/mixer/write_frame.h>\r
+#include <core/mixer/data_frame.h>\r
+#include <core/mixer/device_frame.h>\r
 #include <core/producer/frame/basic_frame.h>\r
 #include <core/producer/frame/frame_factory.h>\r
 #include <core/producer/frame/frame_transform.h>\r
@@ -113,7 +113,7 @@ public:
 \r
                                graph_->set_value("mix-time", mix_timer_.elapsed()*format_desc_.fps*0.5);\r
                                \r
-                               target_->send(std::make_pair(make_safe<read_frame>(format_desc_.width, format_desc_.height, std::move(image), std::move(audio)), packet.second));       \r
+                               target_->send(std::make_pair(make_safe<data_frame>(format_desc_.width, format_desc_.height, std::move(image), std::move(audio)), packet.second));       \r
                        }\r
                        catch(...)\r
                        {\r
index 519b546de4b0e5594842f5e1400fd09c83fc7da4..a8fecd71013d6816cb66f6c75930b4daf57b6c14 100644 (file)
@@ -41,7 +41,7 @@ class mixer sealed : public target<std::pair<std::map<int, safe_ptr<class basic_
                                   , boost::noncopyable\r
 {\r
 public:        \r
-       typedef target<std::pair<safe_ptr<class read_frame>, std::shared_ptr<void>>> target_t;\r
+       typedef target<std::pair<safe_ptr<class data_frame>, std::shared_ptr<void>>> target_t;\r
 \r
        explicit mixer(const safe_ptr<target_t>& target, const safe_ptr<diagnostics::graph>& graph, const struct video_format_desc& format_desc, const safe_ptr<class ogl_device>& ogl);\r
                \r
diff --git a/core/mixer/write_frame.cpp b/core/mixer/write_frame.cpp
deleted file mode 100644 (file)
index c4de6af..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-/*\r
-* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
-*\r
-* This file is part of CasparCG (www.casparcg.com).\r
-*\r
-* CasparCG is free software: you can redistribute it and/or modify\r
-* it under the terms of the GNU General Public License as published by\r
-* the Free Software Foundation, either version 3 of the License, or\r
-* (at your option) any later version.\r
-*\r
-* CasparCG is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-* GNU General Public License for more details.\r
-*\r
-* You should have received a copy of the GNU General Public License\r
-* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-* Author: Robert Nagy, ronag89@gmail.com\r
-*/\r
-\r
-#include "../stdafx.h"\r
-\r
-#include "write_frame.h"\r
-\r
-#include "gpu/ogl_device.h"\r
-#include "gpu/host_buffer.h"\r
-#include "gpu/device_buffer.h"\r
-\r
-#include <core/producer/frame/frame_visitor.h>\r
-#include <core/producer/frame/pixel_format.h>\r
-#include <common/scope_guard.h>\r
-#include <common/gl/gl_check.h>\r
-\r
-#include <boost/lexical_cast.hpp>\r
-\r
-namespace caspar { namespace core {\r
-                                                                                                                                                                                                                                                                                                                       \r
-struct write_frame::impl : boost::noncopyable\r
-{                      \r
-       std::shared_ptr<ogl_device>                                     ogl_;\r
-       std::vector<std::shared_ptr<host_buffer>>       buffers_;\r
-       std::vector<safe_ptr<device_buffer>>            textures_;\r
-       audio_buffer                                                            audio_data_;\r
-       const core::pixel_format_desc                           desc_;\r
-       const void*                                                                     tag_;\r
-       core::field_mode                                                        mode_;\r
-\r
-       impl(const void* tag)\r
-               : tag_(tag)\r
-               , mode_(core::field_mode::empty)\r
-       {\r
-       }\r
-\r
-       impl(const safe_ptr<ogl_device>& ogl, const void* tag, const core::pixel_format_desc& desc) \r
-               : ogl_(ogl)\r
-               , desc_(desc)\r
-               , tag_(tag)\r
-               , mode_(core::field_mode::progressive)\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
-       void accept(write_frame& self, core::frame_visitor& visitor)\r
-       {\r
-               visitor.begin(self);\r
-               visitor.visit(self);\r
-               visitor.end();\r
-       }\r
-\r
-       boost::iterator_range<uint8_t*> image_data(int index)\r
-       {\r
-               if(index >= buffers_.size() || !buffers_[index]->data())\r
-                       return boost::iterator_range<uint8_t*>();\r
-               auto ptr = static_cast<uint8_t*>(buffers_[index]->data());\r
-               return boost::iterator_range<uint8_t*>(ptr, ptr+buffers_[index]->size());\r
-       }\r
-       \r
-       void commit()\r
-       {\r
-               for(int n = 0; n < buffers_.size(); ++n)\r
-                       commit(n);\r
-       }\r
-\r
-       void commit(int plane_index)\r
-       {\r
-               if(plane_index >= buffers_.size())\r
-                       return;\r
-                               \r
-               auto buffer = std::move(buffers_[plane_index]); // Release buffer once done.\r
-\r
-               if(!buffer)\r
-                       return;\r
-\r
-               auto texture = textures_.at(plane_index);\r
-               \r
-               ogl_->begin_invoke([=]\r
-               {                       \r
-                       buffer->unmap();\r
-                       buffer->bind();\r
-                       \r
-                       ogl_->push_state();\r
-                       auto restore_state = make_scope_guard([&]\r
-                       {\r
-                               ogl_->pop_state();\r
-                       });\r
-\r
-                       ogl_->bind(*texture, 0);\r
-                       GL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->width(), texture->height(), format(texture->stride()), GL_UNSIGNED_BYTE, NULL));\r
-                       \r
-                       buffer->unbind();\r
-               }, high_priority);\r
-       }\r
-};\r
-       \r
-write_frame::write_frame(const void* tag) : impl_(new impl(tag)){}\r
-write_frame::write_frame(const safe_ptr<ogl_device>& ogl, const void* tag, const core::pixel_format_desc& desc) \r
-       : impl_(new impl(ogl, tag, desc)){}\r
-write_frame::write_frame(write_frame&& other) : impl_(std::move(other.impl_)){}\r
-write_frame& write_frame::operator=(write_frame&& other)\r
-{\r
-       write_frame temp(std::move(other));\r
-       temp.swap(*this);\r
-       return *this;\r
-}\r
-void write_frame::swap(write_frame& other){impl_.swap(other.impl_);}\r
-boost::iterator_range<uint8_t*> write_frame::image_data(int index){return impl_->image_data(index);}\r
-audio_buffer& write_frame::audio_data() { return impl_->audio_data_; }\r
-const void* write_frame::tag() const {return impl_->tag_;}\r
-const core::pixel_format_desc& write_frame::get_pixel_format_desc() const{return impl_->desc_;}\r
-const std::vector<safe_ptr<device_buffer>>& write_frame::get_textures() const{return impl_->textures_;}\r
-void write_frame::commit(int plane_index){impl_->commit(plane_index);}\r
-void write_frame::commit(){impl_->commit();}\r
-void write_frame::set_type(const field_mode& mode){impl_->mode_ = mode;}\r
-core::field_mode write_frame::get_type() const{return impl_->mode_;}\r
-void write_frame::accept(core::frame_visitor& visitor){impl_->accept(*this, visitor);}\r
-\r
-}}
\ No newline at end of file
index 34d19f554f5f4ee33311edb9ab8ee70eb0f6ba22..98a886c878d6ca5191e0f0ecaf55005b0eff8166 100644 (file)
@@ -31,8 +31,8 @@
 #include "../frame/basic_frame.h"\r
 #include "../frame/frame_factory.h"\r
 #include "../frame/pixel_format.h"\r
-#include "../../mixer/write_frame.h"\r
-#include "../../mixer/read_frame.h"\r
+#include "../../mixer/device_frame.h"\r
+#include "../../mixer/data_frame.h"\r
 \r
 #include <common/exception/exceptions.h>\r
 \r
@@ -44,7 +44,7 @@ namespace caspar { namespace core {
 \r
 class channel_consumer : public frame_consumer\r
 {      \r
-       tbb::concurrent_bounded_queue<std::shared_ptr<read_frame>>      frame_buffer_;\r
+       tbb::concurrent_bounded_queue<std::shared_ptr<data_frame>>      frame_buffer_;\r
        core::video_format_desc                                                                         format_desc_;\r
        int                                                                                                                     channel_index_;\r
        tbb::atomic<bool>                                                                                       is_running_;\r
@@ -63,7 +63,7 @@ public:
 \r
        // frame_consumer\r
 \r
-       virtual bool send(const safe_ptr<read_frame>& frame) override\r
+       virtual bool send(const safe_ptr<data_frame>& frame) override\r
        {\r
                frame_buffer_.try_push(frame);\r
                return is_running_;\r
@@ -108,7 +108,7 @@ public:
        void stop()\r
        {\r
                is_running_ = false;\r
-               frame_buffer_.try_push(make_safe<read_frame>());\r
+               frame_buffer_.try_push(make_safe<data_frame>());\r
        }\r
        \r
        const core::video_format_desc& get_video_format_desc()\r
@@ -116,11 +116,11 @@ public:
                return format_desc_;\r
        }\r
 \r
-       std::shared_ptr<read_frame> receive()\r
+       std::shared_ptr<data_frame> receive()\r
        {\r
                if(!is_running_)\r
-                       return make_safe<read_frame>();\r
-               std::shared_ptr<read_frame> frame;\r
+                       return make_safe<data_frame>();\r
+               std::shared_ptr<data_frame> frame;\r
                frame_buffer_.try_pop(frame);\r
                return frame;\r
        }\r
@@ -165,8 +165,8 @@ public:
                        return last_frame_ = frame;\r
                }\r
                \r
-               auto read_frame = consumer_->receive();\r
-               if(!read_frame || read_frame->image_data().empty())\r
+               auto data_frame = consumer_->receive();\r
+               if(!data_frame || data_frame->image_data().empty())\r
                        return basic_frame::late();             \r
 \r
                frame_number_++;\r
@@ -180,11 +180,11 @@ public:
 \r
                desc.pix_fmt = core::pixel_format::bgra;\r
                desc.planes.push_back(core::pixel_format_desc::plane(format_desc.width, format_desc.height, 4));\r
-               auto frame = frame_factory_->create_frame(this, desc);\r
-\r
-               A_memcpy(frame->image_data().begin(), read_frame->image_data().begin(), read_frame->image_data().size());\r
-               frame->commit();\r
-\r
+               auto frame = frame_factory_->create_frame(this, desc, [&](const frame_factory::range_vector_type& ranges)\r
+               {\r
+                       A_memcpy(ranges.at(0).begin(), data_frame->image_data().begin(), data_frame->image_data().size());\r
+               });\r
+               \r
                frame_buffer_.push(frame);      \r
                \r
                if(double_speed)        \r
index 90568e553000c42256656b1b76b889477522f739..cf384579c13d2419d3aa7c9b6353999be21cb000 100644 (file)
@@ -27,7 +27,7 @@
 #include "../frame/basic_frame.h"\r
 #include "../frame/frame_factory.h"\r
 #include "../frame/pixel_format.h"\r
-#include "../../mixer/write_frame.h"\r
+#include "../../mixer/device_frame.h"\r
 \r
 #include <common/exception/exceptions.h>\r
 \r
@@ -127,7 +127,7 @@ safe_ptr<frame_producer> create_color_producer(const safe_ptr<frame_factory>& fr
        return create_producer_print_proxy(\r
                        make_safe<color_producer>(frame_factory, color2));\r
 }\r
-safe_ptr<write_frame> create_color_frame(void* tag, const safe_ptr<frame_factory>& frame_factory, const std::wstring& color)\r
+safe_ptr<device_frame> create_color_frame(void* tag, const safe_ptr<frame_factory>& frame_factory, const std::wstring& color)\r
 {\r
        auto color2 = get_hex_color(color);\r
        if(color2.length() != 9 || color2[0] != '#')\r
@@ -136,18 +136,13 @@ safe_ptr<write_frame> create_color_frame(void* tag, const safe_ptr<frame_factory
        core::pixel_format_desc desc;\r
        desc.pix_fmt = pixel_format::bgra;\r
        desc.planes.push_back(core::pixel_format_desc::plane(1, 1, 4));\r
-       auto frame = frame_factory->create_frame(tag, desc);\r
-               \r
-       // Read color from hex-string and write to frame pixel.\r
-\r
-       auto& value = *reinterpret_cast<uint32_t*>(frame->image_data().begin());\r
-       std::wstringstream str(color2.substr(1));\r
-       if(!(str >> std::hex >> value) || !str.eof())\r
-               BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("color") << arg_value_info(color2) << msg_info("Invalid color."));\r
-\r
-       frame->commit();\r
-               \r
-       return frame;\r
+       return frame_factory->create_frame(tag, desc, [&](const frame_factory::range_vector_type& ranges)\r
+       {               \r
+               auto& value = *reinterpret_cast<uint32_t*>(ranges.at(0).begin());\r
+               std::wstringstream str(color2.substr(1));\r
+               if(!(str >> std::hex >> value) || !str.eof())\r
+                       BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("color") << arg_value_info(color2) << msg_info("Invalid color."));\r
+       });\r
 }\r
 \r
 }}
\ No newline at end of file
index ce6cfde36157e72777937ee242ffdddd080f46cf..deb18b9d82d8bc123f32446163094552ed5c710c 100644 (file)
@@ -29,6 +29,6 @@
 namespace caspar { namespace core {\r
        \r
 safe_ptr<struct frame_producer> create_color_producer(const safe_ptr<struct frame_factory>& frame_factory, const std::vector<std::wstring>& params);\r
-safe_ptr<class write_frame> create_color_frame(void* tag, const safe_ptr<struct frame_factory>& frame_factory, const std::wstring& color);\r
+safe_ptr<class device_frame> create_color_frame(void* tag, const safe_ptr<struct frame_factory>& frame_factory, const std::wstring& color);\r
 \r
 }}\r
index 159903acb4a6695f80461cdbbcdf0a13bcf508cf..ebeee9891ad72dc9f766d55e1e01e5a0f6add27e 100644 (file)
 #include <common/memory/safe_ptr.h>\r
 \r
 #include <boost/noncopyable.hpp>\r
+#include <boost/range.hpp>\r
 \r
 namespace caspar { namespace core {\r
                        \r
 struct frame_factory : boost::noncopyable\r
 {\r
+       typedef boost::iterator_range<uint8_t*> range_type;\r
+       typedef std::vector<range_type> range_vector_type;\r
+\r
        frame_factory(){}\r
+       \r
+\r
+       virtual safe_ptr<class device_frame> create_frame(const void* video_stream_tag, \r
+                                                                                                        const struct pixel_format_desc& desc, \r
+                                                                                                        const std::function<void(const range_vector_type&)>& func, \r
+                                                                                                        core::field_mode type = core::field_mode::progressive) = 0;    \r
 \r
-       virtual safe_ptr<class write_frame> create_frame(const void* video_stream_tag, const struct pixel_format_desc& desc) = 0;               \r
        virtual struct video_format_desc get_video_format_desc() const = 0; // nothrow\r
 };\r
 \r
index b8b184249441fcfd2a2bb6680c89ca65bac94ad2..c9429c552644b2346081a1ae66bd7fe6852d87de 100644 (file)
@@ -29,7 +29,7 @@ struct frame_visitor : boost::noncopyable
 {\r
        virtual void begin(class basic_frame& frame) = 0;\r
        virtual void end() = 0;\r
-       virtual void visit(class write_frame& frame) = 0;\r
+       virtual void visit(class device_frame& frame) = 0;\r
 };\r
 \r
 }}
\ No newline at end of file
index 42bb8210e902389ac1b6a53026e6e730a336f7ee..0dc392ccfe4bf4529b987761d54d2a93a000a107 100644 (file)
 #include "consumer/output.h"\r
 #include "mixer/mixer.h"\r
 #include "mixer/gpu/ogl_device.h"\r
-#include "mixer/write_frame.h"\r
+#include "mixer/device_frame.h"\r
 #include "producer/stage.h"\r
 #include "producer/frame/frame_factory.h"\r
+#include "producer/frame/pixel_format.h"\r
 \r
 #include <common/diagnostics/graph.h>\r
 #include <common/env.h>\r
@@ -70,9 +71,29 @@ public:
 \r
        // frame_factory\r
                                                \r
-       virtual safe_ptr<write_frame> create_frame(const void* tag, const core::pixel_format_desc& desc) override\r
+       virtual safe_ptr<device_frame> create_frame(const void* tag, const core::pixel_format_desc& desc, const std::function<void(const frame_factory::range_vector_type&)>& func, core::field_mode type) override\r
        {               \r
-               return make_safe<write_frame>(ogl_, tag, desc);\r
+               std::vector<safe_ptr<host_buffer>> buffers;\r
+               BOOST_FOREACH(auto& plane, desc.planes)\r
+                       buffers.push_back(ogl_->create_host_buffer(plane.size, host_buffer::write_only));\r
+\r
+               std::vector<boost::iterator_range<uint8_t*>> dest;\r
+               boost::range::transform(buffers, std::back_inserter(dest), [](const safe_ptr<host_buffer>& buffer) -> boost::iterator_range<uint8_t*>\r
+               {\r
+                       auto ptr = reinterpret_cast<uint8_t*>(buffer->data());\r
+                       return boost::iterator_range<uint8_t*>(ptr, ptr + buffer->size());\r
+               });\r
+\r
+               func(dest);\r
+\r
+               std::vector<boost::unique_future<safe_ptr<device_buffer>>> textures;\r
+               for(std::size_t n = 0; n < desc.planes.size(); ++n)\r
+               {\r
+                       auto texture = ogl_->transfer(buffers.at(n), desc.planes[n].width, desc.planes[n].height, desc.planes[n].channels);\r
+                       textures.push_back(std::move(texture));\r
+               }\r
+               \r
+               return make_safe<device_frame>(std::move(textures), tag, desc, type);\r
        }\r
        \r
        virtual core::video_format_desc get_video_format_desc() const override\r
index 3be523adb39b781d717a6b5f24f21adb38cc51b2..7b95b6c5f1223193f7493cf3c0deb1a18b8cce89 100644 (file)
@@ -26,7 +26,7 @@
 #include "../util/memory.h"\r
 \r
 #include <core/video_format.h>\r
-#include <core/mixer/read_frame.h>\r
+#include <core/mixer/data_frame.h>\r
 \r
 #include <common/concurrency/executor.h>\r
 #include <common/diagnostics/graph.h>\r
@@ -67,7 +67,7 @@ struct bluefish_consumer : boost::noncopyable
        unsigned int                                            vid_fmt_;\r
 \r
        std::array<blue_dma_buffer_ptr, 4>      reserved_frames_;       \r
-       tbb::concurrent_bounded_queue<std::shared_ptr<core::read_frame>> frame_buffer_;\r
+       tbb::concurrent_bounded_queue<std::shared_ptr<core::data_frame>> frame_buffer_;\r
        \r
        const bool                                                      embedded_audio_;\r
        const bool                                                      key_only_;\r
@@ -185,7 +185,7 @@ public:
                        CASPAR_LOG(error)<< print() << TEXT(" Failed to disable video output.");                \r
        }\r
        \r
-       void send(const safe_ptr<core::read_frame>& frame)\r
+       void send(const safe_ptr<core::data_frame>& frame)\r
        {                                       \r
                executor_.begin_invoke([=]\r
                {\r
@@ -202,7 +202,7 @@ public:
                });\r
        }\r
 \r
-       void display_frame(const safe_ptr<core::read_frame>& frame)\r
+       void display_frame(const safe_ptr<core::data_frame>& frame)\r
        {\r
                // Sync\r
 \r
@@ -328,7 +328,7 @@ public:
                CASPAR_LOG(info) << print() << L" Successfully Initialized.";   \r
        }\r
        \r
-       virtual bool send(const safe_ptr<core::read_frame>& frame) override\r
+       virtual bool send(const safe_ptr<core::data_frame>& frame) override\r
        {\r
                CASPAR_VERIFY(audio_cadence_.front() == static_cast<size_t>(frame->audio_data().size()));\r
                boost::range::rotate(audio_cadence_, std::begin(audio_cadence_)+1);\r
index f3241e3cdc33bd3fe03a1e263d5617e3f58415c4..b17ae313f327fb89cd42a12906014d0d88a033fd 100644 (file)
@@ -27,7 +27,7 @@
 \r
 #include "../interop/DeckLinkAPI_h.h"\r
 \r
-#include <core/mixer/read_frame.h>\r
+#include <core/mixer/data_frame.h>\r
 \r
 #include <common/concurrency/executor.h>\r
 #include <common/concurrency/lock.h>\r
@@ -76,13 +76,13 @@ struct configuration
 class decklink_frame : public IDeckLinkVideoFrame\r
 {\r
        tbb::atomic<int>                                                                                        ref_count_;\r
-       std::shared_ptr<core::read_frame>                                                       frame_;\r
+       std::shared_ptr<core::data_frame>                                                       frame_;\r
        const core::video_format_desc                                                           format_desc_;\r
 \r
        const bool                                                                                                      key_only_;\r
        std::vector<uint8_t, tbb::cache_aligned_allocator<uint8_t>> data_;\r
 public:\r
-       decklink_frame(const safe_ptr<core::read_frame>& frame, const core::video_format_desc& format_desc, bool key_only)\r
+       decklink_frame(const safe_ptr<core::data_frame>& frame, const core::video_format_desc& format_desc, bool key_only)\r
                : frame_(frame)\r
                , format_desc_(format_desc)\r
                , key_only_(key_only)\r
@@ -184,8 +184,8 @@ struct decklink_consumer : public IDeckLinkVideoOutputCallback, public IDeckLink
                \r
        boost::circular_buffer<std::vector<int32_t>>    audio_container_;\r
 \r
-       tbb::concurrent_bounded_queue<std::shared_ptr<core::read_frame>> video_frame_buffer_;\r
-       tbb::concurrent_bounded_queue<std::shared_ptr<core::read_frame>> audio_frame_buffer_;\r
+       tbb::concurrent_bounded_queue<std::shared_ptr<core::data_frame>> video_frame_buffer_;\r
+       tbb::concurrent_bounded_queue<std::shared_ptr<core::data_frame>> audio_frame_buffer_;\r
        \r
        safe_ptr<diagnostics::graph> graph_;\r
        boost::timer tick_timer_;\r
@@ -232,7 +232,7 @@ public:
                        output_->BeginAudioPreroll();           \r
                \r
                for(int n = 0; n < buffer_size_; ++n)\r
-                       schedule_next_video(make_safe<core::read_frame>());\r
+                       schedule_next_video(make_safe<core::data_frame>());\r
 \r
                if(!config.embedded_audio)\r
                        start_playback();\r
@@ -241,8 +241,8 @@ public:
        ~decklink_consumer()\r
        {               \r
                is_running_ = false;\r
-               video_frame_buffer_.try_push(std::make_shared<core::read_frame>());\r
-               audio_frame_buffer_.try_push(std::make_shared<core::read_frame>());\r
+               video_frame_buffer_.try_push(std::make_shared<core::data_frame>());\r
+               audio_frame_buffer_.try_push(std::make_shared<core::data_frame>());\r
 \r
                if(output_ != nullptr) \r
                {\r
@@ -349,7 +349,7 @@ public:
                        else if(result == bmdOutputFrameFlushed)\r
                                graph_->set_tag("flushed-frame");\r
 \r
-                       std::shared_ptr<core::read_frame> frame;        \r
+                       std::shared_ptr<core::data_frame> frame;        \r
                        video_frame_buffer_.pop(frame);                                 \r
                        schedule_next_video(make_safe_ptr(frame));      \r
                        \r
@@ -388,7 +388,7 @@ public:
                        }\r
                        else\r
                        {\r
-                               std::shared_ptr<core::read_frame> frame;\r
+                               std::shared_ptr<core::data_frame> frame;\r
                                audio_frame_buffer_.pop(frame);\r
                                schedule_next_audio(frame->audio_data());\r
                        }\r
@@ -420,7 +420,7 @@ public:
                audio_scheduled_ += sample_frame_count;\r
        }\r
                        \r
-       void schedule_next_video(const safe_ptr<core::read_frame>& frame)\r
+       void schedule_next_video(const safe_ptr<core::data_frame>& frame)\r
        {\r
                CComPtr<IDeckLinkVideoFrame> frame2(new decklink_frame(frame, format_desc_, config_.key_only));\r
                if(FAILED(output_->ScheduleVideoFrame(frame2, video_scheduled_, format_desc_.duration, format_desc_.time_scale)))\r
@@ -432,7 +432,7 @@ public:
                tick_timer_.restart();\r
        }\r
 \r
-       void send(const safe_ptr<core::read_frame>& frame)\r
+       void send(const safe_ptr<core::data_frame>& frame)\r
        {\r
                auto exception = lock(exception_mutex_, [&]\r
                {\r
@@ -502,7 +502,7 @@ public:
                });\r
        }\r
        \r
-       virtual bool send(const safe_ptr<core::read_frame>& frame) override\r
+       virtual bool send(const safe_ptr<core::data_frame>& frame) override\r
        {\r
                CASPAR_VERIFY(audio_cadence_.front() == static_cast<int>(frame->audio_data().size()));\r
                boost::range::rotate(audio_cadence_, std::begin(audio_cadence_)+1);\r
index 50940429427e27967881ac9c4b749fe80a5117d4..c557b4e5ab37a5e4e776e2b803671f11816cd108 100644 (file)
@@ -37,7 +37,7 @@
 #include <common/log.h>\r
 #include <common/utility/param.h>\r
 \r
-#include <core/mixer/write_frame.h>\r
+#include <core/mixer/device_frame.h>\r
 #include <core/producer/frame/frame_transform.h>\r
 #include <core/producer/frame/frame_factory.h>\r
 \r
index 88cd2e15b994405f656c09fff86846a3777022ae..c861db899c15fb5a2618ab10478e431f47c2a811 100644 (file)
@@ -25,7 +25,7 @@
 \r
 #include "ffmpeg_consumer.h"\r
 \r
-#include <core/mixer/read_frame.h>\r
+#include <core/mixer/data_frame.h>\r
 #include <core/mixer/audio/audio_util.h>\r
 #include <core/consumer/frame_consumer.h>\r
 #include <core/video_format.h>\r
@@ -280,7 +280,7 @@ public:
                });\r
        }\r
 \r
-       std::shared_ptr<AVFrame> convert_video_frame(const safe_ptr<core::read_frame>& frame, AVCodecContext* c)\r
+       std::shared_ptr<AVFrame> convert_video_frame(const safe_ptr<core::data_frame>& frame, AVCodecContext* c)\r
        {\r
                if(!sws_) \r
                {\r
@@ -301,7 +301,7 @@ public:
                return local_av_frame;\r
        }\r
   \r
-       std::shared_ptr<AVPacket> encode_video_frame(const safe_ptr<core::read_frame>& frame)\r
+       std::shared_ptr<AVPacket> encode_video_frame(const safe_ptr<core::data_frame>& frame)\r
        { \r
                auto c = video_st_->codec;\r
  \r
@@ -336,7 +336,7 @@ public:
                return nullptr;\r
        }\r
                \r
-       std::shared_ptr<AVPacket> encode_audio_frame(const safe_ptr<core::read_frame>& frame)\r
+       std::shared_ptr<AVPacket> encode_audio_frame(const safe_ptr<core::data_frame>& frame)\r
        {                       \r
                auto c = audio_st_->codec;\r
 \r
@@ -361,7 +361,7 @@ public:
                return pkt;\r
        }\r
                 \r
-       void send(const safe_ptr<core::read_frame>& frame)\r
+       void send(const safe_ptr<core::data_frame>& frame)\r
        {\r
                executor_.begin_invoke([=]\r
                {               \r
@@ -412,7 +412,7 @@ public:
                consumer_.reset(new ffmpeg_consumer(filename_, format_desc, codec_, options_));\r
        }\r
        \r
-       virtual bool send(const safe_ptr<core::read_frame>& frame) override\r
+       virtual bool send(const safe_ptr<core::data_frame>& frame) override\r
        {\r
                consumer_->send(frame);\r
                return true;\r
index bd2925ea294fc6838b00e381b54489f6839eb746..b9d897273be8789e66abf51464668626b898446e 100644 (file)
@@ -31,7 +31,7 @@
 #include <core/producer/frame/frame_transform.h>\r
 #include <core/producer/frame/pixel_format.h>\r
 #include <core/producer/frame/frame_factory.h>\r
-#include <core/mixer/write_frame.h>\r
+#include <core/mixer/device_frame.h>\r
 \r
 #include <common/env.h>\r
 #include <common/exception/exceptions.h>\r
@@ -67,7 +67,7 @@ namespace caspar { namespace ffmpeg {
        \r
 struct frame_muxer::impl : boost::noncopyable\r
 {      \r
-       std::queue<std::queue<safe_ptr<write_frame>>>   video_streams_;\r
+       std::queue<std::queue<safe_ptr<device_frame>>>  video_streams_;\r
        std::queue<core::audio_buffer>                                  audio_streams_;\r
        std::queue<safe_ptr<basic_frame>>                               frame_buffer_;\r
        display_mode                                                            display_mode_;\r
@@ -95,7 +95,7 @@ struct frame_muxer::impl : boost::noncopyable
                , filter_str_(filter_str)\r
                , force_deinterlacing_(false)\r
        {\r
-               video_streams_.push(std::queue<safe_ptr<write_frame>>());\r
+               video_streams_.push(std::queue<safe_ptr<device_frame>>());\r
                audio_streams_.push(core::audio_buffer());\r
                \r
                // Note: Uses 1 step rotated cadence for 1001 modes (1602, 1602, 1601, 1602, 1601)\r
@@ -110,11 +110,11 @@ struct frame_muxer::impl : boost::noncopyable
                \r
                if(video_frame == flush_video())\r
                {       \r
-                       video_streams_.push(std::queue<safe_ptr<write_frame>>());\r
+                       video_streams_.push(std::queue<safe_ptr<device_frame>>());\r
                }\r
                else if(video_frame == empty_video())\r
                {\r
-                       video_streams_.back().push(make_safe<core::write_frame>(this));\r
+                       video_streams_.back().push(make_safe<core::device_frame>(this));\r
                        display_mode_ = display_mode::simple;\r
                }\r
                else\r
@@ -143,7 +143,7 @@ struct frame_muxer::impl : boost::noncopyable
                                if(video_frame->format == PIX_FMT_GRAY8 && format == CASPAR_PIX_FMT_LUMA)\r
                                        av_frame->format = format;\r
 \r
-                               video_streams_.back().push(make_write_frame(this, av_frame, frame_factory_, flags));\r
+                               video_streams_.back().push(make_device_frame(this, av_frame, frame_factory_, flags));\r
                        }\r
                }\r
 \r
@@ -250,7 +250,7 @@ struct frame_muxer::impl : boost::noncopyable
                        }\r
                case display_mode::duplicate:   \r
                        {\r
-                               auto frame2                             = make_safe<core::write_frame>(*frame1);\r
+                               auto frame2                             = make_safe<core::device_frame>(*frame1);\r
                                frame2->audio_data()    = pop_audio();\r
 \r
                                frame_buffer_.push(frame1);\r
@@ -269,7 +269,7 @@ struct frame_muxer::impl : boost::noncopyable
                return frame_buffer_.empty() ? nullptr : poll();\r
        }\r
        \r
-       safe_ptr<core::write_frame> pop_video()\r
+       safe_ptr<core::device_frame> pop_video()\r
        {\r
                auto frame = video_streams_.front().front();\r
                video_streams_.front().pop();           \r
@@ -344,7 +344,7 @@ struct frame_muxer::impl : boost::noncopyable
                                filter_.push(frame);\r
                                auto av_frame = filter_.poll();\r
                                if(av_frame)                                                    \r
-                                       video_streams_.back().push(make_write_frame(this, make_safe_ptr(av_frame), frame_factory_, 0));\r
+                                       video_streams_.back().push(make_device_frame(this, make_safe_ptr(av_frame), frame_factory_, 0));\r
                        }\r
                        filter_ = filter(filter_str);\r
                        CASPAR_LOG(info) << L"[frame_muxer] " << display_mode_ << L" " << print_mode(frame->width, frame->height, in_fps_, frame->interlaced_frame > 0);\r
index f92e0fadf1201a9698725f9e0ead5e9ebeb97eb5..af0d9aa5cbf53e4a98dc86589ba5153958218e73 100644 (file)
@@ -37,7 +37,7 @@ namespace caspar {
        \r
 namespace core {\r
 \r
-class write_frame;\r
+class device_frame;\r
 class basic_frame;\r
 struct frame_factory;\r
 \r
index d47f588fa2ae46ef9709b631815fc09506f66b20..fee7ee33097d5de983a28e9b584b4e4a8ce2c90c 100644 (file)
@@ -34,7 +34,7 @@
 #include <core/producer/frame/frame_transform.h>\r
 #include <core/producer/frame/frame_factory.h>\r
 #include <core/producer/frame_producer.h>\r
-#include <core/mixer/write_frame.h>\r
+#include <core/mixer/device_frame.h>\r
 \r
 #include <common/exception/exceptions.h>\r
 \r
@@ -172,12 +172,12 @@ int make_alpha_format(int format)
        }\r
 }\r
 \r
-safe_ptr<core::write_frame> make_write_frame(const void* tag, const safe_ptr<AVFrame>& decoded_frame, const safe_ptr<core::frame_factory>& frame_factory, int flags)\r
+safe_ptr<core::device_frame> make_device_frame(const void* tag, const safe_ptr<AVFrame>& decoded_frame, const safe_ptr<core::frame_factory>& frame_factory, int flags)\r
 {                      \r
        static tbb::concurrent_unordered_map<int, tbb::concurrent_queue<std::shared_ptr<SwsContext>>> sws_contexts_;\r
        \r
        if(decoded_frame->width < 1 || decoded_frame->height < 1)\r
-               return make_safe<core::write_frame>(tag);\r
+               return make_safe<core::device_frame>(tag);\r
 \r
        const auto width  = decoded_frame->width;\r
        const auto height = decoded_frame->height;\r
@@ -186,7 +186,7 @@ safe_ptr<core::write_frame> make_write_frame(const void* tag, const safe_ptr<AVF
        if(flags & core::frame_producer::flags::alpha_only)\r
                desc = get_pixel_format_desc(static_cast<PixelFormat>(make_alpha_format(decoded_frame->format)), width, height);\r
 \r
-       std::shared_ptr<core::write_frame> write;\r
+       std::shared_ptr<core::device_frame> write;\r
 \r
        if(desc.pix_fmt == core::pixel_format::invalid)\r
        {\r
@@ -208,77 +208,72 @@ safe_ptr<core::write_frame> make_write_frame(const void* tag, const safe_ptr<AVF
                \r
                auto target_desc = get_pixel_format_desc(target_pix_fmt, width, height);\r
 \r
-               write = frame_factory->create_frame(tag, target_desc);\r
-               write->set_type(get_mode(*decoded_frame));\r
-\r
-               std::shared_ptr<SwsContext> sws_context;\r
+               write = frame_factory->create_frame(tag, target_desc, [&](const std::vector<boost::iterator_range<uint8_t*>>& dest)\r
+               {\r
+                       std::shared_ptr<SwsContext> sws_context;\r
 \r
-               //CASPAR_LOG(warning) << "Hardware accelerated color transform not supported.";\r
+                       //CASPAR_LOG(warning) << "Hardware accelerated color transform not supported.";\r
 \r
-               int key = ((width << 22) & 0xFFC00000) | ((height << 6) & 0x003FC000) | ((pix_fmt << 7) & 0x00007F00) | ((target_pix_fmt << 0) & 0x0000007F);\r
+                       int key = ((width << 22) & 0xFFC00000) | ((height << 6) & 0x003FC000) | ((pix_fmt << 7) & 0x00007F00) | ((target_pix_fmt << 0) & 0x0000007F);\r
                        \r
-               auto& pool = sws_contexts_[key];\r
+                       auto& pool = sws_contexts_[key];\r
                                                \r
-               if(!pool.try_pop(sws_context))\r
-               {\r
-                       double param;\r
-                       sws_context.reset(sws_getContext(width, height, pix_fmt, width, height, target_pix_fmt, SWS_BILINEAR, nullptr, nullptr, &param), sws_freeContext);\r
-               }\r
+                       if(!pool.try_pop(sws_context))\r
+                       {\r
+                               double param;\r
+                               sws_context.reset(sws_getContext(width, height, pix_fmt, width, height, target_pix_fmt, SWS_BILINEAR, nullptr, nullptr, &param), sws_freeContext);\r
+                       }\r
                        \r
-               if(!sws_context)\r
-               {\r
-                       BOOST_THROW_EXCEPTION(operation_failed() << msg_info("Could not create software scaling context.") << \r
-                                                                       boost::errinfo_api_function("sws_getContext"));\r
-               }       \r
+                       if(!sws_context)\r
+                       {\r
+                               BOOST_THROW_EXCEPTION(operation_failed() << msg_info("Could not create software scaling context.") << \r
+                                                                               boost::errinfo_api_function("sws_getContext"));\r
+                       }       \r
                \r
-               safe_ptr<AVFrame> av_frame(avcodec_alloc_frame(), av_free);     \r
-               avcodec_get_frame_defaults(av_frame.get());                     \r
-               if(target_pix_fmt == PIX_FMT_BGRA)\r
-               {\r
-                       auto size = avpicture_fill(reinterpret_cast<AVPicture*>(av_frame.get()), write->image_data().begin(), PIX_FMT_BGRA, width, height);\r
-                       CASPAR_VERIFY(size == write->image_data().size()); \r
-               }\r
-               else\r
-               {\r
-                       av_frame->width  = width;\r
-                       av_frame->height = height;\r
-                       for(int n = 0; n < target_desc.planes.size(); ++n)\r
+                       safe_ptr<AVFrame> av_frame(avcodec_alloc_frame(), av_free);     \r
+                       avcodec_get_frame_defaults(av_frame.get());                     \r
+                       if(target_pix_fmt == PIX_FMT_BGRA)\r
                        {\r
-                               av_frame->data[n]               = write->image_data(n).begin();\r
-                               av_frame->linesize[n]   = target_desc.planes[n].linesize;\r
+                               avpicture_fill(reinterpret_cast<AVPicture*>(av_frame.get()), dest.at(0).begin(), PIX_FMT_BGRA, width, height);\r
+                       }\r
+                       else\r
+                       {\r
+                               av_frame->width  = width;\r
+                               av_frame->height = height;\r
+                               for(int n = 0; n < target_desc.planes.size(); ++n)\r
+                               {\r
+                                       av_frame->data[n]               = dest.at(n).begin();\r
+                                       av_frame->linesize[n]   = target_desc.planes[n].linesize;\r
+                               }\r
                        }\r
-               }\r
-\r
-               sws_scale(sws_context.get(), decoded_frame->data, decoded_frame->linesize, 0, height, av_frame->data, av_frame->linesize);      \r
-               pool.push(sws_context);\r
 \r
-               write->commit();                \r
+                       sws_scale(sws_context.get(), decoded_frame->data, decoded_frame->linesize, 0, height, av_frame->data, av_frame->linesize);      \r
+                       pool.push(sws_context); \r
+               }, get_mode(*decoded_frame));\r
        }\r
        else\r
        {\r
-               write = frame_factory->create_frame(tag, desc);\r
-               write->set_type(get_mode(*decoded_frame));\r
-\r
-               for(int n = 0; n < static_cast<int>(desc.planes.size()); ++n)\r
+               write = frame_factory->create_frame(tag, desc, [&](const std::vector<boost::iterator_range<uint8_t*>>& dest)\r
                {\r
-                       auto plane            = desc.planes[n];\r
-                       auto result           = write->image_data(n).begin();\r
-                       auto decoded          = decoded_frame->data[n];\r
-                       auto decoded_linesize = decoded_frame->linesize[n];\r
-                       \r
-                       CASPAR_ASSERT(decoded);\r
-                       CASPAR_ASSERT(write->image_data(n).begin());\r
-\r
-                       // Copy line by line since ffmpeg sometimes pads each line.\r
-                       tbb::affinity_partitioner ap;\r
-                       tbb::parallel_for(tbb::blocked_range<int>(0, desc.planes[n].height), [&](const tbb::blocked_range<int>& r)\r
+                       for(int n = 0; n < static_cast<int>(desc.planes.size()); ++n)\r
                        {\r
-                               for(int y = r.begin(); y != r.end(); ++y)\r
-                                       A_memcpy(result + y*plane.linesize, decoded + y*decoded_linesize, plane.linesize);\r
-                       }, ap);\r
+                               auto plane            = desc.planes[n];\r
+                               auto result           = dest.at(n).begin();\r
+                               auto decoded          = decoded_frame->data[n];\r
+                               auto decoded_linesize = decoded_frame->linesize[n];\r
+                       \r
+                               CASPAR_ASSERT(decoded);\r
+                               CASPAR_ASSERT(dest.at(n).begin());\r
 \r
-                       write->commit(n);\r
-               }\r
+                               // Copy line by line since ffmpeg sometimes pads each line.\r
+                               tbb::affinity_partitioner ap;\r
+                               tbb::parallel_for(tbb::blocked_range<int>(0, desc.planes[n].height), [&](const tbb::blocked_range<int>& r)\r
+                               {\r
+                                       for(int y = r.begin(); y != r.end(); ++y)\r
+                                               A_memcpy(result + y*plane.linesize, decoded + y*decoded_linesize, plane.linesize);\r
+                               }, ap);\r
+                       }\r
+               }, get_mode(*decoded_frame));\r
        }\r
 \r
        if(decoded_frame->height == 480) // NTSC DV\r
index 11393946cea8eb2e022882714e3cdb8ed9d9e1fc..2a9d0324dd174e8a971b47d44d0d05541d816e00 100644 (file)
@@ -39,7 +39,7 @@ namespace caspar {
 namespace core {\r
 \r
 struct pixel_format_desc;\r
-class write_frame;\r
+class device_frame;\r
 struct frame_factory;\r
 \r
 }\r
@@ -57,7 +57,7 @@ static const int CASPAR_PIX_FMT_LUMA = 10; // Just hijack some unual pixel forma
 \r
 core::field_mode               get_mode(const AVFrame& frame);\r
 int                                                    make_alpha_format(int format); // NOTE: Be careful about CASPAR_PIX_FMT_LUMA, change it to PIX_FMT_GRAY8 if you want to use the frame inside some ffmpeg function.\r
-safe_ptr<core::write_frame> make_write_frame(const void* tag, const safe_ptr<AVFrame>& decoded_frame, const safe_ptr<core::frame_factory>& frame_factory, int flags);\r
+safe_ptr<core::device_frame> make_device_frame(const void* tag, const safe_ptr<AVFrame>& decoded_frame, const safe_ptr<core::frame_factory>& frame_factory, int flags);\r
 \r
 safe_ptr<AVPacket> create_packet();\r
 \r
index ed84594d81c61bd7f26287bd196af98bd012da59..27b03a8b79c2fe083cce21e1c84c8895e67b65d2 100644 (file)
@@ -33,7 +33,7 @@ namespace caspar {
 \r
 namespace core {\r
        struct frame_factory;\r
-       class write_frame;\r
+       class device_frame;\r
 }\r
 \r
 namespace ffmpeg {\r
index fe62c2a00a8e5106875c641524c3e2ca74ab3162..6a8dbfc66421be99c18f711a3678301e2e9bd5ae 100644 (file)
@@ -34,7 +34,7 @@
 #include <core/producer/frame/basic_frame.h>\r
 #include <core/producer/frame/frame_factory.h>\r
 #include <core/producer/frame/pixel_format.h>\r
-#include <core/mixer/write_frame.h>\r
+#include <core/mixer/device_frame.h>\r
 \r
 #include <common/env.h>\r
 #include <common/concurrency/executor.h>\r
@@ -251,11 +251,10 @@ public:
                        core::pixel_format_desc desc;\r
                        desc.pix_fmt = core::pixel_format::bgra;\r
                        desc.planes.push_back(core::pixel_format_desc::plane(width_, height_, 4));\r
-                       auto frame = frame_factory_->create_frame(this, desc);\r
-\r
-                       A_memcpy(frame->image_data().begin(), bmp_.data(), width_*height_*4);\r
-                       frame->commit();\r
-                       head_ = frame;\r
+                       head_ = frame_factory_->create_frame(this, desc, [&](const core::frame_factory::range_vector_type& ranges)\r
+                       {\r
+                               A_memcpy(ranges.at(0).begin(), bmp_.data(), width_*height_*4);\r
+                       });\r
                }               \r
                                \r
                graph_->set_value("frame-time", static_cast<float>(frame_timer_.elapsed()/frame_time)*0.5f);\r
index 0dc3ac0ea169f34529a71a9c790de77b5a7d5d2a..1ba27353a7b784b51a219caf3c036c0b7ae3c258 100644 (file)
@@ -28,7 +28,7 @@
 \r
 #include <core/consumer/frame_consumer.h>\r
 #include <core/video_format.h>\r
-#include <core/mixer/read_frame.h>\r
+#include <core/mixer/data_frame.h>\r
 \r
 #include <boost/date_time/posix_time/posix_time.hpp>\r
 #include <boost/thread.hpp>\r
@@ -53,7 +53,7 @@ public:
        {\r
        }\r
        \r
-       virtual bool send(const safe_ptr<core::read_frame>& frame) override\r
+       virtual bool send(const safe_ptr<core::data_frame>& frame) override\r
        {                               \r
                boost::thread async([frame]\r
                {\r
index d987640b48b167fda3a34f2dcd78a60ca068aa4d..c00b271d838bee0c7457d0195842bc2e334c3443 100644 (file)
@@ -28,7 +28,7 @@
 #include <core/producer/frame/basic_frame.h>\r
 #include <core/producer/frame/frame_factory.h>\r
 #include <core/producer/frame/pixel_format.h>\r
-#include <core/mixer/write_frame.h>\r
+#include <core/mixer/device_frame.h>\r
 \r
 #include <common/env.h>\r
 #include <common/log.h>\r
@@ -58,11 +58,11 @@ struct image_producer : public core::frame_producer
                core::pixel_format_desc desc;\r
                desc.pix_fmt = core::pixel_format::bgra;\r
                desc.planes.push_back(core::pixel_format_desc::plane(FreeImage_GetWidth(bitmap.get()), FreeImage_GetHeight(bitmap.get()), 4));\r
-               auto frame = frame_factory->create_frame(this, desc);\r
 \r
-               std::copy_n(FreeImage_GetBits(bitmap.get()), frame->image_data().size(), frame->image_data().begin());\r
-               frame->commit();\r
-               frame_ = std::move(frame);\r
+               frame_ = frame_factory->create_frame(this, desc, [&](const core::frame_factory::range_vector_type& ranges)\r
+               {\r
+                       std::copy_n(FreeImage_GetBits(bitmap.get()), ranges[0].size(), ranges[0].begin());\r
+               });\r
        }\r
        \r
        // frame_producer\r
index 8e30eccfe5685815a3a44777876540b68a3aebe7..634da0716d85704015615de4736705ce3a6afac0 100644 (file)
@@ -29,7 +29,7 @@
 #include <core/producer/frame/frame_factory.h>\r
 #include <core/producer/frame/frame_transform.h>\r
 #include <core/producer/frame/pixel_format.h>\r
-#include <core/mixer/write_frame.h>\r
+#include <core/mixer/device_frame.h>\r
 \r
 #include <common/env.h>\r
 #include <common/log.h>\r
@@ -88,21 +88,21 @@ struct image_scroll_producer : public core::frame_producer
                                core::pixel_format_desc desc;\r
                                desc.pix_fmt = core::pixel_format::bgra;\r
                                desc.planes.push_back(core::pixel_format_desc::plane(width_, format_desc_.height, 4));\r
-                               auto frame = frame_factory->create_frame(reinterpret_cast<void*>(rand()), desc);\r
+                               auto frame = frame_factory->create_frame(reinterpret_cast<void*>(rand()), desc, [&](const core::frame_factory::range_vector_type& ranges)\r
+                               {                                       \r
+                                       if(count >= ranges.at(0).size())\r
+                                       {       \r
+                                               std::copy_n(bytes + count - ranges.at(0).size(), ranges.at(0).size(), ranges.at(0).begin());\r
+                                               count -= static_cast<int>(ranges.at(0).size());\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               memset(ranges.at(0).begin(), 0, ranges.at(0).size());   \r
+                                               std::copy_n(bytes, count, ranges.at(0).begin() + format_desc_.size - count);\r
+                                               count = 0;\r
+                                       }                       \r
+                               });\r
 \r
-                               if(count >= frame->image_data().size())\r
-                               {       \r
-                                       std::copy_n(bytes + count - frame->image_data().size(), frame->image_data().size(), frame->image_data().begin());\r
-                                       count -= static_cast<int>(frame->image_data().size());\r
-                               }\r
-                               else\r
-                               {\r
-                                       memset(frame->image_data().begin(), 0, frame->image_data().size());     \r
-                                       std::copy_n(bytes, count, frame->image_data().begin() + format_desc_.size - count);\r
-                                       count = 0;\r
-                               }\r
-                       \r
-                               frame->commit();\r
                                frames_.push_back(frame);\r
                        }\r
                        \r
@@ -121,26 +121,27 @@ struct image_scroll_producer : public core::frame_producer
                                core::pixel_format_desc desc;\r
                                desc.pix_fmt = core::pixel_format::bgra;\r
                                desc.planes.push_back(core::pixel_format_desc::plane(format_desc_.width, height_, 4));\r
-                               auto frame = frame_factory->create_frame(reinterpret_cast<void*>(rand()), desc);\r
-                               if(count >= frame->image_data().size())\r
+                               auto frame = frame_factory->create_frame(reinterpret_cast<void*>(rand()), desc, [&](const core::frame_factory::range_vector_type& ranges)\r
                                {       \r
-                                       for(int y = 0; y < height_; ++y)\r
-                                               std::copy_n(bytes + i * format_desc_.width*4 + y * width_*4, format_desc_.width*4, frame->image_data().begin() + y * format_desc_.width*4);\r
+                                       if(count >= ranges.at(0).size())\r
+                                       {       \r
+                                               for(int y = 0; y < height_; ++y)\r
+                                                       std::copy_n(bytes + i * format_desc_.width*4 + y * width_*4, format_desc_.width*4, ranges.at(0).begin() + y * format_desc_.width*4);\r
                                        \r
-                                       ++i;\r
-                                       count -= static_cast<int>(frame->image_data().size());\r
-                               }\r
-                               else\r
-                               {\r
-                                       memset(frame->image_data().begin(), 0, frame->image_data().size());     \r
-                                       int width2 = width_ % format_desc_.width;\r
-                                       for(int y = 0; y < height_; ++y)\r
-                                               std::copy_n(bytes + i * format_desc_.width*4 + y * width_*4, width2*4, frame->image_data().begin() + y * format_desc_.width*4);\r
-\r
-                                       count = 0;\r
-                               }\r
+                                               ++i;\r
+                                               count -= static_cast<int>(ranges.at(0).size());\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               memset(ranges.at(0).begin(), 0, ranges.at(0).size());   \r
+                                               int width2 = width_ % format_desc_.width;\r
+                                               for(int y = 0; y < height_; ++y)\r
+                                                       std::copy_n(bytes + i * format_desc_.width*4 + y * width_*4, width2*4, ranges.at(0).begin() + y * format_desc_.width*4);\r
+\r
+                                               count = 0;\r
+                                       }\r
+                               });\r
                        \r
-                               frame->commit();\r
                                frames_.push_back(frame);\r
                        }\r
 \r
index 85c11816956b6c422237f977b591e8b841a81aa0..350c07aad998fe67ca8320f841193a8a294b7a35 100644 (file)
@@ -31,7 +31,7 @@
 #include <core/mixer/audio/audio_util.h>\r
 #include <core/video_format.h>\r
 \r
-#include <core/mixer/read_frame.h>\r
+#include <core/mixer/data_frame.h>\r
 \r
 #include <SFML/Audio/SoundStream.hpp>\r
 \r
@@ -97,7 +97,7 @@ public:
                CASPAR_LOG(info) << print() << " Sucessfully Initialized.";\r
        }\r
        \r
-       virtual bool send(const safe_ptr<core::read_frame>& frame) override\r
+       virtual bool send(const safe_ptr<core::data_frame>& frame) override\r
        {                       \r
                input_.push(std::make_shared<audio_buffer_16>(core::audio_32_to_16(frame->audio_data())));\r
                return true;\r
index 472a22d29a8a795f01f5ac740faa4243a6a43444..316aa8fc6943ebeb4680370e1624213d2ef22453 100644 (file)
@@ -34,7 +34,7 @@
 #include <ffmpeg/producer/filter/filter.h>\r
 \r
 #include <core/video_format.h>\r
-#include <core/mixer/read_frame.h>\r
+#include <core/mixer/data_frame.h>\r
 #include <core/consumer/frame_consumer.h>\r
 \r
 #include <boost/timer.hpp>\r
@@ -131,7 +131,7 @@ struct ogl_consumer : boost::noncopyable
        boost::timer                                    perf_timer_;\r
        boost::timer                                    tick_timer_;\r
 \r
-       tbb::concurrent_bounded_queue<safe_ptr<core::read_frame>>       frame_buffer_;\r
+       tbb::concurrent_bounded_queue<safe_ptr<core::data_frame>>       frame_buffer_;\r
 \r
        boost::thread                   thread_;\r
        tbb::atomic<bool>               is_running_;\r
@@ -194,7 +194,7 @@ public:
        ~ogl_consumer()\r
        {\r
                is_running_ = false;\r
-               frame_buffer_.try_push(make_safe<core::read_frame>());\r
+               frame_buffer_.try_push(make_safe<core::data_frame>());\r
                thread_.join();\r
        }\r
 \r
@@ -268,7 +268,7 @@ public:
                                                        is_running_ = false;\r
                                        }\r
                        \r
-                                       safe_ptr<core::read_frame> frame;\r
+                                       safe_ptr<core::data_frame> frame;\r
                                        frame_buffer_.pop(frame);\r
                                        \r
                                        perf_timer_.restart();\r
@@ -310,7 +310,7 @@ public:
                return av_frame;\r
        }\r
 \r
-       void render(const safe_ptr<core::read_frame>& frame)\r
+       void render(const safe_ptr<core::data_frame>& frame)\r
        {                       \r
                if(static_cast<int>(frame->image_data().size()) != format_desc_.size)\r
                        return;\r
@@ -377,7 +377,7 @@ public:
                std::rotate(pbos_.begin(), pbos_.begin() + 1, pbos_.end());\r
        }\r
 \r
-       bool send(const safe_ptr<core::read_frame>& frame)\r
+       bool send(const safe_ptr<core::data_frame>& frame)\r
        {\r
                if(!frame_buffer_.try_push(frame))\r
                        graph_->set_tag("dropped-frame");\r
@@ -476,7 +476,7 @@ public:
                CASPAR_LOG(info) << print() << L" Successfully Initialized.";   \r
        }\r
        \r
-       virtual bool send(const safe_ptr<core::read_frame>& frame) override\r
+       virtual bool send(const safe_ptr<core::data_frame>& frame) override\r
        {\r
                return consumer_->send(frame);\r
        }\r