diff options
author | Max Kellermann <max@musicpd.org> | 2020-11-16 09:41:20 +0100 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2020-11-16 09:41:20 +0100 |
commit | fbbbfb9668f1411a2af0c2928a16c4f13e5f76b1 (patch) | |
tree | a7e4cad7b2c0c9fc59566b1ccbb768f44e8505f5 /src/lib | |
parent | eb9f5339b683d037ab3224e362071e22991e0e83 (diff) | |
parent | 38b41fc3fdc11300296809c08313eca0d6698f76 (diff) |
Merge branch 'v0.22.x'
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/ffmpeg/DetectFilterFormat.cxx | 76 | ||||
-rw-r--r-- | src/lib/ffmpeg/DetectFilterFormat.hxx | 46 | ||||
-rw-r--r-- | src/lib/ffmpeg/meson.build | 5 |
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( |