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
This commit is contained in:
parent
95631c94c4
commit
3e71220efc
Notes:
blender-bot
2023-05-22 08:58:32 +02:00
Referenced by issue #100749, Blender LTS: Maintenance Task 3.3
|
@ -6,6 +6,7 @@ if(WITH_GTESTS)
|
|||
tests/ffmpeg_codecs.cc
|
||||
)
|
||||
set(TEST_INC
|
||||
.
|
||||
)
|
||||
set(TEST_INC_SYS
|
||||
${FFMPEG_INCLUDE_DIRS}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue