\r
boost::timer frame_timer_;\r
boost::timer tick_timer_;\r
- \r
+\r
+ high_prec_timer timer_;\r
public:\r
flash_renderer(const safe_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
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("buffered", diagnostics::color(0.8f, 0.3f, 0.2f));\r
\r
lock(get_global_init_destruct_mutex(), [this]\r
{\r
BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Failed to Set Scale Mode"));\r
\r
ax_->SetSize(width_, height_); \r
- render_frame();\r
+ render_frame(0.0);\r
\r
CASPAR_LOG(info) << print() << L" Initialized.";\r
}\r
return result;\r
}\r
\r
- safe_ptr<core::basic_frame> render_frame()\r
+ safe_ptr<core::basic_frame> render_frame(double sync)\r
{\r
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 (!ax_->IsReadyToRender())\r
return head_;\r
\r
if(ax_->IsEmpty())\r
return core::basic_frame::empty();\r
+\r
+ if (sync > 0.00001)\r
+ timer_.tick(frame_time*sync); // This will block the thread.\r
\r
+ graph_->set_value("tick-time", static_cast<float>(tick_timer_.elapsed()/frame_time)*0.5f);\r
+ tick_timer_.restart();\r
+\r
frame_timer_.restart();\r
\r
ax_->Tick();\r
fps_ = 0;\r
\r
graph_->set_color("late-frame", diagnostics::color(0.6f, 0.3f, 0.9f));\r
+ graph_->set_color("buffered", diagnostics::color(0.8f, 0.3f, 0.2f));\r
graph_->set_text(print());\r
diagnostics::register_graph(graph_);\r
\r
}\r
\r
// frame_producer\r
+\r
+ void log_buffered()\r
+ {\r
+ double buffered = output_buffer_.size();\r
+ auto ratio = buffered / buffer_size_;\r
+ graph_->set_value("buffered", ratio);\r
+ }\r
\r
virtual safe_ptr<core::basic_frame> receive(int) override\r
{ \r
auto frame = core::basic_frame::late();\r
- \r
- double buffered = output_buffer_.size();\r
- auto ratio = buffered / buffer_size_;\r
- graph_->set_value("buffered", ratio);\r
\r
if(output_buffer_.try_pop(frame))\r
last_frame_ = frame;\r
\r
if (initialize_renderer)\r
{\r
- do_fill_buffer();\r
+ do_fill_buffer(true);\r
}\r
\r
return result;\r
{\r
executor_.begin_invoke([this]\r
{\r
- do_fill_buffer();\r
+ do_fill_buffer(false);\r
});\r
}\r
\r
- void do_fill_buffer()\r
+ void do_fill_buffer(bool initial_buffer_fill)\r
{\r
int nothing_rendered = 0;\r
const int MAX_NOTHING_RENDERED_RETRIES = 4;\r
\r
auto to_render = buffer_size_ - output_buffer_.size();\r
+ bool allow_faster_rendering = !initial_buffer_fill;\r
int rendered = 0;\r
\r
while (rendered < to_render)\r
{\r
- bool was_rendered = next();\r
+ bool was_rendered = next(allow_faster_rendering);\r
+ log_buffered();\r
\r
if (was_rendered)\r
{\r
}\r
}\r
\r
- bool next()\r
+ bool next(bool allow_faster_rendering)\r
{ \r
if(!renderer_)\r
frame_buffer_.push(core::basic_frame::empty());\r
\r
if(abs(renderer_->fps()/2.0 - format_desc.fps) < 2.0) // flash == 2 * format -> interlace\r
{\r
- auto frame1 = render_frame();\r
+ auto frame1 = render_frame(allow_faster_rendering);\r
\r
if (frame1 != core::basic_frame::late())\r
{\r
- auto frame2 = render_frame();\r
+ auto frame2 = render_frame(allow_faster_rendering);\r
frame_buffer_.push(core::basic_frame::interlace(frame1, frame2, format_desc.field_mode));\r
}\r
}\r
else if(abs(renderer_->fps() - format_desc.fps/2.0) < 2.0) // format == 2 * flash -> duplicate\r
{\r
- auto frame = render_frame();\r
+ auto frame = render_frame(allow_faster_rendering);\r
\r
if (frame != core::basic_frame::late())\r
{\r
}\r
else //if(abs(renderer_->fps() - format_desc_.fps) < 0.1) // format == flash -> simple\r
{\r
- auto frame = render_frame();\r
+ auto frame = render_frame(allow_faster_rendering);\r
\r
if (frame != core::basic_frame::late())\r
frame_buffer_.push(frame);\r
}\r
}\r
\r
- safe_ptr<core::basic_frame> render_frame()\r
- { \r
- return renderer_->render_frame();\r
+ safe_ptr<core::basic_frame> render_frame(bool allow_faster_rendering)\r
+ {\r
+ double sync;\r
+\r
+ if (allow_faster_rendering)\r
+ {\r
+ double ratio = std::min(\r
+ 1.0,\r
+ static_cast<double>(output_buffer_.size())\r
+ / static_cast<double>(std::max(1, buffer_size_ - 1)));\r
+ sync = 2 * ratio - ratio * ratio;\r
+ }\r
+ else\r
+ {\r
+ sync = 1.0;\r
+ }\r
+\r
+ return renderer_->render_frame(sync);\r
}\r
\r
core::monitor::subject& monitor_output()\r