]> git.sesse.net Git - casparcg/commitdiff
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches...
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Thu, 27 Oct 2011 20:02:23 +0000 (20:02 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Thu, 27 Oct 2011 20:02:23 +0000 (20:02 +0000)
modules/ffmpeg/producer/audio/audio_decoder.cpp
modules/ffmpeg/producer/frame_muxer.cpp
modules/ffmpeg/producer/input.cpp
modules/ffmpeg/producer/util.cpp
modules/ffmpeg/producer/util.h
modules/ffmpeg/producer/video/video_decoder.cpp

index fbfeb313194277bdf134986588bd00d703a52dd0..ec3bea9e8d34a3979d55bd7c189e4e91f2dec441 100644 (file)
@@ -96,10 +96,10 @@ public:
                                auto ticket = governor_.acquire();\r
                                auto packet = receive(source_);\r
                        \r
-                               if(packet == loop_packet(index_))\r
+                               if(packet == flush_packet(index_))\r
                                {\r
                                        avcodec_flush_buffers(codec_context_.get());\r
-                                       send(target_, loop_audio());\r
+                                       send(target_, flush_audio());\r
                                        continue;\r
                                }\r
 \r
index d9d99170e9179a16633ec40556d07e8e58612e54..3b4c45043b47949437f4886fa1e8b4a5cbcdfd30 100644 (file)
@@ -59,7 +59,6 @@ struct frame_muxer2::implementation : public Concurrency::agent, boost::noncopya
        std::wstring                                                                            filter_str_;\r
 \r
        governor                                                                                        governor_;\r
-       tbb::atomic<bool>                                                                       is_running_;\r
        \r
        implementation(frame_muxer2::video_source_t* video_source,\r
                                   frame_muxer2::audio_source_t* audio_source,\r
@@ -76,7 +75,6 @@ struct frame_muxer2::implementation : public Concurrency::agent, boost::noncopya
                , frame_factory_(frame_factory)\r
                , governor_(2)\r
        {               \r
-               is_running_ = true;\r
                start();\r
        }\r
 \r
@@ -96,40 +94,42 @@ struct frame_muxer2::implementation : public Concurrency::agent, boost::noncopya
                \r
                video = receive(video_source_);\r
                \r
-               if(video == loop_video())\r
+               if(video == flush_video())\r
+               {\r
+                       if(filter_.has_value())\r
+                               filter_.value()->push(nullptr);\r
                        return receive_video();\r
+               }\r
 \r
                if(video == eof_video())\r
-               {\r
-                       is_running_ = false;\r
-                       return nullptr;\r
-               }\r
+                       return nullptr;         \r
 \r
                if(!display_mode_.has_value())\r
                        initialize_display_mode(*video);\r
                        \r
-               filter_.value()->push(std::move(video));\r
+               filter_.value()->push(video);\r
+               video.reset();\r
 \r
                return receive_video();\r
        }\r
        \r
-       std::shared_ptr<core::audio_buffer> receive_audio()\r
+       std::shared_ptr<core::audio_buffer> receive_audio(size_t n_samples)\r
        {               \r
                if(!audio_source_)\r
-                       return make_safe<core::audio_buffer>(format_desc_.audio_samples_per_frame, 0);\r
+                       return make_safe<core::audio_buffer>(n_samples, 0);\r
                                        \r
-               if(audio_data_.size() >= format_desc_.audio_samples_per_frame)\r
+               if(audio_data_.size() >= n_samples)\r
                {\r
                        auto begin = audio_data_.begin(); \r
-                       auto end   = begin + format_desc_.audio_samples_per_frame;\r
+                       auto end   = begin + n_samples;\r
                        auto audio = make_safe<core::audio_buffer>(begin, end);\r
                        audio_data_.erase(begin, end);\r
                        return audio;\r
                }\r
                                \r
-               auto audio = receive(audio_source_);\r
+               std::shared_ptr<core::audio_buffer> audio = receive(audio_source_);\r
 \r
-               if(audio == loop_audio())\r
+               if(audio == flush_audio())\r
                {\r
                        if(!audio_data_.empty())\r
                        {\r
@@ -139,14 +139,12 @@ struct frame_muxer2::implementation : public Concurrency::agent, boost::noncopya
                }\r
 \r
                if(audio == eof_audio())\r
-               {\r
-                       is_running_ = false;\r
                        return nullptr;\r
-               }\r
 \r
                audio_data_.insert(audio_data_.end(), audio->begin(), audio->end());    \r
-\r
-               return receive_audio();\r
+               audio.reset();\r
+               \r
+               return receive_audio(n_samples);\r
        }\r
                        \r
        virtual void run()\r
@@ -154,68 +152,10 @@ struct frame_muxer2::implementation : public Concurrency::agent, boost::noncopya
                try\r
                {\r
                        win32_exception::install_handler();\r
-                       while(is_running_)\r
+                       while(display())\r
                        {       \r
-                               auto ticket = governor_.acquire();\r
-\r
-                               auto video = receive_video();\r
-                               if(!video)\r
-                                       break;\r
-\r
-                               auto audio = receive_audio();\r
-\r
-                               if(!audio)\r
-                                       break;\r
-\r
-                               video->audio_data() = std::move(*audio);\r
+                       }\r
                                \r
-                               switch(display_mode_.value())\r
-                               {\r
-                               case display_mode::simple:                      \r
-                               case display_mode::deinterlace:\r
-                               case display_mode::deinterlace_bob:\r
-                                       {\r
-                                               send(target_, frame_muxer2::target_element_t(video, ticket));\r
-\r
-                                               break;\r
-                                       }\r
-                               case display_mode::duplicate:                                   \r
-                                       {                       \r
-                                               auto video2 = make_safe<core::write_frame>(*video);     \r
-                                               auto audio2 = receive_audio();\r
-                                               \r
-                                               send(target_, frame_muxer2::target_element_t(video, ticket));\r
-                                               if(audio2)\r
-                                               {\r
-                                                       video2->audio_data() = std::move(*receive_audio());                                     \r
-                                                       send(target_, frame_muxer2::target_element_t(video2, ticket));\r
-                                               }\r
-\r
-                                               break;\r
-                                       }\r
-                               case display_mode::half:                                                \r
-                                       {                                                               \r
-                                               send(target_, frame_muxer2::target_element_t(video, ticket));\r
-                                               receive_video();\r
-\r
-                                               break;\r
-                                       }\r
-                               case display_mode::deinterlace_bob_reinterlace:\r
-                               case display_mode::interlace:                                   \r
-                                       {                                       \r
-                                               std::shared_ptr<core::basic_frame> video2 = receive_video();\r
-                                               if(!video2)\r
-                                                       video2 = core::basic_frame::empty();\r
-                                                                                               \r
-                                               auto frame = core::basic_frame::interlace(make_safe_ptr(video), make_safe_ptr(video2), format_desc_.field_mode);        \r
-                                               send(target_, frame_muxer2::target_element_t(frame, ticket));\r
-\r
-                                               break;\r
-                                       }\r
-                               default:        \r
-                                       BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("invalid display-mode"));\r
-                               }\r
-                       }       \r
                }\r
                catch(...)\r
                {\r
@@ -227,6 +167,69 @@ struct frame_muxer2::implementation : public Concurrency::agent, boost::noncopya
                done();\r
        }\r
 \r
