]> git.sesse.net Git - casparcg/commitdiff
2.1.0: SEEK doesn't block rendering thread and is more accurate.
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Mon, 26 Mar 2012 22:57:57 +0000 (22:57 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Mon, 26 Mar 2012 22:57:57 +0000 (22:57 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.1.0@2761 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

core/producer/frame_producer.cpp
core/producer/frame_producer.h
core/producer/layer.cpp
core/producer/separated/separated_producer.cpp
core/producer/transition/transition_producer.cpp
modules/ffmpeg/consumer/ffmpeg_consumer.cpp
modules/ffmpeg/producer/ffmpeg_producer.cpp
modules/ffmpeg/producer/input/input.cpp

index 6ac4bce3244d3f5c5d1e65e8d9f26d750a1ba03c..75f5678ae73af483ea75e4db4e0d22b66e1e3726 100644 (file)
@@ -80,7 +80,7 @@ struct frame_producer_base::impl
                paused_ = value;\r
        }\r
 \r
-       draw_frame last_frame() const\r
+       draw_frame last_frame()\r
        {\r
                return draw_frame::still(last_frame_);\r
        }\r
@@ -104,7 +104,7 @@ void frame_producer_base::paused(bool value)
        impl_->paused(value);\r
 }\r
 \r
-draw_frame frame_producer_base::last_frame() const\r
+draw_frame frame_producer_base::last_frame()\r
 {\r
        return impl_->last_frame();\r
 }\r
@@ -139,7 +139,7 @@ const spl::shared_ptr<frame_producer>& frame_producer::empty()
                std::wstring name() const override {return L"empty";}\r
                uint32_t frame_number() const override {return 0;}\r
                boost::unique_future<std::wstring> call(const std::wstring& params) override{CASPAR_THROW_EXCEPTION(not_supported());}\r
-               draw_frame last_frame() const {return draw_frame::empty();}\r
+               draw_frame last_frame() {return draw_frame::empty();}\r
        \r
                boost::property_tree::wptree info() const override\r
                {\r
@@ -209,7 +209,7 @@ public:
        boost::unique_future<std::wstring>                                      call(const std::wstring& str) override                                                                                  {return producer_->call(str);}\r
        void                                                                                            leading_producer(const spl::shared_ptr<frame_producer>& producer) override              {return producer_->leading_producer(producer);}\r
        uint32_t                                                                                        nb_frames() const override                                                                                                              {return producer_->nb_frames();}\r
-       class draw_frame                                                                        last_frame() const                                                                                                                              {return producer_->last_frame();}\r
+       class draw_frame                                                                        last_frame()                                                                                                                            {return producer_->last_frame();}\r
        void                                                                                            subscribe(const monitor::observable::observer_ptr& o)                                                   {return producer_->subscribe(o);}\r
        void                                                                                            unsubscribe(const monitor::observable::observer_ptr& o)                                                 {return producer_->unsubscribe(o);}\r
 };\r
index a18ae586a10e5976e1e90f1f0cc5ea10090fd507..587ca1e67b649fe3705067d2bd8a4c31ab84e046 100644 (file)
@@ -77,7 +77,7 @@ public:
        virtual boost::property_tree::wptree            info() const = 0;\r
        virtual uint32_t                                                        nb_frames() const = 0;\r
        virtual uint32_t                                                        frame_number() const = 0;\r
-       virtual class draw_frame                                        last_frame() const = 0;\r
+       virtual class draw_frame                                        last_frame() = 0;\r
        virtual void                                                            leading_producer(const spl::shared_ptr<frame_producer>&) {}  \r
 };\r
 \r
@@ -99,7 +99,7 @@ public:
        void                                            paused(bool value) override;    \r
        uint32_t                                        nb_frames() const override;\r
        uint32_t                                        frame_number() const override;\r
-       virtual class draw_frame        last_frame() const override;\r
+       virtual class draw_frame        last_frame() override;\r
 \r
 private:\r
        virtual class draw_frame        receive() override;\r
index 7aebe0cf4354fb919236cf945aae170d1fc631a9..40defdbc3e9f6a3171c9242aae1fb289b217d197 100644 (file)
@@ -71,7 +71,6 @@ public:
                if(preview)\r
                {\r
                        play();\r
-                       foreground_->receive();\r
                        foreground_->paused(true);\r
                }\r
 \r
