\r
typedef boost::chrono::duration<double, boost::ratio<1, 1>> duration;\r
\r
-typedef boost::variant<bool, int32_t, int64_t, float, double, std::string, std::vector<int8_t>, duration> param;\r
+typedef boost::variant<bool, int32_t, int64_t, float, double, std::string, std::wstring, std::vector<int8_t>, duration> param;\r
\r
std::ostream& operator<<(std::ostream& o, const param& p);\r
\r
#include <core/frame/draw_frame.h>\r
#include <core/frame/frame_factory.h>\r
#include <core/frame/pixel_format.h>\r
+#include <core/monitor/monitor.h>\r
\r
#include <common/except.h>\r
#include <common/memory/array.h>\r
\r
class color_producer : public frame_producer\r
{\r
- draw_frame frame_;\r
- const std::wstring color_str_;\r
+ monitor::basic_subject event_subject_;\r
+\r
+ draw_frame frame_;\r
+ const std::wstring color_str_;\r
\r
public:\r
explicit color_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const std::wstring& color) \r
\r
virtual draw_frame receive(int) override\r
{\r
+ event_subject_ << monitor::event("color") % color_str_;\r
+\r
return frame_;\r
} \r
\r
info.add(L"color", color_str_);\r
return info;\r
}\r
+\r
+ virtual void subscribe(const monitor::observable::observer_ptr& o) override \r
+ {\r
+ return event_subject_.subscribe(o);\r
+ }\r
+\r
+ virtual void unsubscribe(const monitor::observable::observer_ptr& o) override \r
+ {\r
+ return event_subject_.unsubscribe(o);\r
+ }\r
};\r
\r
std::wstring get_hex_color(const std::wstring& str)\r
\r
// monitor::observable\r
\r
- virtual void subscribe(const monitor::observable::observer_ptr& o) {}\r
- virtual void unsubscribe(const monitor::observable::observer_ptr& o) {}\r
+ virtual void subscribe(const monitor::observable::observer_ptr& o) = 0;\r
+ virtual void unsubscribe(const monitor::observable::observer_ptr& o) = 0;\r
\r
// Properties\r
\r
<< monitor::event("frame") % static_cast<int64_t>(frame_number_)\r
% static_cast<int64_t>((static_cast<int64_t>(foreground_->nb_frames()) - static_cast<int64_t>(auto_play_delta_ ? *auto_play_delta_ : 0)));\r
\r
- foreground_event_subject_ << monitor::event("type") % u8(foreground_->name());\r
- background_event_subject_ << monitor::event("type") % u8(background_->name());\r
+ foreground_event_subject_ << monitor::event("type") % foreground_->name();\r
+ background_event_subject_ << monitor::event("type") % background_->name();\r
\r
return frame;\r
}\r
\r
#include "separated_producer.h"\r
\r
-#include "../frame_producer.h"\r
-#include "../../frame/draw_frame.h"\r
+#include <core/producer/frame_producer.h>\r
+#include <core/frame/draw_frame.h>\r
+#include <core/monitor/monitor.h>\r
\r
#include <tbb/parallel_invoke.h>\r
\r
\r
class separated_producer : public frame_producer\r
{ \r
+ monitor::basic_subject event_subject_;\r
+ monitor::basic_subject key_event_subject_;\r
+\r
spl::shared_ptr<frame_producer> fill_producer_;\r
spl::shared_ptr<frame_producer> key_producer_;\r
draw_frame fill_;\r
\r
public:\r
explicit separated_producer(const spl::shared_ptr<frame_producer>& fill, const spl::shared_ptr<frame_producer>& key) \r
- : fill_producer_(fill)\r
+ : key_event_subject_("keyer") \r
+ , fill_producer_(fill)\r
, key_producer_(key)\r
, fill_(core::draw_frame::late())\r
, key_(core::draw_frame::late())\r
, last_frame_(core::draw_frame::empty())\r
{\r
CASPAR_LOG(info) << print() << L" Initialized";\r
+\r
+ key_event_subject_.subscribe(event_subject_);\r
+\r
+ key_producer_->subscribe(key_event_subject_);\r
+ fill_producer_->subscribe(event_subject_);\r
}\r
\r
// frame_producer\r
\r
virtual void subscribe(const monitor::observable::observer_ptr& o) override \r
{\r
- return fill_producer_->subscribe(o);\r
+ return event_subject_.subscribe(o);\r
}\r
\r
virtual void unsubscribe(const monitor::observable::observer_ptr& o) override \r
{\r
- return fill_producer_->unsubscribe(o);\r
+ return event_subject_.unsubscribe(o);\r
}\r
};\r
\r
\r
++current_frame_;\r
\r
- event_subject_ << monitor::event("transition/frame") % current_frame_ % info_.duration\r
- << monitor::event("transition/type") % [&]() -> std::string\r
- {\r
- switch(info_.type.value())\r
- {\r
- case transition_type::mix: return "mix";\r
- case transition_type::wipe: return "wipe";\r
- case transition_type::slide: return "slide";\r
- case transition_type::push: return "push";\r
- case transition_type::cut: return "cut";\r
- default: return "n/a";\r
- }\r
- }();\r
-\r
auto dest = draw_frame::empty();\r
auto source = draw_frame::empty();\r
\r
source = source_producer_->last_frame();\r
}); \r
\r
+ event_subject_ << monitor::event("transition/frame") % current_frame_ % info_.duration\r
+ << monitor::event("transition/type") % [&]() -> std::string\r
+ {\r
+ switch(info_.type.value())\r
+ {\r
+ case transition_type::mix: return "mix";\r
+ case transition_type::wipe: return "wipe";\r
+ case transition_type::slide: return "slide";\r
+ case transition_type::push: return "push";\r
+ case transition_type::cut: return "cut";\r
+ default: return "n/a";\r
+ }\r
+ }();\r
+\r
return compose(dest, source);\r
}\r
\r
graph_->set_value("tick-time", frame_timer.elapsed()*format_desc.fps*0.5);\r
\r
event_subject_ << monitor::event("profiler/time") % frame_timer.elapsed() % (1.0/format_desc_.fps)\r
- << monitor::event("format") % u8(format_desc.name);\r
+ << monitor::event("format") % format_desc.name;\r
}\r
catch(...)\r
{\r
#include <core/frame/draw_frame.h>\r
#include <core/frame/frame_transform.h>\r
#include <core/frame/frame_factory.h>\r
+#include <core/monitor/monitor.h>\r
\r
#include <tbb/concurrent_queue.h>\r
\r
\r
class decklink_producer : boost::noncopyable, public IDeckLinkInputCallback\r
{ \r
+ monitor::basic_subject event_subject_;\r
spl::shared_ptr<diagnostics::graph> graph_;\r
boost::timer tick_timer_;\r
- boost::timer frame_timer_;\r
\r
CComPtr<IDeckLink> decklink_;\r
CComQIPtr<IDeckLinkInput> input_;\r
graph_->set_value("tick-time", tick_timer_.elapsed()*out_format_desc_.fps*0.5);\r
tick_timer_.restart();\r
\r
- frame_timer_.restart();\r
+ boost::timer frame_timer; \r
\r
// PUSH\r
\r
av_frame->interlaced_frame = in_format_desc_.field_mode != core::field_mode::progressive;\r
av_frame->top_field_first = in_format_desc_.field_mode == core::field_mode::upper ? 1 : 0;\r
\r
+ event_subject_ << monitor::event("file/name") % model_name_\r
+ << monitor::event("file/path") % device_index_\r
+ << monitor::event("file/video/width") % video->GetWidth()\r
+ << monitor::event("file/video/height") % video->GetHeight()\r
+ << monitor::event("file/video/field") % u8(!av_frame->interlaced_frame ? "progressive" : (av_frame->top_field_first ? "upper" : "lower"))\r
+ << monitor::event("file/audio/sample-rate") % 48000\r
+ << monitor::event("file/audio/channels") % 2\r
+ << monitor::event("file/audio/format") % u8(av_get_sample_fmt_name(AV_SAMPLE_FMT_S32))\r
+ << monitor::event("file/fps") % in_format_desc_.fps;\r
+\r
std::shared_ptr<core::audio_buffer> audio_buffer;\r
\r
// It is assumed that audio is always equal or ahead of video.\r
graph_->set_tag("dropped-frame");\r
}\r
\r
- graph_->set_value("frame-time", frame_timer_.elapsed()*out_format_desc_.fps*0.5);\r
+ graph_->set_value("frame-time", frame_timer.elapsed()*out_format_desc_.fps*0.5); \r
+ event_subject_ << monitor::event("profiler/time") % frame_timer.elapsed() % out_format_desc_.fps;\r
\r
graph_->set_value("output-buffer", static_cast<float>(frame_buffer_.size())/static_cast<float>(frame_buffer_.capacity())); \r
+ event_subject_ << monitor::event("buffer") % frame_buffer_.size() % frame_buffer_.capacity();\r
}\r
catch(...)\r
{\r
{\r
return model_name_ + L" [" + boost::lexical_cast<std::wstring>(device_index_) + L"|" + in_format_desc_.name + L"]";\r
}\r
+\r
+ void subscribe(const monitor::observable::observer_ptr& o)\r
+ {\r
+ event_subject_.subscribe(o);\r
+ }\r
+\r
+ void unsubscribe(const monitor::observable::observer_ptr& o)\r
+ {\r
+ event_subject_.unsubscribe(o);\r
+ }\r
};\r
\r
class decklink_producer_proxy : public core::frame_producer\r
CoUninitialize();\r
});\r
}\r
+\r
+ virtual void subscribe(const monitor::observable::observer_ptr& o) override\r
+ {\r
+ producer_->subscribe(o);\r
+ }\r
+\r
+ virtual void unsubscribe(const monitor::observable::observer_ptr& o) override\r
+ {\r
+ producer_->unsubscribe(o);\r
+ }\r
\r
// frame_producer\r
\r
// frame_producer\r
\r
virtual core::draw_frame receive(int flags) override\r
- { \r
+ { \r
boost::timer frame_timer;\r
\r
auto frame = core::draw_frame::late(); \r
}\r
\r
graph_->set_value("frame-time", frame_timer.elapsed()*format_desc_.fps*0.5);\r
- \r
- event_subject_ << monitor::event("profiler/time") % frame_timer.elapsed() % (1.0/format_desc_.fps) \r
- << monitor::event("file/time") % monitor::duration(file_frame_number()/fps_) \r
- % monitor::duration(file_nb_frames()/fps_)\r
- << monitor::event("file/frame") % static_cast<int32_t>(file_frame_number())\r
- % static_cast<int32_t>(file_nb_frames())\r
- << monitor::event("file/fps") % fps_\r
- << monitor::event("filename") % u8(filename_)\r
- << monitor::event("loop") % input_.loop();\r
- \r
+ event_subject_ << monitor::event("profiler/time") % frame_timer.elapsed() % (1.0/format_desc_.fps); \r
+ \r
graph_->set_text(print());\r
\r
if(frame != core::draw_frame::late())\r
last_frame_ = frame;\r
}\r
\r
+ event_subject_ << monitor::event("file/time") % monitor::duration(file_frame_number()/fps_) \r
+ % monitor::duration(file_nb_frames()/fps_)\r
+ << monitor::event("file/frame") % static_cast<int32_t>(file_frame_number())\r
+ % static_cast<int32_t>(file_nb_frames())\r
+ << monitor::event("file/fps") % fps_\r
+ << monitor::event("file/path") % filename_\r
+ << monitor::event("loop") % input_.loop();\r
+\r
return frame;\r
}\r
\r
#include <core/frame/draw_frame.h>\r
#include <core/frame/frame_factory.h>\r
#include <core/frame/pixel_format.h>\r
+#include <core/monitor/monitor.h>\r
\r
#include <common/env.h>\r
#include <common/concurrency/executor.h>\r
}\r
} com_init_;\r
\r
- const std::wstring filename_;\r
+ monitor::basic_subject& event_subject_;\r
\r
- const std::shared_ptr<core::frame_factory> frame_factory_;\r
+ const std::wstring filename_;\r
+\r
+ const std::shared_ptr<core::frame_factory> frame_factory_;\r
\r
CComObject<caspar::flash::FlashAxContainer>* ax_;\r
- core::draw_frame head_;\r
- bitmap bmp_;\r
+ core::draw_frame head_;\r
+ bitmap bmp_;\r
\r
- spl::shared_ptr<diagnostics::graph> graph_;\r
- boost::timer frame_timer_;\r
- boost::timer tick_timer_;\r
-\r
- prec_timer timer_;\r
+ spl::shared_ptr<diagnostics::graph> graph_;\r
+ \r
+ prec_timer timer_;\r
\r
- const int width_;\r
- const int height_;\r
+ const int width_;\r
+ const int height_;\r
\r
public:\r
- flash_renderer(const spl::shared_ptr<diagnostics::graph>& graph, const std::shared_ptr<core::frame_factory>& frame_factory, const std::wstring& filename, int width, int height) \r
- : graph_(graph)\r
+ flash_renderer(monitor::basic_subject& event_subject, const spl::shared_ptr<diagnostics::graph>& graph, const std::shared_ptr<core::frame_factory>& frame_factory, const std::wstring& filename, int width, int height) \r
+ : event_subject_(event_subject)\r
+ , graph_(graph)\r
, filename_(filename)\r
, frame_factory_(frame_factory)\r
, ax_(nullptr)\r
, height_(height)\r
{ \r
graph_->set_color("frame-time", diagnostics::color(0.1f, 1.0f, 0.1f));\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("sync", diagnostics::color(0.8f, 0.3f, 0.2f)); \r
\r
{ \r
const float frame_time = 1.0f/ax_->GetFPS();\r
\r
- graph_->set_value("tick-time", static_cast<float>(tick_timer_.elapsed()/frame_time)*0.5f);\r
- tick_timer_.restart();\r
- \r
if(sync > 0.00001) \r
timer_.tick(frame_time*sync); // This will block the thread.\r
else\r
graph_->set_tag("sync");\r
\r
graph_->set_value("sync", sync);\r
+ event_subject_ << monitor::event("sync") % sync;\r
\r
ax_->Tick();\r
\r
{ \r
const float frame_time = 1.0f/fps();\r
\r
- frame_timer_.restart();\r
+ boost::timer frame_timer;\r
\r
if(ax_->InvalidRect())\r
{ \r
head_ = core::draw_frame(std::move(frame)); \r
} \r
\r
- graph_->set_value("frame-time", static_cast<float>(frame_timer_.elapsed()/frame_time)*0.5f);\r
+ graph_->set_value("frame-time", static_cast<float>(frame_timer.elapsed()/frame_time)*0.5f);\r
+ event_subject_ << monitor::event("renderer/profiler/time") % frame_timer.elapsed() % frame_time;\r
return head_;\r
}\r
\r
\r
struct flash_producer : public core::frame_producer\r
{ \r
+ monitor::basic_subject event_subject_;\r
const std::wstring filename_; \r
const spl::shared_ptr<core::frame_factory> frame_factory_;\r
const core::video_format_desc format_desc_;\r
std::queue<core::draw_frame> frame_buffer_;\r
tbb::concurrent_bounded_queue<core::draw_frame> output_buffer_;\r
\r
+ boost::timer tick_timer_;\r
std::unique_ptr<flash_renderer> renderer_;\r
\r
core::draw_frame last_frame_;\r
fps_ = 0;\r
\r
graph_->set_color("buffer-size", diagnostics::color(1.0f, 1.0f, 0.0f));\r
+ graph_->set_color("tick-time", diagnostics::color(0.0f, 0.6f, 0.9f));\r
graph_->set_color("late-frame", diagnostics::color(0.6f, 0.3f, 0.9f));\r
graph_->set_text(print());\r
diagnostics::register_graph(graph_);\r
if(frame != core::draw_frame::late())\r
last_frame_ = frame;\r
\r
+ event_subject_ << monitor::event("host/path") % filename_\r
+ << monitor::event("host/width") % width_\r
+ << monitor::event("host/height") % height_\r
+ << monitor::event("host/fps") % fps_\r
+ << monitor::event("buffer") % output_buffer_.size() % buffer_size_;\r
+\r
return frame;\r
}\r
\r
{\r
if(!renderer_)\r
{\r
- renderer_.reset(new flash_renderer(graph_, frame_factory_, filename_, width_, height_));\r
+ renderer_.reset(new flash_renderer(event_subject_, graph_, frame_factory_, filename_, width_, height_));\r
\r
while(output_buffer_.size() < buffer_size_)\r
output_buffer_.push(core::draw_frame::empty());\r
return info;\r
}\r
\r
+ virtual void subscribe(const monitor::observable::observer_ptr& o) override\r
+ {\r
+ event_subject_.subscribe(o);\r
+ }\r
+\r
+ virtual void unsubscribe(const monitor::observable::observer_ptr& o) override\r
+ {\r
+ event_subject_.unsubscribe(o);\r
+ }\r
+\r
// flash_producer\r
\r
void tick()\r
if(!renderer_)\r
frame_buffer_.push(core::draw_frame::empty());\r
\r
+ tick_timer_.restart(); \r
+\r
if(frame_buffer_.empty())\r
{ \r
tick();\r
renderer_.reset();\r
}\r
\r
+ graph_->set_value("tick-time", static_cast<float>(tick_timer_.elapsed()/fps_)*0.5f);\r
+ event_subject_ << monitor::event("profiler/time") % tick_timer_.elapsed() % fps_;\r
+\r
output_buffer_.push(std::move(frame_buffer_.front()));\r
frame_buffer_.pop();\r
}\r
\r
#include <core/video_format.h>\r
\r
+#include <core/producer/frame_producer.h>\r
#include <core/frame/frame.h>\r
#include <core/frame/draw_frame.h>\r
#include <core/frame/frame_factory.h>\r
#include <core/frame/pixel_format.h>\r
+#include <core/monitor/monitor.h>\r
\r
#include <common/env.h>\r
#include <common/log.h>\r
\r
struct image_producer : public core::frame_producer\r
{ \r
- const std::wstring filename_;\r
- core::draw_frame frame_;\r
+ monitor::basic_subject event_subject_;\r
+ const std::wstring filename_;\r
+ core::draw_frame frame_;\r
\r
explicit image_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const std::wstring& filename) \r
: filename_(filename)\r
\r
virtual core::draw_frame receive(int) override\r
{\r
+ event_subject_ << monitor::event("file/path") % filename_;\r
+\r
return frame_;\r
}\r
\r
info.add(L"filename", filename_);\r
return info;\r
}\r
+\r
+ virtual void subscribe(const monitor::observable::observer_ptr& o) override \r
+ {\r
+ return event_subject_.subscribe(o);\r
+ }\r
+\r
+ virtual void unsubscribe(const monitor::observable::observer_ptr& o) override \r
+ {\r
+ return event_subject_.unsubscribe(o);\r
+ }\r
};\r
\r
spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params)\r
#include <core/frame/frame_factory.h>\r
#include <core/frame/frame_transform.h>\r
#include <core/frame/pixel_format.h>\r
+#include <core/monitor/monitor.h>\r
\r
#include <common/env.h>\r
#include <common/log.h>\r
\r
struct image_scroll_producer : public core::frame_producer\r
{ \r
+ monitor::basic_subject event_subject_;\r
+\r
const std::wstring filename_;\r
std::vector<core::draw_frame> frames_;\r
core::video_format_desc format_desc_;\r
frames_[n].transform().image_transform.fill_translation[1] = start_offset_[1];\r
}\r
}\r
+ \r
+ event_subject_ << monitor::event("file/path") % filename_\r
+ << monitor::event("delta") % delta_ \r
+ << monitor::event("speed") % speed_;\r
\r
return last_frame_ = core::draw_frame(frames_);\r
}\r
return result;\r
}\r
}\r
+\r
+ virtual void subscribe(const monitor::observable::observer_ptr& o) override \r
+ {\r
+ return event_subject_.subscribe(o);\r
+ }\r
+\r
+ virtual void unsubscribe(const monitor::observable::observer_ptr& o) override \r
+ {\r
+ return event_subject_.unsubscribe(o);\r
+ }\r
};\r
\r
spl::shared_ptr<core::frame_producer> create_scroll_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params)\r
void operator()(const float value) {o << value;}\r
void operator()(const double value) {o << static_cast<float>(value);}\r
void operator()(const std::string& value) {o << value.c_str();}\r
+ void operator()(const std::wstring& value) {o << u8(value).c_str();}\r
void operator()(const std::vector<int8_t>& value) {o << ::osc::Blob(value.data(), static_cast<unsigned long>(value.size()));}\r
void operator()(const monitor::duration& value)\r
{\r