]> git.sesse.net Git - casparcg/blobdiff - modules/ffmpeg/producer/ffmpeg_producer.cpp
2.1.0: -frame_producer: Refactored last_frame.
[casparcg] / modules / ffmpeg / producer / ffmpeg_producer.cpp
index 4c58d4acdad1c09a40e6a34fa3edc4dc86d0d7cd..919011fc208e9eb5bfb4f9a0a4cec86a188a0e0c 100644 (file)
@@ -33,7 +33,7 @@
 \r
 #include <common/env.h>\r
 #include <common/log.h>\r
-#include <common/utility/param.h>\r
+#include <common/param.h>\r
 #include <common/diagnostics/graph.h>\r
 \r
 #include <core/video_format.h>\r
@@ -41,6 +41,7 @@
 #include <core/frame/frame_factory.h>\r
 #include <core/frame/draw_frame.h>\r
 #include <core/frame/frame_transform.h>\r
+#include <core/monitor/monitor.h>\r
 \r
 #include <boost/algorithm/string.hpp>\r
 #include <common/assert.h>\r
@@ -64,12 +65,12 @@ namespace caspar { namespace ffmpeg {
                                \r
 struct ffmpeg_producer : public core::frame_producer\r
 {\r
+       monitor::basic_subject                                                                          event_subject_;\r
        const std::wstring                                                                                      filename_;\r
        \r
-       const safe_ptr<diagnostics::graph>                                                      graph_;\r
-       boost::timer                                                                                            frame_timer_;\r
+       const spl::shared_ptr<diagnostics::graph>                                       graph_;\r
                                        \r
-       const safe_ptr<core::frame_factory>                                                     frame_factory_;\r
+       const spl::shared_ptr<core::frame_factory>                                      frame_factory_;\r
        const core::video_format_desc                                                           format_desc_;\r
 \r
        input                                                                                                           input_; \r
@@ -80,21 +81,18 @@ struct ffmpeg_producer : public core::frame_producer
        const double                                                                                            fps_;\r
        const uint32_t                                                                                          start_;\r
        const uint32_t                                                                                          length_;\r
-\r
-       safe_ptr<core::draw_frame>                                                                      last_frame_;\r
-       \r
+               \r
        int64_t                                                                                                         frame_number_;\r
        \r
 public:\r
-       explicit ffmpeg_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::wstring& filename, const std::wstring& filter, bool loop, uint32_t start, uint32_t length) \r
+       explicit ffmpeg_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const std::wstring& filename, const std::wstring& filter, bool loop, uint32_t start, uint32_t length) \r
                : filename_(filename)\r
                , frame_factory_(frame_factory)         \r
-               , format_desc_(frame_factory->get_video_format_desc())\r
+               , format_desc_(frame_factory->video_format_desc())\r
                , input_(graph_, filename_, loop, start, length)\r
                , fps_(read_fps(*input_.context(), format_desc_.fps))\r
                , start_(start)\r
                , length_(length)\r
-               , last_frame_(core::draw_frame::empty())\r
                , frame_number_(0)\r
        {\r
                graph_->set_color("frame-time", diagnostics::color(0.1f, 1.0f, 0.1f));\r
@@ -104,6 +102,7 @@ public:
                try\r
                {\r
                        video_decoder_.reset(new video_decoder(input_.context()));\r
+                       video_decoder_->subscribe(event_subject_);\r
                        CASPAR_LOG(info) << print() << L" " << video_decoder_->print();\r
                }\r
                catch(averror_stream_not_found&)\r
@@ -118,7 +117,8 @@ public:
 \r
                try\r
                {\r
-                       audio_decoder_.reset(new audio_decoder(input_.context(), frame_factory->get_video_format_desc()));\r
+                       audio_decoder_.reset(new audio_decoder(input_.context(), frame_factory->video_format_desc()));\r
+                       audio_decoder_->subscribe(event_subject_);\r
                        CASPAR_LOG(info) << print() << L" " << audio_decoder_->print();\r
                }\r
                catch(averror_stream_not_found&)\r
@@ -139,33 +139,37 @@ public:
 \r
        // frame_producer\r
        \r
-       virtual safe_ptr<core::draw_frame> receive(int flags) override\r
+       virtual spl::shared_ptr<core::draw_frame> receive(int flags) override\r
        {               \r
-               frame_timer_.restart();\r
+               boost::timer frame_timer;\r
                                \r
                std::shared_ptr<core::draw_frame> frame = try_decode_frame(flags);\r
                                                        \r
-               graph_->set_value("frame-time", frame_timer_.elapsed()*format_desc_.fps*0.5);\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
                if(!frame)\r
                {\r
-                       if(!input_.eof())                               \r
+                       if(!input_.eof())               \r
                                graph_->set_tag("underflow");   \r
-                       return last_frame();\r
+                       return core::draw_frame::late();\r
                }\r
                                \r
                ++frame_number_;\r
 \r
                graph_->set_text(print());\r
 \r
-               return last_frame_ = make_safe_ptr(frame);\r
+               return spl::make_shared_ptr(frame);\r
        }\r
-\r
-       virtual safe_ptr<core::draw_frame> last_frame() const override\r
-       {\r
-               return core::draw_frame::silence(last_frame_);\r
-       }\r
-\r
+       \r
        virtual uint32_t nb_frames() const override\r
        {\r
                if(input_.loop())\r
@@ -206,10 +210,15 @@ public:
                                                  + boost::lexical_cast<std::wstring>(file_frame_number()) + L"/" + boost::lexical_cast<std::wstring>(file_nb_frames()) + L"]";\r
        }\r
 \r
+       virtual std::wstring name() const override\r
+       {\r
+               return L"ffmpeg";\r
+       }\r
+\r
        boost::property_tree::wptree info() const override\r
        {\r
                boost::property_tree::wptree info;\r
-               info.add(L"type",                               L"ffmpeg-producer");\r
+               info.add(L"type",                               L"ffmpeg");\r
                info.add(L"filename",                   filename_);\r
                info.add(L"width",                              video_decoder_ ? video_decoder_->width() : 0);\r
                info.add(L"height",                             video_decoder_ ? video_decoder_->height() : 0);\r
@@ -223,12 +232,22 @@ public:
                info.add(L"file-nb-frames",             file_nb_frames());\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
        // ffmpeg_producer\r
 \r
        std::wstring print_mode() const\r
        {\r
-               return video_decoder_ ? ffmpeg::print_mode(video_decoder_->width(), video_decoder_->height(), fps_, !video_decoder_->is_progressive()) : L"";\r
+               return video_decoder_ ? ffmpeg::print_mode(video_decoder_->width(), video_decoder_->height(), fps_, !video_decoder_->is_progressive()) : L"n/a";\r
        }\r
                                        \r
        std::wstring do_call(const std::wstring& param)\r
@@ -307,7 +326,7 @@ public:
        }\r
 };\r
 \r
-safe_ptr<core::frame_producer> create_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params)\r
+spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params)\r
 {              \r
        auto filename = probe_stem(env::media_folder() + L"\\" + params.at(0));\r
 \r
@@ -322,9 +341,7 @@ safe_ptr<core::frame_producer> create_producer(const safe_ptr<core::frame_factor
        boost::replace_all(filter_str, L"DEINTERLACE", L"YADIF=0:-1");\r
        boost::replace_all(filter_str, L"DEINTERLACE_BOB", L"YADIF=1:-1");\r
        \r
-       return create_producer_destroy_proxy(\r
-                  create_producer_print_proxy(\r
-                       make_safe<ffmpeg_producer>(frame_factory, filename, filter_str, loop, start, length)));\r
+       return core::wrap_producer(spl::make_shared<ffmpeg_producer>(frame_factory, filename, filter_str, loop, start, length));\r
 }\r
 \r
 }}
\ No newline at end of file