#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
, bmp_(width, height)\r
, width_(width)\r
, height_(height)\r
- {\r
+ { \r
graph_->add_guide("frame-time", 0.5f);\r
graph_->set_color("frame-time", diagnostics::color(0.1f, 1.0f, 0.1f));\r
graph_->add_guide("tick-time", 0.5);\r
- graph_->set_color("tick-time", diagnostics::color(0.0f, 0.6f, 0.9f)); \r
+ graph_->set_color("tick-time", diagnostics::color(0.0f, 0.6f, 0.9f));\r
graph_->set_color("param", diagnostics::color(1.0f, 0.5f, 0.0f)); \r
graph_->set_color("underflow", diagnostics::color(0.6f, 0.3f, 0.9f)); \r
\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
fps_ = 0;\r
\r
graph_ = diagnostics::create_graph([this]{return print();});\r
- graph_->set_color("buffer-count", diagnostics::color(0.4f, 0.8f, 0.8f));\r
- \r
- frame_buffer_.set_capacity(1); \r
- initialize();\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
\r
~flash_producer()\r
frame_buffer_.clear();\r
}\r
\r
- void initialize()\r
- { \r
- context_.reset(nullptr);\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
// frame_producer\r
\r
virtual safe_ptr<core::basic_frame> receive(int)\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("buffer-count", static_cast<float>(frame_buffer_.size())/static_cast<float>(frame_buffer_.capacity()));\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
if(frame_buffer_.try_pop(frame))\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
+ //const auto& format_desc = frame_factory_->get_video_format_desc();\r
+ //if(abs(context_->fps() - format_desc.fps) > 0.01 && abs(context_->fps()/2.0 - format_desc.fps) > 0.01)\r
+ // CASPAR_LOG(warning) << print() << " Invalid frame-rate: " << context_->fps() << L". Should be either " << format_desc.fps << L" or " << format_desc.fps*2.0 << L".";\r
}\r
catch(...)\r
{\r
- try\r
- {\r
- CASPAR_LOG_CURRENT_EXCEPTION();\r
- CASPAR_LOG(error) << print() << L" param failed. Trying to re-initialize flash and re-execute param.";\r
-\r
- initialize(); \r
- context_->param(param); \r
- }\r
- catch(...)\r
- {\r
- CASPAR_LOG_CURRENT_EXCEPTION();\r
-\r
- context_.reset(nullptr);\r
-\r
- tbb::spin_mutex::scoped_lock lock(exception_mutex_);\r
- exception_ = std::current_exception();\r
- }\r
+ CASPAR_LOG_CURRENT_EXCEPTION();\r
+ context_.reset(nullptr);\r
+ frame_buffer_.push(core::basic_frame::empty());\r
}\r
-\r
- const auto& format_desc = frame_factory_->get_video_format_desc();\r
- if(abs(context_->fps() - format_desc.fps) > 2.0 && abs(context_->fps()/2.0 - format_desc.fps) > 2.0)\r
- CASPAR_LOG(warning) << print() << " Invalid frame-rate: " << context_->fps() << L". Should be either " << format_desc.fps << L" or " << format_desc.fps*2.0 << L".";\r
});\r
}\r
\r
virtual std::wstring print() const\r
{ \r
- return L"flash[" + boost::filesystem::wpath(filename_).filename() + L", " + boost::lexical_cast<std::wstring>(fps_) + L"]"; \r
+ return L"flash[" + boost::filesystem::wpath(filename_).filename() + L", " + \r
+ boost::lexical_cast<std::wstring>(fps_) + L"]"; \r
} \r
\r
// flash_producer\r
\r
- void render()\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
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
frame_buffer_.push(frame);\r
}\r
\r
- graph_->set_value("buffer-count", static_cast<float>(frame_buffer_.size())/static_cast<float>(frame_buffer_.capacity())); \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();\r
+ render(renderer);\r
}\r
catch(...)\r
{\r
CASPAR_LOG_CURRENT_EXCEPTION();\r
context_.reset(nullptr);\r
- \r
- tbb::spin_mutex::scoped_lock lock(exception_mutex_);\r
- exception_ = std::current_exception();\r
+ frame_buffer_.push(core::basic_frame::empty());\r
}\r
});\r
}\r