#include "executor.h"\r
\r
#include "../log/log.h"\r
+#include "../exception/exceptions.h"\r
\r
#define NOMINMAX\r
#define WIN32_LEAN_AND_MEAN\r
::CoUninitialize();\r
}).timed_wait(boost::posix_time::milliseconds(500)))\r
{\r
- CASPAR_LOG(error) << L"[com_contex] Timer expired, deadlock detected and released, leaking resources";\r
+ CASPAR_LOG(error) << L"[com_contex] Timer expired, deadlock detected and released, leaking resources.";\r
}\r
}\r
\r
});\r
}\r
\r
- T& operator*() const { return *instance_.get();} // noexcept\r
+ T& operator*() const \r
+ {\r
+ if(instance_ == nullptr)\r
+ BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("Tried to access null context."));\r
+\r
+ return *instance_.get();\r
+ } // noexcept\r
\r
- T* operator->() const { return instance_.get();} // noexcept\r
+ T* operator->() const \r
+ {\r
+ if(instance_ == nullptr)\r
+ BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("Tried to access null context."));\r
+ return instance_.get();\r
+ } // noexcept\r
\r
- T* get() const { return instance_.get();} // noexcept\r
+ T* get() const\r
+ {\r
+ return instance_.get();\r
+ } // noexcept\r
\r
operator bool() const {return get() != nullptr;}\r
};\r
{ \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
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
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
}\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
class output : boost::noncopyable\r
{\r
public:\r
- explicit output(video_channel_context& video_channel);\r
+ explicit output(video_channel_context& video_channel, const std::function<void()>& restart_channel);\r
\r
void add(int index, safe_ptr<frame_consumer>&& consumer);\r
void remove(int index);\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
- , output_(new caspar::core::output(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
{\r
CASPAR_LOG_CURRENT_EXCEPTION();\r
CASPAR_LOG(error) << context_.print() << L" Unexpected exception. Clearing stage and freeing memory";\r
-\r
- stage_->clear();\r
- context_.ogl().gc().wait();\r
-\r
- mixer_ = nullptr;\r
- mixer_.reset(new caspar::core::mixer(context_));\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
const bool embedded_audio_;\r
const bool key_only_;\r
core::video_format_desc format_desc_;\r
- size_t fail_count_;\r
public:\r
\r
bluefish_consumer_proxy(size_t device_index, bool embedded_audio, bool key_only)\r
: device_index_(device_index)\r
, embedded_audio_(embedded_audio)\r
, key_only_(key_only)\r
- , fail_count_(0)\r
{\r
}\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_, key_only_));\r
-\r
- try\r
- {\r
- consumer_->send(frame);\r
- fail_count_ = 0;\r
- }\r
- catch(...)\r
- {\r
- consumer_.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
+ consumer_->send(frame);\r
return true;\r
}\r
\r
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
\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
\r
\r
/* File created by MIDL compiler version 7.00.0555 */\r
-/* at Sun Aug 21 14:54:35 2011\r
+/* at Fri Aug 26 23:40:03 2011\r
*/\r
/* Compiler settings for interop\DeckLinkAPI.idl:\r
Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 7.00.0555 \r
\r
\r
/* File created by MIDL compiler version 7.00.0555 */\r
-/* at Sun Aug 21 14:54:35 2011\r
+/* at Fri Aug 26 23:40:03 2011\r
*/\r
/* Compiler settings for interop\DeckLinkAPI.idl:\r
Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 7.00.0555 \r
\r
virtual bool send(const safe_ptr<core::read_frame>& frame)\r
{\r
- try\r
- {\r
- consumer_->send(frame);\r
- }\r
- catch(...)\r
- {\r
- CASPAR_LOG_CURRENT_EXCEPTION()\r
- return false;\r
- }\r
-\r
+ consumer_->send(frame);\r
return true;\r
}\r
\r
<?xml version="1.0" encoding="utf-8"?>\r
<configuration>\r
<paths>\r
- <media-path>L:\casparcg\_media\</media-path>\r
+ <media-path>C:\Lokala Filer\server\branches\2.0.0.2\bin\_media\</media-path>\r
<log-path>L:\casparcg\_log\</log-path>\r
<data-path>L:\casparcg\_data\</data-path>\r
<template-path>L:\casparcg\_templates\</template-path>\r
</template-hosts>\r
</producers>\r
<channels>\r
- <channel>\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
- <device>1</device>\r
- <key-only>true</key-only>\r
- </screen>\r
- </consumers>\r
- </channel>\r
<channel>\r
- <video-mode>1080p5000</video-mode>\r
+ <video-mode>PAL</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
+ <screen>\r
+ <device>0</device>\r
+ </screen>\r
</consumers>\r
</channel>\r
-</channels>\r
+ </channels>\r
<controllers>\r
<tcp>\r
<port>5250</port>\r