From ca2439f595b8fbf8a370744fd9f2ade25525d013 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 23 Aug 2021 21:36:57 +0200 Subject: [PATCH] filter/ffmpeg: pass "channel_layout" instead of "channels" to buffersrc Fixes part 1 of https://github.com/MusicPlayerDaemon/MPD/issues/1235 --- NEWS | 2 + src/lib/ffmpeg/ChannelLayout.hxx | 66 ++++++++++++++++++++++++++++++++ src/lib/ffmpeg/Filter.cxx | 7 +++- 3 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 src/lib/ffmpeg/ChannelLayout.hxx diff --git a/NEWS b/NEWS index 4f7ecf500..dece9dc95 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,8 @@ ver 0.22.11 (not yet released) * protocol - fix "albumart" crash +* filter + - ffmpeg: pass "channel_layout" instead of "channels" to buffersrc * Android - build with NDK r23 diff --git a/src/lib/ffmpeg/ChannelLayout.hxx b/src/lib/ffmpeg/ChannelLayout.hxx new file mode 100644 index 000000000..02f74b268 --- /dev/null +++ b/src/lib/ffmpeg/ChannelLayout.hxx @@ -0,0 +1,66 @@ +/* + * Copyright 2003-2021 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_CHANNEL_LAYOUT_HXX +#define MPD_FFMPEG_CHANNEL_LAYOUT_HXX + +extern "C" { +#include +} + +/** + * Convert a MPD channel count to a libavutil channel_layout bit mask. + */ +static constexpr uint64_t +ToFfmpegChannelLayout(unsigned channels) noexcept +{ + switch (channels) { + case 1: + return AV_CH_LAYOUT_MONO; + + case 2: + return AV_CH_LAYOUT_STEREO; + + case 3: + return AV_CH_LAYOUT_SURROUND; + + case 4: + // TODO is this AV_CH_LAYOUT_2_2? + return AV_CH_LAYOUT_QUAD; + + case 5: + // TODO is this AV_CH_LAYOUT_5POINT0_BACK? + return AV_CH_LAYOUT_5POINT0; + + case 6: + return AV_CH_LAYOUT_5POINT1; + + case 7: + return AV_CH_LAYOUT_6POINT1; + + case 8: + return AV_CH_LAYOUT_7POINT1; + + default: + /* unreachable */ + return 0; + } +} + +#endif diff --git a/src/lib/ffmpeg/Filter.cxx b/src/lib/ffmpeg/Filter.cxx index 1749082c6..a91a30a53 100644 --- a/src/lib/ffmpeg/Filter.cxx +++ b/src/lib/ffmpeg/Filter.cxx @@ -18,10 +18,13 @@ */ #include "Filter.hxx" +#include "ChannelLayout.hxx" #include "SampleFormat.hxx" #include "pcm/AudioFormat.hxx" #include "util/RuntimeError.hxx" +#include + #include namespace Ffmpeg { @@ -57,10 +60,10 @@ FilterContext::MakeAudioBufferSource(AudioFormat &audio_format, char abuffer_args[256]; sprintf(abuffer_args, - "sample_rate=%u:sample_fmt=%s:channels=%u:time_base=1/%u", + "sample_rate=%u:sample_fmt=%s:channel_layout=0x%" PRIx64 ":time_base=1/%u", audio_format.sample_rate, av_get_sample_fmt_name(src_format), - audio_format.channels, + ToFfmpegChannelLayout(audio_format.channels), audio_format.sample_rate); return {RequireFilterByName("abuffer"), "abuffer", abuffer_args, nullptr, graph_ctx};