]> git.sesse.net Git - casparcg/commitdiff
2.0. Optimized key-only.
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Fri, 26 Aug 2011 11:07:57 +0000 (11:07 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Fri, 26 Aug 2011 11:07:57 +0000 (11:07 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@1293 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

common/memory/memshfl.h
core/consumer/frame_consumer.h
core/consumer/output.cpp
modules/bluefish/consumer/bluefish_consumer.cpp
modules/decklink/consumer/decklink_consumer.cpp
modules/ogl/consumer/ogl_consumer.cpp
shell/casparcg.config

index 32b6c0a4241b5586e971e1ed03f3e40e8f497001..d3babc06288259a0d1d4a350a93fbfc1d9aa3c70 100644 (file)
@@ -29,7 +29,7 @@ namespace caspar {
 \r
 namespace internal {\r
 \r
-static void* fast_memsfhl(void* dest, const void* source, size_t count, int m1, int m2, int m3, int m4)\r
+static void* fast_memshfl(void* dest, const void* source, size_t count, int m1, int m2, int m3, int m4)\r
 {\r
        __m128i*           dest128 = reinterpret_cast<__m128i*>(dest);  \r
        const __m128i* source128 = reinterpret_cast<const __m128i*>(source);\r
@@ -56,12 +56,12 @@ static void* fast_memsfhl(void* dest, const void* source, size_t count, int m1,
 \r
 }\r
 \r
-static void* fast_memsfhl(void* dest, const void* source, size_t count, int m1, int m2, int m3, int m4)\r
+static void* fast_memshfl(void* dest, const void* source, size_t count, int m1, int m2, int m3, int m4)\r
 {   \r
        tbb::affinity_partitioner ap;\r
        tbb::parallel_for(tbb::blocked_range<size_t>(0, count/128), [&](const tbb::blocked_range<size_t>& r)\r
        {       \r
-               internal::fast_memsfhl(reinterpret_cast<char*>(dest) + r.begin()*128, reinterpret_cast<const char*>(source) + r.begin()*128, r.size()*128, m1, m2, m3, m4);   \r
+               internal::fast_memshfl(reinterpret_cast<char*>(dest) + r.begin()*128, reinterpret_cast<const char*>(source) + r.begin()*128, r.size()*128, m1, m2, m3, m4);   \r
        }, ap);\r
 \r
        return dest;\r
index bbea02a3f52cd58a06f06509bbc76f6b0a407bf0..4e6fef7323ae9a5c4de4c62d3609952eba78ac1c 100644 (file)
@@ -41,7 +41,6 @@ struct frame_consumer : boost::noncopyable
        virtual ~frame_consumer() {}\r
        \r
        virtual bool send(const safe_ptr<read_frame>& frame) = 0;\r
-       virtual bool key_only() const{ return false;}\r
        virtual void initialize(const video_format_desc& format_desc) = 0;\r
        virtual std::wstring print() const = 0;\r
        virtual bool has_synchronization_clock() const {return true;}\r
index fce751112bad59671f656f4563f77b262b5df331..dde9c009aa9ab6189efe5129198ecf610fac2b2d 100644 (file)
 \r
 namespace caspar { namespace core {\r
 \r
-class deferred_key_read_Frame : public core::read_frame\r
-{\r
-       ogl_device&                                              ogl_;\r
-       safe_ptr<read_frame>                     fill_;\r
-       std::shared_ptr<host_buffer>     key_;\r
-       tbb::mutex                                           mutex_;\r
-public:\r
-       deferred_key_read_Frame(ogl_device& ogl, const safe_ptr<read_frame>& fill)\r
-               : ogl_(ogl)\r
-               , fill_(fill)\r
-       {\r
-       }\r
-\r
-       virtual const boost::iterator_range<const uint8_t*> image_data()\r
-       {\r
-               tbb::mutex::scoped_lock lock(mutex_);\r
-               if(!key_)\r
-               {\r
-                       key_ = ogl_.create_host_buffer(fill_->image_data().size(), host_buffer::write_only);                            \r
-                       fast_memsfhl(key_->data(), fill_->image_data().begin(), fill_->image_data().size(), 0x0F0F0F0F, 0x0B0B0B0B, 0x07070707, 0x03030303);\r
-               }\r
-\r
-               auto ptr = static_cast<const uint8_t*>(key_->data());\r
-               return boost::iterator_range<const uint8_t*>(ptr, ptr + key_->size());\r
-       }\r
-\r
-       virtual const boost::iterator_range<const int16_t*> audio_data()\r
-       {\r
-               return fill_->audio_data();\r
-       }       \r
-};\r
-       \r
 struct output::implementation\r
 {      \r
        typedef std::pair<safe_ptr<read_frame>, safe_ptr<read_frame>> fill_and_key;\r
@@ -128,10 +96,7 @@ public:
                        timer_.tick(1.0/channel_.get_format_desc().fps);\r
                        return;\r
                }\r
-\r
-               auto fill = frame;\r
-               auto key = make_safe<deferred_key_read_Frame>(channel_.ogl(), frame);\r
-\r
+               \r
                auto it = consumers_.begin();\r
                while(it != consumers_.end())\r
                {\r
@@ -140,7 +105,7 @@ public:
                        if(consumer->get_video_format_desc() != channel_.get_format_desc())\r
                                consumer->initialize(channel_.get_format_desc());\r
 \r
-                       if(consumer->send(consumer->key_only() ? key : fill))\r
+                       if(consumer->send(frame))\r
                                ++it;\r
                        else\r
                                consumers_.erase(it++);\r
index 714d2e575583659e25c7a646ff90d2b33179f690..ab73cac358894d64ae3f9cf412d7e29f65185888 100644 (file)
@@ -28,8 +28,9 @@
 \r
 #include <common/concurrency/executor.h>\r
 #include <common/diagnostics/graph.h>\r
-#include <common/memory/memcpy.h>\r
 #include <common/memory/memclr.h>\r
+#include <common/memory/memcpy.h>\r
+#include <common/memory/memshfl.h>\r
 #include <common/utility/timer.h>\r
 \r
 #include <core/consumer/frame_consumer.h>\r
@@ -64,10 +65,11 @@ struct bluefish_consumer : boost::noncopyable
        int                                                                     preroll_count_;\r
 \r
        const bool                                                      embedded_audio_;\r
+       const bool                                                      key_only_;\r
        \r
        executor                                                        executor_;\r
 public:\r
-       bluefish_consumer(const core::video_format_desc& format_desc, unsigned int device_index, bool embedded_audio) \r
+       bluefish_consumer(const core::video_format_desc& format_desc, unsigned int device_index, bool embedded_audio, bool key_only\r
                : blue_(create_blue(device_index))\r
                , device_index_(device_index)\r
                , format_desc_(format_desc) \r
@@ -75,6 +77,7 @@ public:
                , vid_fmt_(get_video_mode(*blue_, format_desc))\r
                , preroll_count_(0)\r
                , embedded_audio_(embedded_audio)\r
+               , key_only_(key_only)\r
                , executor_(print())\r
        {\r
                executor_.set_capacity(core::consumer_buffer_depth());\r
@@ -218,10 +221,15 @@ public:
                                // Copy to local buffers\r
 \r
                                if(!frame->image_data().empty())\r
-                                       fast_memcpy(reserved_frames_.front()->image_data(), frame->image_data().begin(), frame->image_data().size());\r
+                               {\r
+                                       if(key_only_)                                           \r
+                                               fast_memshfl(reserved_frames_.front()->image_data(), frame->image_data().begin(), frame->image_data().size(), 0x0F0F0F0F, 0x0B0B0B0B, 0x07070707, 0x03030303);\r
+                                       else\r
+                                               fast_memcpy(reserved_frames_.front()->image_data(), frame->image_data().begin(), frame->image_data().size());\r
+                               }\r
                                else\r
                                        fast_memclr(reserved_frames_.front()->image_data(), reserved_frames_.front()->image_size());\r
-\r
+                                                               \r
                                // Sync\r
 \r
                                sync_timer_.restart();\r
@@ -325,13 +333,13 @@ public:
        virtual void initialize(const core::video_format_desc& format_desc)\r
        {\r
                format_desc_ = format_desc;\r
-               consumer_.reset(new bluefish_consumer(format_desc, device_index_, embedded_audio_));\r
+               consumer_.reset(new bluefish_consumer(format_desc, device_index_, embedded_audio_, key_only_));\r
        }\r
        \r
        virtual bool send(const safe_ptr<core::read_frame>& frame)\r
        {\r
                if(!consumer_)\r
-                       consumer_.reset(new bluefish_consumer(format_desc_, device_index_, embedded_audio_));\r
+                       consumer_.reset(new bluefish_consumer(format_desc_, device_index_, embedded_audio_, key_only_));\r
 \r
                try\r
                {\r
@@ -363,11 +371,6 @@ public:
 \r
                return L"bluefish [" + boost::lexical_cast<std::wstring>(device_index_) + L"]";\r
        }\r
-\r
-       virtual bool key_only() const\r
-       {\r
-               return key_only_;\r
-       }\r
 };     \r
 \r
 safe_ptr<core::frame_consumer> create_bluefish_consumer(const std::vector<std::wstring>& params)\r
index 601d875175c1a61da4864983787a1f73d062de1b..7699f7fd846894dcb91150690de41776013fca30 100644 (file)
@@ -38,6 +38,7 @@
 #include <core/consumer/frame_consumer.h>\r
 \r
 #include <tbb/concurrent_queue.h>\r
+#include <tbb/cache_aligned_allocator.h>\r
 \r
 #include <boost/circular_buffer.hpp>\r
 #include <boost/timer.hpp>\r
@@ -64,29 +65,48 @@ struct configuration
 \r
 class decklink_frame : public IDeckLinkVideoFrame\r
 {\r
-       const safe_ptr<core::read_frame>        frame_;\r
-       const core::video_format_desc           format_desc_;\r
+       const std::shared_ptr<core::read_frame>                                         frame_;\r
+       const core::video_format_desc                                                           format_desc_;\r
+\r
+       bool                                                                                                            key_only_;\r
+       std::vector<uint8_t, tbb::cache_aligned_allocator<uint8_t>> key_data_;\r
 public:\r
-       decklink_frame(const safe_ptr<core::read_frame>& frame, const core::video_format_desc& format_desc)\r
+       decklink_frame(const safe_ptr<core::read_frame>& frame, const core::video_format_desc& format_desc, bool key_only)\r
                : frame_(frame)\r
-               , format_desc_(format_desc){}\r
+               , format_desc_(format_desc)\r
+               , key_only_(key_only){}\r
        \r
-       STDMETHOD (QueryInterface(REFIID, LPVOID*))     {return E_NOINTERFACE;}\r
-       STDMETHOD_(ULONG, AddRef())                                     {return 1;}\r
-       STDMETHOD_(ULONG, Release())                            {return 1;}\r
-\r
-       STDMETHOD_(long, GetWidth())                            {return format_desc_.width;}        \r
-    STDMETHOD_(long, GetHeight())                              {return format_desc_.height;}        \r
-    STDMETHOD_(long, GetRowBytes())                            {return format_desc_.width*4;}        \r
-       STDMETHOD_(BMDPixelFormat, GetPixelFormat()){return bmdFormat8BitBGRA;}        \r
-    STDMETHOD_(BMDFrameFlags, GetFlags())              {return bmdFrameFlagDefault;}\r
+       STDMETHOD (QueryInterface(REFIID, LPVOID*))             {return E_NOINTERFACE;}\r
+       STDMETHOD_(ULONG,                       AddRef())                       {return 1;}\r
+       STDMETHOD_(ULONG,                       Release())                      {return 1;}\r
+\r
+       STDMETHOD_(long,                        GetWidth())                     {return format_desc_.width;}        \r
+    STDMETHOD_(long,                   GetHeight())            {return format_desc_.height;}        \r
+    STDMETHOD_(long,                   GetRowBytes())          {return format_desc_.width*4;}        \r
+       STDMETHOD_(BMDPixelFormat,      GetPixelFormat())       {return bmdFormat8BitBGRA;}        \r
+    STDMETHOD_(BMDFrameFlags,  GetFlags())                     {return bmdFrameFlagDefault;}\r
         \r
     STDMETHOD(GetBytes(void** buffer))\r
        {\r
                static std::vector<uint8_t> zeros(1920*1080*4, 0);\r
-               *buffer = const_cast<uint8_t*>(frame_->image_data().begin());\r
                if(static_cast<size_t>(frame_->image_data().size()) != format_desc_.size)\r
+               {\r
                        *buffer = zeros.data();\r
+                       return S_OK;\r
+               }\r
+\r
+               if(!key_only_)\r
+                       *buffer = const_cast<uint8_t*>(frame_->image_data().begin());\r
+               else\r
+               {\r
+                       if(key_data_.empty())\r
+                       {\r
+                               key_data_.resize(frame_->image_data().size());\r
+                               fast_memshfl(key_data_.data(), frame_->image_data().begin(), frame_->image_data().size(), 0x0F0F0F0F, 0x0B0B0B0B, 0x07070707, 0x03030303);\r
+                       }\r
+                       *buffer = key_data_.data();\r
+               }\r
+\r
                return S_OK;\r
        }\r
         \r
@@ -96,7 +116,7 @@ public:
 \r
 struct decklink_consumer : public IDeckLinkVideoOutputCallback, public IDeckLinkAudioOutputCallback, boost::noncopyable\r
 {              \r
-       const configuration config_;\r
+       const configuration                                     config_;\r
 \r
        CComPtr<IDeckLink>                                      decklink_;\r
        CComQIPtr<IDeckLinkOutput>                      output_;\r
@@ -349,7 +369,7 @@ public:
                        \r
        void schedule_next_video(const safe_ptr<core::read_frame>& frame)\r
        {\r
-               frame_container_.push_back(std::make_shared<decklink_frame>(frame, format_desc_));\r
+               frame_container_.push_back(std::make_shared<decklink_frame>(frame, format_desc_, config_.key_only));\r
                if(FAILED(output_->ScheduleVideoFrame(frame_container_.back().get(), (frames_scheduled_++) * format_desc_.duration, format_desc_.duration, format_desc_.time_scale)))\r
                        CASPAR_LOG(error) << print() << L" Failed to schedule video.";\r
 \r
index 76c06055c46b9847f3f6e908c845260b33beb6da..4cdfa93fe036083e9bb6d388769dac9bea4faf78 100644 (file)
@@ -28,6 +28,7 @@
 #include <common/log/log.h>\r
 #include <common/memory/safe_ptr.h>\r
 #include <common/memory/memcpy.h>\r
+#include <common/memory/memshfl.h>\r
 #include <common/utility/timer.h>\r
 #include <common/utility/string.h>\r
 \r
@@ -44,7 +45,7 @@
 #include <tbb/concurrent_queue.h>\r
 \r
 #include <algorithm>\r
-#include <array>\r
+#include <vector>\r
 \r
 namespace caspar {\r
                \r
@@ -61,6 +62,7 @@ struct ogl_consumer : boost::noncopyable
        core::video_format_desc format_desc_;\r
        \r
        GLuint                                  texture_;\r
+       std::vector<GLuint>             pbos_;\r
        \r
        float                                   width_;\r
        float                                   height_;\r
@@ -87,10 +89,13 @@ struct ogl_consumer : boost::noncopyable
 \r
        boost::thread                   thread_;\r
        tbb::atomic<bool>               is_running_;\r
+\r
+       const bool key_only_;\r
 public:\r
-       ogl_consumer(unsigned int screen_index, stretch stretch, bool windowed, const core::video_format_desc& format_desc) \r
+       ogl_consumer(unsigned int screen_index, stretch stretch, bool windowed, const core::video_format_desc& format_desc, bool key_only\r
                : format_desc_(format_desc)\r
                , texture_(0)\r
+               , pbos_(2, 0)\r
                , stretch_(stretch)\r
                , windowed_(windowed)\r
                , screen_index_(screen_index)           \r
@@ -100,6 +105,7 @@ public:
                , square_height_(format_desc.height)\r
                , graph_(diagnostics::create_graph(narrow(print())))\r
                , input_buffer_(core::consumer_buffer_depth()-1)\r
+               , key_only_(key_only)\r
        {               \r
                frame_buffer_.set_capacity(2);\r
 \r
@@ -181,7 +187,15 @@ public:
                GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP));\r
                GL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, format_desc_.width, format_desc_.height, 0, GL_BGRA, GL_UNSIGNED_BYTE, 0));\r
                GL(glBindTexture(GL_TEXTURE_2D, 0));\r
+                                       \r
+               GL(glGenBuffers(2, pbos_.data()));\r
                        \r
+               glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbos_[0]);\r
+               glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, format_desc_.size, 0, GL_STREAM_DRAW_ARB);\r
+               glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbos_[1]);\r
+               glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, format_desc_.size, 0, GL_STREAM_DRAW_ARB);\r
+               glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);\r
+\r
                CASPAR_LOG(info) << print() << " Sucessfully Initialized.";\r
        }\r
 \r
@@ -190,6 +204,12 @@ public:
                if(texture_)\r
                        glDeleteTextures(1, &texture_);\r
 \r
+               BOOST_FOREACH(auto& pbo, pbos_)\r
+               {\r
+                       if(pbo)\r
+                               glDeleteBuffers(1, &pbo);\r
+               }\r
+\r
                CASPAR_LOG(info) << print() << " Sucessfully Uninitialized.";\r
        }\r
 \r
@@ -245,10 +265,27 @@ public:
                if(frame->image_data().empty())\r
                        return;\r
 \r
-               GL(glBindTexture(GL_TEXTURE_2D, texture_));\r
+               glBindTexture(GL_TEXTURE_2D, texture_);\r
+\r
+               glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbos_[0]);\r
+               glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, format_desc_.width, format_desc_.height, GL_BGRA, GL_UNSIGNED_BYTE, 0);\r
 \r
-               GL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, format_desc_.width, format_desc_.height, GL_BGRA, GL_UNSIGNED_BYTE, frame->image_data().begin()));\r
-                                               \r
+               glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbos_[1]);\r
+               glBufferData(GL_PIXEL_UNPACK_BUFFER, format_desc_.size, 0, GL_STREAM_DRAW);\r
+\r
+               auto ptr = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);\r
+               if(ptr)\r
+               {\r
+                       if(key_only_)\r
+                               fast_memshfl(reinterpret_cast<char*>(ptr), frame->image_data().begin(), frame->image_data().size(), 0x0F0F0F0F, 0x0B0B0B0B, 0x07070707, 0x03030303);\r
+                       else\r
+                               fast_memcpy(reinterpret_cast<char*>(ptr), frame->image_data().begin(), frame->image_data().size());\r
+\r
+                       glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); // release the mapped buffer\r
+               }\r
+\r
+               glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);\r
+                               \r
                GL(glClear(GL_COLOR_BUFFER_BIT));                       \r
                glBegin(GL_QUADS);\r
                                glTexCoord2f(0.0f,        1.0f);        glVertex2f(-width_, -height_);\r
