#include <boost/range/algorithm_ext/erase.hpp>\r
#include <boost/range/algorithm.hpp>\r
#include <boost/circular_buffer.hpp>\r
+#include <boost/timer.hpp>\r
\r
namespace caspar { namespace core {\r
\r
\r
std::map<int, std::shared_ptr<frame_consumer>> consumers_; // Valid iterators after erase\r
\r
+ safe_ptr<diagnostics::graph> diag_;\r
+\r
video_format_desc format_desc_;\r
+\r
+ boost::timer frame_timer_;\r
+ boost::timer tick_timer_;\r
\r
executor executor_; \r
public:\r
implementation( const video_format_desc& format_desc) \r
: format_desc_(format_desc)\r
- , executor_(L"frame_consumer_device")\r
+ , diag_(diagnostics::create_graph(std::string("frame_consumer_device")))\r
+ , executor_(L"frame_consumer_device", true)\r
{ \r
+ diag_->set_color("input-buffer", diagnostics::color(1.0f, 1.0f, 0.0f)); \r
+ diag_->add_guide("frame-time", 0.5f); \r
+ diag_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
+ diag_->set_color("tick-time", diagnostics::color(0.1f, 0.7f, 0.8f));\r
+\r
executor_.set_capacity(1);\r
- executor_.start();\r
+ executor_.begin_invoke([]\r
+ {\r
+ SetThreadPriority(GetCurrentThread(), ABOVE_NORMAL_PRIORITY_CLASS);\r
+ });\r
}\r
\r
void add(int index, safe_ptr<frame_consumer>&& consumer)\r
void send(const safe_ptr<const read_frame>& frame)\r
{ \r
executor_.begin_invoke([=]\r
- { \r
+ {\r
+ diag_->set_value("input-buffer", static_cast<float>(executor_.size())/static_cast<float>(executor_.capacity()));\r
+ frame_timer_.restart();\r
+\r
buffer_.push_back(std::move(frame));\r
\r
if(!buffer_.full())\r
CASPAR_LOG(error) << print() << L" " << it->second->print() << L" Removed.";\r
}\r
}\r
+ diag_->update_value("frame-time", static_cast<float>(frame_timer_.elapsed()/format_desc_.interval*0.5));\r
+ \r
+ diag_->update_value("tick-time", static_cast<float>(tick_timer_.elapsed()/format_desc_.interval*0.5));\r
+ tick_timer_.restart();\r
});\r
+ diag_->set_value("input-buffer", static_cast<float>(executor_.size())/static_cast<float>(executor_.capacity()));\r
}\r
\r
std::wstring print() const\r
const core::video_format_desc format_desc_;\r
\r
safe_ptr<diagnostics::graph> diag_;\r
- boost::timer perf_timer_;\r
- boost::timer wait_perf_timer_;\r
+ boost::timer frame_timer_;\r
+ boost::timer tick_timer_;\r
\r
audio_mixer audio_mixer_;\r
image_mixer image_mixer_;\r
: format_desc_(format_desc)\r
, diag_(diagnostics::create_graph(narrow(print())))\r
, image_mixer_(format_desc)\r
- , executor_(L"frame_mixer_device")\r
+ , executor_(L"frame_mixer_device", true)\r
{\r
diag_->add_guide("frame-time", 0.5f); \r
diag_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
diag_->set_color("tick-time", diagnostics::color(0.1f, 0.7f, 0.8f));\r
diag_->set_color("input-buffer", diagnostics::color(1.0f, 1.0f, 0.0f)); \r
executor_.set_capacity(1); \r
- executor_.start();\r
+ executor_.begin_invoke([]\r
+ {\r
+ SetThreadPriority(GetCurrentThread(), ABOVE_NORMAL_PRIORITY_CLASS);\r
+ });\r
+\r
CASPAR_LOG(info) << print() << L" Successfully initialized."; \r
}\r
\r
void send(const std::map<int, safe_ptr<core::basic_frame>>& frames)\r
{ \r
executor_.begin_invoke([=]\r
- { \r
- perf_timer_.restart();\r
+ { \r
+ diag_->set_value("input-buffer", static_cast<float>(executor_.size())/static_cast<float>(executor_.capacity())); \r
+ frame_timer_.restart();\r
\r
auto image_future = mix_image(frames);\r
auto audio = mix_audio(frames);\r
auto image = image_future.get();\r
\r
- diag_->update_value("frame-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
+ diag_->update_value("frame-time", static_cast<float>(frame_timer_.elapsed()/format_desc_.interval*0.5));\r
\r
output_(make_safe<const gpu_read_frame>(std::move(image), std::move(audio)));\r
\r
- diag_->update_value("tick-time", static_cast<float>(wait_perf_timer_.elapsed()/format_desc_.interval*0.5));\r
- wait_perf_timer_.restart();\r
-\r
- diag_->set_value("input-buffer", static_cast<float>(executor_.size())/static_cast<float>(executor_.capacity()));\r
+ diag_->update_value("tick-time", static_cast<float>(tick_timer_.elapsed()/format_desc_.interval*0.5));\r
+ tick_timer_.restart();\r
});\r
diag_->set_value("input-buffer", static_cast<float>(executor_.size())/static_cast<float>(executor_.capacity()));\r
}\r
#include <core/producer/frame/basic_frame.h>\r
#include <core/producer/frame/frame_factory.h>\r
\r
+#include <common/diagnostics/graph.h>\r
+\r
#include "layer.h"\r
\r
#include <common/concurrency/executor.h>\r
\r
#include <boost/range/algorithm_ext/erase.hpp>\r
#include <boost/lexical_cast.hpp>\r
+#include <boost/timer.hpp>\r
\r
#include <tbb/parallel_for.h>\r
#include <tbb/mutex.h>\r
std::map<int, layer> layers_; \r
\r
const video_format_desc format_desc_;\r
+ \r
+ safe_ptr<diagnostics::graph> diag_;\r
\r
output_t output_;\r
+\r
+ boost::timer frame_timer_;\r
+ boost::timer tick_timer_;\r
+ boost::timer output_timer_;\r
\r
mutable executor executor_;\r
public:\r
implementation(const video_format_desc& format_desc) \r
: format_desc_(format_desc)\r
- , executor_(L"frame_producer_device")\r
+ , diag_(diagnostics::create_graph(std::string("frame_producer_device")))\r
+ , executor_(L"frame_producer_device", true)\r
{\r
- executor_.start();\r
+ diag_->add_guide("frame-time", 0.5f); \r
+ diag_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
+ diag_->set_color("tick-time", diagnostics::color(0.1f, 0.7f, 0.8f));\r
+ diag_->set_color("output-time", diagnostics::color(0.5f, 1.0f, 0.2f));\r
+ executor_.begin_invoke([]\r
+ {\r
+ SetThreadPriority(GetCurrentThread(), ABOVE_NORMAL_PRIORITY_CLASS);\r
+ });\r
}\r
\r
boost::signals2::connection connect(const output_t::slot_type& subscriber)\r
{ \r
if(output_.empty())\r
return; \r
-\r
+ \r
+ output_timer_.restart();\r
output_(draw());\r
+ diag_->update_value("output-time", static_cast<float>(output_timer_.elapsed()/format_desc_.interval*0.5));\r
+\r
executor_.begin_invoke([=]{tick();});\r
}\r
\r
std::map<int, safe_ptr<basic_frame>> draw()\r
{ \r
+ frame_timer_.restart();\r
+\r
tbb::combinable<std::map<int, safe_ptr<basic_frame>>> frames;\r
\r
tbb::parallel_for_each(layers_.begin(), layers_.end(), [&](decltype(*layers_.begin())& pair)\r
result.insert(map.begin(), map.end());\r
});\r
\r
+ diag_->update_value("frame-time", static_cast<float>(frame_timer_.elapsed()/format_desc_.interval*0.5));\r
+ \r
+ diag_->update_value("tick-time", static_cast<float>(tick_timer_.elapsed()/format_desc_.interval*0.5));\r
+ tick_timer_.restart();\r
+\r
return result;\r
}\r
\r
const unsigned int device_index_;\r
\r
std::shared_ptr<diagnostics::graph> graph_;\r
- boost::timer perf_timer_;\r
+ boost::timer frame_timer_;\r
+ boost::timer tick_timer_;\r
+ boost::timer sync_timer_;\r
\r
boost::unique_future<void> active_;\r
\r
graph_ = diagnostics::create_graph(narrow(print()));\r
graph_->add_guide("tick-time", 0.5);\r
graph_->set_color("tick-time", diagnostics::color(0.1f, 0.7f, 0.8f));\r
+ graph_->add_guide("frame-time", 0.5f); \r
+ graph_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
+ graph_->add_guide("frame-time", 0.5f); \r
+ graph_->set_color("sync-time", diagnostics::color(0.5f, 1.0f, 0.2f));\r
\r
//void* pBlueDevice = blue_attach_to_device(1);\r
//EBlueConnectorPropertySetting video_routing[1];\r
{\r
try\r
{\r
+ frame_timer_.restart();\r
+\r
const size_t audio_samples = static_cast<size_t>(48000.0 / format_desc_.fps);\r
const size_t audio_nchannels = 2;\r
\r
fast_memcpy(reserved_frames_.front()->image_data(), frame->image_data().begin(), frame->image_data().size());\r
\r
+ sync_timer_.restart();\r
+ unsigned long n_field = 0;\r
+ blue_->wait_output_video_synch(UPD_FMT_FRAME, n_field);\r
+ graph_->update_value("sync-time", static_cast<float>(sync_timer_.elapsed()/format_desc_.interval*0.5));\r
+\r
if(embedded_audio_)\r
{ \r
auto frame_audio_data = frame->audio_data().empty() ? silence.data() : const_cast<short*>(frame->audio_data().begin());\r
CASPAR_LOG(warning) << print() << TEXT(" render_buffer_update failed.");\r
}\r
\r
- unsigned long n_field = 0;\r
- blue_->wait_output_video_synch(UPD_FMT_FRAME, n_field);\r
-\r
std::rotate(reserved_frames_.begin(), reserved_frames_.begin() + 1, reserved_frames_.end());\r
- graph_->update_value("tick-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5));\r
- perf_timer_.restart();\r
+ \r
+ graph_->update_value("frame-time", static_cast<float>(frame_timer_.elapsed()/format_desc_.interval*0.5));\r
+\r
+ graph_->update_value("tick-time", static_cast<float>(tick_timer_.elapsed()/format_desc_.interval*0.5));\r
+ tick_timer_.restart();\r
}\r
catch(...)\r
{\r
</bluefish>\r
</consumers>\r
</channel>\r
- <channel>\r
- <videomode>PAL</videomode>\r
- <consumers>\r
- <ogl>\r
- <device>0</device>\r
- <stretch>uniform</stretch>\r
- <windowed>true</windowed>\r
- </ogl>\r
- <audio/>\r
- </consumers>\r
- </channel>\r
</channels>\r
<controllers>\r
<tcp>\r
#endif\r
\r
// Increase process priotity.\r
- SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS);\r
+ SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);\r
\r
// Install structured exception handler.\r
caspar::win32_exception::install_handler();\r