+       bool display()\r
+       {\r
+               auto ticket = governor_.acquire();\r
+\r
+               auto video = receive_video();\r
+               if(!video)\r
+                       return false;\r
+\r
+               auto audio = receive_audio(format_desc_.audio_samples_per_frame);\r
+               if(!audio)\r
+                       return false;\r
+                               \r
+               video->audio_data() = std::move(*audio);\r
+\r
+               switch(display_mode_.value())\r
+               {\r
+               case display_mode::simple:                      \r
+               case display_mode::deinterlace:\r
+               case display_mode::deinterlace_bob:\r
+                       {\r
+                               send(target_, frame_muxer2::target_element_t(video, ticket));\r
+                               \r
+                               return true;\r
+                       }\r
+               case display_mode::duplicate:                                   \r
+                       {                       \r
+                               send(target_, frame_muxer2::target_element_t(video, ticket));\r
+                                                               \r
+                               auto video2 = make_safe<core::write_frame>(*video);     \r
+                               auto audio2 = receive_audio(format_desc_.audio_samples_per_frame);\r
+\r
+                               if(audio2)\r
+                               {\r
+                                       video2->audio_data() = std::move(*audio2);\r
+                                       send(target_, frame_muxer2::target_element_t(video2, ticket));\r
+                               }\r
+\r
+                               return audio2 != nullptr;\r
+                       }\r
+               case display_mode::half:                                                \r
+                       {                                                               \r
+                               send(target_, frame_muxer2::target_element_t(video, ticket));\r
+                               auto video2 = receive_video();\r
+                               \r
+                               return video2 != nullptr;\r
+                       }\r
+               case display_mode::deinterlace_bob_reinterlace:\r
+               case display_mode::interlace:                                   \r
+                       {                                       \r
+                               std::shared_ptr<core::basic_frame> video2 = receive_video();\r
+                               if(!video2)\r
+                                       video2 = core::basic_frame::empty();\r
+                                                                                               \r
+                               auto frame = core::basic_frame::interlace(make_safe_ptr(video), make_safe_ptr(video2), format_desc_.field_mode);        \r
+                               send(target_, frame_muxer2::target_element_t(frame, ticket));\r
+                               \r
+                               return video2 != nullptr;\r
+                       }\r
+               default:        \r
+                       BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("invalid display-mode"));\r
+               }\r
+       }       \r
+       \r
        void initialize_display_mode(AVFrame& frame)\r
        {\r
                auto display_mode = display_mode::invalid;\r
index 710b9faa947a903a147cdc664e1dc49246425ab2..871bc9dbbc4484809dcd69e7fbbce3385bfeae0e 100644 (file)
@@ -146,6 +146,8 @@ public:
                        CASPAR_LOG_CURRENT_EXCEPTION();\r
                }       \r
        \r
