From 6016fd682b267d2886babd51b1faa9cdd1812d54 Mon Sep 17 00:00:00 2001 From: ronag Date: Fri, 2 Sep 2011 12:55:20 +0000 Subject: [PATCH] 2.0. audio: Audio pipeline is now in 32 bit. decklink_consumer: Added support for 32 bit audio. git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@1321 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d --- core/mixer/audio/audio_mixer.cpp | 24 +++--- core/mixer/audio/audio_mixer.h | 2 +- core/mixer/mixer.cpp | 2 +- core/mixer/read_frame.cpp | 14 +-- core/mixer/read_frame.h | 4 +- core/mixer/write_frame.cpp | 8 +- core/mixer/write_frame.h | 4 +- core/video_format.cpp | 1 - core/video_format.h | 1 - .../bluefish/consumer/bluefish_consumer.cpp | 10 ++- .../decklink/consumer/decklink_consumer.cpp | 6 +- .../decklink/producer/decklink_producer.cpp | 4 +- modules/ffmpeg/ffmpeg.vcxproj | 7 ++ modules/ffmpeg/ffmpeg.vcxproj.filters | 6 ++ .../ffmpeg/producer/audio/audio_decoder.cpp | 62 +++++-------- modules/ffmpeg/producer/audio/audio_decoder.h | 2 +- .../ffmpeg/producer/audio/audio_resampler.cpp | 86 +++++++++++++++++++ .../ffmpeg/producer/audio/audio_resampler.h | 22 +++++ modules/ffmpeg/producer/frame_muxer.cpp | 12 +-- modules/ffmpeg/producer/frame_muxer.h | 2 +- modules/oal/consumer/oal_consumer.cpp | 18 ++-- 21 files changed, 202 insertions(+), 95 deletions(-) create mode 100644 modules/ffmpeg/producer/audio/audio_resampler.cpp create mode 100644 modules/ffmpeg/producer/audio/audio_resampler.h diff --git a/core/mixer/audio/audio_mixer.cpp b/core/mixer/audio/audio_mixer.cpp index a899d949c..1c3a77364 100644 --- a/core/mixer/audio/audio_mixer.cpp +++ b/core/mixer/audio/audio_mixer.cpp @@ -26,6 +26,8 @@ #include +#include + #include #include @@ -35,7 +37,7 @@ struct audio_item { const void* tag; frame_transform transform; - std::vector audio_data; + std::vector audio_data; }; struct audio_mixer::implementation @@ -73,7 +75,7 @@ public: audio_item item; item.tag = frame.tag(); item.transform = transform_stack_.top(); - item.audio_data = std::vector(frame.audio_data().begin(), frame.audio_data().end()); + item.audio_data = std::vector(frame.audio_data().begin(), frame.audio_data().end()); items.push_back(item); } @@ -88,9 +90,9 @@ public: transform_stack_.pop(); } - std::vector mix() + std::vector mix() { - auto result = std::vector(format_desc_.audio_samples_per_frame); + auto result = std::vector(format_desc_.audio_samples_per_frame); std::map next_frame_transforms; @@ -108,10 +110,10 @@ public: if(next.volume < 0.001 && prev.volume < 0.001) continue; - static const int BASE = 1<<15; + static const int BASE = 1<<31; - const auto next_volume = static_cast(next.volume*BASE); - const auto prev_volume = static_cast(prev.volume*BASE); + const auto next_volume = static_cast(next.volume*BASE); + const auto prev_volume = static_cast(prev.volume*BASE); const int n_samples = result.size(); @@ -128,9 +130,9 @@ public: { for(size_t n = r.begin(); n < r.end(); ++n) { - const int sample_volume = (prev_volume - (prev_volume * n)/n_samples) + (next_volume * n)/n_samples; - const int sample = (static_cast(item.audio_data[n])*sample_volume)/BASE; - result[n] = static_cast((static_cast(result[n]) + sample) & 0xFFFF); + const auto sample_volume = (prev_volume - (prev_volume * n)/n_samples) + (next_volume * n)/n_samples; + const auto sample = static_cast((static_cast(item.audio_data[n])*sample_volume)/BASE); + result[n] = result[n] + sample; } } ); @@ -147,7 +149,7 @@ audio_mixer::audio_mixer(const core::video_format_desc& format_desc) : impl_(new void audio_mixer::begin(core::basic_frame& frame){impl_->begin(frame);} void audio_mixer::visit(core::write_frame& frame){impl_->visit(frame);} void audio_mixer::end(){impl_->end();} -std::vector audio_mixer::mix(){return impl_->mix();} +std::vector audio_mixer::mix(){return impl_->mix();} audio_mixer& audio_mixer::operator=(audio_mixer&& other) { impl_ = std::move(other.impl_); diff --git a/core/mixer/audio/audio_mixer.h b/core/mixer/audio/audio_mixer.h index 6cdafca5d..3a5648230 100644 --- a/core/mixer/audio/audio_mixer.h +++ b/core/mixer/audio/audio_mixer.h @@ -40,7 +40,7 @@ public: virtual void visit(core::write_frame& frame); virtual void end(); - std::vector mix(); + std::vector mix(); audio_mixer& operator=(audio_mixer&& other); private: diff --git a/core/mixer/mixer.cpp b/core/mixer/mixer.cpp index 0f0e1ad56..95721d044 100644 --- a/core/mixer/mixer.cpp +++ b/core/mixer/mixer.cpp @@ -96,7 +96,7 @@ struct mixer::implementation : boost::noncopyable std::unordered_map> transforms_; std::unordered_map blend_modes_; - std::queue>, std::vector>> buffer_; + std::queue>, std::vector>> buffer_; const size_t buffer_size_; diff --git a/core/mixer/read_frame.cpp b/core/mixer/read_frame.cpp index 4555d67fa..77ab0c3b6 100644 --- a/core/mixer/read_frame.cpp +++ b/core/mixer/read_frame.cpp @@ -35,10 +35,10 @@ struct read_frame::implementation : boost::noncopyable size_t size_; safe_ptr image_data_; tbb::mutex mutex_; - std::vector audio_data_; + std::vector audio_data_; public: - implementation(ogl_device& ogl, size_t size, safe_ptr&& image_data, std::vector&& audio_data) + implementation(ogl_device& ogl, size_t size, safe_ptr&& image_data, std::vector&& audio_data) : ogl_(ogl) , size_(size) , image_data_(std::move(image_data)) @@ -59,13 +59,13 @@ public: auto ptr = static_cast(image_data_->data()); return boost::iterator_range(ptr, ptr + image_data_->size()); } - const boost::iterator_range audio_data() + const boost::iterator_range audio_data() { - return boost::iterator_range(audio_data_.data(), audio_data_.data() + audio_data_.size()); + return boost::iterator_range(audio_data_.data(), audio_data_.data() + audio_data_.size()); } }; -read_frame::read_frame(ogl_device& ogl, size_t size, safe_ptr&& image_data, std::vector&& audio_data) +read_frame::read_frame(ogl_device& ogl, size_t size, safe_ptr&& image_data, std::vector&& audio_data) : impl_(new implementation(ogl, size, std::move(image_data), std::move(audio_data))){} read_frame::read_frame(){} const boost::iterator_range read_frame::image_data() @@ -73,9 +73,9 @@ const boost::iterator_range read_frame::image_data() return impl_ ? impl_->image_data() : boost::iterator_range(); } -const boost::iterator_range read_frame::audio_data() +const boost::iterator_range read_frame::audio_data() { - return impl_ ? impl_->audio_data() : boost::iterator_range(); + return impl_ ? impl_->audio_data() : boost::iterator_range(); } size_t read_frame::image_size() const{return impl_ ? impl_->size_ : 0;} diff --git a/core/mixer/read_frame.h b/core/mixer/read_frame.h index 133dbf609..a3afc36cd 100644 --- a/core/mixer/read_frame.h +++ b/core/mixer/read_frame.h @@ -37,10 +37,10 @@ class read_frame : boost::noncopyable { public: read_frame(); - read_frame(ogl_device& ogl, size_t size, safe_ptr&& image_data, std::vector&& audio_data); + read_frame(ogl_device& ogl, size_t size, safe_ptr&& image_data, std::vector&& audio_data); virtual const boost::iterator_range image_data(); - virtual const boost::iterator_range audio_data(); + virtual const boost::iterator_range audio_data(); virtual size_t image_size() const; diff --git a/core/mixer/write_frame.cpp b/core/mixer/write_frame.cpp index 9bd533b09..1fc455349 100644 --- a/core/mixer/write_frame.cpp +++ b/core/mixer/write_frame.cpp @@ -37,7 +37,7 @@ struct write_frame::implementation ogl_device* ogl_; std::vector> buffers_; std::vector> textures_; - std::vector audio_data_; + std::vector audio_data_; const core::pixel_format_desc desc_; const void* tag_; core::field_mode::type mode_; @@ -142,14 +142,14 @@ write_frame& write_frame::operator=(write_frame&& other) void write_frame::swap(write_frame& other){impl_.swap(other.impl_);} boost::iterator_range write_frame::image_data(size_t index){return impl_->image_data(index);} -std::vector& write_frame::audio_data() { return impl_->audio_data_; } +std::vector& write_frame::audio_data() { return impl_->audio_data_; } const boost::iterator_range write_frame::image_data(size_t index) const { return boost::iterator_range(impl_->image_data(index).begin(), impl_->image_data(index).end()); } -const boost::iterator_range write_frame::audio_data() const +const boost::iterator_range write_frame::audio_data() const { - return boost::iterator_range(impl_->audio_data_.data(), impl_->audio_data_.data() + impl_->audio_data_.size()); + return boost::iterator_range(impl_->audio_data_.data(), impl_->audio_data_.data() + impl_->audio_data_.size()); } const void* write_frame::tag() const {return impl_->tag_;} const core::pixel_format_desc& write_frame::get_pixel_format_desc() const{return impl_->desc_;} diff --git a/core/mixer/write_frame.h b/core/mixer/write_frame.h index 6566fe838..9f295f819 100644 --- a/core/mixer/write_frame.h +++ b/core/mixer/write_frame.h @@ -54,8 +54,8 @@ public: boost::iterator_range image_data(size_t plane_index = 0); const boost::iterator_range image_data(size_t plane_index = 0) const; - std::vector& audio_data(); - const boost::iterator_range audio_data() const; + std::vector& audio_data(); + const boost::iterator_range audio_data() const; void commit(uint32_t plane_index); void commit(); diff --git a/core/video_format.cpp b/core/video_format.cpp index d412fbabe..c3db0e792 100644 --- a/core/video_format.cpp +++ b/core/video_format.cpp @@ -38,7 +38,6 @@ (m == field_mode::progressive ? 1 : 2),\ ((w)*(h)*4),\ (name),\ - (2),\ (48000),\ (2),\ (static_cast(48000.0*2.0/((double)scale/(double)duration)+0.99))\ diff --git a/core/video_format.h b/core/video_format.h index fdbe1bd3e..58634a827 100644 --- a/core/video_format.h +++ b/core/video_format.h @@ -93,7 +93,6 @@ struct video_format_desc size_t size; // output frame size in bytes std::wstring name; // name of output format - size_t audio_bytes_per_sample; size_t audio_sample_rate; size_t audio_channels; size_t audio_samples_per_frame; diff --git a/modules/bluefish/consumer/bluefish_consumer.cpp b/modules/bluefish/consumer/bluefish_consumer.cpp index d04fc4351..04636b216 100644 --- a/modules/bluefish/consumer/bluefish_consumer.cpp +++ b/modules/bluefish/consumer/bluefish_consumer.cpp @@ -207,7 +207,7 @@ public: void schedule_next_video(const safe_ptr& frame) { - static std::vector silence(MAX_HANC_BUFFER_SIZE, 0); + static std::vector silence(MAX_HANC_BUFFER_SIZE, 0); executor_.begin_invoke([=] { @@ -241,9 +241,13 @@ public: if(embedded_audio_) { - auto frame_audio_data = frame->audio_data().empty() ? silence.data() : const_cast(frame->audio_data().begin()); + auto frame_audio_data = frame->audio_data().empty() ? silence.data() : const_cast(frame->audio_data().begin()); + + std::vector frame_audio_data16(audio_samples); + for(size_t n = 0; n < frame_audio_data16.size(); ++n) + frame_audio_data16[n] = (frame_audio_data[n] >> 16) & 0xffff; - encode_hanc(reinterpret_cast(reserved_frames_.front()->hanc_data()), frame_audio_data, audio_samples, audio_nchannels); + encode_hanc(reinterpret_cast(reserved_frames_.front()->hanc_data()), frame_audio_data16.data(), audio_samples, audio_nchannels); blue_->system_buffer_write_async(const_cast(reserved_frames_.front()->image_data()), reserved_frames_.front()->image_size(), diff --git a/modules/decklink/consumer/decklink_consumer.cpp b/modules/decklink/consumer/decklink_consumer.cpp index bc1d9e2a9..03131d310 100644 --- a/modules/decklink/consumer/decklink_consumer.cpp +++ b/modules/decklink/consumer/decklink_consumer.cpp @@ -151,7 +151,7 @@ struct decklink_consumer : public IDeckLinkVideoOutputCallback, public IDeckLink size_t preroll_count_; - boost::circular_buffer> audio_container_; + boost::circular_buffer> audio_container_; tbb::concurrent_bounded_queue> video_frame_buffer_; tbb::concurrent_bounded_queue> audio_frame_buffer_; @@ -262,7 +262,7 @@ public: void enable_audio() { - if(FAILED(output_->EnableAudioOutput(bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger, 2, bmdAudioOutputStreamTimestamped))) + if(FAILED(output_->EnableAudioOutput(bmdAudioSampleRate48kHz, bmdAudioSampleType32bitInteger, 2, bmdAudioOutputStreamTimestamped))) BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Could not enable audio output.")); if(FAILED(output_->SetAudioCallback(this))) @@ -369,7 +369,7 @@ public: { const int sample_frame_count = frame->audio_data().size()/format_desc_.audio_channels; - audio_container_.push_back(std::vector(frame->audio_data().begin(), frame->audio_data().end())); + audio_container_.push_back(std::vector(frame->audio_data().begin(), frame->audio_data().end())); if(FAILED(output_->ScheduleAudioSamples(audio_container_.back().data(), sample_frame_count, (audio_scheduled_++) * sample_frame_count, format_desc_.audio_sample_rate, nullptr))) CASPAR_LOG(error) << print() << L" Failed to schedule audio."; diff --git a/modules/decklink/producer/decklink_producer.cpp b/modules/decklink/producer/decklink_producer.cpp index 595413364..3ab270649 100644 --- a/modules/decklink/producer/decklink_producer.cpp +++ b/modules/decklink/producer/decklink_producer.cpp @@ -195,10 +195,10 @@ public: { auto sample_frame_count = audio->GetSampleFrameCount(); auto audio_data = reinterpret_cast(bytes); - muxer_.push(std::make_shared>(audio_data, audio_data + sample_frame_count*2)); + muxer_.push(std::make_shared>(audio_data, audio_data + sample_frame_count*2)); } else - muxer_.push(std::make_shared>(frame_factory_->get_video_format_desc().audio_samples_per_frame, 0)); + muxer_.push(std::make_shared>(frame_factory_->get_video_format_desc().audio_samples_per_frame, 0)); muxer_.commit(); diff --git a/modules/ffmpeg/ffmpeg.vcxproj b/modules/ffmpeg/ffmpeg.vcxproj index cc0f30750..ad2bdc716 100644 --- a/modules/ffmpeg/ffmpeg.vcxproj +++ b/modules/ffmpeg/ffmpeg.vcxproj @@ -286,6 +286,12 @@ ../../StdAfx.h ../../StdAfx.h + + ../../StdAfx.h + ../../StdAfx.h + ../../StdAfx.h + ../../StdAfx.h + ../StdAfx.h ../StdAfx.h @@ -352,6 +358,7 @@ + diff --git a/modules/ffmpeg/ffmpeg.vcxproj.filters b/modules/ffmpeg/ffmpeg.vcxproj.filters index 055aedc01..86ea6ace6 100644 --- a/modules/ffmpeg/ffmpeg.vcxproj.filters +++ b/modules/ffmpeg/ffmpeg.vcxproj.filters @@ -61,6 +61,9 @@ source\producer\format + + source\producer\audio + @@ -103,5 +106,8 @@ source\producer\format + + source\producer\audio + \ No newline at end of file diff --git a/modules/ffmpeg/producer/audio/audio_decoder.cpp b/modules/ffmpeg/producer/audio/audio_decoder.cpp index 63a01bf54..dd0a9e586 100644 --- a/modules/ffmpeg/producer/audio/audio_decoder.cpp +++ b/modules/ffmpeg/producer/audio/audio_decoder.cpp @@ -21,6 +21,8 @@ #include "audio_decoder.h" +#include "audio_resampler.h" + #include "../../ffmpeg_error.h" #include @@ -49,10 +51,9 @@ struct audio_decoder::implementation : boost::noncopyable std::shared_ptr codec_context_; const core::video_format_desc format_desc_; int index_; - std::shared_ptr resampler_; + std::unique_ptr resampler_; std::vector> buffer1_; - std::vector> buffer2_; std::queue> packets_; @@ -73,27 +74,9 @@ public: buffer1_.resize(AVCODEC_MAX_AUDIO_FRAME_SIZE*2); - if(codec_context_->sample_rate != static_cast(format_desc_.audio_sample_rate) || - codec_context_->channels != static_cast(format_desc_.audio_channels) || - codec_context_->sample_fmt != AV_SAMPLE_FMT_S16) - { - auto resampler = av_audio_resample_init(format_desc_.audio_channels, codec_context_->channels, - format_desc_.audio_sample_rate, codec_context_->sample_rate, - AV_SAMPLE_FMT_S16, codec_context_->sample_fmt, - 16, 10, 0, 0.8); - - buffer2_.resize(AVCODEC_MAX_AUDIO_FRAME_SIZE*2); - - CASPAR_LOG(warning) << L"Invalid audio format. Resampling." << - L" sample_rate:" << static_cast(codec_context_->sample_rate) << - L" audio_channels:" << static_cast(codec_context_->channels) << - L" sample_fmt:" << static_cast(codec_context_->sample_fmt); - - if(resampler) - resampler_.reset(resampler, audio_resample_close); - else - codec_context_ = nullptr; - } + resampler_.reset(new audio_resampler(format_desc_.audio_channels, codec_context_->channels, + format_desc_.audio_sample_rate, codec_context_->sample_rate, + AV_SAMPLE_FMT_S32, codec_context_->sample_fmt)); } catch(...) { @@ -112,9 +95,9 @@ public: packets_.push(packet); } - std::vector>> poll() + std::vector>> poll() { - std::vector>> result; + std::vector>> result; if(packets_.empty()) return result; @@ -140,7 +123,7 @@ public: return result; } - std::vector>> empty_poll() + std::vector>> empty_poll() { auto packet = packets_.front(); packets_.pop(); @@ -148,33 +131,28 @@ public: if(!packet) return boost::assign::list_of(nullptr); - return boost::assign::list_of(std::make_shared>(format_desc_.audio_samples_per_frame, 0)); + return boost::assign::list_of(std::make_shared>(format_desc_.audio_samples_per_frame, 0)); } - std::shared_ptr> decode(AVPacket& pkt) + std::shared_ptr> decode(AVPacket& pkt) { + buffer1_.resize(AVCODEC_MAX_AUDIO_FRAME_SIZE*2); int written_bytes = buffer1_.size() - FF_INPUT_BUFFER_PADDING_SIZE; - + int ret = THROW_ON_ERROR2(avcodec_decode_audio3(codec_context_.get(), reinterpret_cast(buffer1_.data()), &written_bytes, &pkt), "[audio_decoder]"); // There might be several frames in one packet. pkt.size -= ret; pkt.data += ret; - if(resampler_) - { - auto ret = audio_resample(resampler_.get(), - reinterpret_cast(buffer2_.data()), - reinterpret_cast(buffer1_.data()), - written_bytes / (av_get_bytes_per_sample(codec_context_->sample_fmt) * codec_context_->channels)); - written_bytes = ret * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) * format_desc_.audio_channels; - std::swap(buffer1_, buffer2_); - } + buffer1_.resize(written_bytes); - const auto n_samples = written_bytes / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16); - const auto samples = reinterpret_cast(buffer1_.data()); + buffer1_ = resampler_->resample(std::move(buffer1_)); + + const auto n_samples = buffer1_.size() / av_get_bytes_per_sample(AV_SAMPLE_FMT_S32); + const auto samples = reinterpret_cast(buffer1_.data()); - return std::make_shared>(samples, samples + n_samples); + return std::make_shared>(samples, samples + n_samples); } bool ready() const @@ -186,6 +164,6 @@ public: audio_decoder::audio_decoder(const safe_ptr& context, const core::video_format_desc& format_desc) : impl_(new implementation(context, format_desc)){} void audio_decoder::push(const std::shared_ptr& packet){impl_->push(packet);} bool audio_decoder::ready() const{return impl_->ready();} -std::vector>> audio_decoder::poll(){return impl_->poll();} +std::vector>> audio_decoder::poll(){return impl_->poll();} int64_t audio_decoder::nb_frames() const{return impl_->nb_frames_;} } \ No newline at end of file diff --git a/modules/ffmpeg/producer/audio/audio_decoder.h b/modules/ffmpeg/producer/audio/audio_decoder.h index 2ef82eaab..8ad020697 100644 --- a/modules/ffmpeg/producer/audio/audio_decoder.h +++ b/modules/ffmpeg/producer/audio/audio_decoder.h @@ -43,7 +43,7 @@ public: void push(const std::shared_ptr& packet); bool ready() const; - std::vector>> poll(); + std::vector>> poll(); int64_t nb_frames() const; diff --git a/modules/ffmpeg/producer/audio/audio_resampler.cpp b/modules/ffmpeg/producer/audio/audio_resampler.cpp new file mode 100644 index 000000000..baa24774b --- /dev/null +++ b/modules/ffmpeg/producer/audio/audio_resampler.cpp @@ -0,0 +1,86 @@ +#include "../../StdAfx.h" + +#include "audio_resampler.h" + +#include + +#if defined(_MSC_VER) +#pragma warning (push) +#pragma warning (disable : 4244) +#endif +extern "C" +{ + #include +} +#if defined(_MSC_VER) +#pragma warning (pop) +#endif + + +namespace caspar { + +struct audio_resampler::implementation +{ + std::shared_ptr resampler_; + + std::vector> copy_buffer_; + std::vector> buffer2_; + + const size_t output_channels_; + const AVSampleFormat output_sample_format_; + + const size_t input_channels_; + const AVSampleFormat input_sample_format_; + + implementation(size_t output_channels, size_t input_channels, size_t output_sample_rate, size_t input_sample_rate, AVSampleFormat output_sample_format, AVSampleFormat input_sample_format) + : output_channels_(output_channels) + , output_sample_format_(output_sample_format) + , input_channels_(input_channels) + , input_sample_format_(input_sample_format) + { + if(input_channels != output_channels || + input_sample_rate != output_sample_rate || + input_sample_format != output_sample_format) + { + auto resampler = av_audio_resample_init(output_channels, input_channels, + output_sample_rate, input_sample_rate, + output_sample_format, input_sample_format, + 16, 10, 0, 0.8); + + buffer2_.resize(AVCODEC_MAX_AUDIO_FRAME_SIZE*2); + + CASPAR_LOG(warning) << L"Resampling." << + L" sample_rate:" << input_channels << + L" audio_channels:" << input_channels << + L" sample_fmt:" << input_sample_format; + + if(resampler) + resampler_.reset(resampler, audio_resample_close); + else + BOOST_THROW_EXCEPTION(caspar_exception()); + } + } + + std::vector> resample(std::vector>&& data) + { + if(resampler_) + { + buffer2_.resize(AVCODEC_MAX_AUDIO_FRAME_SIZE*2); + auto ret = audio_resample(resampler_.get(), + reinterpret_cast(buffer2_.data()), + reinterpret_cast(data.data()), + data.size() / (av_get_bytes_per_sample(input_sample_format_) * input_channels_)); + buffer2_.resize(ret * av_get_bytes_per_sample(output_sample_format_) * output_channels_); + std::swap(data, buffer2_); + } + + return std::move(data); + } +}; + + +audio_resampler::audio_resampler(size_t output_channels, size_t input_channels, size_t output_sample_rate, size_t input_sample_rate, AVSampleFormat output_sample_format, AVSampleFormat input_sample_format) + : impl_(new implementation(output_channels, input_channels, output_sample_rate, input_sample_rate, output_sample_format, input_sample_format)){} +std::vector> audio_resampler::resample(std::vector>&& data){return impl_->resample(std::move(data));} + +} \ No newline at end of file diff --git a/modules/ffmpeg/producer/audio/audio_resampler.h b/modules/ffmpeg/producer/audio/audio_resampler.h new file mode 100644 index 000000000..bc03bcb22 --- /dev/null +++ b/modules/ffmpeg/producer/audio/audio_resampler.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +#include + +namespace caspar { + +class audio_resampler +{ +public: + audio_resampler(size_t output_channels, size_t input_channels, + size_t output_sample_rate, size_t input_sample_rate, + AVSampleFormat output_sample_format, AVSampleFormat input_sample_format); + + std::vector> resample(std::vector>&& data); +private: + struct implementation; + std::shared_ptr impl_; +}; + +} \ No newline at end of file diff --git a/modules/ffmpeg/producer/frame_muxer.cpp b/modules/ffmpeg/producer/frame_muxer.cpp index d478c9fa4..affb1c329 100644 --- a/modules/ffmpeg/producer/frame_muxer.cpp +++ b/modules/ffmpeg/producer/frame_muxer.cpp @@ -136,7 +136,7 @@ display_mode::type get_display_mode(const core::field_mode::type in_mode, double struct frame_muxer::implementation : boost::noncopyable { std::deque>> video_streams_; - std::deque> audio_streams_; + std::deque> audio_streams_; std::deque> frame_buffer_; display_mode::type display_mode_; const double in_fps_; @@ -238,12 +238,12 @@ struct frame_muxer::implementation : boost::noncopyable BOOST_THROW_EXCEPTION(invalid_operation() << source_info("frame_muxer") << msg_info("video-stream overflow. This can be caused by incorrect frame-rate. Check clip meta-data.")); } - void push(const std::shared_ptr>& audio_samples) + void push(const std::shared_ptr>& audio_samples) { if(!audio_samples) { CASPAR_LOG(debug) << L"audio-chunk-count: " << audio_sample_count_/format_desc_.audio_samples_per_frame; - audio_streams_.push_back(std::vector()); + audio_streams_.push_back(std::vector()); audio_sample_count_ = 0; return; } @@ -276,14 +276,14 @@ struct frame_muxer::implementation : boost::noncopyable return frame; } - std::vector pop_audio() + std::vector pop_audio() { CASPAR_VERIFY(audio_streams_.front().size() >= format_desc_.audio_samples_per_frame); auto begin = audio_streams_.front().begin(); auto end = begin + format_desc_.audio_samples_per_frame; - auto samples = std::vector(begin, end); + auto samples = std::vector(begin, end); audio_streams_.front().erase(begin, end); return samples; @@ -410,7 +410,7 @@ struct frame_muxer::implementation : boost::noncopyable frame_muxer::frame_muxer(double in_fps, const safe_ptr& frame_factory) : impl_(new implementation(in_fps, frame_factory)){} void frame_muxer::push(const std::shared_ptr& video_frame, int hints){impl_->push(video_frame, hints);} -void frame_muxer::push(const std::shared_ptr>& audio_samples){return impl_->push(audio_samples);} +void frame_muxer::push(const std::shared_ptr>& audio_samples){return impl_->push(audio_samples);} void frame_muxer::commit(){impl_->commit();} safe_ptr frame_muxer::pop(){return impl_->pop();} size_t frame_muxer::size() const {return impl_->size();} diff --git a/modules/ffmpeg/producer/frame_muxer.h b/modules/ffmpeg/producer/frame_muxer.h index f6730c2a8..da9f41086 100644 --- a/modules/ffmpeg/producer/frame_muxer.h +++ b/modules/ffmpeg/producer/frame_muxer.h @@ -24,7 +24,7 @@ public: frame_muxer(double in_fps, const safe_ptr& frame_factory); void push(const std::shared_ptr& video_frame, int hints = 0); - void push(const std::shared_ptr>& audio_samples); + void push(const std::shared_ptr>& audio_samples); void commit(); diff --git a/modules/oal/consumer/oal_consumer.cpp b/modules/oal/consumer/oal_consumer.cpp index 867d06714..cb727f629 100644 --- a/modules/oal/consumer/oal_consumer.cpp +++ b/modules/oal/consumer/oal_consumer.cpp @@ -45,7 +45,7 @@ struct oal_consumer : public core::frame_consumer, public sf::SoundStream safe_ptr graph_; boost::timer perf_timer_; - tbb::concurrent_bounded_queue> input_; + tbb::concurrent_bounded_queue>> input_; boost::circular_buffer> container_; tbb::atomic is_running_; @@ -69,8 +69,8 @@ public: ~oal_consumer() { is_running_ = false; - input_.try_push(std::vector()); - input_.try_push(std::vector()); + input_.try_push(std::make_shared>()); + input_.try_push(std::make_shared>()); Stop(); CASPAR_LOG(info) << print() << L" Shutting down."; } @@ -86,22 +86,26 @@ public: { if(preroll_count_ < input_.capacity()) { - while(input_.try_push(std::vector(format_desc_.audio_samples_per_frame, 0))) + while(input_.try_push(std::make_shared>(format_desc_.audio_samples_per_frame, 0))) ++preroll_count_; Play(); } - input_.push(std::vector(frame->audio_data().begin(), frame->audio_data().end())); + std::vector audio16(frame->audio_data().size()); + for(size_t n = 0; n < audio16.size(); ++n) + audio16[n] = (frame->audio_data()[n] >> 16) & 0xffff; + + input_.push(std::make_shared>(std::move(audio16))); return true; } virtual bool OnGetData(sf::SoundStream::Chunk& data) { - std::vector audio_data; + std::shared_ptr> audio_data; input_.pop(audio_data); - container_.push_back(std::move(audio_data)); + container_.push_back(std::move(*audio_data)); data.Samples = container_.back().data(); data.NbSamples = container_.back().size(); -- 2.39.2