]> git.sesse.net Git - casparcg/blobdiff - core/consumer/output.cpp
2.0. stage: Changed error handling.
[casparcg] / core / consumer / output.cpp
index dde9c009aa9ab6189efe5129198ecf610fac2b2d..426013cac5e63790167c084bbfa36fac45b788ce 100644 (file)
@@ -45,7 +45,8 @@ struct output::implementation
 {      \r
        typedef std::pair<safe_ptr<read_frame>, safe_ptr<read_frame>> fill_and_key;\r
        \r
-       video_channel_context& channel_;\r
+       video_channel_context&          channel_;\r
+       const std::function<void()> restart_channel_;\r
 \r
        std::map<int, safe_ptr<frame_consumer>> consumers_;\r
        typedef std::map<int, safe_ptr<frame_consumer>>::value_type layer_t;\r
@@ -53,8 +54,11 @@ struct output::implementation
        high_prec_timer timer_;\r
                \r
 public:\r
-       implementation(video_channel_context& video_channel) \r
-               : channel_(video_channel){}     \r
+       implementation(video_channel_context& video_channel, const std::function<void()>& restart_channel) \r
+               : channel_(video_channel)\r
+               , restart_channel_(restart_channel)\r
+       {\r
+       }       \r
        \r
        void add(int index, safe_ptr<frame_consumer>&& consumer)\r
        {               \r
@@ -105,10 +109,41 @@ public:
                        if(consumer->get_video_format_desc() != channel_.get_format_desc())\r
                                consumer->initialize(channel_.get_format_desc());\r
 \r
-                       if(consumer->send(frame))\r
-                               ++it;\r
-                       else\r
-                               consumers_.erase(it++);\r
+                       try\r
+                       {\r
+                               if(consumer->send(frame))\r
+                                       ++it;\r
+                               else\r
+                                       consumers_.erase(it++);\r
+                       }\r
+                       catch(...)\r
+                       {\r
+                               CASPAR_LOG_CURRENT_EXCEPTION();\r
+                               CASPAR_LOG(warning) << "Trying to restart consumer: " << consumer->print() << L".";\r
+                               try\r
+                               {\r
+                                       consumer->initialize(channel_.get_format_desc());\r
+                                       consumer->send(frame);\r
+                               }\r
+                               catch(...)\r
+                               {       \r
+                                       CASPAR_LOG_CURRENT_EXCEPTION(); \r
+                                       CASPAR_LOG(warning) << "Consumer restart failed, trying to restart channel: " << consumer->print() << L".";     \r
+\r
+                                       try\r
+                                       {\r
+                                               restart_channel_();\r
+                                               consumer->initialize(channel_.get_format_desc());\r
+                                               consumer->send(frame);\r
+                                       }\r
+                                       catch(...)\r
+                                       {\r
+                                               CASPAR_LOG_CURRENT_EXCEPTION();\r
+                                               CASPAR_LOG(error) << "Failed to recover consumer: " << consumer->print() << L". Removing it.";\r
+                                               consumers_.erase(it++);\r
+                                       }\r
+                               }\r
+                       }\r
                }\r
        }\r
 \r
@@ -128,7 +163,7 @@ private:
        }\r
 };\r
 \r
-output::output(video_channel_context& video_channel) : impl_(new implementation(video_channel)){}\r
+output::output(video_channel_context& video_channel, const std::function<void()>& restart_channel) : impl_(new implementation(video_channel, restart_channel)){}\r
 void output::add(int index, safe_ptr<frame_consumer>&& consumer){impl_->add(index, std::move(consumer));}\r
 void output::remove(int index){impl_->remove(index);}\r
 void output::execute(const safe_ptr<read_frame>& frame) {impl_->execute(frame); }\r