+               BOOST_FOREACH(auto stream, streams_)\r
+                       Concurrency::send(target_, flush_packet(stream->index));        \r
                BOOST_FOREACH(auto stream, streams_)\r
                        Concurrency::send(target_, eof_packet(stream->index));  \r
 \r
@@ -232,7 +234,7 @@ public:
                packet->size = 0;\r
 \r
                BOOST_FOREACH(auto stream, streams_)\r
-                       Concurrency::asend(target_, loop_packet(stream->index));        \r
+                       Concurrency::asend(target_, flush_packet(stream->index));       \r
 \r
                graph_->add_tag("seek");                \r
        }               \r
index cb096916244bc3bfc9827dd44280c183f9d39905..1f31c9607e1728175aef678276e7d8440d3180ab 100644 (file)
@@ -319,7 +319,7 @@ safe_ptr<AVPacket> create_packet()
        return packet;\r
 }\r
 \r
-safe_ptr<AVPacket> loop_packet(int index)\r
+safe_ptr<AVPacket> flush_packet(int index)\r
 {\r
        static safe_ptr<AVPacket> packets[] = {create_packet(), create_packet(), create_packet(), create_packet(), create_packet(), create_packet()};\r
        \r
@@ -339,7 +339,7 @@ safe_ptr<AVPacket> eof_packet(int index)
        return packet;\r
 }\r
 \r
-safe_ptr<AVFrame> loop_video()\r
+safe_ptr<AVFrame> flush_video()\r
 {\r
        static auto frame1 = safe_ptr<AVFrame>(avcodec_alloc_frame(), av_free);\r
        return frame1;\r
@@ -351,7 +351,7 @@ safe_ptr<AVFrame> eof_video()
        return frame2;\r
 }\r
 \r
-safe_ptr<core::audio_buffer> loop_audio()\r
+safe_ptr<core::audio_buffer> flush_audio()\r
 {\r
        static auto audio1 = safe_ptr<core::audio_buffer>();\r
        return audio1;\r
index a86d711d2a26e8b7bbd15e2fe5bde4940e7ea7ef..7d76f35842e5e4d01eef017f9407ead6819ec163 100644 (file)
@@ -38,11 +38,11 @@ namespace ffmpeg {
        \r
 // Dataflow\r
        \r
-safe_ptr<AVPacket>                             loop_packet(int index);\r
+safe_ptr<AVPacket>                             flush_packet(int index);\r
 safe_ptr<AVPacket>                             eof_packet(int index);\r
-safe_ptr<AVFrame>                              loop_video();\r
+safe_ptr<AVFrame>                              flush_video();\r
 safe_ptr<AVFrame>                              eof_video();\r
-safe_ptr<core::audio_buffer>   loop_audio();\r
+safe_ptr<core::audio_buffer>   flush_audio();\r
 safe_ptr<core::audio_buffer>   eof_audio();\r
 \r
 // Utils\r
index 748084a30c5f07e4fc97090f1475c1831efbf0c2..d0438e7e8f1c2da9519e7044a390e421e28c9887 100644 (file)
@@ -53,14 +53,13 @@ namespace caspar { namespace ffmpeg {
 struct video_decoder::implementation : public Concurrency::agent, boost::noncopyable\r
 {      \r
        int                                                                             index_;\r
-       std::shared_ptr<AVCodecContext>                 codec_context_;\r
+       const safe_ptr<AVCodecContext>                  codec_context_;\r
        \r
-       double                                                                  fps_;\r
-       int64_t                                                                 nb_frames_;\r
-\r
-       size_t                                                                  width_;\r
-       size_t                                                                  height_;\r
-       bool                                                                    is_progressive_;\r
+       const double                                                                            fps_;\r
+       const int64_t                                                                           nb_frames_;\r
+       const size_t                                                                            width_;\r
+       const size_t                                                                            height_;\r
+       bool                                                                                            is_progressive_;\r
        \r
        unbounded_buffer<video_decoder::source_element_t>       source_;\r
        ITarget<video_decoder::target_element_t>&                       target_;\r
@@ -101,7 +100,7 @@ public:
                                auto ticket = governor_.acquire();\r
                                auto packet = receive(source_);\r
                        \r
-                               if(packet == loop_packet(index_))\r
+                               if(packet == flush_packet(index_))\r
                                {                                       \r
                                        if(codec_context_->codec->capabilities & CODEC_CAP_DELAY)\r
                                        {\r
@@ -118,7 +117,7 @@ public:
                                        }\r
 \r
                                        avcodec_flush_buffers(codec_context_.get());\r
-                                       send(target_, loop_video());\r
+                                       send(target_, flush_video());\r
                                        continue;\r
                                }\r
 \r