]> git.sesse.net Git - casparcg/blobdiff - modules/ffmpeg/ffmpeg_pipeline_backend_internal.cpp
[ffmpeg] Copied flush logic when seeking from 2.0, as well as current frame in clip...
[casparcg] / modules / ffmpeg / ffmpeg_pipeline_backend_internal.cpp
index f512ebfdc9133812929555fa32c7f537f323c8c7..9feb2d734c147d6d7c42a7e999c9d17a94930290 100644 (file)
@@ -17,6 +17,7 @@
 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
 *
 * Author: Helge Norberg, helge.norberg@svt.se
+* Author: Robert Nagy, ronag89@gmail.com
 */
 
 #include "StdAfx.h"
@@ -181,7 +182,7 @@ public:
                {
                        try
                        {
-                               audio_decoders_.push_back(spl::make_shared<audio_decoder>(*input_, core::video_format_desc(), i));
+                               audio_decoders_.push_back(spl::make_shared<audio_decoder>(*input_, core::video_format::invalid, i));
                        }
                        catch (...)
                        {
@@ -356,7 +357,7 @@ public:
                                {
                                        frame = (*a_decoder)();
 
-                                       if (frame && frame->data[0])
+                                       if (frame == flush() || (frame && frame->data[0]))
                                                break;
                                        else
                                                frame.reset();
@@ -375,7 +376,7 @@ public:
                        {
                                frame = (*v_decoder)();
 
-                               if (frame && frame->data[0])
+                               if (frame == flush() || (frame && frame->data[0]))
                                        return { frame };
                        }
                }
@@ -603,11 +604,12 @@ struct sink
        virtual void                                                    framerate(boost::rational<int> framerate)                                                                               { CASPAR_THROW_EXCEPTION(invalid_operation() << msg_info(print() + L" not an encoder.")); }
        virtual void                                                    start(bool has_audio, bool has_video)                                                                                   { CASPAR_THROW_EXCEPTION(not_implemented() << msg_info(print())); }
        virtual void                                                    stop()                                                                                                                                                  { }
+       virtual void                                                    flush_all()                                                                                                                                             { }
        virtual std::vector<AVSampleFormat>             supported_sample_formats() const                                                                                                { CASPAR_THROW_EXCEPTION(not_implemented() << msg_info(print())); }
        virtual std::vector<int>                                supported_samplerates() const                                                                                                   { CASPAR_THROW_EXCEPTION(not_implemented() << msg_info(print())); }
        virtual std::vector<AVPixelFormat>              supported_pixel_formats() const                                                                                                 { CASPAR_THROW_EXCEPTION(not_implemented() << msg_info(print())); }
        virtual int                                                             wanted_num_audio_streams() const                                                                                                { CASPAR_THROW_EXCEPTION(not_implemented() << msg_info(print())); }
-       virtual boost::optional<int>                    wanted_num_channels_per_stream() const                                                                          { CASPAR_THROW_EXCEPTION(not_implemented() << msg_info(print())); }
+       virtual boost::optional<int>                    wanted_num_channels_per_stream() const                                                                                  { CASPAR_THROW_EXCEPTION(not_implemented() << msg_info(print())); }
        virtual boost::optional<AVMediaType>    try_push(AVMediaType type, int stream_index, spl::shared_ptr<AVFrame> frame)    { CASPAR_THROW_EXCEPTION(not_implemented() << msg_info(print())); }
        virtual void                                                    eof()                                                                                                                                                   { CASPAR_THROW_EXCEPTION(not_implemented() << msg_info(print())); }
 };
@@ -699,8 +701,7 @@ public:
        void stop() override
        {
                running_ = false;
-               try_pop_frame();
-               try_pop_frame();
+               output_frames_.set_capacity(4);
        }
 
        std::vector<AVSampleFormat> supported_sample_formats() const override
@@ -738,6 +739,14 @@ public:
                return boost::none;
        }
 
+       void flush_all() override
+       {
+               audio_samples_.clear();
+
+               while (!video_frames_.empty())
+                       video_frames_.pop();
+       }
+
        boost::optional<AVMediaType> try_push(AVMediaType type, int stream_index, spl::shared_ptr<AVFrame> av_frame) override
        {
                if (!has_audio_ && !has_video_)
@@ -859,8 +868,9 @@ public:
 
 struct audio_stream_info
 {
-       int                             num_channels = 0;
-       AVSampleFormat  sampleformat = AVSampleFormat::AV_SAMPLE_FMT_NONE;
+       int                             num_channels    = 0;
+       AVSampleFormat  sampleformat    = AVSampleFormat::AV_SAMPLE_FMT_NONE;
+       uint64_t                channel_layout  = 0;
 };
 
 struct video_stream_info
@@ -1109,8 +1119,21 @@ private:
                        {
                                auto needed                                             = *result;
                                auto input_frames_for_streams   = source_->get_input_frames_for_streams(needed);
+                               bool flush_all                                  = !input_frames_for_streams.empty() && input_frames_for_streams.at(0) == flush();
 
-                               if (!input_frames_for_streams.empty() && input_frames_for_streams.at(0))
+                               if (flush_all)
+                               {
+                                       sink_->flush_all();
+                                       
+                                       if (source_->has_audio() && source_->has_video())
+                                               result = needed == AVMediaType::AVMEDIA_TYPE_AUDIO ? AVMediaType::AVMEDIA_TYPE_VIDEO : AVMediaType::AVMEDIA_TYPE_AUDIO;
+
+                                       continue;
+                               }
+
+                               bool got_requested_media_type   = !input_frames_for_streams.empty() && input_frames_for_streams.at(0);
+
+                               if (got_requested_media_type)
                                {
                                        for (int input_stream_index = 0; input_stream_index < input_frames_for_streams.size(); ++input_stream_index)
                                        {
@@ -1193,8 +1216,13 @@ private:
                        auto& av_frame  = *av_frames_per_stream.at(i);
                        auto& stream    = source_audio_streams_.at(i);
 
+                       auto channel_layout = av_frame.channel_layout == 0
+                                       ? av_get_default_channel_layout(av_frame.channels)
+                                       : av_frame.channel_layout;
+
                        set_if_changed(changed, stream.sampleformat, static_cast<AVSampleFormat>(av_frame.format));
                        set_if_changed(changed, stream.num_channels, av_frame.channels);
+                       set_if_changed(changed, stream.channel_layout, channel_layout);
                }
 
                if (changed)
@@ -1212,7 +1240,7 @@ private:
                                        boost::rational<int>(1, source_->samplerate()),
                                        source_->samplerate(),
                                        source_audio_stream.sampleformat,
-                                       av_get_default_channel_layout(source_audio_stream.num_channels));
+                                       source_audio_stream.channel_layout);
                }
 
                auto total_num_channels = cpplinq::from(source_audio_streams_)