]> git.sesse.net Git - casparcg/blobdiff - modules/ffmpeg/producer/audio/audio_decoder.cpp
[ffmpeg] Copied flush logic when seeking from 2.0, as well as current frame in clip...
[casparcg] / modules / ffmpeg / producer / audio / audio_decoder.cpp
index 18a78cd730c09e27f670dcf8565741699d530145..e92a7c18134859e05370fc65b13e6fb18a5d720e 100644 (file)
@@ -28,6 +28,7 @@
 #include "../../ffmpeg_error.h"
 
 #include <core/video_format.h>
+#include <core/frame/audio_channel_layout.h>
 
 #include <common/log.h>
 #include <common/cache_aligned_vector.h>
@@ -50,7 +51,7 @@ extern "C"
 
 namespace caspar { namespace ffmpeg {
        
-uint64_t get_channel_layout(AVCodecContext* dec)
+uint64_t get_ffmpeg_channel_layout(AVCodecContext* dec)
 {
        auto layout = (dec->channel_layout && dec->channels == av_get_channel_layout_nb_channels(dec->channel_layout)) ? dec->channel_layout : av_get_default_channel_layout(dec->channels);
        return layout;
@@ -59,18 +60,19 @@ uint64_t get_channel_layout(AVCodecContext* dec)
 struct audio_decoder::impl : boost::noncopyable
 {      
        core::monitor::subject                                                                          monitor_subject_;
-       input*                                                                                                          input_;
+       input&                                                                                                          input_;
        int                                                                                                                     index_;
+       int                                                                                                                     actual_index_;
        const core::video_format_desc                                                           format_desc_;
-       const spl::shared_ptr<AVCodecContext>                                           codec_context_ = open_codec(input_->context(), AVMEDIA_TYPE_AUDIO, index_);
+       const spl::shared_ptr<AVCodecContext>                                           codec_context_          = open_codec(input_.context(), AVMEDIA_TYPE_AUDIO, actual_index_, false);
 
        std::shared_ptr<SwrContext>                                                                     swr_                            {
                                                                                                                                                                                swr_alloc_set_opts(
                                                                                                                                                                                                nullptr,
-                                                                                                                                                                                               av_get_default_channel_layout(format_desc_.audio_channels),
+                                                                                                                                                                                               create_channel_layout_bitmask(codec_context_->channels),//get_ffmpeg_channel_layout(codec_context_.get()),
                                                                                                                                                                                                AV_SAMPLE_FMT_S32,
                                                                                                                                                                                                format_desc_.audio_sample_rate,
-                                                                                                                                                                                               get_channel_layout(codec_context_.get()),
+                                                                                                                                                                                               create_channel_layout_bitmask(codec_context_->channels),//get_ffmpeg_channel_layout(codec_context_.get()),
                                                                                                                                                                                                codec_context_->sample_fmt,
                                                                                                                                                                                                codec_context_->sample_rate,
                                                                                                                                                                                                0,
@@ -83,12 +85,16 @@ struct audio_decoder::impl : boost::noncopyable
        std::shared_ptr<AVPacket>                                                                       current_packet_;
        
 public:
-       explicit impl(input& in, const core::video_format_desc& format_desc) 
-               : input_(&in)
-               , format_desc_(format_desc)     
-               , codec_context_(open_codec(input_->context(), AVMEDIA_TYPE_AUDIO, index_))
+       explicit impl(
+                       input& in,
+                       const core::video_format_desc& format_desc,
+                       int audio_stream_index)
+               : input_(in)
+               , index_(audio_stream_index)
+               , actual_index_(input_.get_actual_audio_stream_index(index_))
+               , format_desc_(format_desc)
                , buffer_(480000 * 4)
-       {               
+       {
                if(!swr_)
                        CASPAR_THROW_EXCEPTION(bad_alloc());
 
@@ -97,22 +103,22 @@ public:
                
        std::shared_ptr<AVFrame> poll()
        {               
-               if(!current_packet_ && !input_->try_pop_audio(current_packet_))
+               if(!current_packet_ && !input_.try_pop_audio(current_packet_, index_))
                        return nullptr;
                
                std::shared_ptr<AVFrame> audio;
 
-               if(!current_packet_)    
-               {
-                       avcodec_flush_buffers(codec_context_.get());    
-               }
-               else if(!current_packet_->data)
+               if (!current_packet_->data)
                {
                        if(codec_context_->codec->capabilities & CODEC_CAP_DELAY)                       
                                audio = decode(*current_packet_);
                        
-                       if(!audio)
+                       if (!audio)
+                       {
+                               avcodec_flush_buffers(codec_context_.get());
                                current_packet_.reset();
+                               audio = flush();
+                       }
                }
                else
                {
@@ -122,7 +128,7 @@ public:
                                current_packet_.reset();
                }
        
-               return audio ? audio : poll();
+               return audio;
        }
 
        std::shared_ptr<AVFrame> decode(AVPacket& pkt)
@@ -148,14 +154,14 @@ public:
                uint8_t* out[]          = {buffer_.data()};
 
                auto channel_samples = swr_convert(swr_.get(), 
-                                                                                       out, static_cast<int>(buffer_.size()) / format_desc_.audio_channels / av_get_bytes_per_sample(AV_SAMPLE_FMT_S32), 
-                                                                                       in, frame->nb_samples); 
+                                                                                       out, static_cast<int>(buffer_.size()) / codec_context_->channels / av_get_bytes_per_sample(AV_SAMPLE_FMT_S32),
+                                                                                       in, frame->nb_samples);
 
                frame->data[0]          = buffer_.data();
-               frame->linesize[0]      = channel_samples * format_desc_.audio_channels * av_get_bytes_per_sample(AV_SAMPLE_FMT_S32);
+               frame->linesize[0]      = channel_samples * codec_context_->channels * av_get_bytes_per_sample(AV_SAMPLE_FMT_S32);
                frame->nb_samples       = channel_samples;
                frame->format           = AV_SAMPLE_FMT_S32;
-                                                       
+
                monitor_subject_  << core::monitor::message("/file/audio/sample-rate")  % codec_context_->sample_rate
                                                << core::monitor::message("/file/audio/channels")       % codec_context_->channels
                                                << core::monitor::message("/file/audio/format")         % u8(av_get_sample_fmt_name(codec_context_->sample_fmt))
@@ -175,11 +181,12 @@ public:
        }
 };
 
-audio_decoder::audio_decoder(input& input, const core::video_format_desc& format_desc) : impl_(new impl(input, format_desc)){}
+audio_decoder::audio_decoder(input& input, const core::video_format_desc& format_desc, int audio_stream_index) : impl_(new impl(input, format_desc, audio_stream_index)){}
 audio_decoder::audio_decoder(audio_decoder&& other) : impl_(std::move(other.impl_)){}
 audio_decoder& audio_decoder::operator=(audio_decoder&& other){impl_ = std::move(other.impl_); return *this;}
 std::shared_ptr<AVFrame> audio_decoder::operator()(){return impl_->poll();}
 uint32_t audio_decoder::nb_frames() const{return impl_->nb_frames();}
 std::wstring audio_decoder::print() const{return impl_->print();}
 core::monitor::subject& audio_decoder::monitor_output() { return impl_->monitor_subject_;}
+
 }}