diff --git a/NEWS b/NEWS
index 2abb4f0e1..a09c1c144 100644
--- a/NEWS
+++ b/NEWS
@@ -19,6 +19,7 @@ ver 0.21 (not yet released)
 * tags
   - new tags "OriginalDate", "MUSICBRAINZ_WORKID"
 * decoder
+  - ffmpeg: require at least version 11.12
   - gme: try loading m3u sidecar files
   - hybrid_dsd: new decoder plugin
   - mad: move "gapless_mp3_playback" setting to "decoder" block
diff --git a/configure.ac b/configure.ac
index 5031c1715..69cb2dce5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -911,7 +911,7 @@ MPD_ENABLE_AUTO_LIB(aac, FAAD, faad, NeAACDecOpen, [-lfaad], [],
 
 dnl ---------------------------------- ffmpeg ---------------------------------
 MPD_ENABLE_AUTO_PKG(ffmpeg, FFMPEG,
-	[libavformat >= 53.17 libavcodec >= 53.25 libavutil >= 51.17],
+	[libavformat >= 56.1 libavcodec >= 56.1 libavutil >= 54.3],
 	[ffmpeg decoder library], [libavformat+libavcodec+libavutil not found])
 
 dnl ----------------------------------- FLAC ----------------------------------
diff --git a/src/decoder/plugins/FfmpegDecoderPlugin.cxx b/src/decoder/plugins/FfmpegDecoderPlugin.cxx
index cecfb51f8..b65fd0284 100644
--- a/src/decoder/plugins/FfmpegDecoderPlugin.cxx
+++ b/src/decoder/plugins/FfmpegDecoderPlugin.cxx
@@ -47,10 +47,7 @@ extern "C" {
 #include <libavformat/avformat.h>
 #include <libavformat/avio.h>
 #include <libavutil/avutil.h>
-
-#if LIBAVUTIL_VERSION_MAJOR >= 53
 #include <libavutil/frame.h>
-#endif
 }
 
 #include <assert.h>
@@ -539,8 +536,6 @@ FfmpegScanMetadata(const AVFormatContext &format_context, int audio_stream,
 			   handler);
 }
 
-#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(56, 1, 0)
-
 static void
 FfmpegScanTag(const AVFormatContext &format_context, int audio_stream,
 	      TagBuilder &tag)
@@ -571,8 +566,6 @@ FfmpegCheckTag(DecoderClient &client, InputStream &is,
 		client.SubmitTag(is, tag.Commit());
 }
 
-#endif
-
 static void
 FfmpegDecode(DecoderClient &client, InputStream &input,
 	     AVFormatContext &format_context)
@@ -598,17 +591,11 @@ FfmpegDecode(DecoderClient &client, InputStream &input,
 
 	const auto &codec_params = GetCodecParameters(av_stream);
 
-#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 25, 0)
 	const AVCodecDescriptor *codec_descriptor =
 		avcodec_descriptor_get(codec_params.codec_id);
 	if (codec_descriptor != nullptr)
 		FormatDebug(ffmpeg_domain, "codec '%s'",
 			    codec_descriptor->name);
-#else
-	if (codec_context->codec_name[0] != 0)
-		FormatDebug(ffmpeg_domain, "codec '%s'",
-			    codec_context->codec_name);
-#endif
 
 	AVCodec *codec = avcodec_find_decoder(codec_params.codec_id);
 
@@ -670,24 +657,14 @@ FfmpegDecode(DecoderClient &client, InputStream &input,
 
 	FfmpegParseMetaData(client, format_context, audio_stream);
 
-#if LIBAVUTIL_VERSION_MAJOR >= 53
 	AVFrame *frame = av_frame_alloc();
-#else
-	AVFrame *frame = avcodec_alloc_frame();
-#endif
 	if (!frame) {
 		LogError(ffmpeg_domain, "Could not allocate frame");
 		return;
 	}
 
 	AtScopeExit(&frame) {
-#if LIBAVUTIL_VERSION_MAJOR >= 53
 		av_frame_free(&frame);
-#elif LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 28, 0)
-		avcodec_free_frame(&frame);
-#else
-		av_free(frame);
-#endif
 	};
 
 	FfmpegBuffer interleaved_buffer;
@@ -720,9 +697,7 @@ FfmpegDecode(DecoderClient &client, InputStream &input,
 			/* end of file */
 			break;
 
-#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(56, 1, 0)
 		FfmpegCheckTag(client, input, format_context, audio_stream);
-#endif
 
 		if (packet.size > 0 && packet.stream_index == audio_stream) {
 			cmd = ffmpeg_send_packet(client, input,
diff --git a/src/lib/ffmpeg/Buffer.hxx b/src/lib/ffmpeg/Buffer.hxx
index 400d0f014..0d0ae9cea 100644
--- a/src/lib/ffmpeg/Buffer.hxx
+++ b/src/lib/ffmpeg/Buffer.hxx
@@ -22,15 +22,6 @@
 
 extern "C" {
 #include <libavutil/mem.h>
-
-#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(52, 18, 0)
-#define HAVE_AV_FAST_MALLOC
-#else
-#include <libavcodec/avcodec.h>
-#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 25, 0)
-#define HAVE_AV_FAST_MALLOC
-#endif
-#endif
 }
 
 #include <stddef.h>
@@ -53,14 +44,7 @@ public:
 
 	gcc_malloc
 	void *Get(size_t min_size) {
-#ifdef HAVE_AV_FAST_MALLOC
 		av_fast_malloc(&data, &size, min_size);
-#else
-		void *new_data = av_fast_realloc(data, &size, min_size);
-		if (new_data == nullptr)
-			return AVERROR(ENOMEM);
-		data = new_data;
-#endif
 		return data;
 	}