]> git.sesse.net Git - casparcg/blobdiff - modules/decklink/consumer/decklink_consumer.cpp
2.0. Optimized key-only.
[casparcg] / modules / decklink / consumer / decklink_consumer.cpp
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