]> git.sesse.net Git - casparcg/blobdiff - core/video_channel.cpp
2.0. stage: Changed error handling.
[casparcg] / core / video_channel.cpp
index 96812ad929e334cc1393e581bcf4fef8c98a3893..476a73eb32190af8e0f2ba8954ebe2eb1a49829e 100644 (file)
 #include "video_channel.h"\r
 \r
 #include "video_channel_context.h"\r
-\r
 #include "video_format.h"\r
-#include "producer/layer.h"\r
+\r
+#include "consumer/output.h"\r
+#include "mixer/mixer.h"\r
+#include "producer/stage.h"\r
 \r
 #include <common/concurrency/executor.h>\r
 #include <common/diagnostics/graph.h>\r
 \r
-#include <boost/range/algorithm_ext/erase.hpp>\r
+#include "mixer/gpu/ogl_device.h"\r
+\r
 #include <boost/timer.hpp>\r
 \r
 #ifdef _MSC_VER\r
@@ -43,27 +46,28 @@ struct video_channel::implementation : boost::noncopyable
 {\r
        video_channel_context                   context_;\r
 \r
-       safe_ptr<frame_consumer_device> consumer_;\r
-       safe_ptr<frame_mixer_device>    mixer_;\r
-       safe_ptr<frame_producer_device> producer_;\r
+       safe_ptr<caspar::core::output>                  output_;\r
+       std::shared_ptr<caspar::core::mixer>    mixer_;\r
+       safe_ptr<caspar::core::stage>                   stage_;\r
 \r
        safe_ptr<diagnostics::graph>    diag_;\r
        boost::timer                                    frame_timer_;\r
        boost::timer                                    tick_timer_;\r
+       boost::timer                                    output_timer_;\r
        \r
 public:\r
        implementation(int index, const video_format_desc& format_desc, ogl_device& ogl)  \r
                : context_(index, ogl, format_desc)\r
                , diag_(diagnostics::create_graph(narrow(print())))\r
-               , consumer_(new frame_consumer_device(context_))\r
-               , mixer_(new frame_mixer_device(context_))\r
-               , producer_(new frame_producer_device(context_))        \r
+               , output_(new caspar::core::output(context_, [this]{restart();}))\r
+               , mixer_(new caspar::core::mixer(context_))\r
+               , stage_(new caspar::core::stage(context_))     \r
        {\r
                diag_->add_guide("produce-time", 0.5f); \r
-               diag_->set_color("produce-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
-               diag_->add_guide("mix-time", 0.5f);     \r
-               diag_->set_color("mix-time", diagnostics::color(1.0f, 0.0f, 1.0f));\r
-               diag_->set_color("tick-time", diagnostics::color(0.1f, 0.7f, 0.8f));    \r
+               diag_->set_color("produce-time", diagnostics::color(0.0f, 1.0f, 0.0f));\r
+               diag_->set_color("tick-time", diagnostics::color(0.0f, 0.6f, 0.9f));    \r
+               diag_->set_color("output-time", diagnostics::color(1.0f, 0.5f, 0.0f));\r
+               diag_->set_color("mix-time", diagnostics::color(1.0f, 1.0f, 0.9f));\r
 \r
                CASPAR_LOG(info) << print() << " Successfully Initialized.";\r
                context_.execution().begin_invoke([this]{tick();});\r
@@ -80,31 +84,54 @@ public:
 \r
        void tick()\r
        {\r
-               // Produce\r
+               try\r
+               {\r
+                       // Produce\r
 \r
-               frame_timer_.restart();\r
+                       frame_timer_.restart();\r
 \r
-               auto simple_frames = producer_->execute();\r
+                       auto simple_frames = stage_->execute();\r
 \r
-               diag_->update_value("produce-time", frame_timer_.elapsed()*context_.get_format_desc().fps*0.5);\r
+                       diag_->update_value("produce-time", frame_timer_.elapsed()*context_.get_format_desc().fps*0.5);\r
                \r
-               // Mix\r
+                       // Mix\r
 \r
-               frame_timer_.restart();\r
+                       frame_timer_.restart();\r
 \r
-               auto finished_frame = mixer_->execute(simple_frames);\r
+                       auto finished_frame = mixer_->execute(simple_frames);\r
+               \r
+                       diag_->update_value("mix-time", frame_timer_.elapsed()*context_.get_format_desc().fps*0.5);\r
+               \r
+                       // Consume\r
                \r
-               diag_->update_value("mix-time", frame_timer_.elapsed()*context_.get_format_desc().fps*0.5);\r
+                       output_timer_.restart();\r
+\r
+                       output_->execute(finished_frame);\r
                \r
-               // Consume\r
+                       diag_->update_value("output-time", frame_timer_.elapsed()*context_.get_format_desc().fps*0.5);\r
 \r
-               consumer_->execute(finished_frame);\r
                \r
-               diag_->update_value("tick-time", tick_timer_.elapsed()*context_.get_format_desc().fps*0.5);\r
-               tick_timer_.restart();\r
+                       diag_->update_value("tick-time", tick_timer_.elapsed()*context_.get_format_desc().fps*0.5);\r
+                       tick_timer_.restart();\r
+               }\r
+               catch(...)\r
+               {\r
+                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+                       CASPAR_LOG(error) << context_.print() << L" Unexpected exception. Clearing stage and freeing memory";\r
+                       restart();\r
+               }\r
 \r
                context_.execution().begin_invoke([this]{tick();});\r
        }\r
+\r
+       void restart()\r
+       {\r
+               stage_->clear();\r
+               context_.ogl().gc().wait();\r
+\r
+               mixer_ = nullptr;\r
+               mixer_.reset(new caspar::core::mixer(context_));\r
+       }\r
                \r
        std::wstring print() const\r
        {\r
@@ -115,6 +142,8 @@ public:
        {\r
                context_.execution().begin_invoke([=]\r
                {\r
+                       stage_->clear();\r
+                       context_.ogl().gc().wait();\r
                        context_.set_format_desc(format_desc);\r
                });\r
        }\r
@@ -122,11 +151,12 @@ public:
 \r
 video_channel::video_channel(int index, const video_format_desc& format_desc, ogl_device& ogl) : impl_(new implementation(index, format_desc, ogl)){}\r
 video_channel::video_channel(video_channel&& other) : impl_(std::move(other.impl_)){}\r
-safe_ptr<frame_producer_device> video_channel::producer() { return impl_->producer_;} \r
-safe_ptr<frame_mixer_device> video_channel::mixer() { return impl_->mixer_;} \r
-safe_ptr<frame_consumer_device> video_channel::consumer() { return impl_->consumer_;} \r
+safe_ptr<stage> video_channel::stage() { return impl_->stage_;} \r
+safe_ptr<mixer> video_channel::mixer() { return make_safe(impl_->mixer_);} \r
+safe_ptr<output> video_channel::output() { return impl_->output_;} \r
 video_format_desc video_channel::get_video_format_desc() const{return impl_->context_.get_format_desc();}\r
 void video_channel::set_video_format_desc(const video_format_desc& format_desc){impl_->set_video_format_desc(format_desc);}\r
 std::wstring video_channel::print() const { return impl_->print();}\r
+video_channel_context& video_channel::context(){return impl_->context_;}\r
 \r
 }}
\ No newline at end of file