summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2020-11-16 09:41:20 +0100
committerMax Kellermann <max@musicpd.org>2020-11-16 09:41:20 +0100
commitfbbbfb9668f1411a2af0c2928a16c4f13e5f76b1 (patch)
treea7e4cad7b2c0c9fc59566b1ccbb768f44e8505f5 /src/lib
parenteb9f5339b683d037ab3224e362071e22991e0e83 (diff)
parent38b41fc3fdc11300296809c08313eca0d6698f76 (diff)
Merge branch 'v0.22.x'
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/ffmpeg/DetectFilterFormat.cxx76
-rw-r--r--src/lib/ffmpeg/DetectFilterFormat.hxx46
-rw-r--r--src/lib/ffmpeg/meson.build5
3 files changed, 126 insertions, 1 deletions
diff --git a/src/lib/ffmpeg/DetectFilterFormat.cxx b/src/lib/ffmpeg/DetectFilterFormat.cxx
new file mode 100644
index 000000000..65b610024
--- /dev/null
+++ b/src/lib/ffmpeg/DetectFilterFormat.cxx
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2003-2020 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "DetectFilterFormat.hxx"
+#include "Frame.hxx"
+#include "SampleFormat.hxx"
+#include "pcm/Silence.hxx"
+#include "pcm/CheckAudioFormat.hxx"
+#include "util/WritableBuffer.hxx"
+
+extern "C" {
+#include <libavfilter/buffersrc.h>
+#include <libavfilter/buffersink.h>
+}
+
+#include <cassert>
+
+namespace Ffmpeg {
+
+AudioFormat
+DetectFilterOutputFormat(const AudioFormat &in_audio_format,
+ AVFilterContext &buffer_src,
+ AVFilterContext &buffer_sink)
+{
+ uint_least64_t silence[MAX_CHANNELS];
+ const size_t silence_size = in_audio_format.GetFrameSize();
+ assert(sizeof(silence) >= silence_size);
+
+ PcmSilence(WritableBuffer<void>{&silence, silence_size},
+ in_audio_format.format);
+
+ Frame frame;
+ frame->format = ToFfmpegSampleFormat(in_audio_format.format);
+ frame->sample_rate = in_audio_format.sample_rate;
+ frame->channels = in_audio_format.channels;
+ frame->nb_samples = 1;
+
+ frame.GetBuffer();
+
+ memcpy(frame.GetData(0), silence, silence_size);
+
+ int err = av_buffersrc_add_frame(&buffer_src, frame.get());
+ if (err < 0)
+ throw MakeFfmpegError(err, "av_buffersrc_add_frame() failed");
+
+ frame.Unref();
+
+ err = av_buffersink_get_frame(&buffer_sink, frame.get());
+ if (err < 0)
+ throw MakeFfmpegError(err, "av_buffersink_get_frame() failed");
+
+ const SampleFormat sample_format = FromFfmpegSampleFormat(AVSampleFormat(frame->format));
+ if (sample_format == SampleFormat::UNDEFINED)
+ throw std::runtime_error("Unsupported FFmpeg sample format");
+
+ return CheckAudioFormat(frame->sample_rate, sample_format,
+ frame->channels);
+}
+
+} // namespace Ffmpeg
diff --git a/src/lib/ffmpeg/DetectFilterFormat.hxx b/src/lib/ffmpeg/DetectFilterFormat.hxx
new file mode 100644
index 000000000..6e9e3877c
--- /dev/null
+++ b/src/lib/ffmpeg/DetectFilterFormat.hxx
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2003-2020 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_FFMPEG_DETECT_FILTER_FORMAT_HXX
+#define MPD_FFMPEG_DETECT_FILTER_FORMAT_HXX
+
+struct AVFilterContext;
+struct AudioFormat;
+
+namespace Ffmpeg {
+
+/**
+ * Attempt to detect the output format of the given FFmpeg filter by
+ * sending one frame of silence and checking what format comes back
+ * from the filter.
+ *
+ * This is a kludge because MPD needs to know the output format of a
+ * filter while initializing and cannot cope with format changes in
+ * between.
+ *
+ * This function can throw if the FFmpeg filter fails.
+ */
+AudioFormat
+DetectFilterOutputFormat(const AudioFormat &in_audio_format,
+ AVFilterContext &buffer_src,
+ AVFilterContext &buffer_sink);
+
+} // namespace Ffmpeg
+
+#endif
diff --git a/src/lib/ffmpeg/meson.build b/src/lib/ffmpeg/meson.build
index fde110edc..31eda8167 100644
--- a/src/lib/ffmpeg/meson.build
+++ b/src/lib/ffmpeg/meson.build
@@ -20,7 +20,10 @@ endif
ffmpeg_sources = []
if libavfilter_dep.found()
- ffmpeg_sources += 'Filter.cxx'
+ ffmpeg_sources += [
+ 'Filter.cxx',
+ 'DetectFilterFormat.cxx',
+ ]
endif
ffmpeg = static_library(