1 From ab430ea4460aba050d97d3e3a712a3b6dd809db9 Mon Sep 17 00:00:00 2001
2 From: Emily <hello@emily.moe>
3 Date: Mon, 15 Jul 2024 00:41:04 +0100
4 Subject: [PATCH 1/4] Fix build with FFmpeg 7
7 libmusly/CMakeLists.txt | 5 --
8 libmusly/decoders/libav.cpp | 136 +++++++++++-------------------------
9 2 files changed, 42 insertions(+), 99 deletions(-)
11 diff --git a/libmusly/CMakeLists.txt b/libmusly/CMakeLists.txt
12 index d6d3680..98151df 100644
13 --- a/libmusly/CMakeLists.txt
14 +++ b/libmusly/CMakeLists.txt
15 @@ -16,11 +16,6 @@ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/external")
16 PROPERTIES COMPILE_FLAGS "-DLIBMUSLY_EXTERNAL ${LIBMUSLY_EXTERNAL_FLAGS}")
19 -if(EXISTS "${LIBAV_INCLUDE_DIRS}/libavutil/channel_layout.h")
20 - set_source_files_properties(decoders/libav.cpp
21 - PROPERTIES COMPILE_FLAGS "-DHAVE_AVUTIL_CHANNEL_LAYOUT")
24 if(USE_OPENMP AND OPENMP_FOUND)
25 # disable OpenMP for kiss FFT, it slows things down terribly
26 set_source_files_properties(kissfft/kiss_fft.c
27 diff --git a/libmusly/decoders/libav.cpp b/libmusly/decoders/libav.cpp
28 index a78b904..90f93ae 100644
29 --- a/libmusly/decoders/libav.cpp
30 +++ b/libmusly/decoders/libav.cpp
33 #include <libavcodec/avcodec.h>
34 #include <libavformat/avformat.h>
35 -#ifdef HAVE_AVUTIL_CHANNEL_LAYOUT
36 #include <libavutil/channel_layout.h>
41 #include "resampler.h"
44 -// We define some macros to be compatible to different libav versions
45 -// without spreading #if and #else all over the place.
46 -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 45, 101)
47 -#define AV_FRAME_ALLOC avcodec_alloc_frame
48 -#define AV_FRAME_UNREF avcodec_get_frame_defaults
49 -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 28, 0)
50 -#define AV_FRAME_FREE(X) av_free(*(X))
52 -#define AV_FRAME_FREE avcodec_free_frame
55 -#define AV_FRAME_ALLOC av_frame_alloc
56 -#define AV_FRAME_UNREF av_frame_unref
57 -#define AV_FRAME_FREE av_frame_free
60 -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 7, 0)
61 -#define AV_PACKET_UNREF av_free_packet
63 -#define AV_PACKET_UNREF av_packet_unref
69 @@ -58,12 +34,6 @@ MUSLY_DECODER_REGIMPL(libav, 0);
73 -#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 9, 100)
76 -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100)
77 - avcodec_register_all();
82 @@ -177,13 +147,7 @@ libav::decodeto_22050hz_mono_float(
83 AVStream *st = fmtx->streams[audio_stream_idx];
85 // find a decoder for the stream
86 -#if (LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 14, 0)) || ((LIBAVCODEC_VERSION_MICRO >= 100) && (LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 33, 100)))
87 - // old libav version (libavcodec < 57.14 for libav, < 57.33 for ffmpeg):
88 - // stream has a codec context we can use
89 - AVCodecContext *decx = st->codec;
90 - #define AVCODEC_FREE_CONTEXT(x)
92 - // new libav version: need to create codec context for stream
93 + // need to create codec context for stream
94 AVCodecParameters *decp = st->codecpar;
95 AVCodecContext *decx = avcodec_alloc_context3(NULL);
97 @@ -200,71 +164,63 @@ libav::decodeto_22050hz_mono_float(
98 avformat_close_input(&fmtx);
99 return std::vector<float>(0);
101 - #if LIBAVCODEC_VERSION_MICRO >= 100
102 - #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58,3,102)
103 - // only available in ffmpeg, deprecated after 58
104 - av_codec_set_pkt_timebase(decx, st->time_base);
107 - #define AVCODEC_FREE_CONTEXT(x) avcodec_free_context(x)
109 - AVCodec *dec = avcodec_find_decoder(decx->codec_id);
110 + const AVCodec *dec = avcodec_find_decoder(decx->codec_id);
112 MINILOG(logERROR) << "Could not find codec.";
114 - AVCODEC_FREE_CONTEXT(&decx);
115 + avcodec_free_context(&decx);
116 avformat_close_input(&fmtx);
117 return std::vector<float>(0);
121 // (kindly ask for stereo downmix and floats, but not all decoders care)
122 - decx->request_channel_layout = AV_CH_LAYOUT_STEREO_DOWNMIX;
123 decx->request_sample_fmt = AV_SAMPLE_FMT_FLT;
128 - avret = avcodec_open2(decx, dec, NULL);
129 + AVDictionary *options = NULL;
130 + av_dict_set(&options, "downmix", "stereo", 0);
131 + avret = avcodec_open2(decx, dec, &options);
134 MINILOG(logERROR) << "Could not open codec.";
136 - AVCODEC_FREE_CONTEXT(&decx);
137 + avcodec_free_context(&decx);
138 avformat_close_input(&fmtx);
139 return std::vector<float>(0);
142 // Currently only mono and stereo files are supported.
143 - if ((decx->channels != 1) && (decx->channels != 2)) {
144 + if ((decx->ch_layout.nb_channels != 1) && (decx->ch_layout.nb_channels != 2)) {
145 MINILOG(logWARNING) << "Unsupported number of channels: "
147 + << decx->ch_layout.nb_channels;
149 - AVCODEC_FREE_CONTEXT(&decx);
150 + avcodec_free_context(&decx);
151 avformat_close_input(&fmtx);
152 return std::vector<float>(0);
156 - AVFrame* frame = AV_FRAME_ALLOC();
157 + AVFrame* frame = av_frame_alloc();
159 MINILOG(logWARNING) << "Could not allocate frame";
161 - AVCODEC_FREE_CONTEXT(&decx);
162 + avcodec_free_context(&decx);
163 avformat_close_input(&fmtx);
164 return std::vector<float>(0);
167 // allocate and initialize a packet
169 - av_init_packet(&pkt);
172 + AVPacket* pkt = av_packet_alloc();
178 const int input_stride = av_get_bytes_per_sample(decx->sample_fmt);
179 - const int num_planes = av_sample_fmt_is_planar(decx->sample_fmt) ? decx->channels : 1;
180 + const int num_planes = av_sample_fmt_is_planar(decx->sample_fmt) ? decx->ch_layout.nb_channels : 1;
181 const int output_stride = sizeof(float) * num_planes;
182 int decode_samples; // how many samples to decode; zero to decode all
184 @@ -296,7 +252,7 @@ libav::decodeto_22050hz_mono_float(
185 // fault when trying to access frame->data[i] for i > 0 further below)
186 if ((excerpt_start > 0) and (av_seek_frame(fmtx, audio_stream_idx,
187 excerpt_start * st->time_base.den / st->time_base.num,
188 - AVSEEK_FLAG_BACKWARD || AVSEEK_FLAG_ANY) >= 0)) {
189 + AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_ANY) >= 0)) {
190 // skipping went fine: decode only what's needed
191 decode_samples = excerpt_length * decx->sample_rate;
193 @@ -333,7 +289,7 @@ libav::decodeto_22050hz_mono_float(
194 // excerpt_start tells us up to how many seconds to cut from the beginning.
197 - const int channels = decx->channels;
198 + const int channels = decx->ch_layout.nb_channels;
199 const int sample_rate = decx->sample_rate;
200 float* buffer = NULL;
202 @@ -344,35 +300,29 @@ libav::decodeto_22050hz_mono_float(
204 // skip all frames that are not part of the audio stream, and spurious
205 // frames possibly found after seeking (wrong channels / sample_rate)
206 - while (((avret = av_read_frame(fmtx, &pkt)) >= 0)
207 - && ((pkt.stream_index != audio_stream_idx) ||
208 - (decx->channels != channels) ||
209 + while (((avret = av_read_frame(fmtx, pkt)) >= 0)
210 + && ((pkt->stream_index != audio_stream_idx) ||
211 + (decx->ch_layout.nb_channels != channels) ||
212 (decx->sample_rate != sample_rate)))
214 - AV_PACKET_UNREF(&pkt);
215 + av_packet_unref(pkt);
216 MINILOG(logTRACE) << "Skipping frame...";
219 // stop decoding if av_read_frame() failed
220 - AV_PACKET_UNREF(&pkt);
221 + av_packet_unref(pkt);
225 - uint8_t* data = pkt.data;
226 - int size = pkt.size;
227 - while (pkt.size > 0) {
228 + uint8_t* data = pkt->data;
229 + int size = pkt->size;
230 + while (pkt->size > 0) {
232 // try to decode a frame
233 - AV_FRAME_UNREF(frame);
234 + av_frame_unref(frame);
238 -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 101)
239 - len = avcodec_decode_audio4(decx, frame, &got_frame, &pkt);
241 - avret = AVERROR(EINVAL);
244 avret = avcodec_receive_frame(decx, frame);
247 @@ -381,14 +331,13 @@ libav::decodeto_22050hz_mono_float(
251 - avret = avcodec_send_packet(decx, &pkt);
252 + avret = avcodec_send_packet(decx, pkt);
256 } else if (avret == AVERROR(EAGAIN)) {
262 MINILOG(logWARNING) << "Error decoding an audio frame";
264 @@ -400,8 +349,8 @@ libav::decodeto_22050hz_mono_float(
266 // if too many frames failed decoding, abort
267 MINILOG(logERROR) << "Too many errors, aborting.";
268 - AV_FRAME_FREE(&frame);
269 - AV_PACKET_UNREF(&pkt);
270 + av_frame_free(&frame);
271 + av_packet_unref(pkt);
272 avformat_close_input(&fmtx);
275 @@ -414,7 +363,7 @@ libav::decodeto_22050hz_mono_float(
278 // do we need to increase the buffer size?
279 - int input_samples = frame->nb_samples*decx->channels;
280 + int input_samples = frame->nb_samples*decx->ch_layout.nb_channels;
281 if (input_samples > buffersize) {
284 @@ -434,8 +383,8 @@ libav::decodeto_22050hz_mono_float(
285 input_samples / num_planes) < 0) {
286 MINILOG(logERROR) << "Strange sample format. Abort.";
288 - AV_FRAME_FREE(&frame);
289 - AV_PACKET_UNREF(&pkt);
290 + av_frame_free(&frame);
291 + av_packet_unref(pkt);
292 avformat_close_input(&fmtx);
295 @@ -445,7 +394,7 @@ libav::decodeto_22050hz_mono_float(
298 // inplace downmix to mono, if required
299 - if (decx->channels == 2) {
300 + if (decx->ch_layout.nb_channels == 2) {
301 for (int i = 0; i < frame->nb_samples; i++) {
302 buffer[i] = (buffer[i*2] + buffer[i*2+1]) / 2.0f;
304 @@ -457,13 +406,13 @@ libav::decodeto_22050hz_mono_float(
307 // consume the packet
318 - AV_PACKET_UNREF(&pkt);
319 + av_packet_unref(pkt);
321 MINILOG(logTRACE) << "Decoding loop finished.";
323 @@ -514,13 +463,12 @@ libav::decodeto_22050hz_mono_float(
327 - AV_FRAME_FREE(&frame);
328 + av_frame_free(&frame);
333 - avcodec_close(decx);
334 - AVCODEC_FREE_CONTEXT(&decx);
335 + avcodec_free_context(&decx);
336 avformat_close_input(&fmtx);