]> git.sesse.net Git - casparcg/commitdiff
2.0.0.2: Fixed some problems related to late frames.
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Mon, 23 May 2011 22:18:32 +0000 (22:18 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Mon, 23 May 2011 22:18:32 +0000 (22:18 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@806 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

core/producer/destroy_producer_proxy.cpp
core/producer/frame/basic_frame.h
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/producer/audio/audio_decoder.cpp
modules/ffmpeg/producer/input.cpp
modules/ffmpeg/producer/video/video_decoder.cpp
modules/flash/producer/cg_producer.cpp

index f85d378b6eb1ee407f14d3efcd718ccd18b76c7f..ff936a5de4d8b97be4ff40a5fb67b69d91e3d2ac 100644 (file)
@@ -56,7 +56,7 @@ destroy_producer_proxy::~destroy_producer_proxy()
        g_destroyer.destroy(std::move(producer_));\r
 }\r
 \r
-safe_ptr<basic_frame> destroy_producer_proxy::receive(){return producer_->receive();}  \r
+safe_ptr<basic_frame> destroy_producer_proxy::receive(){return core::receive(producer_);}  \r
 std::wstring destroy_producer_proxy::print() const {return producer_->print();}   \r
 \r
 void destroy_producer_proxy::param(const std::wstring& param){producer_->param(param);}  \r
index f9a19ff99f0435019b5a6b8b07cbfc7df218be5e..1ab7546db83bd98db226f606e8dacf7ff76ac82a 100644 (file)
@@ -27,6 +27,8 @@
 \r
 #include <boost/range/iterator_range.hpp>\r
 \r
+#include <vector>\r
+\r
 namespace caspar { namespace core {\r
 \r
 class image_transform;\r
index a206482522f1ef82514eebc697d5bd20bf7b0412..2b94133de354af581844db4369b6830754f3ce53 100644 (file)
@@ -44,6 +44,22 @@ const safe_ptr<frame_producer>& frame_producer::empty() // nothrow
        return producer;\r
 }      \r
 \r
+safe_ptr<basic_frame> frame_producer::receive_w_last()\r
+{\r
+       auto frame = receive();\r
+       if(frame != core::basic_frame::late())\r
+       {\r
+               last_frame_ = make_safe<basic_frame>(frame);\r
+               last_frame_->get_audio_transform().set_has_audio(false);\r
+       }       \r
+       return frame;\r
+}\r
+\r
+safe_ptr<basic_frame> receive(safe_ptr<frame_producer>& producer)\r
+{\r
+       return producer->receive_w_last();\r
+}\r
+\r
 safe_ptr<basic_frame> receive_and_follow(safe_ptr<frame_producer>& producer)\r
 {      \r
        if(producer == frame_producer::empty())\r
@@ -52,7 +68,7 @@ safe_ptr<basic_frame> receive_and_follow(safe_ptr<frame_producer>& producer)
        auto frame = basic_frame::eof();\r
        try\r
        {\r
-               frame = producer->receive();\r
+               frame = receive(producer);\r
        }\r
        catch(...)\r
        {\r
@@ -77,6 +93,14 @@ safe_ptr<basic_frame> receive_and_follow(safe_ptr<frame_producer>& producer)
        return frame;\r
 }\r
 \r
+safe_ptr<basic_frame> receive_and_follow_w_last(safe_ptr<frame_producer>& producer)\r
+{\r
+       auto frame = receive_and_follow(producer);\r
+       if(frame == basic_frame::late())\r
+               frame = producer->last_frame();\r
+       return frame;\r
+}\r
+\r
 void register_producer_factory(const producer_factory_t& factory)\r
 {\r
        g_factories.push_back(factory);\r
index b9cecef9b691777b3686c81fa383ae0a6a225a27..f54477d115ba69a0f9577b1f487053358fd1c2a7 100644 (file)
@@ -19,6 +19,9 @@
 */\r
 #pragma once\r
 \r
+#include "frame/basic_frame.h"\r
+#include "frame/audio_transform.h"\r
+\r
 #include <common/memory/safe_ptr.h>\r
 \r
 #include "frame/frame_factory.h"\r
@@ -36,9 +39,9 @@ class basic_frame;
 class frame_producer : boost::noncopyable\r
 {\r
 public:\r
+       frame_producer() : last_frame_(core::basic_frame::empty()){}\r
        virtual ~frame_producer(){}     \r
 \r
-       virtual safe_ptr<basic_frame> receive() = 0;\r
        virtual std::wstring print() const = 0; // nothrow\r
 \r
        virtual void param(const std::wstring&){}\r
@@ -47,9 +50,21 @@ public:
        virtual void set_leading_producer(const safe_ptr<frame_producer>&) {}  // nothrow\r
                \r
        static const safe_ptr<frame_producer>& empty(); // nothrow\r
+\r
+       safe_ptr<core::basic_frame> last_frame() const {return last_frame_;}\r
+       \r
+private:\r
+       virtual safe_ptr<basic_frame> receive() = 0;\r
+       friend safe_ptr<basic_frame> receive(safe_ptr<frame_producer>& producer);\r
+\r
+       safe_ptr<basic_frame> receive_w_last();\r
+\r
+       safe_ptr<core::basic_frame> last_frame_;\r
 };\r
 \r
+safe_ptr<basic_frame> receive(safe_ptr<frame_producer>& producer);\r
 safe_ptr<basic_frame> receive_and_follow(safe_ptr<frame_producer>& producer);\r
+safe_ptr<basic_frame> receive_and_follow_w_last(safe_ptr<frame_producer>& producer);\r
 \r
 typedef std::function<safe_ptr<core::frame_producer>(const safe_ptr<frame_factory>&, const std::vector<std::wstring>&)> producer_factory_t;\r
 void register_producer_factory(const producer_factory_t& factory); // Not thread-safe.\r
index 066180ffe6a80c90bc54d2a06abadcf9b8f04c9f..18b0362c56163069764b81777deab57e3893ee6a 100644 (file)
@@ -32,13 +32,11 @@ struct layer::implementation
 {                              \r
        safe_ptr<frame_producer>        foreground_;\r
        safe_ptr<frame_producer>        background_;\r
-       safe_ptr<basic_frame>           last_frame_;\r
        bool                                            is_paused_;\r
 public:\r
        implementation() \r
                : foreground_(frame_producer::empty())\r
                , background_(frame_producer::empty())\r
-               , last_frame_(basic_frame::empty())\r
                , is_paused_(false){}\r
        \r
        void pause(){is_paused_ = true;}\r
@@ -71,23 +69,15 @@ public:
        void stop()\r
        {\r
                pause();\r
-               last_frame_ = basic_frame::empty();\r
                foreground_ = frame_producer::empty();\r
        }\r
                \r
        safe_ptr<basic_frame> receive()\r
        {               \r
                if(is_paused_)\r
-                       return last_frame_;\r
-\r
-               auto next_frame = receive_and_follow(foreground_);\r
-               if(next_frame == core::basic_frame::late())\r
-                       return last_frame_;\r
-                               \r
-               last_frame_ = basic_frame(next_frame);\r
-               last_frame_->get_audio_transform().set_has_audio(false);\r
-\r
-               return next_frame;\r
+                       return foreground_->last_frame();\r
+               \r
+               return receive_and_follow_w_last(foreground_);\r
        }\r
 };\r
 \r
index a29d04224877ba685f6e08627793af253e9495be..8b59f2a30e636a039fb97d3cd34fa67cace23e5a 100644 (file)
@@ -37,8 +37,8 @@ struct separated_producer : public frame_producer
        explicit separated_producer(const safe_ptr<frame_producer>& fill, const safe_ptr<frame_producer>& key) \r
                : fill_producer_(fill)\r
                , key_producer_(key)\r
-               , fill_(core::basic_frame::empty())\r
-               , key_(core::basic_frame::empty()){}\r
+               , fill_(core::basic_frame::late())\r
+               , key_(core::basic_frame::late()){}\r
        \r
        // frame_producer\r
        \r
@@ -48,12 +48,12 @@ struct separated_producer : public frame_producer
                (\r
                        [&]\r
                        {\r
-                               if(fill_ == core::basic_frame::empty())\r
+                               if(fill_ == core::basic_frame::late())\r
                                        fill_ = receive_and_follow(fill_producer_);\r
                        },\r
                        [&]\r
                        {\r
-                               if(key_ == core::basic_frame::empty())\r
+                               if(key_ == core::basic_frame::late())\r
                                        key_ = receive_and_follow(key_producer_);\r
                        }\r
                );\r
@@ -66,8 +66,8 @@ struct separated_producer : public frame_producer
                \r
                auto frame = basic_frame::fill_and_key(fill_, key_);\r
 \r
-               fill_ = basic_frame::empty();\r
-               key_ = basic_frame::empty();\r
+               fill_ = basic_frame::late();\r
+               key_ = basic_frame::late();\r
 \r
                return frame;\r
        }\r
index f1a03db4fd0865ff2c9964c3eceda33d7725d7ec..9ac26e471cbb19cbbca85472428d1849db09de50 100644 (file)
@@ -38,17 +38,13 @@ struct transition_producer : public frame_producer
        \r
        safe_ptr<frame_producer>        dest_producer_;\r
        safe_ptr<frame_producer>        source_producer_;\r
-       safe_ptr<basic_frame>           last_dest_;\r
-       safe_ptr<basic_frame>           last_source_;\r
                \r
        explicit transition_producer(const video_mode::type& mode, const safe_ptr<frame_producer>& dest, const transition_info& info) \r
                : mode_(mode)\r
                , current_frame_(0)\r
                , info_(info)\r
                , dest_producer_(dest)\r
-               , source_producer_(frame_producer::empty())\r
-               , last_dest_(core::basic_frame::empty())\r
-               , last_source_(core::basic_frame::empty()){}\r
+               , source_producer_(frame_producer::empty()){}\r
        \r
        // frame_producer\r
 \r
@@ -67,31 +63,23 @@ struct transition_producer : public frame_producer
                if(current_frame_++ >= info_.duration)\r
                        return basic_frame::eof();\r
                \r
+               safe_ptr<core::basic_frame> dest;\r
+               safe_ptr<core::basic_frame> source;\r
+\r
                tbb::parallel_invoke\r
                (\r
-                       [&]{last_dest_   = receive_and_follow_w_last(dest_producer_, last_dest_);},\r
-                       [&]{last_source_ = receive_and_follow_w_last(source_producer_, last_source_);}\r
+                       [&]{dest   = receive_and_follow_w_last(dest_producer_);},\r
+                       [&]{source = receive_and_follow_w_last(source_producer_);}\r
                );\r
 \r
-               return compose(last_dest_, last_source_);\r
+               return compose(dest, source);\r
        }\r
 \r
        virtual std::wstring print() const\r
        {\r
                return L"transition";\r
        }\r
-\r
-       safe_ptr<basic_frame> receive_and_follow_w_last(safe_ptr<frame_producer>& producer, safe_ptr<basic_frame> last_frame)\r
-       {\r
-               auto frame = core::receive_and_follow(producer);\r
-               if(frame == basic_frame::late())\r
-               {\r
-                       last_frame->get_audio_transform().set_has_audio(false);\r
-                       frame = last_frame;\r
-               }\r
-               return frame;\r
-       }\r
-\r
+       \r
        // transition_producer\r
                                                \r
        safe_ptr<basic_frame> compose(const safe_ptr<basic_frame>& dest_frame, const safe_ptr<basic_frame>& src_frame) \r
index e68bdc912f8adf4634e9cedef81d31ace9a77d66..20fb263fc0d2702741798d404b27569398c47ad9 100644 (file)
@@ -68,6 +68,12 @@ public:
        {       \r
                if(!audio_packet)\r
                        return;\r
+               \r
+               if(audio_packet->size == 0)\r
+               {\r
+                       avcodec_flush_buffers(&codec_context_);\r
+                       return;\r
+               }\r
 \r
                auto s = current_chunk_.size();\r
                current_chunk_.resize(s + 4*format_desc_.audio_sample_rate*2+FF_INPUT_BUFFER_PADDING_SIZE/2);\r
index 733f8627a608415399fb4026d65310f139bb7d3d..736e1cd1bd492e5a8419764d5019a882aaffa8d9 100644 (file)
@@ -106,6 +106,16 @@ public:
                buffer_.push(pkt);      \r
        }\r
 \r
+       void flush()\r
+       {\r
+               if(index_ == -1)\r
+                       return;\r
+\r
+               std::shared_ptr<AVPacket> flsh_pkt(new AVPacket);\r
+               flsh_pkt->size = 0;\r
+               buffer_.push(flsh_pkt); \r
+       }\r
+\r
        const std::shared_ptr<AVCodecContext>& ctx() { return ctx_; }\r
 \r
        operator bool(){return ctx_ != nullptr;}\r
@@ -310,6 +320,9 @@ private:
                                boost::errinfo_api_function("av_seek_frame") <<\r
                                boost::errinfo_errno(AVUNERROR(errn)));\r
                }\r
+\r
+               video_stream_.flush();\r
+               audio_stream_.flush();\r
        }               \r
 \r
        bool is_eof(int errn)\r
index bf716ba8f1807cb748a6270267f8a70222ef098d..7abedb6ec52ca80a8aa0b3d7c202da423a5342fb 100644 (file)
@@ -153,6 +153,12 @@ public:
        {                               \r
                if(!video_packet)\r
                        return;\r
+\r
+               if(video_packet->size == 0)\r
+               {\r
+                       avcodec_flush_buffers(&codec_context_);\r
+                       return;\r
+               }\r
        \r
                safe_ptr<AVFrame> decoded_frame(avcodec_alloc_frame(), av_free);\r
 \r
index 6a8adb7cc8796f07bcc69b1cd627ad32f06530cf..325cd7af000db0ad17a676d422d9f0051b21a5e6 100644 (file)
@@ -82,7 +82,7 @@ public:
 \r
        safe_ptr<core::basic_frame> receive()\r
        {\r
-               return flash_producer_->receive();\r
+               return core::receive(flash_producer_);\r
        }\r
                        \r
        std::wstring print() const\r