[Bf-blender-cvs] [98fc2aa93f1] temp-asset-representation: Fix support for building with ffmpeg < 5.0

Sebastian Parborg noreply at git.blender.org
Tue Nov 8 12:42:26 CET 2022


Commit: 98fc2aa93f1f699744ce7caca5c4032de2786fb5
Author: Sebastian Parborg
Date:   Mon Nov 7 17:44:14 2022 +0100
Branches: temp-asset-representation
https://developer.blender.org/rB98fc2aa93f1f699744ce7caca5c4032de2786fb5

Fix support for building with ffmpeg < 5.0

Seems like the new audio channel api was not as backwards compatible as we thought.
Therefore we need to reintroduce the usage of the old api to make older ffmpeg version be able to compile Blender.

This change is only intended to stick around for two releases or so. After that we hope that most Linux distros ship
ffmpeg >=5.0 so we can switch to it.

Reviewed By: Sergey

Differential Revision: http://developer.blender.org/D16408

===================================================================

M	intern/ffmpeg/CMakeLists.txt
M	intern/ffmpeg/ffmpeg_compat.h
M	intern/ffmpeg/tests/ffmpeg_codecs.cc
M	source/blender/blenkernel/intern/writeffmpeg.c

===================================================================

diff --git a/intern/ffmpeg/CMakeLists.txt b/intern/ffmpeg/CMakeLists.txt
index 0de8496f3f3..4fb5df9d4cd 100644
--- a/intern/ffmpeg/CMakeLists.txt
+++ b/intern/ffmpeg/CMakeLists.txt
@@ -6,6 +6,7 @@ if(WITH_GTESTS)
     tests/ffmpeg_codecs.cc
   )
   set(TEST_INC
+    .
   )
   set(TEST_INC_SYS
     ${FFMPEG_INCLUDE_DIRS}
diff --git a/intern/ffmpeg/ffmpeg_compat.h b/intern/ffmpeg/ffmpeg_compat.h
index f311e04d8e0..f7d87af8bca 100644
--- a/intern/ffmpeg/ffmpeg_compat.h
+++ b/intern/ffmpeg/ffmpeg_compat.h
@@ -36,6 +36,14 @@
 #  define FFMPEG_INLINE static inline
 #endif
 
+#if (LIBAVFORMAT_VERSION_MAJOR < 59)
+/* For versions older than ffmpeg 5.0, use the old channel layout variables.
+ * We intend to only keep this  workaround for around two releases (3.5, 3.6).
+ * If it sticks around any longer, then we should consider refactoring this.
+ */
+#  define FFMPEG_USE_OLD_CHANNEL_VARS
+#endif
+
 #if (LIBAVFORMAT_VERSION_MAJOR < 58) || \
     ((LIBAVFORMAT_VERSION_MAJOR == 58) && (LIBAVFORMAT_VERSION_MINOR < 76))
 #  define FFMPEG_USE_DURATION_WORKAROUND 1
diff --git a/intern/ffmpeg/tests/ffmpeg_codecs.cc b/intern/ffmpeg/tests/ffmpeg_codecs.cc
index 10cbe4b938b..cd06917f59b 100644
--- a/intern/ffmpeg/tests/ffmpeg_codecs.cc
+++ b/intern/ffmpeg/tests/ffmpeg_codecs.cc
@@ -3,6 +3,8 @@
 #include "testing/testing.h"
 
 extern "C" {
+#include "ffmpeg_compat.h"
+
 #include <libavcodec/avcodec.h>
 #include <libavutil/channel_layout.h>
 #include <libavutil/log.h>
@@ -40,7 +42,11 @@ bool test_acodec(const AVCodec *codec, AVSampleFormat fmt)
     if (ctx) {
       ctx->sample_fmt = fmt;
       ctx->sample_rate = 48000;
+#ifdef FFMPEG_USE_OLD_CHANNEL_VARS
+      ctx->channel_layout = AV_CH_LAYOUT_MONO;
+#else
       av_channel_layout_from_mask(&ctx->ch_layout, AV_CH_LAYOUT_MONO);
+#endif
       ctx->bit_rate = 128000;
       int open = avcodec_open2(ctx, codec, NULL);
       if (open >= 0) {
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index d71db8f71a5..4c11a2896a8 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -141,18 +141,25 @@ static int write_audio_frame(FFMpegContext *context)
   frame->pts = context->audio_time / av_q2d(c->time_base);
   frame->nb_samples = context->audio_input_samples;
   frame->format = c->sample_fmt;
+#    ifdef FFMPEG_USE_OLD_CHANNEL_VARS
+  frame->channels = c->channels;
+  frame->channel_layout = c->channel_layout;
+  const int num_channels = c->channels;
+#    else
   av_channel_layout_copy(&frame->ch_layout, &c->ch_layout);
+  const int num_channels = c->ch_layout.nb_channels;
+#    endif
 
   if (context->audio_deinterleave) {
     int channel, i;
     uint8_t *temp;
 
-    for (channel = 0; channel < c->ch_layout.nb_channels; channel++) {
+    for (channel = 0; channel < num_channels; channel++) {
       for (i = 0; i < frame->nb_samples; i++) {
         memcpy(context->audio_deinterleave_buffer +
                    (i + channel * frame->nb_samples) * context->audio_sample_size,
                context->audio_input_buffer +
-                   (c->ch_layout.nb_channels * i + channel) * context->audio_sample_size,
+                   (num_channels * i + channel) * context->audio_sample_size,
                context->audio_sample_size);
       }
     }
@@ -163,10 +170,10 @@ static int write_audio_frame(FFMpegContext *context)
   }
 
   avcodec_fill_audio_frame(frame,
-                           c->ch_layout.nb_channels,
+                           num_channels,
                            c->sample_fmt,
                            context->audio_input_buffer,
-                           context->audio_input_samples * c->ch_layout.nb_channels *
+                           context->audio_input_samples * num_channels *
                                context->audio_sample_size,
                            1);
 
@@ -944,25 +951,34 @@ static AVStream *alloc_audio_stream(FFMpegContext *context,
   c->sample_rate = rd->ffcodecdata.audio_mixrate;
   c->bit_rate = context->ffmpeg_audio_bitrate * 1000;
   c->sample_fmt = AV_SAMPLE_FMT_S16;
-  c->ch_layout.nb_channels = rd->ffcodecdata.audio_channels;
 
+  const int num_channels = rd->ffcodecdata.audio_channels;
+  int channel_layout_mask = 0;
   switch (rd->ffcodecdata.audio_channels) {
     case FFM_CHANNELS_MONO:
-      av_channel_layout_from_mask(&c->ch_layout, AV_CH_LAYOUT_MONO);
+      channel_layout_mask = AV_CH_LAYOUT_MONO;
       break;
     case FFM_CHANNELS_STEREO:
-      av_channel_layout_from_mask(&c->ch_layout, AV_CH_LAYOUT_STEREO);
+      channel_layout_mask = AV_CH_LAYOUT_STEREO;
       break;
     case FFM_CHANNELS_SURROUND4:
-      av_channel_layout_from_mask(&c->ch_layout, AV_CH_LAYOUT_QUAD);
+      channel_layout_mask = AV_CH_LAYOUT_QUAD;
       break;
     case FFM_CHANNELS_SURROUND51:
-      av_channel_layout_from_mask(&c->ch_layout, AV_CH_LAYOUT_5POINT1_BACK);
+      channel_layout_mask = AV_CH_LAYOUT_5POINT1_BACK;
       break;
     case FFM_CHANNELS_SURROUND71:
-      av_channel_layout_from_mask(&c->ch_layout, AV_CH_LAYOUT_7POINT1);
+      channel_layout_mask = AV_CH_LAYOUT_7POINT1;
       break;
   }
+  BLI_assert(channel_layout_mask != 0);
+
+#  ifdef FFMPEG_USE_OLD_CHANNEL_VARS
+  c->channels = num_channels;
+  c->channel_layout = channel_layout_mask;
+#  else
+  av_channel_layout_from_mask(&c->ch_layout, channel_layout_mask);
+#  endif
 
   if (request_float_audio_buffer(codec_id)) {
     /* mainly for AAC codec which is experimental */
@@ -1027,7 +1043,7 @@ static AVStream *alloc_audio_stream(FFMpegContext *context,
      * not sure if that is needed anymore, so let's try out if there are any
      * complaints regarding some FFmpeg versions users might have. */
     context->audio_input_samples = AV_INPUT_BUFFER_MIN_SIZE * 8 / c->bits_per_coded_sample /
-                                   c->ch_layout.nb_channels;
+                                   num_channels;
   }
   else {
     context->audio_input_samples = c->frame_size;
@@ -1037,11 +1053,11 @@ static AVStream *alloc_audio_stream(FFMpegContext *context,
 
   context->audio_sample_size = av_get_bytes_per_sample(c->sample_fmt);
 
-  context->audio_input_buffer = (uint8_t *)av_malloc(
-      context->audio_input_samples * c->ch_layout.nb_channels * context->audio_sample_size);
+  context->audio_input_buffer = (uint8_t *)av_malloc(context->audio_input_samples * num_channels *
+                                                     context->audio_sample_size);
   if (context->audio_deinterleave) {
     context->audio_deinterleave_buffer = (uint8_t *)av_malloc(
-        context->audio_input_samples * c->ch_layout.nb_channels * context->audio_sample_size);
+        context->audio_input_samples * num_channels * context->audio_sample_size);
   }
 
   context->audio_time = 0.0f;
@@ -1432,7 +1448,11 @@ int BKE_ffmpeg_start(void *context_v,
     AVCodecContext *c = context->audio_codec;
 
     AUD_DeviceSpecs specs;
+#    ifdef FFMPEG_USE_OLD_CHANNEL_VARS
+    specs.channels = c->channels;
+#    else
     specs.channels = c->ch_layout.nb_channels;
+#    endif
 
     switch (av_get_packed_sample_fmt(c->sample_fmt)) {
       case AV_SAMPLE_FMT_U8:



More information about the Bf-blender-cvs mailing list