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