From 97f793740636fd27596ca124b885291e0bdddd2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=9Aled=C5=BA?= Date: Fri, 2 Aug 2024 19:23:13 +0200 Subject: [PATCH] Bring back support for older ffmpegs --- Makefile | 2 +- c_src/xav/channel_layout.h | 12 ++++++++++++ c_src/xav/converter.c | 25 +++++++++++++++++++------ c_src/xav/converter.h | 8 +++++--- c_src/xav/decoder.c | 12 ++++++++++-- c_src/xav/reader.c | 12 ++++++++++-- 6 files changed, 57 insertions(+), 14 deletions(-) create mode 100644 c_src/xav/channel_layout.h diff --git a/Makefile b/Makefile index 4e2c93a..9fdb04d 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ XAV_SO = $(PRIV_DIR)/libxav.so # uncomment to compile with debug logs # XAV_DEBUG_LOGS = -DXAV_DEBUG=1 -HEADERS = $(XAV_DIR)/reader.h $(XAV_DIR)/decoder.h $(XAV_DIR)/converter.h $(XAV_DIR)/utils.h +HEADERS = $(XAV_DIR)/reader.h $(XAV_DIR)/decoder.h $(XAV_DIR)/converter.h $(XAV_DIR)/channel_layout.h $(XAV_DIR)/utils.h SOURCES = $(XAV_DIR)/xav_nif.c $(XAV_DIR)/reader.c $(XAV_DIR)/decoder.c $(XAV_DIR)/converter.c $(XAV_DIR)/utils.c CFLAGS = $(XAV_DEBUG_LOGS) -fPIC -shared diff --git a/c_src/xav/channel_layout.h b/c_src/xav/channel_layout.h new file mode 100644 index 0000000..5f7d9d2 --- /dev/null +++ b/c_src/xav/channel_layout.h @@ -0,0 +1,12 @@ +#ifndef CHANNEL_LAYOUT_H +#define CHANNEL_LAYOUT_H +#include + +struct ChannelLayout { +#if LIBAVUTIL_VERSION_MAJOR >= 58 + AVChannelLayout layout; +#else + uint64_t layout; +#endif +}; +#endif \ No newline at end of file diff --git a/c_src/xav/converter.c b/c_src/xav/converter.c index cecaf99..581e7bd 100644 --- a/c_src/xav/converter.c +++ b/c_src/xav/converter.c @@ -5,10 +5,11 @@ #include #include +#include "channel_layout.h" #include "utils.h" -int converter_init(struct Converter *c, AVChannelLayout in_chlayout, int in_sample_rate, - enum AVSampleFormat in_sample_fmt, AVChannelLayout out_chlayout, +int converter_init(struct Converter *c, struct ChannelLayout in_chlayout, int in_sample_rate, + enum AVSampleFormat in_sample_fmt, struct ChannelLayout out_chlayout, int out_sample_rate, enum AVSampleFormat out_sample_fmt) { c->swr_ctx = swr_alloc(); c->in_sample_rate = in_sample_rate; @@ -16,8 +17,13 @@ int converter_init(struct Converter *c, AVChannelLayout in_chlayout, int in_samp c->out_chlayout = out_chlayout; c->out_sample_fmt = out_sample_fmt; - av_opt_set_chlayout(c->swr_ctx, "in_chlayout", &in_chlayout, 0); - av_opt_set_chlayout(c->swr_ctx, "out_chlayout", &out_chlayout, 0); +#if LIBAVUTIL_VERSION_MAJOR >= 58 + av_opt_set_chlayout(c->swr_ctx, "in_chlayout", &in_chlayout.layout, 0); + av_opt_set_chlayout(c->swr_ctx, "out_chlayout", &out_chlayout.layout, 0); +#else + av_opt_set_channel_layout(c->swr_ctx, "in_channel_layout", &in_chlayout.layout, 0); + av_opt_set_channel_layout(c->swr_ctx, "out_channel_layout", &out_chlayout.layout, 0); +#endif av_opt_set_int(c->swr_ctx, "in_sample_rate", in_sample_rate, 0); av_opt_set_int(c->swr_ctx, "out_sample_rate", out_sample_rate, 0); @@ -30,6 +36,13 @@ int converter_init(struct Converter *c, AVChannelLayout in_chlayout, int in_samp int converter_convert(struct Converter *c, AVFrame *src_frame, uint8_t ***out_data, int *out_samples, int *out_size) { + +#if LIBAVUTIL_VERSION_MAJOR >= 58 + int out_nb_channels = c->out_chlayout.layout.nb_channels; +#else + int out_nb_channels = av_get_channel_layout_nb_channels(c->out_chlayout.layout); +#endif + uint8_t **out_data_tmp = NULL; int max_out_nb_samples = swr_get_out_samples(c->swr_ctx, src_frame->nb_samples); int out_bytes_per_sample = av_get_bytes_per_sample(c->out_sample_fmt); @@ -38,7 +51,7 @@ int converter_convert(struct Converter *c, AVFrame *src_frame, uint8_t ***out_da // to use fast/aligned SIMD routines - this is what align option is used for. // See https://stackoverflow.com/questions/35678041/what-is-linesize-alignment-meaning // Because we return the binary straight to the Erlang, we can disable it. - int ret = av_samples_alloc_array_and_samples(&out_data_tmp, NULL, c->out_chlayout.nb_channels, + int ret = av_samples_alloc_array_and_samples(&out_data_tmp, NULL, out_nb_channels, max_out_nb_samples, c->out_sample_fmt, 1); if (ret < 0) { @@ -58,7 +71,7 @@ int converter_convert(struct Converter *c, AVFrame *src_frame, uint8_t ***out_da XAV_LOG_DEBUG("Converted %d samples per channel", *out_samples); - *out_size = *out_samples * out_bytes_per_sample * c->out_chlayout.nb_channels; + *out_size = *out_samples * out_bytes_per_sample * out_nb_channels; return 0; } diff --git a/c_src/xav/converter.h b/c_src/xav/converter.h index f2d1ec2..7117d43 100644 --- a/c_src/xav/converter.h +++ b/c_src/xav/converter.h @@ -4,16 +4,18 @@ #include #include +#include "channel_layout.h" + struct Converter { SwrContext *swr_ctx; int64_t in_sample_rate; int64_t out_sample_rate; - AVChannelLayout out_chlayout; + struct ChannelLayout out_chlayout; enum AVSampleFormat out_sample_fmt; }; -int converter_init(struct Converter *c, AVChannelLayout in_chlayout, int in_sample_rate, - enum AVSampleFormat in_sample_fmt, AVChannelLayout out_chlaout, +int converter_init(struct Converter *c, struct ChannelLayout in_chlayout, int in_sample_rate, + enum AVSampleFormat in_sample_fmt, struct ChannelLayout out_chlaout, int out_sample_rate, enum AVSampleFormat out_sample_fmt); int converter_convert(struct Converter *c, AVFrame *src_frame, uint8_t ***out_data, int *out_samples, int *out_size); diff --git a/c_src/xav/decoder.c b/c_src/xav/decoder.c index 516c332..2155e9b 100644 --- a/c_src/xav/decoder.c +++ b/c_src/xav/decoder.c @@ -32,11 +32,19 @@ int decoder_init(struct Decoder *decoder, const char *codec) { } if (decoder->media_type == AVMEDIA_TYPE_AUDIO) { - AVChannelLayout out_chlayout = decoder->c->ch_layout; int out_sample_rate = decoder->c->sample_rate; enum AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_FLT; - int ret = converter_init(&decoder->converter, decoder->c->ch_layout, decoder->c->sample_rate, + struct ChannelLayout in_chlayout, out_chlayout; +#if LIBAVUTIL_VERSION_MAJOR >= 58 + in_chlayout.layout = decoder->c->ch_layout; + out_chlayout.layout = decoder->c->ch_layout; +#else + in_chlayout.layout = decoder->c->channel_layout; + out_chlayout.layout = decoder->c->channel_layout; +#endif + + int ret = converter_init(&decoder->converter, in_chlayout, decoder->c->sample_rate, decoder->c->sample_fmt, out_chlayout, out_sample_rate, out_sample_fmt); if (ret < 0) { diff --git a/c_src/xav/reader.c b/c_src/xav/reader.c index 61b06e5..4f26406 100644 --- a/c_src/xav/reader.c +++ b/c_src/xav/reader.c @@ -71,11 +71,19 @@ int reader_init(struct Reader *reader, unsigned char *path, size_t path_size, in } if (reader->media_type == AVMEDIA_TYPE_AUDIO) { - AVChannelLayout out_chlayout = AV_CHANNEL_LAYOUT_MONO; int out_sample_rate = 16000; enum AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_FLT; - int ret = converter_init(&reader->converter, reader->c->ch_layout, reader->c->sample_rate, + struct ChannelLayout in_chlayout, out_chlayout; +#if LIBAVUTIL_VERSION_MAJOR >= 58 + in_chlayout.layout = reader->c->ch_layout; + av_channel_layout_from_mask(&out_chlayout.layout, AV_CH_LAYOUT_MONO); +#else + in_chlayout.layout = reader->c->channel_layout; + out_chlayout.layout = AV_CH_LAYOUT_MONO; +#endif + + int ret = converter_init(&reader->converter, in_chlayout, reader->c->sample_rate, reader->c->sample_fmt, out_chlayout, out_sample_rate, out_sample_fmt); if (ret < 0) {