Skip to content

Commit 08d7f33

Browse files
author
Robert-André Mauchin
committed
Add compatibility with FFMPEG 7.0
channel_layout has been replaced with ch_layout Fix #953
1 parent a9e34a9 commit 08d7f33

File tree

3 files changed

+100
-15
lines changed

3 files changed

+100
-15
lines changed

src/FFmpegReader.cpp

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* @ref License
1010
*/
1111

12-
// Copyright (c) 2008-2019 OpenShot Studios, LLC, Fabrice Bellard
12+
// Copyright (c) 2008-2024 OpenShot Studios, LLC, Fabrice Bellard
1313
//
1414
// SPDX-License-Identifier: LGPL-3.0-or-later
1515

@@ -671,8 +671,13 @@ bool FFmpegReader::HasAlbumArt() {
671671

672672
void FFmpegReader::UpdateAudioInfo() {
673673
// Set default audio channel layout (if needed)
674+
#if HAVE_CH_LAYOUT
675+
if (!av_channel_layout_check(&(AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->ch_layout)))
676+
AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->ch_layout = (AVChannelLayout) AV_CHANNEL_LAYOUT_STEREO;
677+
#else
674678
if (AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channel_layout == 0)
675679
AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channel_layout = av_get_default_channel_layout(AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channels);
680+
#endif
676681

677682
if (info.sample_rate > 0) {
678683
// Skip init - if info struct already populated
@@ -683,8 +688,13 @@ void FFmpegReader::UpdateAudioInfo() {
683688
info.has_audio = true;
684689
info.file_size = pFormatCtx->pb ? avio_size(pFormatCtx->pb) : -1;
685690
info.acodec = aCodecCtx->codec->name;
691+
#if HAVE_CH_LAYOUT
692+
info.channels = AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->ch_layout.nb_channels;
693+
info.channel_layout = (ChannelLayout) AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->ch_layout.u.mask;
694+
#else
686695
info.channels = AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channels;
687696
info.channel_layout = (ChannelLayout) AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channel_layout;
697+
#endif
688698
info.sample_rate = AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->sample_rate;
689699
info.audio_bit_rate = AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->bit_rate;
690700
if (info.audio_bit_rate <= 0) {
@@ -1593,11 +1603,16 @@ void FFmpegReader::ProcessAudioPacket(int64_t requested_frame) {
15931603

15941604
// determine how many samples were decoded
15951605
int plane_size = -1;
1596-
data_size = av_samples_get_buffer_size(&plane_size, AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channels,
1606+
#if HAVE_CH_LAYOUT
1607+
int nb_channels = AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->ch_layout.nb_channels;
1608+
#else
1609+
int nb_channels = AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channels;
1610+
#endif
1611+
data_size = av_samples_get_buffer_size(&plane_size, nb_channels,
15971612
audio_frame->nb_samples, (AVSampleFormat) (AV_GET_SAMPLE_FORMAT(aStream, aCodecCtx)), 1);
15981613

15991614
// Calculate total number of samples
1600-
packet_samples = audio_frame->nb_samples * AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channels;
1615+
packet_samples = audio_frame->nb_samples * nb_channels;
16011616
} else {
16021617
if (audio_frame) {
16031618
// Free audio frame
@@ -1655,14 +1670,19 @@ void FFmpegReader::ProcessAudioPacket(int64_t requested_frame) {
16551670

16561671
// setup resample context
16571672
avr = SWR_ALLOC();
1673+
#if HAVE_CH_LAYOUT
1674+
av_opt_set_chlayout(avr, "in_chlayout", &AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->ch_layout, 0);
1675+
av_opt_set_chlayout(avr, "out_chlayout", &AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->ch_layout, 0);
1676+
#else
16581677
av_opt_set_int(avr, "in_channel_layout", AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channel_layout, 0);
16591678
av_opt_set_int(avr, "out_channel_layout", AV_GET_CODEC_ATTRIBUTES(aStream, aCodecCtx)->channel_layout, 0);
1679+
av_opt_set_int(avr, "in_channels", info.channels, 0);
1680+
av_opt_set_int(avr, "out_channels", info.channels, 0);
1681+
#endif
16601682
av_opt_set_int(avr, "in_sample_fmt", AV_GET_SAMPLE_FORMAT(aStream, aCodecCtx), 0);
16611683
av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_FLTP, 0);
16621684
av_opt_set_int(avr, "in_sample_rate", info.sample_rate, 0);
16631685
av_opt_set_int(avr, "out_sample_rate", info.sample_rate, 0);
1664-
av_opt_set_int(avr, "in_channels", info.channels, 0);
1665-
av_opt_set_int(avr, "out_channels", info.channels, 0);
16661686
SWR_INIT(avr);
16671687

16681688
// Convert audio samples

src/FFmpegUtilities.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* @ref License
77
*/
88

9-
// Copyright (c) 2008-2019 OpenShot Studios, LLC
9+
// Copyright (c) 2008-2024 OpenShot Studios, LLC
1010
//
1111
// SPDX-License-Identifier: LGPL-3.0-or-later
1212

@@ -33,6 +33,8 @@
3333
#define USE_SW FFMPEG_USE_SWRESAMPLE
3434
#endif
3535

36+
#define HAVE_CH_LAYOUT (LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100))
37+
3638
// Include the FFmpeg headers
3739
extern "C" {
3840
#include <libavcodec/avcodec.h>

src/FFmpegWriter.cpp

Lines changed: 72 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* @ref License
1010
*/
1111

12-
// Copyright (c) 2008-2019 OpenShot Studios, LLC, Fabrice Bellard
12+
// Copyright (c) 2008-2024 OpenShot Studios, LLC, Fabrice Bellard
1313
//
1414
// SPDX-License-Identifier: LGPL-3.0-or-later
1515

@@ -1042,7 +1042,9 @@ AVStream *FFmpegWriter::add_audio_stream() {
10421042

10431043
// Set the sample parameters
10441044
c->bit_rate = info.audio_bit_rate;
1045+
#if !HAVE_CH_LAYOUT
10451046
c->channels = info.channels;
1047+
#endif
10461048

10471049
// Set valid sample rate (or throw error)
10481050
if (codec->supported_samplerates) {
@@ -1060,6 +1062,24 @@ AVStream *FFmpegWriter::add_audio_stream() {
10601062
c->sample_rate = info.sample_rate;
10611063

10621064

1065+
#if HAVE_CH_LAYOUT
1066+
// Set a valid number of channels (or throw error)
1067+
AVChannelLayout ch_layout;
1068+
av_channel_layout_from_mask(&ch_layout, info.channel_layout);
1069+
if (codec->ch_layouts) {
1070+
int i;
1071+
for (i = 0; av_channel_layout_check(&codec->ch_layouts[i]); i++)
1072+
if (av_channel_layout_compare(&ch_layout, &codec->ch_layouts[i])) {
1073+
// Set valid channel layout
1074+
av_channel_layout_copy(&c->ch_layout, &ch_layout);
1075+
break;
1076+
}
1077+
if (!av_channel_layout_check(&codec->ch_layouts[i]))
1078+
throw InvalidChannels("An invalid channel layout was detected (i.e. MONO / STEREO).", path);
1079+
} else
1080+
// Set valid channel layout
1081+
av_channel_layout_copy(&c->ch_layout, &ch_layout);
1082+
#else
10631083
// Set a valid number of channels (or throw error)
10641084
const uint64_t channel_layout = info.channel_layout;
10651085
if (codec->channel_layouts) {
@@ -1075,6 +1095,7 @@ AVStream *FFmpegWriter::add_audio_stream() {
10751095
} else
10761096
// Set valid channel layout
10771097
c->channel_layout = channel_layout;
1098+
#endif
10781099

10791100
// Choose a valid sample_fmt
10801101
if (codec->sample_fmts) {
@@ -1100,13 +1121,30 @@ AVStream *FFmpegWriter::add_audio_stream() {
11001121

11011122
AV_COPY_PARAMS_FROM_CONTEXT(st, c);
11021123

1124+
int nb_channels;
1125+
uint64_t channel_layout;
1126+
const char* nb_channels_label;
1127+
const char* channel_layout_label;
1128+
1129+
#if HAVE_CH_LAYOUT
1130+
nb_channels = c->ch_layout.nb_channels;
1131+
channel_layout = c->ch_layout.u.mask;
1132+
nb_channels_label = "c->ch_layout.nb_channels";
1133+
channel_layout_label = "c->ch_layout.u.mask";
1134+
#else
1135+
nb_channels = c->channels;
1136+
channel_layout = c->channel_layout;
1137+
nb_channels_label = "c->channels";
1138+
channel_layout_label = "c->channel_layout";
1139+
#endif
1140+
11031141
ZmqLogger::Instance()->AppendDebugMethod(
11041142
"FFmpegWriter::add_audio_stream",
11051143
"c->codec_id", c->codec_id,
11061144
"c->bit_rate", c->bit_rate,
1107-
"c->channels", c->channels,
1145+
nb_channels_label, nb_channels,
11081146
"c->sample_fmt", c->sample_fmt,
1109-
"c->channel_layout", c->channel_layout,
1147+
channel_layout_label, channel_layout,
11101148
"c->sample_rate", c->sample_rate);
11111149

11121150
return st;
@@ -1665,14 +1703,23 @@ void FFmpegWriter::write_audio_packets(bool is_final, std::shared_ptr<openshot::
16651703
// setup resample context
16661704
if (!avr) {
16671705
avr = SWR_ALLOC();
1706+
#if HAVE_CH_LAYOUT
1707+
AVChannelLayout in_chlayout;
1708+
AVChannelLayout out_chlayout;
1709+
av_channel_layout_from_mask(&in_chlayout, channel_layout_in_frame);
1710+
av_channel_layout_from_mask(&out_chlayout, info.channel_layout);
1711+
av_opt_set_chlayout(avr, "in_chlayout", &in_chlayout, 0);
1712+
av_opt_set_chlayout(avr, "out_chlayout", &out_chlayout, 0);
1713+
#else
16681714
av_opt_set_int(avr, "in_channel_layout", channel_layout_in_frame, 0);
16691715
av_opt_set_int(avr, "out_channel_layout", info.channel_layout, 0);
1716+
av_opt_set_int(avr, "in_channels", channels_in_frame, 0);
1717+
av_opt_set_int(avr, "out_channels", info.channels, 0);
1718+
#endif
16701719
av_opt_set_int(avr, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
16711720
av_opt_set_int(avr, "out_sample_fmt", output_sample_fmt, 0); // planar not allowed here
16721721
av_opt_set_int(avr, "in_sample_rate", sample_rate_in_frame, 0);
16731722
av_opt_set_int(avr, "out_sample_rate", info.sample_rate, 0);
1674-
av_opt_set_int(avr, "in_channels", channels_in_frame, 0);
1675-
av_opt_set_int(avr, "out_channels", info.channels, 0);
16761723
SWR_INIT(avr);
16771724
}
16781725
// Convert audio samples
@@ -1768,14 +1815,21 @@ void FFmpegWriter::write_audio_packets(bool is_final, std::shared_ptr<openshot::
17681815
// setup resample context
17691816
if (!avr_planar) {
17701817
avr_planar = SWR_ALLOC();
1818+
#if HAVE_CH_LAYOUT
1819+
AVChannelLayout layout;
1820+
av_channel_layout_from_mask(&layout, info.channel_layout);
1821+
av_opt_set_chlayout(avr_planar, "in_chlayout", &layout, 0);
1822+
av_opt_set_chlayout(avr_planar, "out_chlayout", &layout, 0);
1823+
#else
17711824
av_opt_set_int(avr_planar, "in_channel_layout", info.channel_layout, 0);
17721825
av_opt_set_int(avr_planar, "out_channel_layout", info.channel_layout, 0);
1826+
av_opt_set_int(avr_planar, "in_channels", info.channels, 0);
1827+
av_opt_set_int(avr_planar, "out_channels", info.channels, 0);
1828+
#endif
17731829
av_opt_set_int(avr_planar, "in_sample_fmt", output_sample_fmt, 0);
17741830
av_opt_set_int(avr_planar, "out_sample_fmt", audio_codec_ctx->sample_fmt, 0); // planar not allowed here
17751831
av_opt_set_int(avr_planar, "in_sample_rate", info.sample_rate, 0);
17761832
av_opt_set_int(avr_planar, "out_sample_rate", info.sample_rate, 0);
1777-
av_opt_set_int(avr_planar, "in_channels", info.channels, 0);
1778-
av_opt_set_int(avr_planar, "out_channels", info.channels, 0);
17791833
SWR_INIT(avr_planar);
17801834
}
17811835

@@ -1803,9 +1857,13 @@ void FFmpegWriter::write_audio_packets(bool is_final, std::shared_ptr<openshot::
18031857

18041858
// Create output frame (and allocate arrays)
18051859
frame_final->nb_samples = audio_input_frame_size;
1860+
#if HAVE_CH_LAYOUT
1861+
av_channel_layout_from_mask(&frame_final->ch_layout, info.channel_layout);
1862+
#else
18061863
frame_final->channels = info.channels;
1807-
frame_final->format = audio_codec_ctx->sample_fmt;
18081864
frame_final->channel_layout = info.channel_layout;
1865+
#endif
1866+
frame_final->format = audio_codec_ctx->sample_fmt;
18091867
av_samples_alloc(frame_final->data, frame_final->linesize, info.channels,
18101868
frame_final->nb_samples, audio_codec_ctx->sample_fmt, 0);
18111869

@@ -1854,7 +1912,12 @@ void FFmpegWriter::write_audio_packets(bool is_final, std::shared_ptr<openshot::
18541912
frame_final->nb_samples = audio_input_frame_size;
18551913

18561914
// Fill the final_frame AVFrame with audio (non planar)
1857-
avcodec_fill_audio_frame(frame_final, audio_codec_ctx->channels,
1915+
#if HAVE_CH_LAYOUT
1916+
int nb_channels = audio_codec_ctx->ch_layout.nb_channels;
1917+
#else
1918+
int nb_channels = audio_codec_ctx->channels;
1919+
#endif
1920+
avcodec_fill_audio_frame(frame_final, nb_channels,
18581921
audio_codec_ctx->sample_fmt, (uint8_t *) final_samples,
18591922
audio_encoder_buffer_size, 0);
18601923
}

0 commit comments

Comments
 (0)