@@ -258,6 +295,8 @@ public:
                glEnd();\r
                \r
                glBindTexture(GL_TEXTURE_2D, 0);\r
+\r
+               std::rotate(pbos_.begin(), pbos_.begin() + 1, pbos_.end());\r
        }\r
 \r
        void send(const safe_ptr<core::read_frame>& frame)\r
@@ -353,7 +392,7 @@ public:
        \r
        virtual void initialize(const core::video_format_desc& format_desc)\r
        {\r
-               consumer_.reset(new ogl_consumer(screen_index_, stretch_, windowed_, format_desc));\r
+               consumer_.reset(new ogl_consumer(screen_index_, stretch_, windowed_, format_desc, key_only_));\r
        }\r
        \r
        virtual bool send(const safe_ptr<core::read_frame>& frame)\r
@@ -367,11 +406,6 @@ public:
                return consumer_->print();\r
        }\r
 \r
-       virtual bool key_only() const\r
-       {\r
-               return key_only_;\r
-       }\r
-\r
        virtual bool has_synchronization_clock() const \r
        {\r
                return false;\r
index ecff4f7afbdd295909c7afbda5a9a64e54e08e93..5730f9b0fa377b9291dd7570a4708fbe9ce3ba43 100644 (file)
     </producers>\r
     <channels>\r
     <channel>\r
-      <video-mode>PAL</video-mode>\r
+      <video-mode>1080p5000</video-mode>\r
       <consumers>\r
         <decklink>\r
           <device>1</device>\r
           <embedded-audio>true</embedded-audio>\r
           <external-key>true</external-key>\r
+          <key-only>true</key-only>\r
         </decklink>\r
         <screen>\r
-          <key-only>true</key-only>\r
           <device>1</device>\r
+          <key-only>true</key-only>\r
         </screen>\r
       </consumers>\r
     </channel>\r
+      <channel>\r
+        <video-mode>1080p5000</video-mode>\r
+        <consumers>\r
+          <decklink>\r
+            <device>2</device>\r
+            <embedded-audio>true</embedded-audio>\r
+            <external-key>true</external-key>\r
+          </decklink>\r
+        </consumers>\r
+      </channel>\r
 </channels>\r
   <controllers>\r
     <tcp>\r