index 8c2b263bd72f285018f4fee4493abba7f0905fe6..b18e8a7065705cfda5cfc109efae809ef98118ce 100644 (file)
@@ -84,7 +84,7 @@ public:
                return frame;\r
        }\r
 \r
-       draw_frame last_frame() const\r
+       draw_frame last_frame()\r
        {\r
                return draw_frame::mask(fill_producer_->last_frame(), key_producer_->last_frame());\r
        }\r
index 9426356fb3951a9d018cf60468f7101b205de41a..69b91975681e21b635a5f83226d9f020bbfff6aa 100644 (file)
@@ -110,7 +110,7 @@ public:
                return compose(dest, source);\r
        }\r
 \r
-       draw_frame last_frame() const override\r
+       draw_frame last_frame() override\r
        {\r
                if(current_frame_ >= info_.duration)\r
                        return dest_producer_->last_frame();\r
index fef5f70847d3deadb037c1a7c9bc103572a576e6..c174bd3be055763262cebe5eb72f6fb4e442cff9 100644 (file)
@@ -268,6 +268,8 @@ public:
                , output_format_(format_desc, filename, options)\r
                , executor_(print())\r
        {\r
+               check_space();\r
+\r
                // TODO: Ask stakeholders about case where file already exists.\r
                boost::filesystem::remove(boost::filesystem::path(env::media_folder() + u16(filename))); // Delete the file if it exists\r
 \r
@@ -617,16 +619,19 @@ public:
                return buffer;\r
        }\r
 \r
+       void check_space()\r
+       {\r
+               auto space = boost::filesystem::space(boost::filesystem::path(filename_).parent_path());\r
+               if(space.available < 512*1000000)\r
+                       BOOST_THROW_EXCEPTION(file_write_error() << msg_info("out of space"));\r
+       }\r
+\r
        void encode(const core::const_frame& frame)\r
        {\r
                try\r
                {\r
                        if(frame_number_ % 25 == 0)\r
-                       {\r
-                               auto space = boost::filesystem::space(boost::filesystem::path(filename_).parent_path());\r
-                               if(space.available < 512*1000000)\r
-                                       BOOST_THROW_EXCEPTION(file_write_error() << msg_info("out of space"));\r
-                       }\r
+                               check_space();\r
 \r
                        boost::timer frame_timer;\r
 \r
index 1ce19128921c887c4a4141a9ebc3bf6e364963f0..d014907b7456707011f2d6a1b799652b6c5a0b82 100644 (file)
@@ -87,6 +87,8 @@ struct ffmpeg_producer : public core::frame_producer
        tbb::atomic<uint32_t>                                                   frame_number_;\r
 \r
        core::draw_frame                                                                last_frame_;\r
+\r
+       boost::optional<uint32_t>                                               seek_target_;\r
        \r
 public:\r
        explicit ffmpeg_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, \r
@@ -157,6 +159,8 @@ public:
                auto frame = core::draw_frame::late();          \r
                \r
                boost::timer frame_timer;\r
+               \r
+               end_seek();\r
 \r
                if(paused_)\r
                        frame = last_frame();   \r
@@ -189,8 +193,10 @@ public:
                return frame;\r
        }\r
 \r
-       core::draw_frame last_frame() const override\r
+       core::draw_frame last_frame() override\r
        {\r
+               end_seek();\r
+\r
                return core::draw_frame::still(last_frame_);\r
        }\r
 \r
@@ -314,6 +320,20 @@ public:
 \r
        // ffmpeg_producer\r
        \r
+       void end_seek()\r
+       {\r
+               for(int n = 0; n < 16 && (last_frame_ == core::draw_frame::empty() || (seek_target_ && file_frame_number() != *seek_target_)); ++n)\r
+               {\r
+                       decode_next_frame();\r
+                       if(!muxer_.empty())\r
+                       {\r
+                               last_frame_ = std::move(muxer_.front());\r
+                               muxer_.pop();\r
+                               seek_target_.reset();\r
+                       }\r
+               }\r
+       }\r
+\r
        void loop(bool value)\r
        {\r
                input_.loop(value);\r
@@ -345,28 +365,11 @@ public:
        }\r
 \r
        void seek(uint32_t target)\r
-       {\r
-               muxer_.clear();\r
-               \r
-               // TODO: Fix HACK.\r
-               \r
-               target = std::min(target, file_nb_frames());\r
-               target = std::max<uint32_t>(target, 2) - 2;\r
+       {               \r
+               seek_target_ = std::min(target, file_nb_frames());\r
 \r
-               input_.seek(target);\r
+               input_.seek(*seek_target_);\r
                muxer_.clear();\r
-               \r
-               // BEGIN HACK: There is no way to flush yadif. Need to poll 2 frames.\r
-               for(int n = 0; n < 25 && file_frame_number() != target+2; ++n)\r
-               {\r
-                       decode_next_frame();\r
-                       if(!muxer_.empty())\r
-                       {\r
-                               last_frame_ = std::move(muxer_.front());\r
-                               muxer_.pop();\r
-                       }\r
-               }\r
-               // END HACK             \r
        }\r
 \r
        std::wstring print_mode() const\r
index 41e0d1087ef4aa1e4101c26e96e729b1a38dd02f..b9c4b6c41d7a68492a851ffec474426cac35ddfb 100644 (file)
@@ -95,7 +95,7 @@ public:
                std::shared_ptr<AVPacket> packet;\r
                while(packets_.try_pop(packet));\r
        }\r
-\r
+               \r
        size_type size() const\r
        {\r
                return index_ != -1 ? packets_.size() : std::numeric_limits<size_type>::max();\r
@@ -113,14 +113,13 @@ struct input::impl : boost::noncopyable
        tbb::atomic<uint32_t>                                                                           start_;         \r
        tbb::atomic<uint32_t>                                                                           length_;\r
        tbb::atomic<bool>                                                                                       loop_;\r
-       tbb::atomic<bool>                                                                                       eof_;\r
        double                                                                                                          fps_;\r
        uint32_t                                                                                                        frame_number_;\r
        \r
        stream                                                                                                          video_stream_;\r
        stream                                                                                                          audio_stream_;\r
 \r
-       tbb::atomic<uint32_t>                                                                           seek_target_;\r
+       boost::optional<uint32_t>                                                                       seek_target_;\r
 \r
        tbb::atomic<bool>                                                                                       is_running_;\r
        boost::mutex                                                                                            mutex_;\r
@@ -140,13 +139,11 @@ struct input::impl : boost::noncopyable
                start_                  = start;\r
                length_                 = length;\r
                loop_                   = loop;\r
-               eof_                    = false;\r
-               seek_target_    = start_ != 0 ? start_ : std::numeric_limits<uint32_t>::max();\r
                is_running_             = true;\r
 \r
-               while(!full())\r
-                       tick();\r
-                                                                                               \r
+               if(start_ != 0)\r
+                       seek_target_ = start_;\r
+                                                                                                               \r
                graph_->set_color("seek", diagnostics::color(1.0f, 0.5f, 0.0f));        \r
                graph_->set_color("audio-buffer", diagnostics::color(0.7f, 0.4f, 0.4f));\r
                graph_->set_color("video-buffer", diagnostics::color(1.0f, 1.0f, 0.0f));        \r
@@ -191,12 +188,8 @@ struct input::impl : boost::noncopyable
                        seek_target_ = target;\r
                        video_stream_.clear();\r
                        audio_stream_.clear();\r
-                       eof_ = false;\r
                }\r
-\r
-               while(!full())\r
-                       tick();\r
-\r
+               \r
                cond_.notify_one();\r
        }\r
                \r
@@ -240,9 +233,11 @@ private:
 \r
        void tick()\r
        {\r
-               auto target = seek_target_.fetch_and_store(std::numeric_limits<uint32_t>::max());\r
-               if(target != std::numeric_limits<uint32_t>::max())                              \r
-                       internal_seek(target);\r
+               if(seek_target_)                                \r
+               {\r
+                       internal_seek(*seek_target_);\r
+                       seek_target_.reset();\r
+               }\r
 \r
                auto packet = create_packet();\r
                \r
@@ -261,8 +256,6 @@ private:
                                internal_seek(start_);\r
                                graph_->set_tag("seek");                \r
                        }\r
-                       else\r
-                               eof_ = true;\r
                }\r
                else\r
                {               \r
@@ -311,7 +304,7 @@ private:
                                {\r
                                        boost::unique_lock<boost::mutex> lock(mutex_);\r
 \r
-                                       while((full() || eof_) && is_running_)\r
+                                       while(full() && !seek_target_ && is_running_)\r
                                                cond_.wait(lock);\r
                                        \r
                                        tick();\r