]> git.sesse.net Git - casparcg/blobdiff - modules/decklink/consumer/decklink_consumer.cpp
2.0. stage: Changed error handling.
[casparcg] / modules / decklink / consumer / decklink_consumer.cpp
index 7699f7fd846894dcb91150690de41776013fca30..a68513157bafad1383988aabfd2cc6e08b664be8 100644 (file)
@@ -65,7 +65,8 @@ struct configuration
 \r
 class decklink_frame : public IDeckLinkVideoFrame\r
 {\r
-       const std::shared_ptr<core::read_frame>                                         frame_;\r
+       tbb::atomic<int>                                                                                        ref_count_;\r
+       std::shared_ptr<core::read_frame>                                                       frame_;\r
        const core::video_format_desc                                                           format_desc_;\r
 \r
        bool                                                                                                            key_only_;\r
@@ -74,11 +75,23 @@ public:
        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
-               , key_only_(key_only){}\r
+               , key_only_(key_only)\r
+       {\r
+               ref_count_ = 0;\r
+       }\r
        \r
        STDMETHOD (QueryInterface(REFIID, LPVOID*))             {return E_NOINTERFACE;}\r
-       STDMETHOD_(ULONG,                       AddRef())                       {return 1;}\r
-       STDMETHOD_(ULONG,                       Release())                      {return 1;}\r
+       STDMETHOD_(ULONG,                       AddRef())                       \r
+       {\r
+               return ++ref_count_;\r
+       }\r
+       STDMETHOD_(ULONG,                       Release())                      \r
+       {\r
+               --ref_count_;\r
+               if(ref_count_ == 0)\r
+                       delete this;\r
+               return ref_count_;\r
+       }\r
 \r
        STDMETHOD_(long,                        GetWidth())                     {return format_desc_.width;}        \r
     STDMETHOD_(long,                   GetHeight())            {return format_desc_.height;}        \r
@@ -103,6 +116,7 @@ public:
                        {\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
+                               frame_.reset();\r
                        }\r
                        *buffer = key_data_.data();\r
                }\r
@@ -137,7 +151,6 @@ struct decklink_consumer : public IDeckLinkVideoOutputCallback, public IDeckLink
 \r
        size_t                                                          preroll_count_;\r
                \r
-       std::list<std::shared_ptr<IDeckLinkVideoFrame>> frame_container_; // Must be std::list in order to guarantee that pointers are always valid.\r
        boost::circular_buffer<std::vector<int16_t>>    audio_container_;\r
 \r
        tbb::concurrent_bounded_queue<std::shared_ptr<core::read_frame>> video_frame_buffer_;\r
@@ -304,11 +317,6 @@ public:
                        else if(result == bmdOutputFrameFlushed)\r
                                graph_->add_tag("flushed-frame");\r
 \r
-                       frame_container_.erase(std::find_if(frame_container_.begin(), frame_container_.end(), [&](const std::shared_ptr<IDeckLinkVideoFrame>& frame)\r
-                       {\r
-                               return frame.get() == completed_frame;\r
-                       }));\r
-\r
                        std::shared_ptr<core::read_frame> frame;        \r
                        video_frame_buffer_.pop(frame);                                 \r
                        schedule_next_video(make_safe(frame));  \r
@@ -369,8 +377,8 @@ 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_, 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
+               CComPtr<IDeckLinkVideoFrame> frame2(new decklink_frame(frame, format_desc_, config_.key_only));\r
+               if(FAILED(output_->ScheduleVideoFrame(frame2, (frames_scheduled_++) * format_desc_.duration, format_desc_.duration, format_desc_.time_scale)))\r
                        CASPAR_LOG(error) << print() << L" Failed to schedule video.";\r
 \r
                graph_->update_value("tick-time", tick_timer_.elapsed()*format_desc_.fps*0.5);\r
@@ -404,13 +412,11 @@ struct decklink_consumer_proxy : public core::frame_consumer
        const configuration                             config_;\r
        com_context<decklink_consumer>  context_;\r
        core::video_format_desc                 format_desc_;\r
-       size_t                                                  fail_count_;\r
 public:\r
 \r
        decklink_consumer_proxy(const configuration& config)\r
                : config_(config)\r
                , context_(L"decklink_consumer[" + boost::lexical_cast<std::wstring>(config.device_index) + L"]")\r
-               , fail_count_(0)\r
        {\r
        }\r
 \r
@@ -431,24 +437,7 @@ public:
        \r
        virtual bool send(const safe_ptr<core::read_frame>& frame)\r
        {\r
-               if(!context_)\r
-                       context_.reset([&]{return new decklink_consumer(config_, format_desc_);});\r
-\r
-               try\r
-               {\r
-                       context_->send(frame);\r
-                       fail_count_ = 0;\r
-               }\r
-               catch(...)\r
-               {\r
-                       context_.reset();\r
-\r
-                       if(fail_count_++ > 3)\r
-                               return false;  // Outside didn't handle exception properly, just give up.\r
-                       \r
-                       throw;\r
-               }\r
-\r
+               context_->send(frame);\r
                return true;\r
        }\r
        \r
@@ -456,12 +445,7 @@ public:
        {\r
                return context_ ? context_->print() : L"decklink_consumer";\r
        }\r
-\r
-       virtual bool key_only() const\r
-       {\r
-               return config_.key_only;\r
-       }\r
-               \r
+                       \r
        virtual const core::video_format_desc& get_video_format_desc() const\r
        {\r
                return format_desc_;\r