\r
namespace caspar { namespace ffmpeg {\r
\r
-struct ffmpeg_producer : public core::frame_producer_base\r
+struct ffmpeg_producer : public core::frame_producer\r
{\r
monitor::basic_subject event_subject_;\r
const std::wstring filename_;\r
\r
input input_; \r
\r
+ tbb::atomic<bool> paused_;\r
const double fps_;\r
const uint32_t start_;\r
\r
audio_decoder audio_decoder_; \r
frame_muxer muxer_;\r
\r
+ tbb::atomic<uint32_t> frame_number_;\r
+\r
+ core::draw_frame last_frame_;\r
+ \r
public:\r
explicit ffmpeg_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, \r
const core::video_format_desc& format_desc, \r
, fps_(read_fps(*input_.context(), format_desc_.fps))\r
, muxer_(fps_, frame_factory, format_desc_, filter)\r
, start_(start)\r
+ , last_frame_(core::draw_frame::empty())\r
{\r
+ paused_ = false;\r
+ frame_number_ = 0;\r
+\r
graph_->set_color("frame-time", diagnostics::color(0.1f, 1.0f, 0.1f));\r
graph_->set_color("underflow", diagnostics::color(0.6f, 0.3f, 0.9f)); \r
diagnostics::register_graph(graph_);\r
\r
// frame_producer\r
\r
- core::draw_frame receive_impl() override\r
+ core::draw_frame receive() override\r
{ \r
+ if(paused_)\r
+ return last_frame();\r
+\r
boost::timer frame_timer;\r
\r
auto frame = core::draw_frame::late(); \r
event_subject_ << monitor::event("profiler/time") % frame_timer.elapsed() % (1.0/format_desc_.fps); \r
\r
graph_->set_text(print());\r
- \r
+\r
+ if(frame != core::draw_frame::late()) \r
+ ++frame_number_; \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
<< monitor::event("file/path") % filename_\r
<< monitor::event("loop") % input_.loop();\r
\r
- if(frame == core::draw_frame::late() && input_.eof())\r
+ if(frame == core::draw_frame::late())\r
+ return frame;\r
+ else if(input_.eof())\r
return last_frame();\r
+ else\r
+ return last_frame_ = frame;\r
+ }\r
\r
- return frame;\r
+ core::draw_frame last_frame() const override\r
+ {\r
+ return core::draw_frame::still(last_frame_);\r
}\r
- \r
+\r
+ void paused(bool value)\r
+ {\r
+ paused_ = value;\r
+ }\r
+\r
+ uint32_t frame_number() const override\r
+ {\r
+ return frame_number_;\r
+ }\r
+ \r
uint32_t nb_frames() const override\r
{\r
if(input_.loop())\r
info.add(L"progressive", video_decoder_.is_progressive());\r
info.add(L"fps", fps_);\r
info.add(L"loop", input_.loop());\r
- info.add(L"frame-number", frame_number());\r
+ info.add(L"frame-number", frame_number_);\r
auto nb_frames2 = nb_frames();\r
info.add(L"nb-frames", nb_frames2 == std::numeric_limits<int64_t>::max() ? -1 : nb_frames2);\r
info.add(L"file-frame-number", file_frame_number());\r
audio_decoder_.clear();\r
\r
input_.seek(target);\r
- \r
- receive_impl();\r
- receive_impl();\r
- receive_impl();\r
- receive_impl();\r
+ \r
+ auto frame = core::draw_frame::late(); \r
+ \r
+ try_decode_frame(frame);\r
+ try_decode_frame(frame);\r
+ try_decode_frame(frame);\r
+ try_decode_frame(frame);\r
+ try_decode_frame(frame);\r
+\r
+ if(frame != core::draw_frame::late())\r
+ last_frame_ = frame;\r
}\r
\r
std::wstring print_mode() const\r