]> git.sesse.net Git - casparcg/commitdiff
2.0.0.2:
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Sat, 6 Nov 2010 11:33:45 +0000 (11:33 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Sat, 6 Nov 2010 11:33:45 +0000 (11:33 +0000)
- Colorspace transform on GPU.

git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@237 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

32 files changed:
common/common.vcxproj
common/common.vcxproj.filters
common/concurrency/function_task.h [deleted file]
common/gl/pixel_buffer_object.cpp
common/gl/pixel_buffer_object.h
common/utility/memory.cpp
common/utility/memory.h
core/consumer/decklink/DecklinkVideoConsumer.cpp
core/consumer/ogl/ogl_consumer.cpp
core/core.vcxproj
core/core.vcxproj.filters
core/frame/frame_factory.h
core/frame/gpu_composite_frame.cpp
core/frame/gpu_composite_frame.h
core/frame/gpu_frame.cpp
core/frame/gpu_frame.h
core/frame/gpu_frame_processor.cpp
core/frame/gpu_frame_processor.h
core/frame/gpu_frame_transform.cpp [new file with mode: 0644]
core/frame/gpu_frame_transform.h [new file with mode: 0644]
core/producer/color/color_producer.cpp
core/producer/ffmpeg/video/video_transformer.cpp
core/producer/flash/flash_producer.cpp
core/producer/image/image_producer.cpp
core/producer/image/image_scroll_producer.cpp
core/producer/transition/transition_producer.cpp
shell/My Amplifier Results/r000hs/r000hs.ampl [new file with mode: 0644]
shell/My Amplifier Results/r001hs/r001hs.ampl [new file with mode: 0644]
shell/My Amplifier Results/r002hs/r002hs.ampl [new file with mode: 0644]
shell/shell.vcxproj
shell/shell.vcxproj.filters
test/producer/transition/transition_producer_test.cpp

index 347e08e8d0908a661af536cf84871d5d3deb3055..cf5c53be6ace38641847128e6c0c3e71ab2a5d85 100644 (file)
@@ -92,7 +92,6 @@
   </ItemDefinitionGroup>\r
   <ItemGroup>\r
     <ClInclude Include="concurrency\executor.h" />\r
-    <ClInclude Include="concurrency\function_task.h" />\r
     <ClInclude Include="concurrency\Thread.h" />\r
     <ClInclude Include="config.h" />\r
     <ClInclude Include="exception\exceptions.h" />\r
index ea6f5f56de4be552fec563678d6664d3afa485f4..f874e8fffd7897e68fbd010602f25f55730b4063 100644 (file)
@@ -87,9 +87,6 @@
     <ClInclude Include="concurrency\executor.h">\r
       <Filter>Source\concurrency</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="concurrency\function_task.h">\r
-      <Filter>Source\concurrency</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="config.h">\r
       <Filter>Source</Filter>\r
     </ClInclude>\r
diff --git a/common/concurrency/function_task.h b/common/concurrency/function_task.h
deleted file mode 100644 (file)
index 8d32f19..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-#pragma once\r
-\r
-#include <tbb/task.h>\r
-#include <tbb/concurrent_queue.h>\r
-#include <boost/thread/future.hpp>\r
-\r
-namespace caspar { namespace common { namespace function_task {\r
-       \r
-namespace detail {\r
-       \r
-       template<typename Func>\r
-       class packaged_task : public tbb::task\r
-       {\r
-       public:\r
-               packaged_task(boost::packaged_task<Func>&& task) : task_(std::forward<boost::packaged_task<Func>>(task)) {}\r
-       \r
-       private:\r
-               tbb::task* execute() \r
-               {\r
-                       task_();\r
-                       return nullptr;\r
-               }\r
-\r
-               boost::packaged_task<Func> task_;\r
-       };\r
-\r
-       template<typename Func>\r
-       class internal_function_task : public tbb::task\r
-       {\r
-       public:\r
-               internal_function_task(Func&& func) : func_(std::forward<Func>(func)) {}\r
-       private:\r
-               tbb::task* execute() \r
-               {\r
-                       func_();\r
-                       return nullptr;\r
-               }\r
-\r
-               Func func_;\r
-       };\r
-}\r
-               \r
-template <typename Func>\r
-void enqueue(Func&& func)\r
-{\r
-       tbb::task::enqueue(*new(tbb::task::allocate_root()) detail::internal_function_task<Func>(std::forward<Func>(func)));\r
-}\r
-\r
-template<typename Func>\r
-auto begin_invoke(Func&& func) -> boost::unique_future<decltype(func())>\r
-{                      \r
-       auto task = boost::packaged_task<decltype(func())>(std::forward<Func>(func));\r
-       auto future = task.get_future();\r
-       tbb::task::enqueue(*new(tbb::task::allocate_root()) detail::packaged_task<decltype(func())>(boost::move(task)));                \r
-       return std::move(future);               \r
-}\r
-\r
-template<typename Func>\r
-auto invoke(Func&& func) -> decltype(func())\r
-{      \r
-       return function_task::begin_invoke(std::forward<Func>(func)).get();             \r
-}\r
-\r
-};\r
-\r
-}}
\ No newline at end of file
index e3e6b7aa3e209966091d99210e8ccb8dc8fad1fa..5ce272c9f96a0c98b0ce2cca93b840d65f5c96d5 100644 (file)
@@ -10,9 +10,34 @@ namespace caspar { namespace common { namespace gl {
                                                                                                                                                                                                                                                                                                                        \r
 struct pixel_buffer_object::implementation : boost::noncopyable\r
 {\r
-       implementation(size_t width, size_t height) \r
-               : width_(width), height_(height), size_(width*height*4), pbo_(0),\r
-                       texture_(0), writing_(false), reading_(false), mapped_(false){}\r
+       implementation(size_t width, size_t height, GLenum format) \r
+               : width_(width), height_(height), pbo_(0), format_(format),\r
+                       texture_(0), writing_(false), reading_(false), mapped_(false)\r
+       {\r
+               switch(format)\r
+               {\r
+               case GL_RGBA:\r
+               case GL_BGRA:\r
+                       internal_ = GL_RGBA8;\r
+                       size_ = width*height*4;\r
+                       break;\r
+               case GL_BGR:\r
+                       internal_ = GL_RGB8;\r
+                       size_ = width*height*3;\r
+                       break;\r
+               case GL_LUMINANCE_ALPHA:\r
+                       internal_ = GL_LUMINANCE_ALPHA;\r
+                       size_ = width*height*2;\r
+                       break;\r
+               case GL_LUMINANCE:\r
+               case GL_ALPHA:\r
+                       internal_ = GL_LUMINANCE;\r
+                       size_ = width*height*1;\r
+                       break;\r
+               default:\r
+                       BOOST_THROW_EXCEPTION(invalid_argument() << msg_info("format"));\r
+               }\r
+       }\r
 \r
        ~implementation()\r
        {\r
@@ -45,7 +70,7 @@ struct pixel_buffer_object::implementation : boost::noncopyable
                        GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));\r
                        GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));\r
 \r
-                       GL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width_, height_, 0, GL_BGRA\r
+                       GL(glTexImage2D(GL_TEXTURE_2D, 0, internal_, width_, height_, 0, format_\r
                                                                GL_UNSIGNED_BYTE, NULL));\r
                }\r
                GL(glBindTexture(GL_TEXTURE_2D, texture_));\r
@@ -58,7 +83,7 @@ struct pixel_buffer_object::implementation : boost::noncopyable
                        GL(glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER));\r
                mapped_ = false;\r
                bind_texture();\r
-               GL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width_, height_, GL_BGRA\r
+               GL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width_, height_, format_\r
                                                        GL_UNSIGNED_BYTE, NULL));\r
                unbind_pbo(GL_PIXEL_UNPACK_BUFFER);\r
                writing_ = true;\r
@@ -118,14 +143,17 @@ struct pixel_buffer_object::implementation : boost::noncopyable
        bool mapped_;\r
        bool writing_;\r
        bool reading_;\r
+\r
+       GLint internal_;\r
+       GLenum format_;\r
 };\r
 \r
 pixel_buffer_object::pixel_buffer_object(){}\r
