X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fffmpeg%2Fproducer%2Ffilter%2Faudio_filter.cpp;h=05159e4194deb18aa952c0888e55919239824001;hb=7ec897903893b6bd5f2a595191fd121a075ed430;hp=ac70f04c0ede531c6f718e42f0e59a47300cc2b4;hpb=49f6906495afac6548207a49a0f3c8a9e92709d6;p=casparcg diff --git a/modules/ffmpeg/producer/filter/audio_filter.cpp b/modules/ffmpeg/producer/filter/audio_filter.cpp index ac70f04c0..05159e419 100644 --- a/modules/ffmpeg/producer/filter/audio_filter.cpp +++ b/modules/ffmpeg/producer/filter/audio_filter.cpp @@ -72,30 +72,9 @@ std::string create_sourcefilter_str(const audio_input_pad& input_pad, std::strin return asrc_options; } -std::string create_filter_list(const std::vector& items) -{ - return boost::join(items, "|"); -} - -std::string channel_layout_to_string(uint64_t channel_layout) -{ - return (boost::format("0x%|1$x|") % channel_layout).str(); -} - std::string create_sinkfilter_str(const audio_output_pad& output_pad, std::string name) { - const auto asink_options = (boost::format("[%4%] abuffersink")//=sample_fmts=%1%:channel_layouts=%2%:sample_rates=%3%") - % create_filter_list(cpplinq::from(output_pad.sample_fmts) - .select(&av_get_sample_fmt_name) - .select([](const char* str) { return std::string(str); }) - .to_vector()) - % create_filter_list(cpplinq::from(output_pad.sample_fmts) - .select(&channel_layout_to_string) - .to_vector()) - % create_filter_list(cpplinq::from(output_pad.sample_rates) - .select([](int samplerate) { return boost::lexical_cast(samplerate); }) - .to_vector()) - % name).str(); + const auto asink_options = (boost::format("[%1%] abuffersink") % name).str(); return asink_options; } @@ -111,9 +90,9 @@ struct audio_filter::implementation std::vector input_pads_; implementation( - std::vector input_pads, - std::vector output_pads, - const std::string& filtergraph) + std::vector input_pads, + std::vector output_pads, + const std::string& filtergraph) : filtergraph_(boost::to_lower_copy(filtergraph)) , input_pads_(std::move(input_pads)) { @@ -146,14 +125,21 @@ struct audio_filter::implementation { int i = 0; for (auto& output_pad : output_pads) + { complete_filter_graph.push_back(create_sinkfilter_str(output_pad, "aout:" + boost::lexical_cast(i++))); + + output_pad.sample_fmts.push_back(AVSampleFormat::AV_SAMPLE_FMT_NONE); + output_pad.audio_channel_layouts.push_back(0); + output_pad.sample_rates.push_back(-1); + } } configure_filtergraph( *audio_graph_, boost::join(complete_filter_graph, ";"), audio_graph_inputs_, - audio_graph_outputs_); + audio_graph_outputs_, + output_pads); if (is_logging_quiet_for_thread()) CASPAR_LOG(trace) @@ -173,7 +159,8 @@ struct audio_filter::implementation AVFilterGraph& graph, const std::string& filtergraph, std::vector& source_contexts, - std::vector& sink_contexts) + std::vector& sink_contexts, + const std::vector& output_pads) { AVFilterInOut* outputs = nullptr; AVFilterInOut* inputs = nullptr; @@ -202,11 +189,46 @@ struct audio_filter::implementation for (AVFilterInOut* iter = outputs; iter; iter = iter->next) sink_contexts.push_back(iter->filter_ctx); + for (int i = 0; i < sink_contexts.size(); ++i) + { + auto sink_context = sink_contexts.at(i); + auto& output_pad = output_pads.at(i); + +#pragma warning (push) +#pragma warning (disable : 4245) + FF(av_opt_set_int_list( + sink_context, + "sample_fmts", + output_pad.sample_fmts.data(), + -1, + AV_OPT_SEARCH_CHILDREN)); + + FF(av_opt_set_int_list( + sink_context, + "channel_layouts", + output_pad.audio_channel_layouts.data(), + 0, + AV_OPT_SEARCH_CHILDREN)); + + FF(av_opt_set_int_list( + sink_context, + "sample_rates", + output_pad.sample_rates.data(), + -1, + AV_OPT_SEARCH_CHILDREN)); +#pragma warning (pop) + } + FF(avfilter_graph_config( &graph, nullptr)); } + void set_guaranteed_output_num_samples_per_frame(int output_pad_id, int num_samples) + { + av_buffersink_set_frame_size(audio_graph_outputs_.at(output_pad_id), num_samples); + } + void push(int input_pad_id, const std::shared_ptr& src_av_frame) { FF(av_buffersrc_add_frame( @@ -254,6 +276,11 @@ struct audio_filter::implementation return filt_frame; } + + const AVFilterLink& get_output_pad_info(int output_pad_id) const + { + return *audio_graph_outputs_.at(output_pad_id)->inputs[0]; + } }; audio_filter::audio_filter( @@ -265,10 +292,13 @@ audio_filter::audio_filter( } audio_filter::audio_filter(audio_filter&& other) : impl_(std::move(other.impl_)){} audio_filter& audio_filter::operator=(audio_filter&& other){impl_ = std::move(other.impl_); return *this;} +void audio_filter::set_guaranteed_output_num_samples_per_frame(int output_pad_id, int num_samples) { impl_->set_guaranteed_output_num_samples_per_frame(output_pad_id, num_samples); } void audio_filter::push(int input_pad_id, const std::shared_ptr& frame){impl_->push(input_pad_id, frame);} void audio_filter::push(int input_pad_id, const boost::iterator_range& frame_samples) { impl_->push(input_pad_id, frame_samples); } std::shared_ptr audio_filter::poll(int output_pad_id){return impl_->poll(output_pad_id);} std::wstring audio_filter::filter_str() const{return u16(impl_->filtergraph_);} +int audio_filter::get_num_output_pads() const { return static_cast(impl_->audio_graph_outputs_.size()); } +const AVFilterLink& audio_filter::get_output_pad_info(int output_pad_id) const { return impl_->get_output_pad_info(output_pad_id); } std::vector> audio_filter::poll_all(int output_pad_id) { std::vector> frames;