CComQIPtr<IDeckLinkConfiguration> configuration_;\r
CComQIPtr<IDeckLinkKeyer> keyer_;\r
\r
+ tbb::spin_mutex exception_mutex_;\r
std::exception_ptr exception_;\r
\r
tbb::atomic<bool> is_running_;\r
}\r
catch(...)\r
{\r
+ tbb::spin_mutex::scoped_lock lock(exception_mutex_);\r
exception_ = std::current_exception();\r
return E_FAIL;\r
}\r
}\r
catch(...)\r
{\r
+ tbb::spin_mutex::scoped_lock lock(exception_mutex_);\r
exception_ = std::current_exception();\r
return E_FAIL;\r
}\r
\r
void send(const safe_ptr<core::read_frame>& frame)\r
{\r
- if(exception_ != nullptr)\r
- std::rethrow_exception(exception_);\r
+ {\r
+ tbb::spin_mutex::scoped_lock lock(exception_mutex_);\r
+ if(exception_ != nullptr)\r
+ std::rethrow_exception(exception_);\r
+ }\r
\r
if(!is_running_)\r
BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Is not running."));\r
#include <boost/thread.hpp>\r
#include <boost/timer.hpp>\r
\r
+#include <tbb/spin_mutex.h>\r
+\r
#include <functional>\r
\r
namespace caspar {\r
\r
com_context<flash_renderer> context_; \r
\r
+ tbb::spin_mutex exception_mutex_;\r
+ std::exception_ptr exception_;\r
+\r
int width_;\r
int height_;\r
public:\r
graph_->set_color("output-buffer", diagnostics::color(0.0f, 1.0f, 0.0f));\r
\r
frame_buffer_.set_capacity(1);\r
-\r
- initialize(); \r
+ \r
+ context_.reset([&]{return new flash_renderer(safe_ptr<diagnostics::graph>(graph_), frame_factory_, filename_, width_, height_);});\r
+ while(frame_buffer_.try_push(core::basic_frame::empty())){} \r
+ render(); \r
}\r
\r
~flash_producer()\r
// frame_producer\r
\r
virtual safe_ptr<core::basic_frame> receive(int)\r
- { \r
+ { \r
+ { \r
+ tbb::spin_mutex::scoped_lock lock(exception_mutex_);\r
+ if(exception_ != nullptr)\r
+ std::rethrow_exception(exception_);\r
+ }\r
+\r
graph_->set_value("output-buffer", static_cast<float>(frame_buffer_.size())/static_cast<float>(frame_buffer_.capacity()));\r
\r
auto frame = core::basic_frame::late();\r
\r
virtual void param(const std::wstring& param) \r
{ \r
+ { \r
+ tbb::spin_mutex::scoped_lock lock(exception_mutex_);\r
+ if(exception_ != nullptr)\r
+ std::rethrow_exception(exception_);\r
+ }\r
+\r
context_.begin_invoke([=]\r
{\r
- if(!context_)\r
- initialize();\r
-\r
try\r
{\r
context_->param(param); \r
{\r
CASPAR_LOG_CURRENT_EXCEPTION();\r
context_.reset(nullptr);\r
- frame_buffer_.push(core::basic_frame::empty());\r
+\r
+ tbb::spin_mutex::scoped_lock lock(exception_mutex_);\r
+ exception_ = std::current_exception();\r
}\r
});\r
}\r
\r
virtual std::wstring print() const\r
{ \r
- return L"flash[" + boost::filesystem::wpath(filename_).filename() + L", " + \r
- boost::lexical_cast<std::wstring>(fps_) + L"]"; \r
+ return L"flash[" + boost::filesystem::wpath(filename_).filename() + L", " + boost::lexical_cast<std::wstring>(fps_) + L"]"; \r
} \r
\r
// flash_producer\r
\r
- void initialize()\r
- {\r
- context_.reset([&]{return new flash_renderer(safe_ptr<diagnostics::graph>(graph_), frame_factory_, filename_, width_, height_);});\r
- while(frame_buffer_.try_push(core::basic_frame::empty())){} \r
- render(context_.get());\r
- }\r
-\r
- void render(const flash_renderer* renderer)\r
- { \r
+ void render()\r
+ { \r
context_.begin_invoke([=]\r
{\r
- if(context_.get() != renderer) // Since initialize will start a new recursive call make sure the recursive calls are only for a specific instance.\r
- return;\r
-\r
try\r
{ \r
const auto& format_desc = frame_factory_->get_video_format_desc();\r
graph_->set_value("output-buffer", static_cast<float>(frame_buffer_.size())/static_cast<float>(frame_buffer_.capacity())); \r
fps_.fetch_and_store(static_cast<int>(context_->fps()*100.0));\r
\r
- render(renderer);\r
+ render();\r
}\r
catch(...)\r
{\r
CASPAR_LOG_CURRENT_EXCEPTION();\r
context_.reset(nullptr);\r
- frame_buffer_.push(core::basic_frame::empty());\r
+ \r
+ tbb::spin_mutex::scoped_lock lock(exception_mutex_);\r
+ exception_ = std::current_exception();\r
}\r
});\r
}\r