-pixel_buffer_object::pixel_buffer_object(size_t width, size_t height) \r
-       : impl_(new implementation(width, height)){}\r
-void pixel_buffer_object::create(size_t width, size_t height)\r
+pixel_buffer_object::pixel_buffer_object(size_t width, size_t height, GLenum format\r
+       : impl_(new implementation(width, height, format)){}\r
+void pixel_buffer_object::create(size_t width, size_t height, GLenum format)\r
 {\r
-       impl_.reset(new implementation(width, height));\r
+       impl_.reset(new implementation(width, height, format));\r
 }\r
 void pixel_buffer_object::begin_write() { impl_->begin_write();}\r
 void* pixel_buffer_object::end_write() {return impl_->end_write();} \r
@@ -133,7 +161,7 @@ void pixel_buffer_object::begin_read() { impl_->begin_read();}
 void* pixel_buffer_object::end_read(){return impl_->end_read();}\r
 void pixel_buffer_object::bind_texture() {impl_->bind_texture();}\r
 size_t pixel_buffer_object::width() const {return impl_->width_;}\r
-size_t pixel_buffer_object::heigth() const {return impl_->height_;}\r
+size_t pixel_buffer_object::height() const {return impl_->height_;}\r
 size_t pixel_buffer_object::size() const {return impl_->size_;}\r
 bool pixel_buffer_object::is_reading() const { return impl_->reading_;}\r
 bool pixel_buffer_object::is_writing() const { return impl_->writing_;}\r
index 858c2445646d55415a414fdbee8c691ef7ad9ae1..65b0a6a36dba5fca8cf87e5a556e5e801afe08a5 100644 (file)
@@ -15,8 +15,8 @@ class pixel_buffer_object : boost::noncopyable
 {\r
 public:\r
        pixel_buffer_object();\r
-       pixel_buffer_object(size_t width, size_t height);\r
-       void create(size_t width, size_t height);\r
+       pixel_buffer_object(size_t width, size_t height, GLenum format = GL_BGRA);\r
+       void create(size_t width, size_t height, GLenum format = GL_BGRA);\r
        ~pixel_buffer_object(){}\r
 \r
        void begin_write();\r
@@ -28,7 +28,7 @@ public:
        void bind_texture();\r
 \r
        size_t width() const;\r
-       size_t heigth() const;\r
+       size_t height() const;\r
        size_t size() const;\r
 \r
        bool is_reading() const;\r
index 7f6d38391e265849d1a958886a9efc94f524b455..704dc7044450c6cf968cc762cfb8c38c79609738 100644 (file)
@@ -9,7 +9,7 @@
 \r
 namespace caspar { namespace common {\r
        \r
-void* memcpy_SSE2(void* dest, const void* source, size_t num)\r
+void* aligned_memcpy(void* dest, const void* source, size_t num)\r
 {      \r
        __asm\r
        {\r
@@ -53,14 +53,14 @@ void* memcpy_SSE2(void* dest, const void* source, size_t num)
        return dest;\r
 }\r
 \r
-void* aligned_memcpy(void* dest, const void* source, size_t num)\r
+void* aligned_parallel_memcpy(void* dest, const void* source, size_t num)\r
 {      \r
        if(num < 128)\r
                return memcpy(dest, source, num);\r
 \r
        tbb::parallel_for(tbb::blocked_range<size_t>(0, num/128), [&](const tbb::blocked_range<size_t>& r)\r
        {\r
-               memcpy_SSE2(reinterpret_cast<char*>(dest) + r.begin()*128, reinterpret_cast<const char*>(source) + r.begin()*128, r.size()*128);\r
+               aligned_memcpy(reinterpret_cast<char*>(dest) + r.begin()*128, reinterpret_cast<const char*>(source) + r.begin()*128, r.size()*128);\r
        }, tbb::affinity_partitioner());\r
 \r
        return dest;\r
index 56ff5a17a16c3f2e48af0400c295468e4231a73d..477b59ccf0d26cbd7d001dfbd0b2b8335f2dfe5f 100644 (file)
@@ -3,6 +3,7 @@
 namespace caspar { namespace common {\r
                \r
 void* aligned_memcpy(void* dest, const void* source, size_t size);\r
+void* aligned_parallel_memcpy(void* dest, const void* source, size_t size);\r
 void* clear(void* dest, size_t size);\r
 \r
 }}
\ No newline at end of file
index 36de5f8e0f14fb823a8b3ceb1ea4714f426d8847..24c64f4f15e28ba3f09a903093a023c84defbf94 100644 (file)
@@ -129,7 +129,7 @@ struct DecklinkVideoConsumer::Implementation : public IDeckLinkVideoOutputCallba
                                std::shared_ptr<DecklinkVideoFrame> pTempFrame = GetReservedFrame();\r
                                if(pTempFrame && frame->size() == pTempFrame->size())\r
                                {\r
-                                       common::aligned_memcpy(pTempFrame->data(), frame->data(), pTempFrame->size());\r
+                                       common::aligned_parallel_memcpy(pTempFrame->data(), frame->data(), pTempFrame->size());\r
                                        DoRender(pTempFrame);\r
                                }\r
                                else\r
index f6396ee932b81839eef8e5b55331e8743bbc6df6..b7658ca4dab9e446f5dcd519f2c53b2b4376f6a0 100644 (file)
@@ -165,7 +165,7 @@ struct consumer::implementation : boost::noncopyable
                int next_index = (index_ + 1) % 2;\r
                                \r
                auto ptr = pbos_[index_].end_write();\r
-               common::aligned_memcpy(ptr, frame->data(), frame->size());\r
+               common::aligned_parallel_memcpy(ptr, frame->data(), frame->size());\r
 \r
                GL(glClear(GL_COLOR_BUFFER_BIT));       \r
                pbos_[next_index].bind_texture();                               \r
index f25dfe2562a2f3f55139e56ac3ca29abaa0e748c..1938e7df4f5617ce41f2a87be90a508591a2a052 100644 (file)
     <ClInclude Include="frame\frame_fwd.h" />\r
     <ClInclude Include="frame\gpu_frame.h" />\r
     <ClInclude Include="frame\gpu_frame_processor.h" />\r
+    <ClInclude Include="frame\gpu_frame_transform.h" />\r
     <ClInclude Include="producer\color\color_producer.h" />\r
     <ClInclude Include="producer\ffmpeg\audio\audio_decoder.h" />\r
     <ClInclude Include="producer\ffmpeg\ffmpeg_producer.h" />\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../stdafx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../stdafx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
+    <ClCompile Include="frame\gpu_frame_transform.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../stdafx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../stdafx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
     <ClCompile Include="producer\color\color_producer.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
index 7fe4acaf19be1b1fa4ef91d9b2df90f534829bd2..aa91590a239cade79915f0d0f74ce134057ac7db 100644 (file)
     <ClInclude Include="consumer\decklink\DeckLinkAPI_h.h">\r
       <Filter>Source\consumer\decklink\interop</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="consumer\frame_consumer.h">\r
-      <Filter>Source\consumer</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="producer\color\color_producer.h">\r
       <Filter>Source\producer\color</Filter>\r
     </ClInclude>\r
     <ClInclude Include="config.h">\r
       <Filter>Source</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="frame\gpu_frame_transform.h">\r
+      <Filter>Source\frame\gpu</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="consumer\frame_consumer.h">\r
+      <Filter>Source\consumer</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClCompile Include="StdAfx.cpp">\r
     <ClCompile Include="renderer\display_device.cpp">\r
       <Filter>Source\renderer</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="frame\gpu_frame_transform.cpp">\r
+      <Filter>Source\frame\gpu</Filter>\r
+    </ClCompile>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <Midl Include="consumer\decklink\DeckLinkAPI_v7_3.idl">\r
index ee0c55bdf62d569e887976a73a68282d68e6479c..ba799a3393eb444654df9c1e90deaf24aed12d29 100644 (file)
@@ -4,16 +4,19 @@
 #include "frame_format.h"\r
 \r
 #include <memory>\r
+#include <array>\r
 \r
 namespace caspar { namespace core { \r
-\r
+       \r
 struct frame_factory\r
 {\r
        virtual ~frame_factory(){}\r
-       virtual gpu_frame_ptr create_frame(size_t width, size_t height) = 0;\r
-       gpu_frame_ptr create_frame(const frame_format_desc format_desc)\r
+       virtual void release_frames(void* tag) = 0;\r
+       virtual gpu_frame_ptr create_frame(size_t width, size_t height, void* tag) = 0;\r
+       virtual gpu_frame_ptr create_frame(const planar_frame_dimension& data_size, void* tag) = 0;\r
+       gpu_frame_ptr create_frame(const frame_format_desc format_desc, void* tag)\r
        {\r
-               return create_frame(format_desc.width, format_desc.height);\r
+               return create_frame(format_desc.width, format_desc.height, tag);\r
        }\r
 };\r
 \r
index 917fb1f3428703d32ab4a5fe3a6b75cd4c6dcc69..9ee2951ea7084a92e4946e4c92e0db621e5b2a5c 100644 (file)
@@ -37,11 +37,11 @@ struct gpu_composite_frame::implementation : boost::noncopyable
                boost::range::for_each(frames_, std::mem_fn(&gpu_frame::end_read));     \r
        }\r
 \r
-       void draw()\r
+       void draw(const gpu_frame_transform_ptr& transform)\r
        {\r
                glPushMatrix();\r
                glTranslated(self_->x()*2.0, self_->y()*2.0, 0.0);\r
-               boost::range::for_each(frames_, std::mem_fn(&gpu_frame::draw));\r
+               boost::range::for_each(frames_, std::bind(&gpu_frame::draw, std::placeholders::_1, transform));\r
                glPopMatrix();\r
        }\r
                \r
@@ -69,7 +69,7 @@ struct gpu_composite_frame::implementation : boost::noncopyable
                }\r
        }\r
 \r
-       unsigned char* data()\r
+       unsigned char* data(size_t index)\r
        {\r
                BOOST_THROW_EXCEPTION(invalid_operation());\r
        }\r
@@ -87,8 +87,8 @@ void gpu_composite_frame::begin_write(){impl_->begin_write();}
 void gpu_composite_frame::end_write(){impl_->end_write();}     \r
 void gpu_composite_frame::begin_read(){impl_->begin_read();}\r
 void gpu_composite_frame::end_read(){impl_->end_read();}\r
-void gpu_composite_frame::draw(){impl_->draw();}\r
-unsigned char* gpu_composite_frame::data(){return impl_->data();}\r
+void gpu_composite_frame::draw(const gpu_frame_transform_ptr& transform){impl_->draw(transform);}\r
+unsigned char* gpu_composite_frame::data(size_t index){return impl_->data(index);}\r
 void gpu_composite_frame::add(const gpu_frame_ptr& frame){impl_->add(frame);}\r
 \r
 gpu_frame_ptr gpu_composite_frame::interlace(const gpu_frame_ptr& frame1,\r
index e9f76a250817b1f93f922746f92801f64ad305f6..9071282bcb325ec1cafeb2244631a147aedfe564 100644 (file)
@@ -19,12 +19,12 @@ public:
                                                                        const gpu_frame_ptr& frame2, video_mode mode);\r
        \r
 private:\r
-       virtual unsigned char* data();\r
+       virtual unsigned char* data(size_t index);\r
        virtual void begin_write();\r
        virtual void end_write();\r
        virtual void begin_read();\r
        virtual void end_read();\r
-       virtual void draw();\r
+       virtual void draw(const gpu_frame_transform_ptr& transform);\r
 \r
        struct implementation;\r
        std::shared_ptr<implementation> impl_;\r
index f66b3581536f3bd2a511db68cf24ad0cfed6702a..b659a5b3daf6552b9231c43a80d1e04e943325a4 100644 (file)
@@ -64,40 +64,55 @@ GLubyte lower_pattern[] = {
                                                                                                                                                                                                                                                                                                                \r
 struct gpu_frame::implementation : boost::noncopyable\r
 {\r
-       implementation(size_t width, size_t height) \r
-               : pbo_(width, height), data_(nullptr), width_(width), height_(height), \r
-                       size_(width*height*4), reading_(false), alpha_(1.0f), \r
-                       x_(0.0f), y_(0.0f), mode_(video_mode::progressive), \r
-                       texcoords_(0.0, 1.0, 1.0, 0.0), writing_(false), mapped_(false)\r
-       {       \r
+       implementation(size_t width, size_t height)\r
+               : reading_(false), alpha_(1.0f),        x_(0.0f), y_(0.0f), mode_(video_mode::progressive), \r
+                       texcoords_(0.0, 1.0, 1.0, 0.0), writing_(false), mapped_(false), pix_format_(pixel_format::bgra)\r
+       {                       \r
+               data_.resize(1, 0);\r
+               pbo_.push_back(std::make_shared<common::gl::pixel_buffer_object>(width, height, GL_BGRA));\r
                if(width > 0 && height > 0)\r
                        end_write();\r
        }\r
+\r
+       implementation(const planar_frame_dimension& data_size)\r
+               : reading_(false), alpha_(1.0f),        x_(0.0f), y_(0.0f), mode_(video_mode::progressive), \r
+                       texcoords_(0.0, 1.0, 1.0, 0.0), writing_(false), mapped_(false), pix_format_(pixel_format::bgra)\r
+       {                       \r
+               data_.resize(data_size.size(), 0);\r
+               for(size_t n = 0; n < data_size.size() && data_size[n].first > 0 && data_size[n].second > 0; ++n)\r
+                       pbo_.push_back(std::make_shared<common::gl::pixel_buffer_object>(data_size[n].first, data_size[n].second, GL_LUMINANCE));\r
+               end_write();\r
+       }\r
        \r
        void begin_write()\r
        {\r
-               data_ = nullptr;\r
-               pbo_.begin_write();             \r
+               data_ = std::vector<unsigned char*>(4, 0);\r
+               for(size_t n = 0; n < pbo_.size(); ++n)\r
+                       pbo_[n]->begin_write();         \r
        }\r
 \r
        void end_write()\r
        {\r
-               data_ = static_cast<unsigned char*>(pbo_.end_write());\r
+               for(size_t n = 0; n < pbo_.size(); ++n)\r
+                       data_[n] = static_cast<unsigned char*>(pbo_[n]->end_write());\r
        }\r
        \r
        void begin_read()\r
        {       \r
-               data_ = nullptr;\r
-               pbo_.begin_read();\r
+               data_ = std::vector<unsigned char*>(4, 0);\r
+               for(size_t n = 0; n < pbo_.size(); ++n)\r
+                       pbo_[n]->begin_read();  \r
        }\r
 \r
        void end_read()\r
        {\r
-               data_ = static_cast<unsigned char*>(pbo_.end_read());\r
+               for(size_t n = 0; n < pbo_.size(); ++n)\r
+                       data_[n] = static_cast<unsigned char*>(pbo_[n]->end_read());\r
        }\r
 \r
-       void draw()\r
+       void draw(const gpu_frame_transform_ptr& transform)\r
        {\r
+               transform->set_pixel_format(pix_format_);\r
                glPushMatrix();\r
                glTranslated(x_*2.0, y_*2.0, 0.0);\r
                glColor4d(1.0, 1.0, 1.0, alpha_);\r
@@ -109,7 +124,11 @@ struct gpu_frame::implementation : boost::noncopyable
                else if(mode_ == video_mode::lower)\r
                        glPolygonStipple(lower_pattern);\r
 \r
-               pbo_.bind_texture();\r
+               for(size_t n = 0; n < pbo_.size(); ++n)\r
+               {\r
+                       glActiveTexture(GL_TEXTURE0+n);\r
+                       pbo_[n]->bind_texture();\r
+               }\r
                glBegin(GL_QUADS);\r
                        glTexCoord2d(texcoords_.left,   texcoords_.bottom); glVertex2d(-1.0, -1.0);\r
                        glTexCoord2d(texcoords_.right,  texcoords_.bottom); glVertex2d( 1.0, -1.0);\r
@@ -119,11 +138,11 @@ struct gpu_frame::implementation : boost::noncopyable
                glPopMatrix();\r
        }\r
                \r
-       unsigned char* data()\r
+       unsigned char* data(size_t index)\r
        {\r
-               if(data_ == nullptr)\r
+               if(pbo_.size() < index || data_[index] == nullptr)\r
                        BOOST_THROW_EXCEPTION(invalid_operation());\r
-               return data_;\r
+               return data_[index];\r
        }\r
 \r
        void reset()\r
@@ -136,12 +155,10 @@ struct gpu_frame::implementation : boost::noncopyable
                mode_      = video_mode::progressive;\r
        }\r
 \r
-       common::gl::pixel_buffer_object pbo_;\r
+       std::vector<common::gl::pixel_buffer_object_ptr> pbo_;\r
+       std::vector<unsigned char*> data_;\r
+\r
        gpu_frame* self_;\r
-       unsigned char* data_;\r
-       size_t width_;\r
-       size_t height_;\r
-       size_t size_;\r
 \r
        bool reading_;\r
        bool writing_;\r
@@ -154,20 +171,23 @@ struct gpu_frame::implementation : boost::noncopyable
        double y_;\r
        video_mode mode_;\r
        rectangle texcoords_;\r
+       pixel_format pix_format_;\r
 };\r
 \r
 gpu_frame::gpu_frame(size_t width, size_t height) \r
        : impl_(new implementation(width, height)){}\r
+gpu_frame::gpu_frame(const planar_frame_dimension& data_size)\r
+       : impl_(new implementation(data_size)){}\r
 void gpu_frame::begin_write(){impl_->begin_write();}\r
 void gpu_frame::end_write(){impl_->end_write();}       \r
 void gpu_frame::begin_read(){impl_->begin_read();}\r
 void gpu_frame::end_read(){impl_->end_read();}\r
-void gpu_frame::draw(){impl_->draw();}\r
-unsigned char* gpu_frame::data(){return impl_->data();}\r
-size_t gpu_frame::size() const { return impl_->size_; }\r
-size_t gpu_frame::width() const { return impl_->width_;}\r
-size_t gpu_frame::height() const { return impl_->height_;}\r
-const std::vector<short>& gpu_frame::audio_data() const{return impl_->audio_data_;}    \r
+void gpu_frame::draw(const gpu_frame_transform_ptr& transform){impl_->draw(transform);}\r
+void gpu_frame::set_pixel_format(pixel_format format) {impl_->pix_format_ = format;}\r
+unsigned char* gpu_frame::data(size_t index){return impl_->data(index);}\r
+size_t gpu_frame::size(size_t index) const { return impl_->pbo_.at(index)->size(); }\r
+size_t gpu_frame::width(size_t index) const { return impl_->pbo_.at(index)->width();}\r
+size_t gpu_frame::height(size_t index) const { return impl_->pbo_.at(index)->height();}\r
 std::vector<short>& gpu_frame::audio_data() { return impl_->audio_data_; }\r
 void gpu_frame::reset(){impl_->reset();}\r
 double gpu_frame::alpha() const{ return impl_->alpha_;}\r
index fffe00c894b1e23e113c934c4099d928fb8179a9..6eb42474b5a549292577be55668bbfdff025f3b1 100644 (file)
@@ -2,7 +2,10 @@
 \r
 #include "frame_format.h"\r
 \r
+#include "gpu_frame_transform.h"\r
+\r
 #include <memory>\r
+#include <array>\r
 \r
 #include <boost/noncopyable.hpp>\r
 \r
@@ -12,6 +15,8 @@
 \r
 namespace caspar { namespace core {\r
        \r
+typedef std::array<std::pair<size_t, size_t>, 4> planar_frame_dimension;\r
+\r
 struct rectangle\r
 {\r
        rectangle(double left, double top, double right, double bottom)\r
@@ -28,12 +33,11 @@ class gpu_frame : boost::noncopyable
 public:\r
        virtual ~gpu_frame(){}\r
                        \r
-       virtual unsigned char* data();\r
-       virtual size_t size() const;\r
-       virtual size_t width() const;\r
-       virtual size_t height() const;\r
+       virtual unsigned char* data(size_t index = 0);\r
+       virtual size_t size(size_t index = 0) const;\r
+       virtual size_t width(size_t index = 0) const;\r
+       virtual size_t height(size_t index = 0) const;\r
                                \r
-       virtual const std::vector<short>& audio_data() const;   \r
        virtual std::vector<short>& audio_data();\r
 \r
        virtual double alpha() const;\r
@@ -47,6 +51,8 @@ public:
        virtual void mode(video_mode mode);\r
        virtual video_mode mode() const;\r
 \r
+       virtual void set_pixel_format(pixel_format format);\r
+\r
        static std::shared_ptr<gpu_frame> null()\r
        {\r
                static auto my_null_frame = std::shared_ptr<gpu_frame>(new gpu_frame(0,0));\r
@@ -55,6 +61,7 @@ public:
                \r
 protected:\r
        gpu_frame(size_t width, size_t height);\r
+       gpu_frame(const planar_frame_dimension& data_size);\r
 \r
        friend class gpu_frame_processor;\r
        \r
@@ -62,7 +69,7 @@ protected:
        virtual void end_write();\r
        virtual void begin_read();\r
        virtual void end_read();\r
-       virtual void draw();\r
+       virtual void draw(const gpu_frame_transform_ptr& transform);\r
        virtual void reset();\r
 \r
 private:\r
index 73183644a0f663056efe98ae576887d973f8b582..bbc3ec359e7d4baf2a964085ea60bcc3ef4e178a 100644 (file)
@@ -2,6 +2,7 @@
 \r
 #include "gpu_frame_processor.h"\r
 \r
+#include "gpu_frame_transform.h"\r
 #include "gpu_frame.h"\r
 #include "gpu_composite_frame.h"\r
 #include "frame_format.h"\r
@@ -29,6 +30,7 @@
 #include <functional>\r
 #include <unordered_map>\r
 #include <numeric>\r
+#include <math.h>\r
 \r
 namespace caspar { namespace core {\r
        \r
@@ -60,6 +62,8 @@ struct gpu_frame_processor::implementation : boost::noncopyable
                        // Fill pipeline\r
                        for(int n = 0; n < 2; ++n)\r
                                composite(std::vector<gpu_frame_ptr>());\r
+\r
+                       transform_ = std::make_shared<gpu_frame_transform>();\r
                });\r
        }\r
 \r
@@ -105,7 +109,7 @@ struct gpu_frame_processor::implementation : boost::noncopyable
 \r
                                // 2. Draw to framebuffer and start asynchronous DMA transfer \r
                                // to page-locked memory.\r
-                               writing_[next_index]->draw();\r
+                               writing_[next_index]->draw(transform_);\r
                                \r
                                // Create an output frame\r
                                auto temp_frame = create_output_frame();\r
@@ -140,9 +144,8 @@ struct gpu_frame_processor::implementation : boost::noncopyable
                });\r
        }\r
                        \r
-       gpu_frame_ptr create_frame(size_t width, size_t height)\r
+       gpu_frame_ptr do_create_frame(size_t key, const std::function<gpu_frame*()>& constructor)\r
        {\r
-               size_t key = width | (height << 16);\r
                auto& pool = writing_pools_[key];\r
                \r
                gpu_frame_ptr frame;\r
@@ -150,7 +153,7 @@ struct gpu_frame_processor::implementation : boost::noncopyable
                {\r
                        frame = executor_.invoke([&]\r
                        {\r
-                               return std::shared_ptr<gpu_frame>(new gpu_frame(width, height));\r
+                               return std::shared_ptr<gpu_frame>(constructor());\r
                        });\r
                }\r
                \r
@@ -165,12 +168,35 @@ struct gpu_frame_processor::implementation : boost::noncopyable
                        executor_.begin_invoke(destructor);\r
                });\r
        }\r
+\r
+       gpu_frame_ptr create_frame(size_t width, size_t height, void* tag)\r
+       {\r
+               size_t key = reinterpret_cast<size_t>(tag);\r
+               return do_create_frame(key, [&]\r
+               {\r
+                       return new gpu_frame(width, height);\r
+               });\r
+       }\r
+       \r
+       gpu_frame_ptr create_frame(const planar_frame_dimension& data_size, void* tag)\r
+       {\r
+               size_t key = reinterpret_cast<size_t>(tag);\r
+               return do_create_frame(key, [&]\r
+               {\r
+                       return new gpu_frame(data_size);\r
+               });\r
+       }\r
        \r
        void pop(gpu_frame_ptr& frame)\r
        {\r
                output_.pop(frame);\r
        }\r
-                       \r
+\r
+       void release_frames(void* tag)\r
+       {\r
+               writing_pools_[reinterpret_cast<size_t>(tag)].clear();\r
+       }\r
+                               \r
        typedef tbb::concurrent_bounded_queue<gpu_frame_ptr> gpu_frame_queue;\r
        tbb::concurrent_unordered_map<size_t, gpu_frame_queue> writing_pools_;\r
        gpu_frame_queue reading_pool_;  \r
@@ -189,11 +215,14 @@ struct gpu_frame_processor::implementation : boost::noncopyable
        common::executor executor_;\r
 \r
        common::gl::frame_buffer_object fbo_;\r
+\r
+       gpu_frame_transform_ptr transform_;\r
 };\r
        \r
 gpu_frame_processor::gpu_frame_processor(const frame_format_desc& format_desc) : impl_(new implementation(format_desc)){}\r
 void gpu_frame_processor::push(const std::vector<gpu_frame_ptr>& frames){ impl_->composite(frames);}\r
 void gpu_frame_processor::pop(gpu_frame_ptr& frame){impl_->pop(frame);}\r
-gpu_frame_ptr gpu_frame_processor::create_frame(size_t width, size_t height){return impl_->create_frame(width, height);}\r
-\r
+gpu_frame_ptr gpu_frame_processor::create_frame(size_t width, size_t height, void* tag){return impl_->create_frame(width, height, tag);}\r
+gpu_frame_ptr gpu_frame_processor::create_frame(const planar_frame_dimension& data_size, void* tag){return impl_->create_frame(data_size, tag);}\r
+void gpu_frame_processor::release_frames(void* tag){impl_->release_frames(tag);}\r
 }}
\ No newline at end of file
index f9d4d0905498bcdf18915b54e41939c06b4d429a..c586eda50b5b3f8d9fd71e998128b0cac6ae9a1e 100644 (file)
@@ -34,8 +34,10 @@ public:
                \r
        void push(const std::vector<gpu_frame_ptr>& frames);\r
        void pop(gpu_frame_ptr& frame);\r
-\r
-       gpu_frame_ptr create_frame(size_t width, size_t height);\r
+       \r
+       void release_frames(void* tag);\r
+       gpu_frame_ptr create_frame(size_t width, size_t height, void* tag);\r
+       gpu_frame_ptr create_frame(const planar_frame_dimension& data_size, void* tag);\r
 private:\r
        struct implementation;\r
        std::shared_ptr<implementation> impl_;\r
diff --git a/core/frame/gpu_frame_transform.cpp b/core/frame/gpu_frame_transform.cpp
new file mode 100644 (file)
index 0000000..e926600
--- /dev/null
@@ -0,0 +1,211 @@
+#include "../StdAfx.h"\r
+\r
+#include "gpu_frame_transform.h"\r
+\r
+#include "../../common/exception/exceptions.h"\r
+#include "../../common/gl/gl_check.h"\r
+\r
+#include <Glee.h>\r
+\r
+#include <fstream>\r
+#include <unordered_map>\r
+\r
+namespace caspar { namespace core {\r
+       \r
+class shader_program\r
+{\r
+public:\r
+       shader_program(const std::string& fragment_source_str)\r
+       {\r
+               try\r
+               {               \r
+                       const char* fragment_source = fragment_source_str.c_str();\r
+                       static const char* vertex_source = \r
+                               "void main()"\r
+                               "{"\r
+                                       "gl_TexCoord[0] = gl_MultiTexCoord0;"\r
+                                       "gl_FrontColor = gl_Color;"\r
+                                       "gl_Position = ftransform();"\r
+                               "}";\r
+\r
+                       program_ = glCreateProgramObjectARB();\r
+\r
+                       auto vertex_shader   = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);\r
+                       auto fragmemt_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);\r
+\r
+                       GL(glShaderSourceARB(vertex_shader, 1, &vertex_source,   NULL));\r
+                       GL(glShaderSourceARB(fragmemt_shader, 1, &fragment_source, NULL));\r
+                       GL(glCompileShaderARB(vertex_shader));\r
+                       GL(glCompileShaderARB(fragmemt_shader));\r
+\r
+                       GLint success;\r
+                       GL(glGetObjectParameterivARB(vertex_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success));\r
+                       if (success == GL_FALSE)\r
+                       {\r
+                               char log[1024];\r
+                               GL(glGetInfoLogARB(vertex_shader, sizeof(log), 0, log));\r
+                               GL(glDeleteObjectARB(vertex_shader));\r
+                               GL(glDeleteObjectARB(fragmemt_shader));\r
+                               GL(glDeleteObjectARB(program_));\r
+                               std::stringstream str;\r
+                               str << "Failed to compile vertex shader:" << std::endl << log << std::endl;\r
+                               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(str.str()));\r
+                       }\r
+                       GL(glGetObjectParameterivARB(fragmemt_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success));\r
+                       if (success == GL_FALSE)\r
+                       {\r
+                               char log[1024];\r
+                               GL(glGetInfoLogARB(fragmemt_shader, sizeof(log), 0, log));\r
+                               GL(glDeleteObjectARB(vertex_shader));\r
+                               GL(glDeleteObjectARB(fragmemt_shader));\r
+                               GL(glDeleteObjectARB(program_));\r
+                               std::stringstream str;\r
+                               str << "Failed to compile fragment shader:" << std::endl << log << std::endl;\r
+                               BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(str.str()));\r
+                       }\r
+\r
+                       GL(glAttachObjectARB(program_, vertex_shader));\r
+                       GL(glAttachObjectARB(program_, fragmemt_shader));\r
+\r
+                       GL(glDeleteObjectARB(vertex_shader));\r
+                       GL(glDeleteObjectARB(fragmemt_shader));\r
+\r
+                       GL(glLinkProgramARB(program_));\r
+\r
+                       GL(glGetObjectParameterivARB(program_, GL_OBJECT_LINK_STATUS_ARB, &success));\r
+                       if (success == GL_FALSE)\r
+                       {\r
+                               char log[1024];\r
+                               GL(glGetInfoLogARB(program_, sizeof(log), 0, log));\r
+                               CASPAR_LOG(warning) << "Failed to link shader:" << std::endl\r
+                                               << log << std::endl;\r
+                               GL(glDeleteObjectARB(program_));\r
+                               BOOST_THROW_EXCEPTION(caspar_exception());\r
+                       }\r
+                       GL(glUseProgramObjectARB(program_));\r
+                       glUniform1i(glGetUniformLocation(program_, "tex0"), 0);\r
+                       glUniform1i(glGetUniformLocation(program_, "tex1"), 1);\r
+                       glUniform1i(glGetUniformLocation(program_, "tex2"), 2);\r
+                       glUniform1i(glGetUniformLocation(program_, "tex3"), 3);\r
+               }\r
+               catch(...)\r
+               {\r
+                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+                       throw;\r
+               }\r
+       }\r
+\r
+       void use()\r
+       {\r
+               GL(glUseProgramObjectARB(program_));\r
+       }\r
+\r
+private:\r
+       GLuint program_;\r
+};\r
+typedef std::shared_ptr<shader_program> shader_program_ptr;\r
+\r
+struct gpu_frame_transform::implementation\r
+{\r
+       implementation() : current_(pixel_format::invalid_pixel_format)\r
+       {\r
+               std::string common = \r
+                       "uniform sampler2D tex0;"\r
+                       "uniform sampler2D tex1;"\r
+                       "uniform sampler2D tex2;"\r
+                       "uniform sampler2D tex3;"\r
+\r
+                       "vec4 yuva_to_bgra(float y, float u, float v, float a)"\r
+                       "{"\r
+                          "vec4 color;"\r
+   \r
+                          "u -= 0.5;"\r
+                          "v -= 0.5;"\r
+\r
+                          "color.r = clamp(y + 1.370705 * v, 0.0 , 1.0);"\r
+                          "color.g = clamp(y - 0.698001 * v - 0.337633 * u, 0.0 , 1.0);"\r
+                          "color.b = clamp(y + 1.732446 * u, 0.0 , 1.0);"\r
+                          "color.a = a;"\r
+\r
+                         " return color;"\r
+                       "}";\r
+\r
+               shaders_[pixel_format::abgr] = std::make_shared<shader_program>\r
+               (\r
+                       common +\r
+\r
+                       "void main()"\r
+                       "{"\r
+                               "gl_FragColor = texture2D(tex0, gl_TexCoord[0].st).argb * gl_Color;"\r
+                       "}"\r
+               );\r
+               shaders_[pixel_format::argb] = std::make_shared<shader_program>\r
+               (\r
+                       common +\r
+\r
+                       "void main()"\r
+                       "{"\r
+                               "gl_FragColor = texture2D(tex0, gl_TexCoord[0].st).grab * gl_Color;"\r
+                       "}"\r
+               );\r
+               shaders_[pixel_format::bgra] = std::make_shared<shader_program>\r
+               (\r
+                       common +\r
+\r
+                       "void main()"\r
+                       "{"\r
+                               "gl_FragColor = texture2D(tex0, gl_TexCoord[0].st).rgba * gl_Color;"\r
+                       "}"\r
+               );\r
+               shaders_[pixel_format::rgba] = std::make_shared<shader_program>\r
+               (\r
+                       common +\r
+\r
+                       "void main()"\r
+                       "{"\r
+                               "gl_FragColor = texture2D(tex0, gl_TexCoord[0].st).bgra * gl_Color;"\r
+                       "}"\r
+               );\r
+               shaders_[pixel_format::yuv] = std::make_shared<shader_program>\r
+               (\r
+                       common +\r
+\r
+                       "void main()"\r
+                       "{"\r
+                               "float y = texture2D(tex0, gl_TexCoord[0].st).r;"\r
+                               "float u = texture2D(tex1, gl_TexCoord[0].st).r;"\r
+                               "float v = texture2D(tex2, gl_TexCoord[0].st).r;"\r
+                               "gl_FragColor = yuva_to_bgra(y, u , v, 1.0) * gl_Color;"\r
+                       "}"\r
+               );\r
+               shaders_[pixel_format::yuva] = std::make_shared<shader_program>\r
+               (\r
+                       common +\r
+\r
+                       "void main()"\r
+                       "{"\r
+                               "float y = texture2D(tex0, gl_TexCoord[0].st).r;"\r
+                               "float u = texture2D(tex1, gl_TexCoord[0].st).r;"\r
+                               "float v = texture2D(tex2, gl_TexCoord[0].st).r;"\r
+                               "float a = texture2D(tex3, gl_TexCoord[0].st).r;"\r
+                               "gl_FragColor = yuva_to_bgra(y, u, v, a) * gl_Color;"\r
+                       "}"\r
+               );\r
+       }\r
+\r
+       void set_pixel_format(pixel_format format)\r
+       {\r
+               if(current_ == format)\r
+                       return;\r
+               current_ = format;\r
+               shaders_[format]->use();\r
+       }\r
+\r
+       pixel_format current_;\r
+       std::map<pixel_format, shader_program_ptr> shaders_;\r
+};\r
+\r
+gpu_frame_transform::gpu_frame_transform() : impl_(new implementation()){}\r
+void gpu_frame_transform::set_pixel_format(pixel_format format){impl_->set_pixel_format(format);}\r
+\r
+}}
\ No newline at end of file
diff --git a/core/frame/gpu_frame_transform.h b/core/frame/gpu_frame_transform.h
new file mode 100644 (file)
index 0000000..54e998d
--- /dev/null
@@ -0,0 +1,29 @@
+#pragma once\r
+\r
+#include <memory>\r
+\r
+enum pixel_format\r
+{\r
+    bgra = 1,\r
+    rgba,\r
+    argb,\r
+    abgr,\r
+       yuv,\r
+       yuva,\r
+       invalid_pixel_format,\r
+};\r
+\r
+namespace caspar { namespace core {\r
+       \r
+class gpu_frame_transform\r
+{\r
+public:\r
+       gpu_frame_transform();\r
+       void set_pixel_format(pixel_format format);\r
+private:\r
+       struct implementation;\r
+       std::shared_ptr<implementation> impl_;\r
+};\r
+typedef std::shared_ptr<gpu_frame_transform> gpu_frame_transform_ptr;\r
+\r
+}}
\ No newline at end of file
index 58d2fd5315d1f7ab3e5d3cfdc8f7905ecc29e44e..d6a48a9ebe4324d02d4e49a0f3b075d9f5449119 100644 (file)
@@ -35,18 +35,27 @@ public:
        explicit color_producer(unsigned int color_value, const frame_format_desc& format_desc) \r
                : color_value_(color_value), format_desc_(format_desc){}\r
 \r
