return asrc_options;
}
-std::string create_filter_list(const std::vector<std::string>& 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<std::string>(samplerate); })
- .to_vector())
- % name).str();
+ const auto asink_options = (boost::format("[%1%] abuffersink") % name).str();
return asink_options;
}
std::vector<audio_input_pad> input_pads_;
implementation(
- std::vector<audio_input_pad> input_pads,
- std::vector<audio_output_pad> output_pads,
- const std::string& filtergraph)
+ std::vector<audio_input_pad> input_pads,
+ std::vector<audio_output_pad> output_pads,
+ const std::string& filtergraph)
: filtergraph_(boost::to_lower_copy(filtergraph))
, input_pads_(std::move(input_pads))
{
{
int i = 0;
for (auto& output_pad : output_pads)
+ {
complete_filter_graph.push_back(create_sinkfilter_str(output_pad, "aout:" + boost::lexical_cast<std::string>(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)
AVFilterGraph& graph,
const std::string& filtergraph,
std::vector<AVFilterContext*>& source_contexts,
- std::vector<AVFilterContext*>& sink_contexts)
+ std::vector<AVFilterContext*>& sink_contexts,
+ const std::vector<audio_output_pad>& output_pads)
{
AVFilterInOut* outputs = nullptr;
AVFilterInOut* inputs = nullptr;
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<AVFrame>& src_av_frame)
{
FF(av_buffersrc_add_frame(
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(
}
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<AVFrame>& frame){impl_->push(input_pad_id, frame);}
void audio_filter::push(int input_pad_id, const boost::iterator_range<const int32_t*>& frame_samples) { impl_->push(input_pad_id, frame_samples); }
std::shared_ptr<AVFrame> 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<int>(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<spl::shared_ptr<AVFrame>> audio_filter::poll_all(int output_pad_id)
{
std::vector<spl::shared_ptr<AVFrame>> frames;