From 8686d7e237476e677c3bd7d0bcc962f49022aca5 Mon Sep 17 00:00:00 2001
From: Benjamin Radel <benjamin@radel.tk>
Date: Sat, 29 Jun 2024 00:57:24 +0200
Subject: [PATCH] Use new ffmpeg-7 API for channel_layout -> ch_layout

Adapt DCPoMatic for using the new ffmpeg 7 ch_layout API.
Currently, this commit makes DCPoMatic incompatible with older
ffmpeg versions.
---
 src/lib/audio_filter_graph.cc  | 15 +++++++--------
 src/lib/audio_filter_graph.h   |  2 +-
 src/lib/ffmpeg_decoder.cc      |  2 +-
 src/lib/ffmpeg_examiner.cc     |  7 +++----
 src/lib/ffmpeg_file_encoder.cc |  8 +++++---
 5 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/src/lib/audio_filter_graph.cc b/src/lib/audio_filter_graph.cc
index 4e3052d57..d601e9d02 100644
--- a/src/lib/audio_filter_graph.cc
+++ b/src/lib/audio_filter_graph.cc
@@ -49,9 +49,9 @@ AudioFilterGraph::AudioFilterGraph (int sample_rate, int channels)
 	   so we need to tell it we're using 16 channels if we are using more than 8.
 	*/
 	if (_channels > 8) {
-		_channel_layout = av_get_default_channel_layout (16);
+		av_channel_layout_default (&_channel_layout, 16);
 	} else {
-		_channel_layout = av_get_default_channel_layout (_channels);
+		av_channel_layout_default (&_channel_layout, _channels);
 	}
 
 	_in_frame = av_frame_alloc ();