+       ~color_producer()\r
+       {\r
+               if(factory_)\r
+                       factory_->release_frames(this);\r
+       }\r
+\r
        gpu_frame_ptr get_frame()\r
        { \r
                return frame_;\r
        }\r
+\r
        const frame_format_desc& get_frame_format_desc() const { return format_desc_; }\r
        \r
        void initialize(const frame_factory_ptr& factory)\r
        {\r
-               frame_ = factory->create_frame(format_desc_);\r
+               factory_ = factory;\r
+               frame_ = factory->create_frame(format_desc_, this);\r
                __stosd(reinterpret_cast<unsigned long*>(frame_->data()), color_value_, frame_->size() / sizeof(unsigned long));\r
        }\r
 \r
+       frame_factory_ptr factory_;\r
        frame_format_desc format_desc_;\r
        gpu_frame_ptr frame_;\r
        unsigned int color_value_;\r
index 78bb54961c9f2bc8054f19c416c062b47b069726..cfe7634535d1a6ee1b65f5af7fa6d2fbe44984f0 100644 (file)
@@ -14,6 +14,8 @@
 #include <tbb/concurrent_queue.h>\r
 #include <tbb/scalable_allocator.h>\r
 \r
+#include <unordered_map>\r
+\r
 #if defined(_MSC_VER)\r
 #pragma warning (push)\r
 #pragma warning (disable : 4244)\r
