View Bug Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0002841 | DCP-o-matic | Bugs | public | 2024-06-29 00:16 | 2024-07-04 00:17 |
Reporter | bradel | Assigned To | carl | ||
Priority | normal | Severity | minor | Reproducibility | always |
Status | resolved | Resolution | fixed | ||
Platform | 64-bit | OS | Linux | OS Version | Arch |
Product Version | 2.16.87 | ||||
Summary | 0002841: DCPoMatic does not compile with ffmpeg 7 due to API changes channel_layout -> ch_layout | ||||
Description | Dear Carl, Arch Linux recently rolled ffmpeg 7 out, which has changed the API regarding the channel_layout. I have attempted to adapt DCPoMatic for ffmpeg 7 (see attached patch), however I am by no means an expert in using ffmpeg or in the DCPoMatic code base :). So I am not sure that my patch is actually correct. Also, the patch does not yet consider the installed ffmpeg version, making it basically incompatible with older ffmpeg versions. Best regards, | ||||
Steps To Reproduce | Compile DCPoMatic with ffmpeg 7 | ||||
Additional Information | Additionally I receive the following warnings: ../src/lib/ffmpeg_file_encoder.cc: In destructor ‘ExportAudioStream::~ExportAudioStream()’: ../src/lib/ffmpeg_examiner.cc: In constructor ‘FFmpegExaminer::FFmpegExaminer(std::shared_ptr<const FFmpegContent>, std::shared_ptr<Job>)’: ../test/image_filename_sorter_test.cc: In member function ‘void image_filename_sorter_test2::test_method()’: | ||||
Tags | No tags attached. | ||||
Branch | |||||
Estimated weeks required | |||||
Estimated work required | |||||
|
0002-Use-new-ffmpeg-7-API-for-channel_layout-ch_layout.patch (6,325 bytes)
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 |
|
I have reworked the patch and now included a test for the presence of the AVChannelLayout struct. The new patch should now be compatible with previous ffmpeg versions and ffmpeg 7 0002-Use-new-ffmpeg-7-API-for-channel_layout-ch_layout_V2.patch (8,398 bytes)
From 498d071f8e2c7c46a54ebb7add24d0a4bc43d1b7 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 if detected. --- src/lib/audio_filter_graph.cc | 25 ++++++++++++++++++++++++- src/lib/audio_filter_graph.h | 4 ++++ src/lib/ffmpeg_decoder.cc | 4 ++++ src/lib/ffmpeg_examiner.cc | 11 ++++++++++- src/lib/ffmpeg_file_encoder.cc | 15 +++++++++++++-- wscript | 12 ++++++++++++ 6 files changed, 67 insertions(+), 4 deletions(-) diff --git a/src/lib/audio_filter_graph.cc b/src/lib/audio_filter_graph.cc index 4e3052d57..fc506f1ef 100644 --- a/src/lib/audio_filter_graph.cc +++ b/src/lib/audio_filter_graph.cc @@ -49,9 +49,17 @@ 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) { +#ifdef DCPOMATIC_HAVE_AVCHANNELLAYOUT + av_channel_layout_default (&_channel_layout, 16); +#else _channel_layout = av_get_default_channel_layout (16); +#endif } else { +#ifdef DCPOMATIC_HAVE_AVCHANNELLAYOUT + av_channel_layout_default (&_channel_layout, _channels); +#else _channel_layout = av_get_default_channel_layout (_channels); +#endif } _in_frame = av_frame_alloc (); @@ -69,8 +77,11 @@ string AudioFilterGraph::src_parameters () const { char layout[64]; +#ifdef DCPOMATIC_HAVE_AVCHANNELLAYOUT + av_channel_layout_describe (&_channel_layout, layout, sizeof(layout)); +#else av_get_channel_layout_string (layout, sizeof(layout), 0, _channel_layout); - +#endif char buffer[256]; snprintf ( buffer, sizeof(buffer), "time_base=1/1:sample_rate=%d:sample_fmt=%s:channel_layout=%s", @@ -88,8 +99,12 @@ 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); +#ifdef DCPOMATIC_HAVE_AVCHANNELLAYOUT + r = av_opt_set_chlayout (context, "channel_layouts", &_channel_layout, AV_OPT_SEARCH_CHILDREN); +#else int64_t channel_layouts[] = { _channel_layout, -1 }; r = av_opt_set_int_list (context, "channel_layouts", channel_layouts, -1, AV_OPT_SEARCH_CHILDREN); +#endif DCPOMATIC_ASSERT (r >= 0); int sample_rates[] = { _sample_rate, -1 }; @@ -114,7 +129,11 @@ void AudioFilterGraph::process (shared_ptr<AudioBuffers> buffers) { DCPOMATIC_ASSERT (buffers->frames() > 0); +#ifdef DCPOMATIC_HAVE_AVCHANNELLAYOUT + int const process_channels = _channel_layout.nb_channels; +#else int const process_channels = av_get_channel_layout_nb_channels (_channel_layout); +#endif DCPOMATIC_ASSERT (process_channels >= buffers->channels()); if (buffers->channels() < process_channels) { @@ -144,8 +163,12 @@ 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; +#ifdef DCPOMATIC_HAVE_AVCHANNELLAYOUT + _in_frame->ch_layout = _channel_layout; +#else _in_frame->channel_layout = _channel_layout; _in_frame->channels = process_channels; +#endif 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..9bbd28949 100644 --- a/src/lib/audio_filter_graph.h +++ b/src/lib/audio_filter_graph.h @@ -47,7 +47,11 @@ protected: private: int _sample_rate; int _channels; +#ifdef DCPOMATIC_HAVE_AVCHANNELLAYOUT + AVChannelLayout _channel_layout; +#else int64_t _channel_layout; +#endif AVFrame* _in_frame; }; diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 45983795b..76e52e272 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -260,7 +260,11 @@ deinterleave_audio(AVFrame* frame) /* XXX: can't we use swr_convert() to do the format conversion? */ +#ifdef DCPOMATIC_HAVE_AVCHANNELLAYOUT + int const channels = frame->ch_layout.nb_channels; +#else int const channels = frame->channels; +#endif 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..0ed2aa5c1 100644 --- a/src/lib/ffmpeg_examiner.cc +++ b/src/lib/ffmpeg_examiner.cc @@ -76,10 +76,15 @@ 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. */ - +#ifdef DCPOMATIC_HAVE_AVCHANNELLAYOUT + if (s->codecpar->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) { + av_channel_layout_default (&s->codecpar->ch_layout, s->codecpar->ch_layout.nb_channels); + } +#else if (s->codecpar->channel_layout == 0) { s->codecpar->channel_layout = av_get_default_channel_layout (s->codecpar->channels); } +#endif DCPOMATIC_ASSERT (_format_context->duration != AV_NOPTS_VALUE); DCPOMATIC_ASSERT (codec->name); @@ -91,7 +96,11 @@ 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), +#ifdef DCPOMATIC_HAVE_AVCHANNELLAYOUT + s->codecpar->ch_layout.nb_channels, +#else s->codecpar->channels, +#endif 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..196b8aa98 100644 --- a/src/lib/ffmpeg_file_encoder.cc +++ b/src/lib/ffmpeg_file_encoder.cc @@ -36,7 +36,6 @@ extern "C" { #include "i18n.h" - using std::cout; using std::make_shared; using std::shared_ptr; @@ -73,9 +72,12 @@ public: _codec_context->bit_rate = channels * 128 * 1024; _codec_context->sample_fmt = sample_format; _codec_context->sample_rate = frame_rate; +#ifdef DCPOMATIC_HAVE_AVCHANNELLAYOUT + av_channel_layout_default (&_codec_context->ch_layout, channels); +#else _codec_context->channel_layout = av_get_default_channel_layout (channels); _codec_context->channels = channels; - +#endif int r = avcodec_open2 (_codec_context, _codec, 0); if (r < 0) { throw EncodeError (N_("avcodec_open2"), N_("ExportAudioStream::ExportAudioStream"), r); @@ -134,6 +136,11 @@ public: auto frame = av_frame_alloc (); DCPOMATIC_ASSERT (frame); +#ifdef DCPOMATIC_HAVE_AVCHANNELLAYOUT + AVChannelLayout ch_layout; + av_channel_layout_default (&ch_layout, channels); +#endif + int line_size; int const buffer_size = av_samples_get_buffer_size (&line_size, channels, size, _codec_context->sample_fmt, 0); DCPOMATIC_ASSERT (buffer_size >= 0); @@ -143,7 +150,11 @@ public: frame->nb_samples = size; frame->format = _codec_context->sample_fmt; +#ifdef DCPOMATIC_HAVE_AVCHANNELLAYOUT + frame->ch_layout = ch_layout; +#else frame->channels = channels; +#endif int r = avcodec_fill_audio_frame (frame, channels, _codec_context->sample_fmt, (const uint8_t *) samples, buffer_size, 0); DCPOMATIC_ASSERT (r >= 0); diff --git a/wscript b/wscript index 744e45416..cb1ffadf7 100644 --- a/wscript +++ b/wscript @@ -501,6 +501,18 @@ def configure(conf): define_name='DCPOMATIC_HAVE_AVCOMPONENTDESCRIPTOR_DEPTH_MINUS1', mandatory=False) + # Check to see if we have the AVChannelLayout struct introduced in ffmpeg 7 + conf.check_cxx(fragment=""" + extern "C" {\n + #include <libavutil/channel_layout.h>\n + }\n + int main () { AVChannelLayout ch_layout = {}; }\n + """, + msg='Checking for AVChannelLayout', + uselib='AVUTIL', + define_name='DCPOMATIC_HAVE_AVCHANNELLAYOUT', + mandatory=False) + # See if we have av_register_all and avfilter_register_all conf.check_cxx(fragment=""" extern "C" {\n -- 2.45.2 |
|
Thank you! I think this new API has already been used in DCP-o-matic on the |
|
Ah I am sorry, I missed that you have already adapted the v2.17.x branch. I tried building v2.17.18 and it works if I remove line 146 in AudioFilterGraph. The channels field in the AVFrame struct has been removed in ffmpeg 7. |
|
Great, I fixed up the 2.17 branch to work with FFmpeg 7.0.1 in 5555e580ecbfe6612ac5d18391fc0f6f96b96ac5 and b42699ccbf7865fc84b8c6218c070a1f06d2703a. I added an Thanks for the note and the patch! |
Date Modified | Username | Field | Change |
---|---|---|---|
2024-06-29 00:16 | bradel | New Bug | |
2024-06-29 00:16 | bradel | File Added: 0002-Use-new-ffmpeg-7-API-for-channel_layout-ch_layout.patch | |
2024-06-30 14:32 | bradel | Note Added: 0006468 | |
2024-06-30 14:32 | bradel | File Added: 0002-Use-new-ffmpeg-7-API-for-channel_layout-ch_layout_V2.patch | |
2024-06-30 22:49 | carl | Assigned To | => carl |
2024-06-30 22:49 | carl | Status | new => acknowledged |
2024-06-30 22:50 | carl | Note Added: 0006470 | |
2024-07-01 20:05 | bradel | Note Added: 0006471 | |
2024-07-04 00:17 | carl | Note Added: 0006475 | |
2024-07-04 00:17 | carl | Status | acknowledged => resolved |
2024-07-04 00:17 | carl | Resolution | open => fixed |