@@ -69,7 +69,7 @@ string
 AudioFilterGraph::src_parameters () const
 {
 	char layout[64];
-	av_get_channel_layout_string (layout, sizeof(layout), 0, _channel_layout);
+	av_channel_layout_describe (&_channel_layout, layout, sizeof(layout));
 
 	char buffer[256];
 	snprintf (
@@ -88,8 +88,7 @@ AudioFilterGraph::set_parameters (AVFilterContext* context) const
 	int r = av_opt_set_int_list (context, "sample_fmts", sample_fmts, AV_SAMPLE_FMT_NONE, AV_OPT_SEARCH_CHILDREN);
 	DCPOMATIC_ASSERT (r >= 0);
 
-	int64_t channel_layouts[] = { _channel_layout, -1 };
-	r = av_opt_set_int_list (context, "channel_layouts", channel_layouts, -1, AV_OPT_SEARCH_CHILDREN);
+	r = av_opt_set_chlayout (context, "channel_layouts", &_channel_layout, AV_OPT_SEARCH_CHILDREN);
 	DCPOMATIC_ASSERT (r >= 0);
 
 	int sample_rates[] = { _sample_rate, -1 };
@@ -114,7 +113,7 @@ void
 AudioFilterGraph::process (shared_ptr<AudioBuffers> buffers)
 {
 	DCPOMATIC_ASSERT (buffers->frames() > 0);
-	int const process_channels = av_get_channel_layout_nb_channels (_channel_layout);
+	int const process_channels = _channel_layout.nb_channels;
 	DCPOMATIC_ASSERT (process_channels >= buffers->channels());
 
 	if (buffers->channels() < process_channels) {
@@ -144,8 +143,8 @@ AudioFilterGraph::process (shared_ptr<AudioBuffers> buffers)
 	_in_frame->nb_samples = buffers->frames ();
 	_in_frame->format = AV_SAMPLE_FMT_FLTP;
 	_in_frame->sample_rate = _sample_rate;
-	_in_frame->channel_layout = _channel_layout;
-	_in_frame->channels = process_channels;
+	_in_frame->ch_layout = _channel_layout;
+	// _in_frame->channels = process_channels;
 
 	int r = av_buffersrc_write_frame (_buffer_src_context, _in_frame);
 
diff --git a/src/lib/audio_filter_graph.h b/src/lib/audio_filter_graph.h
index e5c55fa27..1ac2b071b 100644
--- a/src/lib/audio_filter_graph.h
+++ b/src/lib/audio_filter_graph.h
@@ -47,7 +47,7 @@ protected:
 private:
 	int _sample_rate;
 	int _channels;
-	int64_t _channel_layout;
+	AVChannelLayout _channel_layout;
 	AVFrame* _in_frame;
 };
 
diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc
index 45983795b..88b867904 100644
--- a/src/lib/ffmpeg_decoder.cc
+++ b/src/lib/ffmpeg_decoder.cc
@@ -260,7 +260,7 @@ deinterleave_audio(AVFrame* frame)
 
 	/* XXX: can't we use swr_convert() to do the format conversion? */
 
-	int const channels = frame->channels;
+	int const channels = frame->ch_layout.nb_channels;
 	int const frames = frame->nb_samples;
 	int const total_samples = frames * channels;
 	auto audio = make_shared<AudioBuffers>(channels, frames);
diff --git a/src/lib/ffmpeg_examiner.cc b/src/lib/ffmpeg_examiner.cc
index 51ade8e89..1a435482a 100644
--- a/src/lib/ffmpeg_examiner.cc
+++ b/src/lib/ffmpeg_examiner.cc
@@ -76,9 +76,8 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr<const FFmpegContent> c, shared_ptr<Jo
 			/* This is a hack; sometimes it seems that _audio_codec_context->channel_layout isn't set up,
 			   so bodge it here.  No idea why we should have to do this.
 			*/
-
-			if (s->codecpar->channel_layout == 0) {
-				s->codecpar->channel_layout = av_get_default_channel_layout (s->codecpar->channels);
+			if (s->codecpar->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
+				av_channel_layout_default (&s->codecpar->ch_layout, s->codecpar->ch_layout.nb_channels);
 			}
 
 			DCPOMATIC_ASSERT (_format_context->duration != AV_NOPTS_VALUE);
@@ -91,7 +90,7 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr<const FFmpegContent> c, shared_ptr<Jo
 					s->id,
 					s->codecpar->sample_rate,
 					llrint ((double(_format_context->duration) / AV_TIME_BASE) * s->codecpar->sample_rate),
-					s->codecpar->channels,
+					s->codecpar->ch_layout.nb_channels,
 					s->codecpar->bits_per_raw_sample ? s->codecpar->bits_per_raw_sample : s->codecpar->bits_per_coded_sample
 					)
 				);
diff --git a/src/lib/ffmpeg_file_encoder.cc b/src/lib/ffmpeg_file_encoder.cc
index 6d1ad68f7..19a07801e 100644
--- a/src/lib/ffmpeg_file_encoder.cc
+++ b/src/lib/ffmpeg_file_encoder.cc
@@ -73,8 +73,8 @@ public:
 		_codec_context->bit_rate = channels * 128 * 1024;
 		_codec_context->sample_fmt = sample_format;
 		_codec_context->sample_rate = frame_rate;
-		_codec_context->channel_layout = av_get_default_channel_layout (channels);
-		_codec_context->channels = channels;
+		av_channel_layout_default (&_codec_context->ch_layout, channels);
+		//_codec_context->channels = channels;
 
 		int r = avcodec_open2 (_codec_context, _codec, 0);
 		if (r < 0) {
@@ -132,6 +132,8 @@ public:
 		DCPOMATIC_ASSERT (size);
 
 		auto frame = av_frame_alloc ();
+		AVChannelLayout ch_layout;
+		av_channel_layout_default (&ch_layout, channels);
 		DCPOMATIC_ASSERT (frame);
 
 		int line_size;
@@ -143,7 +145,7 @@ public:
 
 		frame->nb_samples = size;
 		frame->format = _codec_context->sample_fmt;
-		frame->channels = channels;
+		frame->ch_layout = ch_layout;
 		int r = avcodec_fill_audio_frame (frame, channels, _codec_context->sample_fmt, (const uint8_t *) samples, buffer_size, 0);
 		DCPOMATIC_ASSERT (r >= 0);
 
-- 
2.45.2