@@ -30,38 +32,126 @@ extern "C"
 \r
 namespace caspar { namespace core { namespace ffmpeg{\r
        \r
+pixel_format get_pixel_format(PixelFormat pix_fmt)\r
+{\r
+       switch(pix_fmt)\r
+       {\r
+               case PIX_FMT_BGRA:              return pixel_format::bgra;\r
+               case PIX_FMT_ARGB:              return pixel_format::argb;\r
+               case PIX_FMT_RGBA:              return pixel_format::rgba;\r
+               case PIX_FMT_ABGR:              return pixel_format::abgr;\r
+               case PIX_FMT_YUV444P:   return pixel_format::yuv;\r
+               case PIX_FMT_YUV422P:   return pixel_format::yuv;\r
+               case PIX_FMT_YUV420P:   return pixel_format::yuv;\r
+               case PIX_FMT_YUV411P:   return pixel_format::yuv;\r
+               case PIX_FMT_YUV410P:   return pixel_format::yuv;\r
+               case PIX_FMT_YUVA420P:  return pixel_format::yuva;\r
+               default:                                return pixel_format::invalid_pixel_format;\r
+       }\r
+}\r
+\r
 struct video_transformer::implementation : boost::noncopyable\r
 {\r
+       ~implementation()\r
+       {\r
+               if(factory_)\r
+                       factory_->release_frames(this);\r
+       }\r
+\r
        video_packet_ptr execute(const video_packet_ptr video_packet)\r
        {                               \r
                assert(video_packet);\r
-               size_t width = video_packet->codec_context->width;\r
-               size_t height = video_packet->codec_context->height;\r
+               int width = video_packet->codec_context->width;\r
+               int height = video_packet->codec_context->height;\r
                auto pix_fmt = video_packet->codec_context->pix_fmt;\r
+               video_packet->decoded_frame;\r
 \r
-               if(!sws_context_)\r
+               switch(pix_fmt)\r
                {\r
-                       double param;\r
-                       sws_context_.reset(sws_getContext(width, height, pix_fmt, width, height, \r
-                                                                                               PIX_FMT_BGRA, SWS_BILINEAR, nullptr, nullptr, &param), sws_freeContext);\r
-               }\r
+               case PIX_FMT_BGRA:\r
+               case PIX_FMT_ARGB:\r
+               case PIX_FMT_RGBA:\r
+               case PIX_FMT_ABGR:\r
+                       {\r
+                               video_packet->frame = factory_->create_frame(width, height, this);\r
+                               tbb::parallel_for(0, height, 1, [&](int y)\r
+                               {\r
+                                       common::aligned_memcpy(\r
+                                               video_packet->frame->data()+y*width*4, \r
+                                               video_packet->decoded_frame->data[0] + y*video_packet->decoded_frame->linesize[0], \r
+                                               width*4); \r
+                               });\r
+                               video_packet->frame->set_pixel_format(get_pixel_format(pix_fmt));\r
+                                               \r
+                               break;\r
+                       }\r
+               case PIX_FMT_YUV444P:\r
+               case PIX_FMT_YUV422P:\r
+               case PIX_FMT_YUV420P:\r
+               case PIX_FMT_YUV411P:\r
+               case PIX_FMT_YUV410P:\r
+               case PIX_FMT_YUVA420P:\r
+                       {                       \r
+                               // Get linesizes\r
+                               AVPicture dummy_pict;   \r
+                               avpicture_fill(&dummy_pict, nullptr, pix_fmt, width, height);\r
+                       \r
+                               // Find chroma height\r
+                               size_t size2 = dummy_pict.data[2] - dummy_pict.data[1];\r
+                               size_t h2 = size2/dummy_pict.linesize[1];\r
 \r
-               //size_t pic_size = avpicture_get_size(PIX_FMT_YUV411P, width, height);\r
+                               planar_frame_dimension data_size;\r
+                               data_size[0] = std::make_pair(dummy_pict.linesize[0], height);\r
+                               data_size[1] = std::make_pair(dummy_pict.linesize[1], h2);\r
+                               data_size[2] = std::make_pair(dummy_pict.linesize[2], h2);\r
+                               data_size[3] = std::make_pair(0, 0);\r
 \r
-               //size_t pic_size_sqr = static_cast<size_t>(sqrt(static_cast<double>(pic_size)))/4;\r
-               //pic_size_sqr += pic_size_sqr % 2;\r
+                               if(pix_fmt == PIX_FMT_YUVA420P)                 \r
+                                       data_size[3] = std::make_pair(dummy_pict.linesize[3], height);\r
 \r
-               video_packet->frame = factory_->create_frame(width, height);\r
-               AVFrame av_frame;       \r
-               avcodec_get_frame_defaults(&av_frame);\r
-               size_t size = avpicture_fill(reinterpret_cast<AVPicture*>(&av_frame), video_packet->frame->data(), PIX_FMT_BGRA, width, height);\r
+                               video_packet->frame = factory_->create_frame(data_size, this);\r
+                               video_packet->frame->set_pixel_format(get_pixel_format(pix_fmt));\r
+\r
+                               tbb::parallel_for(0, static_cast<int>(data_size.size()), 1, [&](int n)\r
+                               {\r
+                                       tbb::parallel_for(0, static_cast<int>(data_size[n].second), 1, [&](int y)\r
+                                       {\r
+                                               memcpy(\r
+                                                       video_packet->frame->data(n)+y*dummy_pict.linesize[n], \r
+                                                       video_packet->decoded_frame->data[n] + y*video_packet->decoded_frame->linesize[n], \r
+                                                       dummy_pict.linesize[n]);\r
+                                       });\r
+                               });\r
+                               break;\r
+                       }               \r
+               default:        \r
+                       {\r
+                               video_packet->frame = factory_->create_frame(width, height, this);\r
+                               video_packet->frame->set_pixel_format(pixel_format::bgra);\r
+\r
+                               AVFrame av_frame;       \r
+                               avcodec_get_frame_defaults(&av_frame);\r
+                               avpicture_fill(reinterpret_cast<AVPicture*>(&av_frame), video_packet->frame->data(), PIX_FMT_BGRA, width, height);\r
+\r
+                               if(!sws_context_)\r
+                               {\r
+                                       double param;\r
+                                       sws_context_.reset(sws_getContext(width, height, pix_fmt, width, height, PIX_FMT_BGRA, SWS_BILINEAR, nullptr, nullptr, &param), sws_freeContext);\r
+                               }               \r
                 \r
-               sws_scale(sws_context_.get(), video_packet->decoded_frame->data, video_packet->decoded_frame->linesize, 0, height, av_frame.data, av_frame.linesize);\r
-                               \r
+                               sws_scale(sws_context_.get(), video_packet->decoded_frame->data, video_packet->decoded_frame->linesize, 0, height, av_frame.data, av_frame.linesize);           \r
+                       }\r
+               }\r
+\r
                if(video_packet->codec->id == CODEC_ID_DVVIDEO) // Move up one field\r
                        video_packet->frame->translate(0.0f, 1.0/static_cast<double>(video_packet->format_desc.height));\r
                \r
-               return video_packet;    \r
+               return video_packet;\r
+       }\r
+\r
+       void initialize(const frame_factory_ptr& factory)\r
+       {\r
+               factory_ = factory;\r
        }\r
 \r
        frame_factory_ptr factory_;\r
@@ -70,5 +160,5 @@ struct video_transformer::implementation : boost::noncopyable
 \r
 video_transformer::video_transformer() : impl_(new implementation()){}\r
 video_packet_ptr video_transformer::execute(const video_packet_ptr& video_packet){return impl_->execute(video_packet);}\r
-void video_transformer::initialize(const frame_factory_ptr& factory){impl_->factory_ = factory; }\r
+void video_transformer::initialize(const frame_factory_ptr& factory){impl_->initialize(factory); }\r
 }}}
