X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fffmpeg%2Fproducer%2Faudio%2Faudio_decoder.cpp;h=e92a7c18134859e05370fc65b13e6fb18a5d720e;hb=70235ae09df45c874e133fd4d3fcc1e6e34e993a;hp=9d279694eac8f82ca3ec1405730b27e65a2bb651;hpb=28d3e7c5efbf12eb494650aeb31d1a379befff21;p=casparcg diff --git a/modules/ffmpeg/producer/audio/audio_decoder.cpp b/modules/ffmpeg/producer/audio/audio_decoder.cpp index 9d279694e..e92a7c181 100644 --- a/modules/ffmpeg/producer/audio/audio_decoder.cpp +++ b/modules/ffmpeg/producer/audio/audio_decoder.cpp @@ -19,7 +19,7 @@ * Author: Robert Nagy, ronag89@gmail.com */ -#include "../../stdafx.h" +#include "../../StdAfx.h" #include "audio_decoder.h" @@ -28,10 +28,10 @@ #include "../../ffmpeg_error.h" #include +#include #include - -#include +#include #include @@ -51,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,29 +59,42 @@ uint64_t get_channel_layout(AVCodecContext* dec) struct audio_decoder::impl : boost::noncopyable { - monitor::subject monitor_subject_; - input* input_; + core::monitor::subject monitor_subject_; + input& input_; int index_; - const spl::shared_ptr codec_context_; + int actual_index_; const core::video_format_desc format_desc_; - - std::shared_ptr swr_; - - std::vector> buffer_; + const spl::shared_ptr codec_context_ = open_codec(input_.context(), AVMEDIA_TYPE_AUDIO, actual_index_, false); + + std::shared_ptr swr_ { + swr_alloc_set_opts( + nullptr, + create_channel_layout_bitmask(codec_context_->channels),//get_ffmpeg_channel_layout(codec_context_.get()), + AV_SAMPLE_FMT_S32, + format_desc_.audio_sample_rate, + create_channel_layout_bitmask(codec_context_->channels),//get_ffmpeg_channel_layout(codec_context_.get()), + codec_context_->sample_fmt, + codec_context_->sample_rate, + 0, + nullptr), + [](SwrContext* p){swr_free(&p); } + }; + + cache_aligned_vector buffer_; std::shared_ptr 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_)) - , swr_(swr_alloc_set_opts(nullptr, - av_get_default_channel_layout(format_desc_.audio_channels), AV_SAMPLE_FMT_S32, format_desc_.audio_sample_rate, - get_channel_layout(codec_context_.get()), codec_context_->sample_fmt, codec_context_->sample_rate, - 0, nullptr), [](SwrContext* p){swr_free(&p);}) - , buffer_(AVCODEC_MAX_AUDIO_FRAME_SIZE*4) - { + 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()); @@ -90,22 +103,22 @@ public: std::shared_ptr 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 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 { @@ -115,7 +128,7 @@ public: current_packet_.reset(); } - return audio ? audio : poll(); + return audio; } std::shared_ptr decode(AVPacket& pkt) @@ -137,22 +150,22 @@ public: if(!got_frame) return nullptr; - const uint8_t *in[] = {frame->data[0]}; + const uint8_t **in = const_cast(frame->extended_data); uint8_t* out[] = {buffer_.data()}; auto channel_samples = swr_convert(swr_.get(), - out, static_cast(buffer_.size()) / format_desc_.audio_channels / av_get_bytes_per_sample(AV_SAMPLE_FMT_S32), - in, frame->nb_samples); + out, static_cast(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_ << monitor::message("/file/audio/sample-rate") % codec_context_->sample_rate - << monitor::message("/file/audio/channels") % codec_context_->channels - << monitor::message("/file/audio/format") % u8(av_get_sample_fmt_name(codec_context_->sample_fmt)) - << monitor::message("/file/audio/codec") % u8(codec_context_->codec->long_name); + + 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)) + << core::monitor::message("/file/audio/codec") % u8(codec_context_->codec->long_name); return frame; } @@ -168,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 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();} -monitor::source& audio_decoder::monitor_output() { return impl_->monitor_subject_;} -}} \ No newline at end of file +core::monitor::subject& audio_decoder::monitor_output() { return impl_->monitor_subject_;} + +}}