From 8439119e244b2456239d9b274a4bf819dd667cd9 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 24 Aug 2021 13:42:00 +0200 Subject: [PATCH] filter/ffmpeg: support double-precision samples Insert an "aformat" filter which converts double-precision to single-precision. Closes https://github.com/MusicPlayerDaemon/MPD/issues/1235 --- NEWS | 1 + src/filter/plugins/FfmpegFilterPlugin.cxx | 11 ++++++++++- src/lib/ffmpeg/Filter.cxx | 8 ++++++++ src/lib/ffmpeg/Filter.hxx | 7 +++++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 966ed91e7..3107a602f 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,7 @@ ver 0.22.11 (not yet released) * filter - ffmpeg: pass "channel_layout" instead of "channels" to buffersrc - ffmpeg: fix "av_buffersink_get_frame() failed: Resource temporarily unavailable" + - ffmpeg: support double-precision samples (by converting to single precision) * Android - build with NDK r23 diff --git a/src/filter/plugins/FfmpegFilterPlugin.cxx b/src/filter/plugins/FfmpegFilterPlugin.cxx index d61a23b95..20d70507d 100644 --- a/src/filter/plugins/FfmpegFilterPlugin.cxx +++ b/src/filter/plugins/FfmpegFilterPlugin.cxx @@ -81,7 +81,16 @@ PreparedFfmpegFilter::Open(AudioFormat &in_audio_format) auto &buffer_sink = Ffmpeg::MakeAudioBufferSink(*graph); - graph.ParseSingleInOut(graph_string, buffer_sink, buffer_src); + /* if the filter's output format is not supported by MPD, this + "aformat" filter is inserted at the end and takes care for + the required conversion */ + auto &aformat = Ffmpeg::MakeAutoAformat(*graph); + + int error = avfilter_link(&aformat, 0, &buffer_sink, 0); + if (error < 0) + throw MakeFfmpegError(error, "avfilter_link() failed"); + + graph.ParseSingleInOut(graph_string, aformat, buffer_src); graph.CheckAndConfigure(); const auto out_audio_format = diff --git a/src/lib/ffmpeg/Filter.cxx b/src/lib/ffmpeg/Filter.cxx index d435ca5c8..ca011a341 100644 --- a/src/lib/ffmpeg/Filter.cxx +++ b/src/lib/ffmpeg/Filter.cxx @@ -130,6 +130,14 @@ MakeAformat(AudioFormat &audio_format, args, nullptr, graph_ctx); } +AVFilterContext & +MakeAutoAformat(AVFilterGraph &graph_ctx) +{ + return CreateFilter(RequireFilterByName("aformat"), "aformat", + "sample_fmts=flt|s32|s16", + nullptr, graph_ctx); +} + void FilterGraph::ParseSingleInOut(const char *filters, AVFilterContext &in, AVFilterContext &out) diff --git a/src/lib/ffmpeg/Filter.hxx b/src/lib/ffmpeg/Filter.hxx index c55ac2b1f..d2e3a38c5 100644 --- a/src/lib/ffmpeg/Filter.hxx +++ b/src/lib/ffmpeg/Filter.hxx @@ -103,6 +103,13 @@ AVFilterContext & MakeAformat(AudioFormat &audio_format, AVFilterGraph &graph_ctx); +/** + * Create an "aformat" filter which automatically converts the output + * to a format supported by MPD. + */ +AVFilterContext & +MakeAutoAformat(AVFilterGraph &graph_ctx); + class FilterGraph { AVFilterGraph *graph = nullptr;