\ No newline at end of file
index eddbe023f8c74f75c54adc76c347a29b033b1596..9b1f114d34ae7bd04a1fe39ed5f1890c8a2e5c5a 100644 (file)
@@ -33,7 +33,6 @@
 #include "../../../common/utility/find_file.h"\r
 #include "../../server.h"\r
 #include "../../../common/concurrency/executor.h"\r
-#include "../../../common/concurrency/function_task.h"\r
 #include "../../../common/utility/memory.h"\r
 #include "../../../common/utility/scope_exit.h"\r
 \r
@@ -72,6 +71,8 @@ struct flash_producer::implementation
        ~implementation() \r
        {\r
                stop();\r
+               if(factory_)\r
+                       factory_->release_frames(this);\r
        }\r
 \r
        void start(bool force = true)\r
@@ -267,8 +268,8 @@ struct flash_producer::implementation
                        });\r
                }       \r
 \r
-               auto frame = factory_->create_frame(format_desc_);\r
-               common::aligned_memcpy(frame->data(), current_frame_->data(), current_frame_->size());  \r
+               auto frame = factory_->create_frame(format_desc_, this);\r
+               common::aligned_parallel_memcpy(frame->data(), current_frame_->data(), current_frame_->size()); \r
 \r
                return frame;\r
        }\r
