Add initial bits for Qt6 support
[carla.git] / source / modules / audio_decoder / ad_ffmpeg.c
blob21156dd495856fc407b7fb1b397494d2f7eb4d3d
1 /**
2 Copyright (C) 2011-2013 Robin Gareus <robin@gareus.org>
3 Copyright (C) 2014-2023 Filipe Coelho <falktx@falktx.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser Public License as published by
7 the Free Software Foundation; either version 2.1, or (at your option)
8 any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "ad_plugin.h"
23 #ifdef HAVE_FFMPEG
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <math.h>
31 #include "ffcompat.h"
33 #ifndef MIN
34 #define MIN(a,b) ( ( (a) < (b) )? (a) : (b) )
35 #endif
37 typedef struct {
38 AVFormatContext* formatContext;
39 AVCodecContext* codecContext;
40 AVCodec* codec;
41 AVPacket packet;
42 int audioStream;
43 int pkt_len;
44 uint8_t* pkt_ptr;
46 int16_t m_tmpBuffer[AVCODEC_MAX_AUDIO_FRAME_SIZE];
47 int16_t* m_tmpBufferStart;
48 unsigned long m_tmpBufferLen;
50 int64_t decoder_clock;
51 int64_t output_clock;
52 int64_t seek_frame;
53 unsigned int samplerate;
54 unsigned int channels;
55 int64_t length;
56 } ffmpeg_audio_decoder;
59 static int ad_info_ffmpeg(void *sf, struct adinfo *nfo) {
60 ffmpeg_audio_decoder *priv = (ffmpeg_audio_decoder*) sf;
61 if (!priv) return -1;
62 if (nfo) {
63 nfo->sample_rate = priv->samplerate;
64 nfo->channels = priv->channels;
65 nfo->frames = priv->length;
66 if (nfo->sample_rate==0) return -1;
67 nfo->length = (nfo->frames * 1000) / nfo->sample_rate;
68 nfo->bit_rate = priv->formatContext->bit_rate;
69 nfo->bit_depth = 0;
70 nfo->meta_data = NULL;
71 nfo->can_seek = 1;
73 #ifdef WITH_GTK // XXX replace g_* functions with POSIX equiv
74 AVDictionaryEntry *tag = NULL;
75 // Tags in container
76 while ((tag = av_dict_get(priv->formatContext->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
77 dbg(2, "FTAG: %s=%s", tag->key, tag->value);
78 char * tmp = g_strdup_printf("%s%s<i>%s</i>:%s", nfo->meta_data?nfo->meta_data:"",nfo->meta_data?"\n":"", tag->key, tag->value);
79 if (nfo->meta_data) g_free(nfo->meta_data);
80 nfo->meta_data = tmp;
82 // Tags in stream
83 tag=NULL;
84 AVStream *stream = priv->formatContext->streams[priv->audioStream];
85 while ((tag = av_dict_get(stream->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
86 dbg(2, "STAG: %s=%s", tag->key, tag->value);
87 char * tmp = g_strdup_printf("%s%s<i>%s</i>:%s", nfo->meta_data?nfo->meta_data:"",nfo->meta_data?"\n":"", tag->key, tag->value);
88 if (nfo->meta_data) g_free(nfo->meta_data);
89 nfo->meta_data = tmp;
91 #endif
93 return 0;
96 static void *ad_open_ffmpeg(const char *fn, struct adinfo *nfo) {
97 ffmpeg_audio_decoder *priv = (ffmpeg_audio_decoder*) calloc(1, sizeof(ffmpeg_audio_decoder));
99 priv->m_tmpBufferStart=NULL;
100 priv->m_tmpBufferLen=0;
101 priv->decoder_clock=priv->output_clock=priv->seek_frame=0;
102 priv->packet.size=0; priv->packet.data=NULL;
104 if (avformat_open_input(&priv->formatContext, fn, NULL, NULL) <0) {
105 dbg(0, "ffmpeg is unable to open file '%s'.", fn);
106 free(priv); return(NULL);
109 if (avformat_find_stream_info(priv->formatContext, NULL) < 0) {
110 avformat_close_input(&priv->formatContext);
111 dbg(0, "av_find_stream_info failed" );
112 free(priv); return(NULL);
115 priv->audioStream = -1;
116 unsigned int i;
117 for (i=0; i<priv->formatContext->nb_streams; i++) {
118 if (priv->formatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
119 priv->audioStream = i;
120 break;
123 if (priv->audioStream == -1) {
124 dbg(0, "No Audio Stream found in file");
125 avformat_close_input(&priv->formatContext);
126 free(priv); return(NULL);
129 priv->codecContext = priv->formatContext->streams[priv->audioStream]->codec;
130 priv->codec = avcodec_find_decoder(priv->codecContext->codec_id);
132 if (priv->codec == NULL) {
133 avformat_close_input(&priv->formatContext);
134 dbg(0, "Codec not supported by ffmpeg");
135 free(priv); return(NULL);
137 if (avcodec_open2(priv->codecContext, priv->codec, NULL) < 0) {
138 dbg(0, "avcodec_open failed" );
139 free(priv); return(NULL);
142 dbg(2, "ffmpeg - audio tics: %i/%i [sec]",priv->formatContext->streams[priv->audioStream]->time_base.num,priv->formatContext->streams[priv->audioStream]->time_base.den);
144 int64_t len = priv->formatContext->duration - priv->formatContext->start_time;
146 priv->formatContext->flags|=AVFMT_FLAG_GENPTS;
147 priv->formatContext->flags|=AVFMT_FLAG_IGNIDX;
149 priv->samplerate = priv->codecContext->sample_rate;
150 priv->channels = priv->codecContext->channels ;
151 priv->length = (int64_t)( len * priv->samplerate / AV_TIME_BASE );
153 if (ad_info_ffmpeg((void*)priv, nfo)) {
154 dbg(0, "invalid file info (sample-rate==0)");
155 free(priv); return(NULL);
158 dbg(1, "ffmpeg - %s", fn);
159 if (nfo)
160 dbg(1, "ffmpeg - sr:%i c:%i d:%"PRIi64" f:%"PRIi64, nfo->sample_rate, nfo->channels, nfo->length, nfo->frames);
162 return (void*) priv;
165 static int ad_close_ffmpeg(void *sf) {
166 ffmpeg_audio_decoder *priv = (ffmpeg_audio_decoder*) sf;
167 if (!priv) return -1;
168 avcodec_close(priv->codecContext);
169 avformat_close_input(&priv->formatContext);
170 free(priv);
171 return 0;
174 static void int16_to_float(int16_t *in, float *out, int num_channels, int num_samples, int out_offset) {
175 int i,ii;
176 for (i=0;i<num_samples;i++) {
177 for (ii=0;ii<num_channels;ii++) {
178 out[(i+out_offset)*num_channels+ii]= (float) in[i*num_channels+ii]/ 32768.0;
183 static ssize_t ad_read_ffmpeg(void *sf, float* d, size_t len) {
184 ffmpeg_audio_decoder *priv = (ffmpeg_audio_decoder*) sf;
185 if (!priv) return -1;
186 size_t frames = len / priv->channels;
188 size_t written = 0;
189 ssize_t ret = 0;
190 while (ret >= 0 && written < frames) {
191 dbg(3,"loop: %i/%i (bl:%lu)",written, frames, priv->m_tmpBufferLen );
192 if (priv->seek_frame == 0 && priv->m_tmpBufferLen > 0 ) {
193 int s = MIN(priv->m_tmpBufferLen / priv->channels, frames - written );
194 int16_to_float(priv->m_tmpBufferStart, d, priv->channels, s , written);
195 written += s;
196 priv->output_clock+=s;
197 s = s * priv->channels;
198 priv->m_tmpBufferStart += s;
199 priv->m_tmpBufferLen -= s;
200 ret = 0;
201 } else {
202 priv->m_tmpBufferStart = priv->m_tmpBuffer;
203 priv->m_tmpBufferLen = 0;
205 if (!priv->pkt_ptr || priv->pkt_len <1 ) {
206 if (priv->packet.data) av_free_packet(&priv->packet);
207 ret = av_read_frame(priv->formatContext, &priv->packet);
208 if (ret<0) { dbg(1, "reached end of file."); break; }
209 priv->pkt_len = priv->packet.size;
210 priv->pkt_ptr = priv->packet.data;
213 if (priv->packet.stream_index != priv->audioStream) {
214 priv->pkt_ptr = NULL;
215 continue;
218 /* decode all chunks in packet */
219 int data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
221 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 0, 0)
222 // TODO use av_frame_alloc() and av_frame_free() with newer ffmpeg
223 AVFrame avf;
224 memset(&avf, 0, sizeof(AVFrame));
225 int got_frame = 0;
226 ret = avcodec_decode_audio4(priv->codecContext, &avf, &got_frame, &priv->packet);
227 if (ret >= 0 && got_frame) {
228 int ch, plane_size;
229 const int planar = av_sample_fmt_is_planar(priv->codecContext->sample_fmt);
230 data_size = av_samples_get_buffer_size(&plane_size, priv->codecContext->channels, avf.nb_samples, priv->codecContext->sample_fmt, 1);
231 if (data_size <= AVCODEC_MAX_AUDIO_FRAME_SIZE) {
232 memcpy(priv->m_tmpBuffer, avf.extended_data[0], plane_size);
233 if (planar && priv->codecContext->channels > 1) {
234 uint8_t *out = ((uint8_t *)priv->m_tmpBuffer) + plane_size;
235 for (ch = 1; ch < priv->codecContext->channels; ch++) {
236 memcpy(out, avf.extended_data[ch], plane_size);
237 out += plane_size;
241 } else {
242 ret = -1;
244 #elif LIBAVUTIL_VERSION_INT > AV_VERSION_INT(49, 15, 0) && LIBAVCODEC_VERSION_INT > AV_VERSION_INT(52, 20, 1) // ??
245 // this was deprecated in LIBAVCODEC_VERSION_MAJOR 53
246 ret = avcodec_decode_audio3(priv->codecContext,
247 priv->m_tmpBuffer, &data_size, &priv->packet);
248 #else
249 int len = priv->packet.size;
250 uint8_t *ptr = priv->packet.data;
251 ret = avcodec_decode_audio2(priv->codecContext,
252 priv->m_tmpBuffer, &data_size, ptr, len);
253 #endif
255 if (ret < 0 || ret > priv->pkt_len) {
256 #if 0
257 dbg(0, "audio decode error");
258 return -1;
259 #endif
260 priv->pkt_len=0;
261 ret=0;
262 continue;
265 priv->pkt_len -= ret; priv->pkt_ptr += ret;
267 /* sample exact alignment */
268 if (priv->packet.pts != AV_NOPTS_VALUE) {
269 priv->decoder_clock = priv->samplerate * av_q2d(priv->formatContext->streams[priv->audioStream]->time_base) * priv->packet.pts;
270 } else {
271 dbg(0, "!!! NO PTS timestamp in file");
272 priv->decoder_clock += (data_size>>1) / priv->channels;
275 if (data_size>0) {
276 priv->m_tmpBufferLen+= (data_size>>1); // 2 bytes per sample
279 /* align buffer after seek. */
280 if (priv->seek_frame > 0) {
281 const int diff = priv->output_clock-priv->decoder_clock;
282 if (diff<0) {
283 /* seek ended up past the wanted sample */
284 dbg(0, " !!! Audio seek failed.");
285 return -1;
286 } else if (priv->m_tmpBufferLen < (diff*priv->channels)) {
287 /* wanted sample not in current buffer - keep going */
288 dbg(2, " !!! seeked sample was not in decoded buffer. frames-to-go: %li", diff);
289 priv->m_tmpBufferLen = 0;
290 } else if (diff!=0 && data_size > 0) {
291 /* wanted sample is in current buffer but not at the beginnning */
292 dbg(2, " !!! sync buffer to seek. (diff:%i)", diff);
293 priv->m_tmpBufferStart+= diff*priv->codecContext->channels;
294 priv->m_tmpBufferLen -= diff*priv->codecContext->channels;
295 #if 1
296 memmove(priv->m_tmpBuffer, priv->m_tmpBufferStart, priv->m_tmpBufferLen);
297 priv->m_tmpBufferStart = priv->m_tmpBuffer;
298 #endif
299 priv->seek_frame=0;
300 priv->decoder_clock += diff;
301 } else if (data_size > 0) {
302 dbg(2, "Audio exact sync-seek (%"PRIi64" == %"PRIi64")", priv->decoder_clock, priv->seek_frame);
303 priv->seek_frame=0;
304 } else {
305 dbg(0, "Error: no audio data in packet");
308 //dbg(0, "PTS: decoder:%"PRIi64". - want: %"PRIi64, priv->decoder_clock, priv->output_clock);
309 //dbg(0, "CLK: frame: %"PRIi64" T:%.3fs",priv->decoder_clock, (float) priv->decoder_clock/priv->samplerate);
312 if (written!=frames) {
313 dbg(2, "short-read");
315 return written * priv->channels;
318 static int64_t ad_seek_ffmpeg(void *sf, int64_t pos) {
319 ffmpeg_audio_decoder *priv = (ffmpeg_audio_decoder*) sf;
320 if (!sf) return -1;
321 if (pos == priv->output_clock) return pos;
323 /* flush internal buffer */
324 priv->m_tmpBufferLen = 0;
325 priv->seek_frame = pos;
326 priv->output_clock = pos;
327 priv->pkt_len = 0; priv->pkt_ptr = NULL;
328 priv->decoder_clock = 0;
330 #if 0
331 /* TODO seek at least 1 packet before target.
332 * for mpeg compressed files, the
333 * output may depend on past frames! */
334 if (pos > 8192) pos -= 8192;
335 else pos = 0;
336 #endif
338 const int64_t timestamp = pos / av_q2d(priv->formatContext->streams[priv->audioStream]->time_base) / priv->samplerate;
339 dbg(2, "seek frame:%"PRIi64" - idx:%"PRIi64, pos, timestamp);
341 av_seek_frame(priv->formatContext, priv->audioStream, timestamp, AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD);
342 avcodec_flush_buffers(priv->codecContext);
343 return pos;
346 static int ad_eval_ffmpeg(const char *f) {
347 char *ext = strrchr(f, '.');
348 if (!ext) return 10;
349 // libavformat.. guess_format..
350 return 40;
352 #endif
354 static const ad_plugin ad_ffmpeg = {
355 #ifdef HAVE_FFMPEG
356 &ad_eval_ffmpeg,
357 &ad_open_ffmpeg,
358 &ad_close_ffmpeg,
359 &ad_info_ffmpeg,
360 &ad_seek_ffmpeg,
361 &ad_read_ffmpeg,
362 &ad_bitrate_null
363 #else
364 &ad_eval_null,
365 &ad_open_null,
366 &ad_close_null,
367 &ad_info_null,
368 &ad_seek_null,
369 &ad_read_null,
370 &ad_bitrate_null
371 #endif
374 /* dlopen handler */
375 const ad_plugin * adp_get_ffmpeg() {
376 #ifdef HAVE_FFMPEG
377 static int ffinit = 0;
378 if (!ffinit) {
379 ffinit=1;
380 #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 5, 0)
381 avcodec_init();
382 #endif
383 av_register_all();
384 avcodec_register_all();
385 if(ad_debug_level <= 1)
386 av_log_set_level(AV_LOG_QUIET);
387 else
388 av_log_set_level(AV_LOG_VERBOSE);
390 #endif
391 return &ad_ffmpeg;