Skip to content

Commit

Permalink
fix #980 building with FFmpeg v7
Browse files Browse the repository at this point in the history
  • Loading branch information
ddennedy committed Apr 13, 2024
1 parent a089fcc commit c461942
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 21 deletions.
6 changes: 6 additions & 0 deletions src/modules/avformat/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,15 @@ int64_t mlt_to_av_channel_layout(mlt_channel_layout layout)
return 0;
}

#ifdef HAVE_FFMPEG_CH_LAYOUT
mlt_channel_layout av_channel_layout_to_mlt(AVChannelLayout *layout)
{
switch (layout->u.mask) {
#else
mlt_channel_layout av_channel_layout_to_mlt(int64_t layout)
{
switch (layout) {
#endif
case 0:
return mlt_channel_independent;
case AV_CH_LAYOUT_MONO:
Expand Down
5 changes: 5 additions & 0 deletions src/modules/avformat/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,15 @@
#include <libswscale/swscale.h>

#define MLT_AVFILTER_SWS_FLAGS "bicubic+accurate_rnd+full_chroma_int+full_chroma_inp"
#define HAVE_FFMPEG_CH_LAYOUT (LIBAVUTIL_VERSION_MAJOR > 57)

int mlt_to_av_sample_format(mlt_audio_format format);
int64_t mlt_to_av_channel_layout(mlt_channel_layout layout);
#ifdef HAVE_FFMPEG_CH_LAYOUT
mlt_channel_layout av_channel_layout_to_mlt(AVChannelLayout *layout);
#else
mlt_channel_layout av_channel_layout_to_mlt(int64_t layout);
#endif
mlt_channel_layout mlt_get_channel_layout_or_default(const char *name, int channels);
int mlt_set_luma_transfer(struct SwsContext *context,
int src_colorspace,
Expand Down
64 changes: 61 additions & 3 deletions src/modules/avformat/consumer_avformat.c
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,12 @@ static AVStream *add_audio_stream(mlt_consumer consumer,
const AVCodec *codec,
AVCodecContext **codec_context,
int channels,
int64_t channel_layout)
#ifdef HAVE_FFMPEG_CH_LAYOUT
AVChannelLayout *channel_layout
#else
int64_t channel_layout
#endif
)
{
// Get the properties
mlt_properties properties = MLT_CONSUMER_PROPERTIES(consumer);
Expand All @@ -740,7 +745,11 @@ static AVStream *add_audio_stream(mlt_consumer consumer,
c->codec_id = codec->id;
c->codec_type = AVMEDIA_TYPE_AUDIO;
c->sample_fmt = pick_sample_fmt(properties, codec);
#ifdef HAVE_FFMPEG_CH_LAYOUT
av_channel_layout_copy(&c->ch_layout, channel_layout);
#else
c->channel_layout = channel_layout;
#endif

// disabled until some audio codecs are multi-threaded
#if 0
Expand Down Expand Up @@ -783,7 +792,11 @@ static AVStream *add_audio_stream(mlt_consumer consumer,
// Set parameters controlled by MLT
c->sample_rate = mlt_properties_get_int(properties, "frequency");
st->time_base = (AVRational){1, c->sample_rate};
#ifdef HAVE_FFMPEG_CH_LAYOUT
c->ch_layout.nb_channels = channels;
#else
c->channels = channels;
#endif

if (mlt_properties_get(properties, "alang") != NULL)
av_dict_set(&oc->metadata, "language", mlt_properties_get(properties, "alang"), 0);
Expand Down Expand Up @@ -1195,13 +1208,15 @@ typedef struct
size_t size;
} buffer_t;

#ifndef HAVE_FFMPEG_CH_LAYOUT
static int mlt_write(void *h, uint8_t *buf, int size)
{
mlt_properties properties = (mlt_properties) h;
buffer_t buffer = {buf, size};
mlt_events_fire(properties, "avformat-write", mlt_event_data_from_object(&buffer));
return 0;
}
#endif

typedef struct encode_ctx_desc
{
Expand Down Expand Up @@ -1295,7 +1310,11 @@ static int encode_audio(encode_ctx_t *ctx)
ctx->audio_avframe->pts = ctx->sample_count[i];
ctx->sample_count[i] += ctx->audio_avframe->nb_samples;
avcodec_fill_audio_frame(ctx->audio_avframe,
#ifdef HAVE_FFMPEG_CH_LAYOUT
codec->ch_layout.nb_channels,
#else
codec->channels,
#endif
codec->sample_fmt,
(const uint8_t *) p,
AUDIO_ENCODE_BUFFER_SIZE,
Expand Down Expand Up @@ -1371,7 +1390,11 @@ static int encode_audio(encode_ctx_t *ctx)
ctx->audio_avframe->pts = ctx->sample_count[i];
ctx->sample_count[i] += ctx->audio_avframe->nb_samples;
avcodec_fill_audio_frame(ctx->audio_avframe,
#ifdef HAVE_FFMPEG_CH_LAYOUT
codec->ch_layout.nb_channels,
#else
codec->channels,
#endif
codec->sample_fmt,
(const uint8_t *) ctx->audio_buf_2,
AUDIO_ENCODE_BUFFER_SIZE,
Expand Down Expand Up @@ -1625,6 +1648,11 @@ static void *consumer_thread(void *arg)
}
if (enc_ctx->audio_codec_id != AV_CODEC_ID_NONE) {
int is_multi = 0;
#ifdef HAVE_FFMPEG_CH_LAYOUT
AVChannelLayout ch_layout;
#else
int64_t ch_layout;
#endif

enc_ctx->total_channels = 0;
// multitrack audio
Expand All @@ -1634,12 +1662,24 @@ static void *consumer_thread(void *arg)
if (j) {
is_multi = 1;
enc_ctx->total_channels += j;
#ifdef HAVE_FFMPEG_CH_LAYOUT
av_channel_layout_default(&ch_layout, j);
enc_ctx->audio_st[i] = add_audio_stream(consumer,
enc_ctx->oc,
audio_codec,
&enc_ctx->acodec_ctx[i],
j,
&ch_layout);
av_channel_layout_uninit(&ch_layout);
#else
ch_layout = av_get_default_channel_layout(j);
enc_ctx->audio_st[i] = add_audio_stream(consumer,
enc_ctx->oc,
audio_codec,
&enc_ctx->acodec_ctx[i],
j,
av_get_default_channel_layout(j));
ch_layout);
#endif
}
}
// single track
Expand All @@ -1650,12 +1690,24 @@ static void *consumer_thread(void *arg)
|| mlt_audio_channel_layout_channels(layout) != enc_ctx->channels) {
layout = mlt_audio_channel_layout_default(enc_ctx->channels);
}
#ifdef HAVE_FFMPEG_CH_LAYOUT
av_channel_layout_from_mask(&ch_layout, mlt_to_av_channel_layout(layout));
enc_ctx->audio_st[0] = add_audio_stream(consumer,
enc_ctx->oc,
audio_codec,
&enc_ctx->acodec_ctx[0],
enc_ctx->channels,
mlt_to_av_channel_layout(layout));
&ch_layout);
av_channel_layout_uninit(&ch_layout);
#else
ch_layout = mlt_to_av_channel_layout(layout);
enc_ctx->audio_st[0] = add_audio_stream(consumer,
enc_ctx->oc,
audio_codec,
&enc_ctx->acodec_ctx[0],
enc_ctx->channels,
ch_layout);
#endif
enc_ctx->total_channels = enc_ctx->channels;
}
}
Expand Down Expand Up @@ -1719,6 +1771,7 @@ static void *consumer_thread(void *arg)

// Setup custom I/O if redirecting
if (mlt_properties_get_int(properties, "redirect")) {
#ifndef HAVE_FFMPEG_CH_LAYOUT
int buffer_size = 32768;
unsigned char *buffer = av_malloc(buffer_size);
AVIOContext *io
Expand All @@ -1739,6 +1792,7 @@ static void *consumer_thread(void *arg)
mlt_log_error(MLT_CONSUMER_SERVICE(consumer),
"failed to setup output redirection\n");
}
#endif
}
// Open the output file, if needed
else if (!(fmt->flags & AVFMT_NOFILE)) {
Expand Down Expand Up @@ -1780,8 +1834,12 @@ static void *consumer_thread(void *arg)
AVCodecContext *c = enc_ctx->acodec_ctx[0];
enc_ctx->audio_avframe->format = c->sample_fmt;
enc_ctx->audio_avframe->nb_samples = enc_ctx->audio_input_frame_size;
#ifdef HAVE_FFMPEG_CH_LAYOUT
av_channel_layout_copy(&enc_ctx->audio_avframe->ch_layout, &c->ch_layout);
#else
enc_ctx->audio_avframe->channel_layout = c->channel_layout;
enc_ctx->audio_avframe->channels = c->channels;
#endif
} else {
mlt_log_error(MLT_CONSUMER_SERVICE(consumer), "failed to allocate audio AVFrame\n");
mlt_events_fire(properties, "consumer-fatal-error", mlt_event_data_none());
Expand Down
31 changes: 29 additions & 2 deletions src/modules/avformat/filter_avfilter.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,6 @@ static void init_audio_filtergraph(mlt_filter filter,
int sample_fmts[] = {-1, -1};
int sample_rates[] = {-1, -1};
int channel_counts[] = {-1, -1};
int64_t channel_layouts[] = {-1, -1};
char channel_layout_str[64];
int ret;

Expand All @@ -192,11 +191,19 @@ static void init_audio_filtergraph(mlt_filter filter,
sample_fmts[0] = mlt_to_av_sample_format(format);
sample_rates[0] = frequency;
channel_counts[0] = channels;
#if HAVE_FFMPEG_CH_LAYOUT
AVChannelLayout ch_layout;
av_channel_layout_default(&ch_layout, channels);
av_channel_layout_describe(&ch_layout, channel_layout_str, sizeof(channel_layout_str));
av_channel_layout_uninit(&ch_layout);
#else
int64_t channel_layouts[] = {-1, -1};
channel_layouts[0] = av_get_default_channel_layout(channels);
av_get_channel_layout_string(channel_layout_str,
sizeof(channel_layout_str),
0,
channel_layouts[0]);
#endif

// Destroy the current filter graph
avfilter_graph_free(&pdata->avfilter_graph);
Expand Down Expand Up @@ -290,6 +297,16 @@ static void init_audio_filtergraph(mlt_filter filter,
mlt_log_error(filter, "Cannot set sink channel counts\n");
goto fail;
}
#if HAVE_FFMPEG_CH_LAYOUT
ret = av_opt_set(pdata->avbuffsink_ctx,
"ch_layouts",
channel_layout_str,
AV_OPT_SEARCH_CHILDREN);
if (ret < 0) {
mlt_log_error(filter, "Cannot set sink ch_layouts\n");
goto fail;
}
#else
ret = av_opt_set_int_list(pdata->avbuffsink_ctx,
"channel_layouts",
channel_layouts,
Expand All @@ -299,6 +316,7 @@ static void init_audio_filtergraph(mlt_filter filter,
mlt_log_error(filter, "Cannot set sink channel_layouts\n");
goto fail;
}
#endif
ret = avfilter_init_str(pdata->avbuffsink_ctx, NULL);
if (ret < 0) {
mlt_log_error(filter, "Cannot init buffer sink\n");
Expand Down Expand Up @@ -676,8 +694,12 @@ static int filter_get_audio(mlt_frame frame,
*channels);
pdata->avinframe->sample_rate = *frequency;
pdata->avinframe->format = mlt_to_av_sample_format(*format);
#ifdef HAVE_FFMPEG_CH_LAYOUT
av_channel_layout_from_mask(&pdata->avinframe->ch_layout, mlt_to_av_channel_layout(layout));
#else
pdata->avinframe->channel_layout = mlt_to_av_channel_layout(layout);
pdata->avinframe->channels = *channels;
#endif
pdata->avinframe->nb_samples = *samples;
pdata->avinframe->pts = samplepos;
ret = av_frame_get_buffer(pdata->avinframe, 1);
Expand Down Expand Up @@ -707,7 +729,12 @@ static int filter_get_audio(mlt_frame frame,
}

// Sanity check the output frame
if (*channels != pdata->avoutframe->channels || *samples != pdata->avoutframe->nb_samples
#ifdef HAVE_FFMPEG_CH_LAYOUT
if (*channels != pdata->avoutframe->ch_layout.nb_channels
#else
if (*channels != pdata->avoutframe->channels
#endif
|| *samples != pdata->avoutframe->nb_samples
|| *frequency != pdata->avoutframe->sample_rate) {
mlt_log_error(filter, "Unexpected return format\n");
goto exit;
Expand Down
35 changes: 33 additions & 2 deletions src/modules/avformat/link_avfilter.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,6 @@ static void init_audio_filtergraph(mlt_link self,
int sample_fmts[] = {-1, -1};
int sample_rates[] = {-1, -1};
int channel_counts[] = {-1, -1};
int64_t channel_layouts[] = {-1, -1};
char channel_layout_str[64];
int ret;

Expand All @@ -217,11 +216,19 @@ static void init_audio_filtergraph(mlt_link self,
sample_fmts[0] = mlt_to_av_sample_format(format);
sample_rates[0] = frequency;
channel_counts[0] = channels;
#if HAVE_FFMPEG_CH_LAYOUT
AVChannelLayout ch_layout;
av_channel_layout_default(&ch_layout, channels);
av_channel_layout_describe(&ch_layout, channel_layout_str, sizeof(channel_layout_str));
av_channel_layout_uninit(&ch_layout);
#else
int64_t channel_layouts[] = {-1, -1};
channel_layouts[0] = av_get_default_channel_layout(channels);
av_get_channel_layout_string(channel_layout_str,
sizeof(channel_layout_str),
0,
channel_layouts[0]);
#endif

// Destroy the current filter graph
avfilter_graph_free(&pdata->avfilter_graph);
Expand Down Expand Up @@ -315,6 +322,16 @@ static void init_audio_filtergraph(mlt_link self,
mlt_log_error(self, "Cannot set sink channel counts\n");
goto fail;
}
#if HAVE_FFMPEG_CH_LAYOUT
ret = av_opt_set(pdata->avbuffsink_ctx,
"ch_layouts",
channel_layout_str,
AV_OPT_SEARCH_CHILDREN);
if (ret < 0) {
mlt_log_error(self, "Cannot set sink ch_layouts\n");
goto fail;
}
#else
ret = av_opt_set_int_list(pdata->avbuffsink_ctx,
"channel_layouts",
channel_layouts,
Expand All @@ -324,6 +341,7 @@ static void init_audio_filtergraph(mlt_link self,
mlt_log_error(self, "Cannot set sink channel_layouts\n");
goto fail;
}
#endif
ret = avfilter_init_str(pdata->avbuffsink_ctx, NULL);
if (ret < 0) {
mlt_log_error(self, "Cannot init buffer sink\n");
Expand Down Expand Up @@ -762,8 +780,12 @@ static int link_get_audio(mlt_frame frame,
int inbufsize = mlt_audio_format_size(in.format, in.samples, in.channels);
pdata->avinframe->sample_rate = in.frequency;
pdata->avinframe->format = mlt_to_av_sample_format(in.format);
#ifdef HAVE_FFMPEG_CH_LAYOUT
av_channel_layout_from_mask(&pdata->avinframe->ch_layout, mlt_to_av_channel_layout(layout));
#else
pdata->avinframe->channel_layout = mlt_to_av_channel_layout(layout);
pdata->avinframe->channels = in.channels;
#endif
pdata->avinframe->nb_samples = in.samples;
pdata->avinframe->pts = samplepos;
ret = av_frame_get_buffer(pdata->avinframe, 1);
Expand Down Expand Up @@ -798,12 +820,21 @@ static int link_get_audio(mlt_frame frame,
}

// Sanity check the output frame
if (*channels != pdata->avoutframe->channels || *samples != pdata->avoutframe->nb_samples
#ifdef HAVE_FFMPEG_CH_LAYOUT
if (*channels != pdata->avoutframe->ch_layout.nb_channels
#else
if (*channels != pdata->avoutframe->channels
#endif
|| *samples != pdata->avoutframe->nb_samples
|| *frequency != pdata->avoutframe->sample_rate) {
mlt_log_error(self,
"Unexpected return format c %d->%d\tf %d->%d\tf %d->%d\n",
*channels,
#ifdef HAVE_FFMPEG_CH_LAYOUT
pdata->avoutframe->ch_layout.nb_channels,
#else
pdata->avoutframe->channels,
#endif
*samples,
pdata->avoutframe->nb_samples,
*frequency,
Expand Down
Loading

0 comments on commit c461942

Please sign in to comment.