index 07135b9ae105621fa3f65a99f1219336412a3c1a..19013f04ee930158af7108e26e88ad579edc59e4 100644 (file)
@@ -19,10 +19,17 @@ struct image_producer : public frame_producer
 {\r
        image_producer(const std::wstring& filename, const frame_format_desc& format_desc) : format_desc_(format_desc), filename_(filename)     {}\r
 \r
+       ~image_producer()\r
+       {\r
+               if(factory_)\r
+                       factory_->release_frames(this);\r
+       }\r
+\r
        gpu_frame_ptr get_frame(){return frame_;}\r
 \r
        void initialize(const frame_factory_ptr& factory)\r
        {\r
+               factory_ = factory;\r
                auto bitmap = load_image(filename_);\r
                if(FreeImage_GetWidth(bitmap.get()) != format_desc_.width || FreeImage_GetHeight(bitmap.get()) == format_desc_.height)\r
                {\r
@@ -32,12 +39,13 @@ struct image_producer : public frame_producer
                }\r
 \r
                FreeImage_FlipVertical(bitmap.get());\r
-               frame_ = factory->create_frame(format_desc_);\r
-               common::aligned_memcpy(frame_->data(), FreeImage_GetBits(bitmap.get()), frame_->size());\r
+               frame_ = factory->create_frame(format_desc_, this);\r
+               common::aligned_parallel_memcpy(frame_->data(), FreeImage_GetBits(bitmap.get()), frame_->size());\r
        }\r
 \r
        const frame_format_desc& get_frame_format_desc() const { return format_desc_; } \r
 \r
+       frame_factory_ptr factory_;\r
        std::wstring filename_;\r
        frame_format_desc format_desc_;\r
        gpu_frame_ptr frame_;\r
index ee1243a3283650d081704ee19efb5cae6795033e..605b9472fddf428faee3afa6464fa860293bbf15 100644 (file)
@@ -63,6 +63,12 @@ struct image_scroll_producer : public frame_producer
 \r
                speed_ = static_cast<int>(abs(static_cast<double>(speed_) / format_desc.fps));\r
        }\r
+       \r
+       ~image_scroll_producer()\r
+       {\r
+               if(factory_)\r
+                       factory_->release_frames(this);\r
+       }\r
 \r
        void load_and_pad_image(const std::wstring& filename)\r
        {\r
@@ -80,12 +86,12 @@ struct image_scroll_producer : public frame_producer
                unsigned char* pBits = FreeImage_GetBits(pBitmap.get());\r
                \r
                for (size_t i = 0; i < height; ++i)\r
-                       common::aligned_memcpy(&image_.get()[i * image_width_ * 4], &pBits[i* width * 4], width * 4);\r
+                       common::aligned_parallel_memcpy(&image_.get()[i * image_width_ * 4], &pBits[i* width * 4], width * 4);\r
        }\r
 \r
        gpu_frame_ptr render_frame()\r
        {\r
-               gpu_frame_ptr frame = factory_->create_frame(format_desc_);\r
+               gpu_frame_ptr frame = factory_->create_frame(format_desc_, this);\r
                common::clear(frame->data(), frame->size());\r
 \r
                const int delta_x = direction_ == direction::Left ? speed_ : -speed_;\r
index 81b86af1debe7aa2481aa22ab06cd63ddab0f353..efacceefde950d55196fb2897ffbcb1ca1670029 100644 (file)
@@ -35,8 +35,7 @@ namespace caspar { namespace core {
 \r
 struct transition_producer::implementation : boost::noncopyable\r
 {\r
-       implementation(const frame_producer_ptr& dest, const transition_info& info, \r
-                                       const frame_format_desc& format_desc) \r
+       implementation(const frame_producer_ptr& dest, const transition_info& info, const frame_format_desc& format_desc) \r
                : current_frame_(0), info_(info), format_desc_(format_desc), dest_producer_(dest)\r
        {\r
                if(!dest)\r
@@ -87,7 +86,8 @@ struct transition_producer::implementation : boost::noncopyable
                        CASPAR_LOG(warning) << "Removed renderer from transition.";\r
                }\r
 \r
-               if(frame == nullptr && producer != nullptr && producer->get_following_producer() != nullptr)\r
+               if(frame == nullptr && producer != nullptr && \r
+                       producer->get_following_producer() != nullptr)\r
                {\r
                        auto following = producer->get_following_producer();\r
                        following->initialize(factory_);\r
@@ -106,8 +106,7 @@ struct transition_producer::implementation : boost::noncopyable
                for(size_t n = 0; n < frame->audio_data().size(); ++n)\r
                        frame->audio_data()[n] = static_cast<short>((static_cast<int>(frame->audio_data()[n])*volume)>>8);\r
        }\r
-                       \r
-\r
+               \r
        gpu_frame_ptr compose(const gpu_frame_ptr& dest_frame, gpu_frame_ptr src_frame) \r
        {       \r
                if(info_.type == transition_type::cut)          \r
@@ -124,24 +123,18 @@ struct transition_producer::implementation : boost::noncopyable
                        [&]{set_volume(dest_frame, volume);},\r
                        [&]{set_volume(src_frame, 256-volume);}\r
                );\r
-                               \r
-               auto composite = std::make_shared<gpu_composite_frame>();\r
-               if(src_frame)\r
-                       composite->add(src_frame);\r
-               composite->add(dest_frame);\r
-\r
-               switch(info_.type)\r
-               {\r
-               case transition_type::mix: \r
-                       dest_frame->alpha(alpha);       \r
-                       break;\r
-               case transition_type::slide:                    \r
+               \r
+               if(info_.type == transition_type::mix)\r
+                       dest_frame->alpha(alpha);               \r
+               else if(info_.type == transition_type::slide)\r
+               {       \r
                        if(info_.direction == transition_direction::from_left)                  \r
                                dest_frame->translate(-1.0+alpha, 0.0);                 \r
                        else if(info_.direction == transition_direction::from_right)\r
                                dest_frame->translate(1.0-alpha, 0.0);          \r
-                       break;\r
-               case transition_type::push:\r
+               }\r
+               else if(info_.type == transition_type::push)\r
+               {\r
                        if(info_.direction == transition_direction::from_left)          \r
                        {\r
                                dest_frame->translate(-1.0+alpha, 0.0);\r
@@ -154,16 +147,6 @@ struct transition_producer::implementation : boost::noncopyable
                                if(src_frame)\r
                                        src_frame->translate(0.0-alpha, 0.0);\r
                        }\r
-                       break;\r
-               }\r
-\r
-               if(info_.type == transition_type::mix)\r
-                       dest_frame->alpha(alpha);               \r
-               else if(info_.type == transition_type::slide)\r
-               {       \r
-               }\r
-               else if(info_.type == transition_type::push)\r
-               {\r
                }\r
                else if(info_.type == transition_type::wipe)\r
                {\r
@@ -178,7 +161,11 @@ struct transition_producer::implementation : boost::noncopyable
                                dest_frame->texcoords(rectangle(1.0-alpha, 1.0, 2.0-alpha, 0.0));\r
                        }\r
                }\r
-\r
+                                               \r
+               auto composite = std::make_shared<gpu_composite_frame>();\r
+               if(src_frame)\r
+                       composite->add(src_frame);\r
+               composite->add(dest_frame);\r
                return composite;\r
        }\r
                \r
diff --git a/shell/My Amplifier Results/r000hs/r000hs.ampl b/shell/My Amplifier Results/r000hs/r000hs.ampl
new file mode 100644 (file)
index 0000000..fd613d9
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<root>\r
+ <rdmgr>\r
+  <buildNumber type="s32_t">114808</buildNumber>\r
+  <hostname>vaxtestcaspar</hostname>\r
+  <os>windows</os>\r
+  <product>Intel® Parallel Amplifier 2011</product>\r
+  <timestamp type="u64_t">1288973781</timestamp>\r
+  <variables>\r
+   <at>hs</at>\r
+  </variables>\r
+ </rdmgr>\r
+</root>\r
diff --git a/shell/My Amplifier Results/r001hs/r001hs.ampl b/shell/My Amplifier Results/r001hs/r001hs.ampl
new file mode 100644 (file)
index 0000000..a4578ca
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<root>\r
+ <rdmgr>\r
+  <buildNumber type="s32_t">114808</buildNumber>\r
+  <hostname>vaxtestcaspar</hostname>\r
+  <os>windows</os>\r
+  <product>Intel® Parallel Amplifier 2011</product>\r
+  <timestamp type="u64_t">1289002710</timestamp>\r
+  <variables>\r
+   <at>hs</at>\r
+  </variables>\r
+ </rdmgr>\r
+</root>\r
diff --git a/shell/My Amplifier Results/r002hs/r002hs.ampl b/shell/My Amplifier Results/r002hs/r002hs.ampl
new file mode 100644 (file)
index 0000000..7b3969c
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<root>\r
+ <rdmgr>\r
+  <buildNumber type="s32_t">114808</buildNumber>\r
+  <hostname>vaxtestcaspar</hostname>\r
+  <os>windows</os>\r
+  <product>Intel® Parallel Amplifier 2011</product>\r
+  <timestamp type="u64_t">1289002916</timestamp>\r
+  <variables>\r
+   <at>hs</at>\r
+  </variables>\r
+ </rdmgr>\r
+</root>\r
index 37c152990bfc7e30b3a3be2acee15cd496015f5b..bdcff40fcd737ff417edc55000db1ad1c4f1d8bc 100644 (file)
@@ -28,6 +28,9 @@
     <None Include="caspar.config">\r
       <SubType>Designer</SubType>\r
     </None>\r
+    <None Include="My Amplifier Results\r000hs\r000hs.ampl" />\r
+    <None Include="My Amplifier Results\r001hs\r001hs.ampl" />\r
+    <None Include="My Amplifier Results\r002hs\r002hs.ampl" />\r
   </ItemGroup>\r
   <PropertyGroup Label="Globals">\r
     <ProjectGuid>{8C26C94F-8092-4769-8D84-DEA479721C5B}</ProjectGuid>\r
index 9f8c384ba6bf3211575c7343f9ae85c4a7e8f13b..5abbbd16a0e40d3d35ef790b99f1627fba2c965f 100644 (file)
@@ -5,5 +5,19 @@
   </ItemGroup>\r
   <ItemGroup>\r
     <None Include="caspar.config" />\r
+    <None Include="My Amplifier Results\r000hs\r000hs.ampl">\r
+      <Filter>My Amplifier Results</Filter>\r
+    </None>\r
+    <None Include="My Amplifier Results\r001hs\r001hs.ampl">\r
+      <Filter>My Amplifier Results</Filter>\r
+    </None>\r
+    <None Include="My Amplifier Results\r002hs\r002hs.ampl">\r
+      <Filter>My Amplifier Results</Filter>\r
+    </None>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Filter Include="My Amplifier Results">\r
+      <UniqueIdentifier>{4df636fc-0183-410c-8d76-2d0e06c29ca3}</UniqueIdentifier>\r
+    </Filter>\r
   </ItemGroup>\r
 </Project>
\ No newline at end of file
index d80cd06e9f920f48f3082c8a03e5e2e2edf9f674..6adc817a7cba064e25d3df80b5a4faadc0adb50e 100644 (file)
@@ -59,7 +59,7 @@ TEST(transition_producer, null_source_get_frame_cut)
        ASSERT_TRUE(producer.get_frame() == nullptr);\r
 }\r
 \r
-TEST(transition_producer, initialize) \r
+TEST(transition_producer, initialize)\r
 {\r
        auto dest = std::make_shared<mock_frame_producer>();\r
        \r