CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/ext/minimp3/minimp3_ex.h
Views: 1401
1
#ifndef MINIMP3_EXT_H
2
#define MINIMP3_EXT_H
3
/*
4
https://github.com/lieff/minimp3
5
To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide.
6
This software is distributed without any warranty.
7
See <http://creativecommons.org/publicdomain/zero/1.0/>.
8
*/
9
#include <stddef.h>
10
#include "minimp3.h"
11
12
/* flags for mp3dec_ex_open_* functions */
13
#define MP3D_SEEK_TO_BYTE 0 /* mp3dec_ex_seek seeks to byte in stream */
14
#define MP3D_SEEK_TO_SAMPLE 1 /* mp3dec_ex_seek precisely seeks to sample using index (created during duration calculation scan or when mp3dec_ex_seek called) */
15
#define MP3D_DO_NOT_SCAN 2 /* do not scan whole stream for duration if vbrtag not found, mp3dec_ex_t::samples will be filled only if mp3dec_ex_t::vbr_tag_found == 1 */
16
#ifdef MINIMP3_ALLOW_MONO_STEREO_TRANSITION
17
#define MP3D_ALLOW_MONO_STEREO_TRANSITION 4
18
#define MP3D_FLAGS_MASK 7
19
#else
20
#define MP3D_FLAGS_MASK 3
21
#endif
22
23
/* compile-time config */
24
#define MINIMP3_PREDECODE_FRAMES 2 /* frames to pre-decode and skip after seek (to fill internal structures) */
25
/*#define MINIMP3_SEEK_IDX_LINEAR_SEARCH*/ /* define to use linear index search instead of binary search on seek */
26
#define MINIMP3_IO_SIZE (128*1024) /* io buffer size for streaming functions, must be greater than MINIMP3_BUF_SIZE */
27
#define MINIMP3_BUF_SIZE (16*1024) /* buffer which can hold minimum 10 consecutive mp3 frames (~16KB) worst case */
28
/*#define MINIMP3_SCAN_LIMIT (256*1024)*/ /* how many bytes will be scanned to search first valid mp3 frame, to prevent stall on large non-mp3 files */
29
#define MINIMP3_ENABLE_RING 0 /* WIP enable hardware magic ring buffer if available, to make less input buffer memmove(s) in callback IO mode */
30
31
/* return error codes */
32
#define MP3D_E_PARAM -1
33
#define MP3D_E_MEMORY -2
34
#define MP3D_E_IOERROR -3
35
#define MP3D_E_USER -4 /* can be used to stop processing from callbacks without indicating specific error */
36
#define MP3D_E_DECODE -5 /* decode error which can't be safely skipped, such as sample rate, layer and channels change */
37
38
typedef struct
39
{
40
mp3d_sample_t *buffer;
41
size_t samples; /* channels included, byte size = samples*sizeof(mp3d_sample_t) */
42
int channels, hz, layer, avg_bitrate_kbps;
43
} mp3dec_file_info_t;
44
45
typedef struct
46
{
47
const uint8_t *buffer;
48
size_t size;
49
} mp3dec_map_info_t;
50
51
typedef struct
52
{
53
uint64_t sample;
54
uint64_t offset;
55
} mp3dec_frame_t;
56
57
typedef struct
58
{
59
mp3dec_frame_t *frames;
60
size_t num_frames, capacity;
61
} mp3dec_index_t;
62
63
typedef size_t (*MP3D_READ_CB)(void *buf, size_t size, void *user_data);
64
typedef int (*MP3D_SEEK_CB)(uint64_t position, void *user_data);
65
66
typedef struct
67
{
68
MP3D_READ_CB read;
69
void *read_data;
70
MP3D_SEEK_CB seek;
71
void *seek_data;
72
} mp3dec_io_t;
73
74
typedef struct
75
{
76
mp3dec_t mp3d;
77
mp3dec_map_info_t file;
78
mp3dec_io_t *io;
79
mp3dec_index_t index;
80
uint64_t offset, samples, detected_samples, cur_sample, start_offset, end_offset;
81
mp3dec_frame_info_t info;
82
mp3d_sample_t buffer[MINIMP3_MAX_SAMPLES_PER_FRAME];
83
size_t input_consumed, input_filled;
84
int is_file, flags, vbr_tag_found, indexes_built;
85
int free_format_bytes;
86
int buffer_samples, buffer_consumed, to_skip, start_delay;
87
int last_error;
88
} mp3dec_ex_t;
89
90
typedef int (*MP3D_ITERATE_CB)(void *user_data, const uint8_t *frame, int frame_size, int free_format_bytes, size_t buf_size, uint64_t offset, mp3dec_frame_info_t *info);
91
typedef int (*MP3D_PROGRESS_CB)(void *user_data, size_t file_size, uint64_t offset, mp3dec_frame_info_t *info);
92
93
#ifdef __cplusplus
94
extern "C" {
95
#endif
96
97
/* detect mp3/mpa format */
98
int mp3dec_detect_buf(const uint8_t *buf, size_t buf_size);
99
int mp3dec_detect_cb(mp3dec_io_t *io, uint8_t *buf, size_t buf_size);
100
/* decode whole buffer block */
101
int mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data);
102
int mp3dec_load_cb(mp3dec_t *dec, mp3dec_io_t *io, uint8_t *buf, size_t buf_size, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data);
103
/* iterate through frames */
104
int mp3dec_iterate_buf(const uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data);
105
int mp3dec_iterate_cb(mp3dec_io_t *io, uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data);
106
/* streaming decoder with seeking capability */
107
int mp3dec_ex_open_buf(mp3dec_ex_t *dec, const uint8_t *buf, size_t buf_size, int flags);
108
int mp3dec_ex_open_cb(mp3dec_ex_t *dec, mp3dec_io_t *io, int flags);
109
void mp3dec_ex_close(mp3dec_ex_t *dec);
110
int mp3dec_ex_seek(mp3dec_ex_t *dec, uint64_t position);
111
size_t mp3dec_ex_read_frame(mp3dec_ex_t *dec, mp3d_sample_t **buf, mp3dec_frame_info_t *frame_info, size_t max_samples);
112
size_t mp3dec_ex_read(mp3dec_ex_t *dec, mp3d_sample_t *buf, size_t samples);
113
#ifndef MINIMP3_NO_STDIO
114
/* stdio versions of file detect, load, iterate and stream */
115
int mp3dec_detect(const char *file_name);
116
int mp3dec_load(mp3dec_t *dec, const char *file_name, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data);
117
int mp3dec_iterate(const char *file_name, MP3D_ITERATE_CB callback, void *user_data);
118
int mp3dec_ex_open(mp3dec_ex_t *dec, const char *file_name, int flags);
119
#ifdef _WIN32
120
int mp3dec_detect_w(const wchar_t *file_name);
121
int mp3dec_load_w(mp3dec_t *dec, const wchar_t *file_name, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data);
122
int mp3dec_iterate_w(const wchar_t *file_name, MP3D_ITERATE_CB callback, void *user_data);
123
int mp3dec_ex_open_w(mp3dec_ex_t *dec, const wchar_t *file_name, int flags);
124
#endif
125
#endif
126
127
#ifdef __cplusplus
128
}
129
#endif
130
#endif /*MINIMP3_EXT_H*/
131
132
#if defined(MINIMP3_IMPLEMENTATION) && !defined(_MINIMP3_EX_IMPLEMENTATION_GUARD)
133
#define _MINIMP3_EX_IMPLEMENTATION_GUARD
134
#include <limits.h>
135
#include "minimp3.h"
136
137
static void mp3dec_skip_id3v1(const uint8_t *buf, size_t *pbuf_size)
138
{
139
size_t buf_size = *pbuf_size;
140
#ifndef MINIMP3_NOSKIP_ID3V1
141
if (buf_size >= 128 && !memcmp(buf + buf_size - 128, "TAG", 3))
142
{
143
buf_size -= 128;
144
if (buf_size >= 227 && !memcmp(buf + buf_size - 227, "TAG+", 4))
145
buf_size -= 227;
146
}
147
#endif
148
#ifndef MINIMP3_NOSKIP_APEV2
149
if (buf_size > 32 && !memcmp(buf + buf_size - 32, "APETAGEX", 8))
150
{
151
buf_size -= 32;
152
const uint8_t *tag = buf + buf_size + 8 + 4;
153
uint32_t tag_size = (uint32_t)(tag[3] << 24) | (tag[2] << 16) | (tag[1] << 8) | tag[0];
154
if (buf_size >= tag_size)
155
buf_size -= tag_size;
156
}
157
#endif
158
*pbuf_size = buf_size;
159
}
160
161
static size_t mp3dec_skip_id3v2(const uint8_t *buf, size_t buf_size)
162
{
163
#define MINIMP3_ID3_DETECT_SIZE 10
164
#ifndef MINIMP3_NOSKIP_ID3V2
165
if (buf_size >= MINIMP3_ID3_DETECT_SIZE && !memcmp(buf, "ID3", 3) && !((buf[5] & 15) || (buf[6] & 0x80) || (buf[7] & 0x80) || (buf[8] & 0x80) || (buf[9] & 0x80)))
166
{
167
size_t id3v2size = (((buf[6] & 0x7f) << 21) | ((buf[7] & 0x7f) << 14) | ((buf[8] & 0x7f) << 7) | (buf[9] & 0x7f)) + 10;
168
if ((buf[5] & 16))
169
id3v2size += 10; /* footer */
170
return id3v2size;
171
}
172
#endif
173
return 0;
174
}
175
176
static void mp3dec_skip_id3(const uint8_t **pbuf, size_t *pbuf_size)
177
{
178
uint8_t *buf = (uint8_t *)(*pbuf);
179
size_t buf_size = *pbuf_size;
180
size_t id3v2size = mp3dec_skip_id3v2(buf, buf_size);
181
if (id3v2size)
182
{
183
if (id3v2size >= buf_size)
184
id3v2size = buf_size;
185
buf += id3v2size;
186
buf_size -= id3v2size;
187
}
188
mp3dec_skip_id3v1(buf, &buf_size);
189
*pbuf = (const uint8_t *)buf;
190
*pbuf_size = buf_size;
191
}
192
193
static int mp3dec_check_vbrtag(const uint8_t *frame, int frame_size, uint32_t *frames, int *delay, int *padding)
194
{
195
static const char g_xing_tag[4] = { 'X', 'i', 'n', 'g' };
196
static const char g_info_tag[4] = { 'I', 'n', 'f', 'o' };
197
#define FRAMES_FLAG 1
198
#define BYTES_FLAG 2
199
#define TOC_FLAG 4
200
#define VBR_SCALE_FLAG 8
201
/* Side info offsets after header:
202
/ Mono Stereo
203
/ MPEG1 17 32
204
/ MPEG2 & 2.5 9 17*/
205
bs_t bs[1];
206
L3_gr_info_t gr_info[4];
207
bs_init(bs, frame + HDR_SIZE, frame_size - HDR_SIZE);
208
if (HDR_IS_CRC(frame))
209
get_bits(bs, 16);
210
if (L3_read_side_info(bs, gr_info, frame) < 0)
211
return 0; /* side info corrupted */
212
213
const uint8_t *tag = frame + HDR_SIZE + bs->pos/8;
214
if (memcmp(g_xing_tag, tag, 4) && memcmp(g_info_tag, tag, 4))
215
return 0;
216
int flags = tag[7];
217
if (!((flags & FRAMES_FLAG)))
218
return -1;
219
tag += 8;
220
*frames = (uint32_t)(tag[0] << 24) | (tag[1] << 16) | (tag[2] << 8) | tag[3];
221
tag += 4;
222
if (flags & BYTES_FLAG)
223
tag += 4;
224
if (flags & TOC_FLAG)
225
tag += 100;
226
if (flags & VBR_SCALE_FLAG)
227
tag += 4;
228
*delay = *padding = 0;
229
if (*tag)
230
{ /* extension, LAME, Lavc, etc. Should be the same structure. */
231
tag += 21;
232
if (tag - frame + 14 >= frame_size)
233
return 0;
234
*delay = ((tag[0] << 4) | (tag[1] >> 4)) + (528 + 1);
235
*padding = (((tag[1] & 0xF) << 8) | tag[2]) - (528 + 1);
236
}
237
return 1;
238
}
239
240
int mp3dec_detect_buf(const uint8_t *buf, size_t buf_size)
241
{
242
return mp3dec_detect_cb(0, (uint8_t *)buf, buf_size);
243
}
244
245
int mp3dec_detect_cb(mp3dec_io_t *io, uint8_t *buf, size_t buf_size)
246
{
247
if (!buf || (size_t)-1 == buf_size || (io && buf_size < MINIMP3_BUF_SIZE))
248
return MP3D_E_PARAM;
249
size_t filled = buf_size;
250
if (io)
251
{
252
if (io->seek(0, io->seek_data))
253
return MP3D_E_IOERROR;
254
filled = io->read(buf, MINIMP3_ID3_DETECT_SIZE, io->read_data);
255
if (filled > MINIMP3_ID3_DETECT_SIZE)
256
return MP3D_E_IOERROR;
257
}
258
if (filled < MINIMP3_ID3_DETECT_SIZE)
259
return MP3D_E_USER; /* too small, can't be mp3/mpa */
260
if (mp3dec_skip_id3v2(buf, filled))
261
return 0; /* id3v2 tag is enough evidence */
262
if (io)
263
{
264
size_t readed = io->read(buf + MINIMP3_ID3_DETECT_SIZE, buf_size - MINIMP3_ID3_DETECT_SIZE, io->read_data);
265
if (readed > (buf_size - MINIMP3_ID3_DETECT_SIZE))
266
return MP3D_E_IOERROR;
267
filled += readed;
268
if (filled < MINIMP3_BUF_SIZE)
269
mp3dec_skip_id3v1(buf, &filled);
270
} else
271
{
272
mp3dec_skip_id3v1(buf, &filled);
273
if (filled > MINIMP3_BUF_SIZE)
274
filled = MINIMP3_BUF_SIZE;
275
}
276
int free_format_bytes, frame_size;
277
mp3d_find_frame(buf, filled, &free_format_bytes, &frame_size);
278
if (frame_size)
279
return 0; /* MAX_FRAME_SYNC_MATCHES consecutive frames found */
280
return MP3D_E_USER;
281
}
282
283
int mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data)
284
{
285
return mp3dec_load_cb(dec, 0, (uint8_t *)buf, buf_size, info, progress_cb, user_data);
286
}
287
288
int mp3dec_load_cb(mp3dec_t *dec, mp3dec_io_t *io, uint8_t *buf, size_t buf_size, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data)
289
{
290
if (!dec || !buf || !info || (size_t)-1 == buf_size || (io && buf_size < MINIMP3_BUF_SIZE))
291
return MP3D_E_PARAM;
292
uint64_t detected_samples = 0;
293
size_t orig_buf_size = buf_size;
294
int to_skip = 0;
295
mp3dec_frame_info_t frame_info;
296
memset(info, 0, sizeof(*info));
297
memset(&frame_info, 0, sizeof(frame_info));
298
299
/* skip id3 */
300
size_t filled = 0, consumed = 0;
301
int eof = 0, ret = 0;
302
if (io)
303
{
304
if (io->seek(0, io->seek_data))
305
return MP3D_E_IOERROR;
306
filled = io->read(buf, MINIMP3_ID3_DETECT_SIZE, io->read_data);
307
if (filled > MINIMP3_ID3_DETECT_SIZE)
308
return MP3D_E_IOERROR;
309
if (MINIMP3_ID3_DETECT_SIZE != filled)
310
return 0;
311
size_t id3v2size = mp3dec_skip_id3v2(buf, filled);
312
if (id3v2size)
313
{
314
if (io->seek(id3v2size, io->seek_data))
315
return MP3D_E_IOERROR;
316
filled = io->read(buf, buf_size, io->read_data);
317
if (filled > buf_size)
318
return MP3D_E_IOERROR;
319
} else
320
{
321
size_t readed = io->read(buf + MINIMP3_ID3_DETECT_SIZE, buf_size - MINIMP3_ID3_DETECT_SIZE, io->read_data);
322
if (readed > (buf_size - MINIMP3_ID3_DETECT_SIZE))
323
return MP3D_E_IOERROR;
324
filled += readed;
325
}
326
if (filled < MINIMP3_BUF_SIZE)
327
mp3dec_skip_id3v1(buf, &filled);
328
} else
329
{
330
mp3dec_skip_id3((const uint8_t **)&buf, &buf_size);
331
if (!buf_size)
332
return 0;
333
}
334
/* try to make allocation size assumption by first frame or vbr tag */
335
mp3dec_init(dec);
336
int samples;
337
do
338
{
339
uint32_t frames;
340
int i, delay, padding, free_format_bytes = 0, frame_size = 0;
341
const uint8_t *hdr;
342
if (io)
343
{
344
if (!eof && filled - consumed < MINIMP3_BUF_SIZE)
345
{ /* keep minimum 10 consecutive mp3 frames (~16KB) worst case */
346
memmove(buf, buf + consumed, filled - consumed);
347
filled -= consumed;
348
consumed = 0;
349
size_t readed = io->read(buf + filled, buf_size - filled, io->read_data);
350
if (readed > (buf_size - filled))
351
return MP3D_E_IOERROR;
352
if (readed != (buf_size - filled))
353
eof = 1;
354
filled += readed;
355
if (eof)
356
mp3dec_skip_id3v1(buf, &filled);
357
}
358
i = mp3d_find_frame(buf + consumed, filled - consumed, &free_format_bytes, &frame_size);
359
consumed += i;
360
hdr = buf + consumed;
361
} else
362
{
363
i = mp3d_find_frame(buf, buf_size, &free_format_bytes, &frame_size);
364
buf += i;
365
buf_size -= i;
366
hdr = buf;
367
}
368
if (i && !frame_size)
369
continue;
370
if (!frame_size)
371
return 0;
372
frame_info.channels = HDR_IS_MONO(hdr) ? 1 : 2;
373
frame_info.hz = hdr_sample_rate_hz(hdr);
374
frame_info.layer = 4 - HDR_GET_LAYER(hdr);
375
frame_info.bitrate_kbps = hdr_bitrate_kbps(hdr);
376
frame_info.frame_bytes = frame_size;
377
samples = hdr_frame_samples(hdr)*frame_info.channels;
378
if (3 != frame_info.layer)
379
break;
380
int ret = mp3dec_check_vbrtag(hdr, frame_size, &frames, &delay, &padding);
381
if (ret > 0)
382
{
383
padding *= frame_info.channels;
384
to_skip = delay*frame_info.channels;
385
detected_samples = samples*(uint64_t)frames;
386
if (detected_samples >= (uint64_t)to_skip)
387
detected_samples -= to_skip;
388
if (padding > 0 && detected_samples >= (uint64_t)padding)
389
detected_samples -= padding;
390
if (!detected_samples)
391
return 0;
392
}
393
if (ret)
394
{
395
if (io)
396
{
397
consumed += frame_size;
398
} else
399
{
400
buf += frame_size;
401
buf_size -= frame_size;
402
}
403
}
404
break;
405
} while(1);
406
size_t allocated = MINIMP3_MAX_SAMPLES_PER_FRAME*sizeof(mp3d_sample_t);
407
if (detected_samples)
408
allocated += detected_samples*sizeof(mp3d_sample_t);
409
else
410
allocated += (buf_size/frame_info.frame_bytes)*samples*sizeof(mp3d_sample_t);
411
info->buffer = (mp3d_sample_t*)malloc(allocated);
412
if (!info->buffer)
413
return MP3D_E_MEMORY;
414
/* save info */
415
info->channels = frame_info.channels;
416
info->hz = frame_info.hz;
417
info->layer = frame_info.layer;
418
/* decode all frames */
419
size_t avg_bitrate_kbps = 0, frames = 0;
420
do
421
{
422
if ((allocated - info->samples*sizeof(mp3d_sample_t)) < MINIMP3_MAX_SAMPLES_PER_FRAME*sizeof(mp3d_sample_t))
423
{
424
allocated *= 2;
425
mp3d_sample_t *alloc_buf = (mp3d_sample_t*)realloc(info->buffer, allocated);
426
if (!alloc_buf)
427
return MP3D_E_MEMORY;
428
info->buffer = alloc_buf;
429
}
430
if (io)
431
{
432
if (!eof && filled - consumed < MINIMP3_BUF_SIZE)
433
{ /* keep minimum 10 consecutive mp3 frames (~16KB) worst case */
434
memmove(buf, buf + consumed, filled - consumed);
435
filled -= consumed;
436
consumed = 0;
437
size_t readed = io->read(buf + filled, buf_size - filled, io->read_data);
438
if (readed != (buf_size - filled))
439
eof = 1;
440
filled += readed;
441
if (eof)
442
mp3dec_skip_id3v1(buf, &filled);
443
}
444
samples = mp3dec_decode_frame(dec, buf + consumed, filled - consumed, info->buffer + info->samples, &frame_info);
445
consumed += frame_info.frame_bytes;
446
} else
447
{
448
samples = mp3dec_decode_frame(dec, buf, MINIMP3_MIN(buf_size, (size_t)INT_MAX), info->buffer + info->samples, &frame_info);
449
buf += frame_info.frame_bytes;
450
buf_size -= frame_info.frame_bytes;
451
}
452
if (samples)
453
{
454
if (info->hz != frame_info.hz || info->layer != frame_info.layer)
455
{
456
ret = MP3D_E_DECODE;
457
break;
458
}
459
if (info->channels && info->channels != frame_info.channels)
460
{
461
#ifdef MINIMP3_ALLOW_MONO_STEREO_TRANSITION
462
info->channels = 0; /* mark file with mono-stereo transition */
463
#else
464
ret = MP3D_E_DECODE;
465
break;
466
#endif
467
}
468
samples *= frame_info.channels;
469
if (to_skip)
470
{
471
size_t skip = MINIMP3_MIN(samples, to_skip);
472
to_skip -= skip;
473
samples -= skip;
474
memmove(info->buffer, info->buffer + skip, samples*sizeof(mp3d_sample_t));
475
}
476
info->samples += samples;
477
avg_bitrate_kbps += frame_info.bitrate_kbps;
478
frames++;
479
if (progress_cb)
480
{
481
ret = progress_cb(user_data, orig_buf_size, orig_buf_size - buf_size, &frame_info);
482
if (ret)
483
break;
484
}
485
}
486
} while (frame_info.frame_bytes);
487
if (detected_samples && info->samples > detected_samples)
488
info->samples = detected_samples; /* cut padding */
489
/* reallocate to normal buffer size */
490
if (allocated != info->samples*sizeof(mp3d_sample_t))
491
{
492
mp3d_sample_t *alloc_buf = (mp3d_sample_t*)realloc(info->buffer, info->samples*sizeof(mp3d_sample_t));
493
if (!alloc_buf && info->samples)
494
return MP3D_E_MEMORY;
495
info->buffer = alloc_buf;
496
}
497
if (frames)
498
info->avg_bitrate_kbps = avg_bitrate_kbps/frames;
499
return ret;
500
}
501
502
int mp3dec_iterate_buf(const uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data)
503
{
504
const uint8_t *orig_buf = buf;
505
if (!buf || (size_t)-1 == buf_size || !callback)
506
return MP3D_E_PARAM;
507
/* skip id3 */
508
mp3dec_skip_id3(&buf, &buf_size);
509
if (!buf_size)
510
return 0;
511
mp3dec_frame_info_t frame_info;
512
memset(&frame_info, 0, sizeof(frame_info));
513
do
514
{
515
int free_format_bytes = 0, frame_size = 0, ret;
516
int i = mp3d_find_frame(buf, buf_size, &free_format_bytes, &frame_size);
517
buf += i;
518
buf_size -= i;
519
if (i && !frame_size)
520
continue;
521
if (!frame_size)
522
break;
523
const uint8_t *hdr = buf;
524
frame_info.channels = HDR_IS_MONO(hdr) ? 1 : 2;
525
frame_info.hz = hdr_sample_rate_hz(hdr);
526
frame_info.layer = 4 - HDR_GET_LAYER(hdr);
527
frame_info.bitrate_kbps = hdr_bitrate_kbps(hdr);
528
frame_info.frame_bytes = frame_size;
529
530
if (callback)
531
{
532
if ((ret = callback(user_data, hdr, frame_size, free_format_bytes, buf_size, hdr - orig_buf, &frame_info)))
533
return ret;
534
}
535
buf += frame_size;
536
buf_size -= frame_size;
537
} while (1);
538
return 0;
539
}
540
541
int mp3dec_iterate_cb(mp3dec_io_t *io, uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data)
542
{
543
if (!io || !buf || (size_t)-1 == buf_size || buf_size < MINIMP3_BUF_SIZE || !callback)
544
return MP3D_E_PARAM;
545
size_t filled = io->read(buf, MINIMP3_ID3_DETECT_SIZE, io->read_data), consumed = 0;
546
uint64_t readed = 0;
547
mp3dec_frame_info_t frame_info;
548
int eof = 0;
549
memset(&frame_info, 0, sizeof(frame_info));
550
if (filled > MINIMP3_ID3_DETECT_SIZE)
551
return MP3D_E_IOERROR;
552
if (MINIMP3_ID3_DETECT_SIZE != filled)
553
return 0;
554
size_t id3v2size = mp3dec_skip_id3v2(buf, filled);
555
if (id3v2size)
556
{
557
if (io->seek(id3v2size, io->seek_data))
558
return MP3D_E_IOERROR;
559
filled = io->read(buf, buf_size, io->read_data);
560
if (filled > buf_size)
561
return MP3D_E_IOERROR;
562
readed += id3v2size;
563
} else
564
{
565
size_t readed = io->read(buf + MINIMP3_ID3_DETECT_SIZE, buf_size - MINIMP3_ID3_DETECT_SIZE, io->read_data);
566
if (readed > (buf_size - MINIMP3_ID3_DETECT_SIZE))
567
return MP3D_E_IOERROR;
568
filled += readed;
569
}
570
if (filled < MINIMP3_BUF_SIZE)
571
mp3dec_skip_id3v1(buf, &filled);
572
do
573
{
574
int free_format_bytes = 0, frame_size = 0, ret;
575
int i = mp3d_find_frame(buf + consumed, filled - consumed, &free_format_bytes, &frame_size);
576
if (i && !frame_size)
577
{
578
consumed += i;
579
continue;
580
}
581
if (!frame_size)
582
break;
583
const uint8_t *hdr = buf + consumed + i;
584
frame_info.channels = HDR_IS_MONO(hdr) ? 1 : 2;
585
frame_info.hz = hdr_sample_rate_hz(hdr);
586
frame_info.layer = 4 - HDR_GET_LAYER(hdr);
587
frame_info.bitrate_kbps = hdr_bitrate_kbps(hdr);
588
frame_info.frame_bytes = frame_size;
589
590
readed += i;
591
if (callback)
592
{
593
if ((ret = callback(user_data, hdr, frame_size, free_format_bytes, filled - consumed, readed, &frame_info)))
594
return ret;
595
}
596
readed += frame_size;
597
consumed += i + frame_size;
598
if (!eof && filled - consumed < MINIMP3_BUF_SIZE)
599
{ /* keep minimum 10 consecutive mp3 frames (~16KB) worst case */
600
memmove(buf, buf + consumed, filled - consumed);
601
filled -= consumed;
602
consumed = 0;
603
size_t readed = io->read(buf + filled, buf_size - filled, io->read_data);
604
if (readed > (buf_size - filled))
605
return MP3D_E_IOERROR;
606
if (readed != (buf_size - filled))
607
eof = 1;
608
filled += readed;
609
if (eof)
610
mp3dec_skip_id3v1(buf, &filled);
611
}
612
} while (1);
613
return 0;
614
}
615
616
static int mp3dec_load_index(void *user_data, const uint8_t *frame, int frame_size, int free_format_bytes, size_t buf_size, uint64_t offset, mp3dec_frame_info_t *info)
617
{
618
mp3dec_frame_t *idx_frame;
619
mp3dec_ex_t *dec = (mp3dec_ex_t *)user_data;
620
if (!dec->index.frames && !dec->start_offset)
621
{ /* detect VBR tag and try to avoid full scan */
622
uint32_t frames;
623
int delay, padding;
624
dec->info = *info;
625
dec->start_offset = dec->offset = offset;
626
dec->end_offset = offset + buf_size;
627
dec->free_format_bytes = free_format_bytes; /* should not change */
628
if (3 == dec->info.layer)
629
{
630
int ret = mp3dec_check_vbrtag(frame, frame_size, &frames, &delay, &padding);
631
if (ret)
632
dec->start_offset = dec->offset = offset + frame_size;
633
if (ret > 0)
634
{
635
padding *= info->channels;
636
dec->start_delay = dec->to_skip = delay*info->channels;
637
dec->samples = hdr_frame_samples(frame)*info->channels*(uint64_t)frames;
638
if (dec->samples >= (uint64_t)dec->start_delay)
639
dec->samples -= dec->start_delay;
640
if (padding > 0 && dec->samples >= (uint64_t)padding)
641
dec->samples -= padding;
642
dec->detected_samples = dec->samples;
643
dec->vbr_tag_found = 1;
644
return MP3D_E_USER;
645
} else if (ret < 0)
646
return 0;
647
}
648
}
649
if (dec->flags & MP3D_DO_NOT_SCAN)
650
return MP3D_E_USER;
651
if (dec->index.num_frames + 1 > dec->index.capacity)
652
{
653
if (!dec->index.capacity)
654
dec->index.capacity = 4096;
655
else
656
dec->index.capacity *= 2;
657
mp3dec_frame_t *alloc_buf = (mp3dec_frame_t *)realloc((void*)dec->index.frames, sizeof(mp3dec_frame_t)*dec->index.capacity);
658
if (!alloc_buf)
659
return MP3D_E_MEMORY;
660
dec->index.frames = alloc_buf;
661
}
662
idx_frame = &dec->index.frames[dec->index.num_frames++];
663
idx_frame->offset = offset;
664
idx_frame->sample = dec->samples;
665
if (!dec->buffer_samples && dec->index.num_frames < 256)
666
{ /* for some cutted mp3 frames, bit-reservoir not filled and decoding can't be started from first frames */
667
/* try to decode up to 255 first frames till samples starts to decode */
668
dec->buffer_samples = mp3dec_decode_frame(&dec->mp3d, frame, MINIMP3_MIN(buf_size, (size_t)INT_MAX), dec->buffer, info);
669
dec->samples += dec->buffer_samples*info->channels;
670
} else
671
dec->samples += hdr_frame_samples(frame)*info->channels;
672
return 0;
673
}
674
675
int mp3dec_ex_open_buf(mp3dec_ex_t *dec, const uint8_t *buf, size_t buf_size, int flags)
676
{
677
if (!dec || !buf || (size_t)-1 == buf_size || (flags & (~MP3D_FLAGS_MASK)))
678
return MP3D_E_PARAM;
679
memset(dec, 0, sizeof(*dec));
680
dec->file.buffer = buf;
681
dec->file.size = buf_size;
682
dec->flags = flags;
683
mp3dec_init(&dec->mp3d);
684
int ret = mp3dec_iterate_buf(dec->file.buffer, dec->file.size, mp3dec_load_index, dec);
685
if (ret && MP3D_E_USER != ret)
686
return ret;
687
mp3dec_init(&dec->mp3d);
688
dec->buffer_samples = 0;
689
dec->indexes_built = !(dec->vbr_tag_found || (flags & MP3D_DO_NOT_SCAN));
690
dec->flags &= (~MP3D_DO_NOT_SCAN);
691
return 0;
692
}
693
694
#ifndef MINIMP3_SEEK_IDX_LINEAR_SEARCH
695
static size_t mp3dec_idx_binary_search(mp3dec_index_t *idx, uint64_t position)
696
{
697
size_t end = idx->num_frames, start = 0, index = 0;
698
while (start <= end)
699
{
700
size_t mid = (start + end) / 2;
701
if (idx->frames[mid].sample >= position)
702
{ /* move left side. */
703
if (idx->frames[mid].sample == position)
704
return mid;
705
end = mid - 1;
706
} else
707
{ /* move to right side */
708
index = mid;
709
start = mid + 1;
710
if (start == idx->num_frames)
711
break;
712
}
713
}
714
return index;
715
}
716
#endif
717
718
int mp3dec_ex_seek(mp3dec_ex_t *dec, uint64_t position)
719
{
720
size_t i;
721
if (!dec)
722
return MP3D_E_PARAM;
723
if (!(dec->flags & MP3D_SEEK_TO_SAMPLE))
724
{
725
if (dec->io)
726
{
727
dec->offset = position;
728
} else
729
{
730
dec->offset = MINIMP3_MIN(position, dec->file.size);
731
}
732
dec->cur_sample = 0;
733
goto do_exit;
734
}
735
dec->cur_sample = position;
736
position += dec->start_delay;
737
if (0 == position)
738
{ /* optimize seek to zero, no index needed */
739
seek_zero:
740
dec->offset = dec->start_offset;
741
dec->to_skip = 0;
742
goto do_exit;
743
}
744
if (!dec->indexes_built)
745
{ /* no index created yet (vbr tag used to calculate track length or MP3D_DO_NOT_SCAN open flag used) */
746
dec->indexes_built = 1;
747
dec->samples = 0;
748
dec->buffer_samples = 0;
749
if (dec->io)
750
{
751
if (dec->io->seek(dec->start_offset, dec->io->seek_data))
752
return MP3D_E_IOERROR;
753
int ret = mp3dec_iterate_cb(dec->io, (uint8_t *)dec->file.buffer, dec->file.size, mp3dec_load_index, dec);
754
if (ret && MP3D_E_USER != ret)
755
return ret;
756
} else
757
{
758
int ret = mp3dec_iterate_buf(dec->file.buffer + dec->start_offset, dec->file.size - dec->start_offset, mp3dec_load_index, dec);
759
if (ret && MP3D_E_USER != ret)
760
return ret;
761
}
762
for (i = 0; i < dec->index.num_frames; i++)
763
dec->index.frames[i].offset += dec->start_offset;
764
dec->samples = dec->detected_samples;
765
}
766
if (!dec->index.frames)
767
goto seek_zero; /* no frames in file - seek to zero */
768
#ifdef MINIMP3_SEEK_IDX_LINEAR_SEARCH
769
for (i = 0; i < dec->index.num_frames; i++)
770
{
771
if (dec->index.frames[i].sample >= position)
772
break;
773
}
774
#else
775
i = mp3dec_idx_binary_search(&dec->index, position);
776
#endif
777
if (i)
778
{
779
int to_fill_bytes = 511;
780
int skip_frames = MINIMP3_PREDECODE_FRAMES
781
#ifdef MINIMP3_SEEK_IDX_LINEAR_SEARCH
782
+ ((dec->index.frames[i].sample == position) ? 0 : 1)
783
#endif
784
;
785
i -= MINIMP3_MIN(i, (size_t)skip_frames);
786
if (3 == dec->info.layer)
787
{
788
while (i && to_fill_bytes)
789
{ /* make sure bit-reservoir is filled when we start decoding */
790
bs_t bs[1];
791
L3_gr_info_t gr_info[4];
792
int frame_bytes, frame_size;
793
const uint8_t *hdr;
794
if (dec->io)
795
{
796
hdr = dec->file.buffer;
797
if (dec->io->seek(dec->index.frames[i - 1].offset, dec->io->seek_data))
798
return MP3D_E_IOERROR;
799
size_t readed = dec->io->read((uint8_t *)hdr, HDR_SIZE, dec->io->read_data);
800
if (readed != HDR_SIZE)
801
return MP3D_E_IOERROR;
802
frame_size = hdr_frame_bytes(hdr, dec->free_format_bytes) + hdr_padding(hdr);
803
readed = dec->io->read((uint8_t *)hdr + HDR_SIZE, frame_size - HDR_SIZE, dec->io->read_data);
804
if (readed != (size_t)(frame_size - HDR_SIZE))
805
return MP3D_E_IOERROR;
806
bs_init(bs, hdr + HDR_SIZE, frame_size - HDR_SIZE);
807
} else
808
{
809
hdr = dec->file.buffer + dec->index.frames[i - 1].offset;
810
frame_size = hdr_frame_bytes(hdr, dec->free_format_bytes) + hdr_padding(hdr);
811
bs_init(bs, hdr + HDR_SIZE, frame_size - HDR_SIZE);
812
}
813
if (HDR_IS_CRC(hdr))
814
get_bits(bs, 16);
815
i--;
816
if (L3_read_side_info(bs, gr_info, hdr) < 0)
817
break; /* frame not decodable, we can start from here */
818
frame_bytes = (bs->limit - bs->pos)/8;
819
to_fill_bytes -= MINIMP3_MIN(to_fill_bytes, frame_bytes);
820
}
821
}
822
}
823
dec->offset = dec->index.frames[i].offset;
824
dec->to_skip = position - dec->index.frames[i].sample;
825
while ((i + 1) < dec->index.num_frames && !dec->index.frames[i].sample && !dec->index.frames[i + 1].sample)
826
{ /* skip not decodable first frames */
827
const uint8_t *hdr;
828
if (dec->io)
829
{
830
hdr = dec->file.buffer;
831
if (dec->io->seek(dec->index.frames[i].offset, dec->io->seek_data))
832
return MP3D_E_IOERROR;
833
size_t readed = dec->io->read((uint8_t *)hdr, HDR_SIZE, dec->io->read_data);
834
if (readed != HDR_SIZE)
835
return MP3D_E_IOERROR;
836
} else
837
hdr = dec->file.buffer + dec->index.frames[i].offset;
838
dec->to_skip += hdr_frame_samples(hdr)*dec->info.channels;
839
i++;
840
}
841
do_exit:
842
if (dec->io)
843
{
844
if (dec->io->seek(dec->offset, dec->io->seek_data))
845
return MP3D_E_IOERROR;
846
}
847
dec->buffer_samples = 0;
848
dec->buffer_consumed = 0;
849
dec->input_consumed = 0;
850
dec->input_filled = 0;
851
dec->last_error = 0;
852
mp3dec_init(&dec->mp3d);
853
return 0;
854
}
855
856
size_t mp3dec_ex_read_frame(mp3dec_ex_t *dec, mp3d_sample_t **buf, mp3dec_frame_info_t *frame_info, size_t max_samples)
857
{
858
if (!dec || !buf || !frame_info)
859
{
860
if (dec)
861
dec->last_error = MP3D_E_PARAM;
862
return 0;
863
}
864
if (dec->detected_samples && dec->cur_sample >= dec->detected_samples)
865
return 0; /* at end of stream */
866
if (dec->last_error)
867
return 0; /* error eof state, seek can reset it */
868
*buf = NULL;
869
uint64_t end_offset = dec->end_offset ? dec->end_offset : dec->file.size;
870
int eof = 0;
871
while (dec->buffer_consumed == dec->buffer_samples)
872
{
873
const uint8_t *dec_buf;
874
if (dec->io)
875
{
876
if (!eof && (dec->input_filled - dec->input_consumed) < MINIMP3_BUF_SIZE)
877
{ /* keep minimum 10 consecutive mp3 frames (~16KB) worst case */
878
memmove((uint8_t*)dec->file.buffer, (uint8_t*)dec->file.buffer + dec->input_consumed, dec->input_filled - dec->input_consumed);
879
dec->input_filled -= dec->input_consumed;
880
dec->input_consumed = 0;
881
size_t readed = dec->io->read((uint8_t*)dec->file.buffer + dec->input_filled, dec->file.size - dec->input_filled, dec->io->read_data);
882
if (readed > (dec->file.size - dec->input_filled))
883
{
884
dec->last_error = MP3D_E_IOERROR;
885
readed = 0;
886
}
887
if (readed != (dec->file.size - dec->input_filled))
888
eof = 1;
889
dec->input_filled += readed;
890
if (eof)
891
mp3dec_skip_id3v1((uint8_t*)dec->file.buffer, &dec->input_filled);
892
}
893
dec_buf = dec->file.buffer + dec->input_consumed;
894
if (!(dec->input_filled - dec->input_consumed))
895
return 0;
896
dec->buffer_samples = mp3dec_decode_frame(&dec->mp3d, dec_buf, dec->input_filled - dec->input_consumed, dec->buffer, frame_info);
897
dec->input_consumed += frame_info->frame_bytes;
898
} else
899
{
900
dec_buf = dec->file.buffer + dec->offset;
901
uint64_t buf_size = end_offset - dec->offset;
902
if (!buf_size)
903
return 0;
904
dec->buffer_samples = mp3dec_decode_frame(&dec->mp3d, dec_buf, MINIMP3_MIN(buf_size, (uint64_t)INT_MAX), dec->buffer, frame_info);
905
}
906
dec->buffer_consumed = 0;
907
if (dec->info.hz != frame_info->hz || dec->info.layer != frame_info->layer)
908
{
909
return_e_decode:
910
dec->last_error = MP3D_E_DECODE;
911
return 0;
912
}
913
if (dec->buffer_samples)
914
{
915
dec->buffer_samples *= frame_info->channels;
916
if (dec->to_skip)
917
{
918
size_t skip = MINIMP3_MIN(dec->buffer_samples, dec->to_skip);
919
dec->buffer_consumed += skip;
920
dec->to_skip -= skip;
921
}
922
if (
923
#ifdef MINIMP3_ALLOW_MONO_STEREO_TRANSITION
924
!(dec->flags & MP3D_ALLOW_MONO_STEREO_TRANSITION) &&
925
#endif
926
dec->buffer_consumed != dec->buffer_samples && dec->info.channels != frame_info->channels)
927
{
928
goto return_e_decode;
929
}
930
} else if (dec->to_skip)
931
{ /* In mp3 decoding not always can start decode from any frame because of bit reservoir,
932
count skip samples for such frames */
933
int frame_samples = hdr_frame_samples(dec_buf)*frame_info->channels;
934
dec->to_skip -= MINIMP3_MIN(frame_samples, dec->to_skip);
935
}
936
dec->offset += frame_info->frame_bytes;
937
}
938
size_t out_samples = MINIMP3_MIN((size_t)(dec->buffer_samples - dec->buffer_consumed), max_samples);
939
if (dec->detected_samples)
940
{ /* count decoded samples to properly cut padding */
941
if (dec->cur_sample + out_samples >= dec->detected_samples)
942
out_samples = dec->detected_samples - dec->cur_sample;
943
}
944
dec->cur_sample += out_samples;
945
*buf = dec->buffer + dec->buffer_consumed;
946
dec->buffer_consumed += out_samples;
947
return out_samples;
948
}
949
950
size_t mp3dec_ex_read(mp3dec_ex_t *dec, mp3d_sample_t *buf, size_t samples)
951
{
952
if (!dec || !buf)
953
{
954
if (dec)
955
dec->last_error = MP3D_E_PARAM;
956
return 0;
957
}
958
mp3dec_frame_info_t frame_info;
959
memset(&frame_info, 0, sizeof(frame_info));
960
size_t samples_requested = samples;
961
while (samples)
962
{
963
mp3d_sample_t *buf_frame = NULL;
964
size_t read_samples = mp3dec_ex_read_frame(dec, &buf_frame, &frame_info, samples);
965
if (!read_samples)
966
{
967
break;
968
}
969
memcpy(buf, buf_frame, read_samples * sizeof(mp3d_sample_t));
970
buf += read_samples;
971
samples -= read_samples;
972
}
973
return samples_requested - samples;
974
}
975
976
int mp3dec_ex_open_cb(mp3dec_ex_t *dec, mp3dec_io_t *io, int flags)
977
{
978
if (!dec || !io || (flags & (~MP3D_FLAGS_MASK)))
979
return MP3D_E_PARAM;
980
memset(dec, 0, sizeof(*dec));
981
#ifdef MINIMP3_HAVE_RING
982
int ret;
983
if (ret = mp3dec_open_ring(&dec->file, MINIMP3_IO_SIZE))
984
return ret;
985
#else
986
dec->file.size = MINIMP3_IO_SIZE;
987
dec->file.buffer = (const uint8_t*)malloc(dec->file.size);
988
if (!dec->file.buffer)
989
return MP3D_E_MEMORY;
990
#endif
991
dec->flags = flags;
992
dec->io = io;
993
mp3dec_init(&dec->mp3d);
994
if (io->seek(0, io->seek_data))
995
return MP3D_E_IOERROR;
996
int ret = mp3dec_iterate_cb(io, (uint8_t *)dec->file.buffer, dec->file.size, mp3dec_load_index, dec);
997
if (ret && MP3D_E_USER != ret)
998
return ret;
999
if (dec->io->seek(dec->start_offset, dec->io->seek_data))
1000
return MP3D_E_IOERROR;
1001
mp3dec_init(&dec->mp3d);
1002
dec->buffer_samples = 0;
1003
dec->indexes_built = !(dec->vbr_tag_found || (flags & MP3D_DO_NOT_SCAN));
1004
dec->flags &= (~MP3D_DO_NOT_SCAN);
1005
return 0;
1006
}
1007
1008
1009
#ifndef MINIMP3_NO_STDIO
1010
1011
#if defined(__linux__) || defined(__FreeBSD__)
1012
#include <errno.h>
1013
#include <sys/mman.h>
1014
#include <sys/types.h>
1015
#include <sys/stat.h>
1016
#include <unistd.h>
1017
#include <fcntl.h>
1018
#if !defined(_GNU_SOURCE)
1019
#include <sys/ipc.h>
1020
#include <sys/shm.h>
1021
#endif
1022
#if !defined(MAP_POPULATE) && defined(__linux__)
1023
#define MAP_POPULATE 0x08000
1024
#elif !defined(MAP_POPULATE)
1025
#define MAP_POPULATE 0
1026
#endif
1027
1028
static void mp3dec_close_file(mp3dec_map_info_t *map_info)
1029
{
1030
if (map_info->buffer && MAP_FAILED != map_info->buffer)
1031
munmap((void *)map_info->buffer, map_info->size);
1032
map_info->buffer = 0;
1033
map_info->size = 0;
1034
}
1035
1036
static int mp3dec_open_file(const char *file_name, mp3dec_map_info_t *map_info)
1037
{
1038
if (!file_name)
1039
return MP3D_E_PARAM;
1040
int file;
1041
struct stat st;
1042
memset(map_info, 0, sizeof(*map_info));
1043
retry_open:
1044
file = open(file_name, O_RDONLY);
1045
if (file < 0 && (errno == EAGAIN || errno == EINTR))
1046
goto retry_open;
1047
if (file < 0 || fstat(file, &st) < 0)
1048
{
1049
close(file);
1050
return MP3D_E_IOERROR;
1051
}
1052
1053
map_info->size = st.st_size;
1054
retry_mmap:
1055
map_info->buffer = (const uint8_t *)mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE | MAP_POPULATE, file, 0);
1056
if (MAP_FAILED == map_info->buffer && (errno == EAGAIN || errno == EINTR))
1057
goto retry_mmap;
1058
close(file);
1059
if (MAP_FAILED == map_info->buffer)
1060
return MP3D_E_IOERROR;
1061
return 0;
1062
}
1063
1064
#if MINIMP3_ENABLE_RING && defined(__linux__) && defined(_GNU_SOURCE)
1065
#define MINIMP3_HAVE_RING
1066
static void mp3dec_close_ring(mp3dec_map_info_t *map_info)
1067
{
1068
#if defined(__linux__) && defined(_GNU_SOURCE)
1069
if (map_info->buffer && MAP_FAILED != map_info->buffer)
1070
munmap((void *)map_info->buffer, map_info->size*2);
1071
#else
1072
if (map_info->buffer)
1073
{
1074
shmdt(map_info->buffer);
1075
shmdt(map_info->buffer + map_info->size);
1076
}
1077
#endif
1078
map_info->buffer = 0;
1079
map_info->size = 0;
1080
}
1081
1082
static int mp3dec_open_ring(mp3dec_map_info_t *map_info, size_t size)
1083
{
1084
int memfd, page_size;
1085
#if defined(__linux__) && defined(_GNU_SOURCE)
1086
void *buffer;
1087
int res;
1088
#endif
1089
memset(map_info, 0, sizeof(*map_info));
1090
1091
#ifdef _SC_PAGESIZE
1092
page_size = sysconf(_SC_PAGESIZE);
1093
#else
1094
page_size = getpagesize();
1095
#endif
1096
map_info->size = (size + page_size - 1)/page_size*page_size;
1097
1098
#if defined(__linux__) && defined(_GNU_SOURCE)
1099
memfd = memfd_create("mp3_ring", 0);
1100
if (memfd < 0)
1101
return MP3D_E_MEMORY;
1102
1103
retry_ftruncate:
1104
res = ftruncate(memfd, map_info->size);
1105
if (res && (errno == EAGAIN || errno == EINTR))
1106
goto retry_ftruncate;
1107
if (res)
1108
goto error;
1109
1110
retry_mmap:
1111
map_info->buffer = (const uint8_t *)mmap(NULL, map_info->size*2, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
1112
if (MAP_FAILED == map_info->buffer && (errno == EAGAIN || errno == EINTR))
1113
goto retry_mmap;
1114
if (MAP_FAILED == map_info->buffer || !map_info->buffer)
1115
goto error;
1116
retry_mmap2:
1117
buffer = mmap((void *)map_info->buffer, map_info->size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, memfd, 0);
1118
if (MAP_FAILED == map_info->buffer && (errno == EAGAIN || errno == EINTR))
1119
goto retry_mmap2;
1120
if (MAP_FAILED == map_info->buffer || buffer != (void *)map_info->buffer)
1121
goto error;
1122
retry_mmap3:
1123
buffer = mmap((void *)map_info->buffer + map_info->size, map_info->size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, memfd, 0);
1124
if (MAP_FAILED == map_info->buffer && (errno == EAGAIN || errno == EINTR))
1125
goto retry_mmap3;
1126
if (MAP_FAILED == map_info->buffer || buffer != (void *)(map_info->buffer + map_info->size))
1127
goto error;
1128
1129
close(memfd);
1130
return 0;
1131
error:
1132
close(memfd);
1133
mp3dec_close_ring(map_info);
1134
return MP3D_E_MEMORY;
1135
#else
1136
memfd = shmget(IPC_PRIVATE, map_info->size, IPC_CREAT | 0700);
1137
if (memfd < 0)
1138
return MP3D_E_MEMORY;
1139
retry_mmap:
1140
map_info->buffer = (const uint8_t *)mmap(NULL, map_info->size*2, PROT_NONE, MAP_PRIVATE, -1, 0);
1141
if (MAP_FAILED == map_info->buffer && (errno == EAGAIN || errno == EINTR))
1142
goto retry_mmap;
1143
if (MAP_FAILED == map_info->buffer)
1144
goto error;
1145
if (map_info->buffer != shmat(memfd, map_info->buffer, 0))
1146
goto error;
1147
if ((map_info->buffer + map_info->size) != shmat(memfd, map_info->buffer + map_info->size, 0))
1148
goto error;
1149
if (shmctl(memfd, IPC_RMID, NULL) < 0)
1150
return MP3D_E_MEMORY;
1151
return 0;
1152
error:
1153
shmctl(memfd, IPC_RMID, NULL);
1154
mp3dec_close_ring(map_info);
1155
return MP3D_E_MEMORY;
1156
#endif
1157
}
1158
#endif /*MINIMP3_ENABLE_RING*/
1159
#elif defined(_WIN32)
1160
#include <windows.h>
1161
1162
static void mp3dec_close_file(mp3dec_map_info_t *map_info)
1163
{
1164
if (map_info->buffer)
1165
UnmapViewOfFile(map_info->buffer);
1166
map_info->buffer = 0;
1167
map_info->size = 0;
1168
}
1169
1170
static int mp3dec_open_file_h(HANDLE file, mp3dec_map_info_t *map_info)
1171
{
1172
memset(map_info, 0, sizeof(*map_info));
1173
1174
HANDLE mapping = NULL;
1175
LARGE_INTEGER s;
1176
s.LowPart = GetFileSize(file, (DWORD*)&s.HighPart);
1177
if (s.LowPart == INVALID_FILE_SIZE && GetLastError() != NO_ERROR)
1178
goto error;
1179
map_info->size = s.QuadPart;
1180
1181
mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
1182
if (!mapping)
1183
goto error;
1184
map_info->buffer = (const uint8_t*)MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, s.QuadPart);
1185
CloseHandle(mapping);
1186
if (!map_info->buffer)
1187
goto error;
1188
1189
CloseHandle(file);
1190
return 0;
1191
error:
1192
mp3dec_close_file(map_info);
1193
CloseHandle(file);
1194
return MP3D_E_IOERROR;
1195
}
1196
1197
static int mp3dec_open_file(const char *file_name, mp3dec_map_info_t *map_info)
1198
{
1199
if (!file_name)
1200
return MP3D_E_PARAM;
1201
HANDLE file = CreateFileA(file_name, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
1202
if (INVALID_HANDLE_VALUE == file)
1203
return MP3D_E_IOERROR;
1204
return mp3dec_open_file_h(file, map_info);
1205
}
1206
1207
static int mp3dec_open_file_w(const wchar_t *file_name, mp3dec_map_info_t *map_info)
1208
{
1209
if (!file_name)
1210
return MP3D_E_PARAM;
1211
HANDLE file = CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
1212
if (INVALID_HANDLE_VALUE == file)
1213
return MP3D_E_IOERROR;
1214
return mp3dec_open_file_h(file, map_info);
1215
}
1216
#else
1217
#include <stdio.h>
1218
1219
static void mp3dec_close_file(mp3dec_map_info_t *map_info)
1220
{
1221
if (map_info->buffer)
1222
free((void *)map_info->buffer);
1223
map_info->buffer = 0;
1224
map_info->size = 0;
1225
}
1226
1227
static int mp3dec_open_file(const char *file_name, mp3dec_map_info_t *map_info)
1228
{
1229
if (!file_name)
1230
return MP3D_E_PARAM;
1231
memset(map_info, 0, sizeof(*map_info));
1232
FILE *file = fopen(file_name, "rb");
1233
if (!file)
1234
return MP3D_E_IOERROR;
1235
int res = MP3D_E_IOERROR;
1236
long size = -1;
1237
if (fseek(file, 0, SEEK_END))
1238
goto error;
1239
size = ftell(file);
1240
if (size < 0)
1241
goto error;
1242
map_info->size = (size_t)size;
1243
if (fseek(file, 0, SEEK_SET))
1244
goto error;
1245
map_info->buffer = (uint8_t *)malloc(map_info->size);
1246
if (!map_info->buffer)
1247
{
1248
res = MP3D_E_MEMORY;
1249
goto error;
1250
}
1251
if (fread((void *)map_info->buffer, 1, map_info->size, file) != map_info->size)
1252
goto error;
1253
fclose(file);
1254
return 0;
1255
error:
1256
mp3dec_close_file(map_info);
1257
fclose(file);
1258
return res;
1259
}
1260
#endif
1261
1262
static int mp3dec_detect_mapinfo(mp3dec_map_info_t *map_info)
1263
{
1264
int ret = mp3dec_detect_buf(map_info->buffer, map_info->size);
1265
mp3dec_close_file(map_info);
1266
return ret;
1267
}
1268
1269
static int mp3dec_load_mapinfo(mp3dec_t *dec, mp3dec_map_info_t *map_info, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data)
1270
{
1271
int ret = mp3dec_load_buf(dec, map_info->buffer, map_info->size, info, progress_cb, user_data);
1272
mp3dec_close_file(map_info);
1273
return ret;
1274
}
1275
1276
static int mp3dec_iterate_mapinfo(mp3dec_map_info_t *map_info, MP3D_ITERATE_CB callback, void *user_data)
1277
{
1278
int ret = mp3dec_iterate_buf(map_info->buffer, map_info->size, callback, user_data);
1279
mp3dec_close_file(map_info);
1280
return ret;
1281
}
1282
1283
static int mp3dec_ex_open_mapinfo(mp3dec_ex_t *dec, int flags)
1284
{
1285
int ret = mp3dec_ex_open_buf(dec, dec->file.buffer, dec->file.size, flags);
1286
dec->is_file = 1;
1287
if (ret)
1288
mp3dec_ex_close(dec);
1289
return ret;
1290
}
1291
1292
int mp3dec_detect(const char *file_name)
1293
{
1294
int ret;
1295
mp3dec_map_info_t map_info;
1296
if ((ret = mp3dec_open_file(file_name, &map_info)))
1297
return ret;
1298
return mp3dec_detect_mapinfo(&map_info);
1299
}
1300
1301
int mp3dec_load(mp3dec_t *dec, const char *file_name, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data)
1302
{
1303
int ret;
1304
mp3dec_map_info_t map_info;
1305
if ((ret = mp3dec_open_file(file_name, &map_info)))
1306
return ret;
1307
return mp3dec_load_mapinfo(dec, &map_info, info, progress_cb, user_data);
1308
}
1309
1310
int mp3dec_iterate(const char *file_name, MP3D_ITERATE_CB callback, void *user_data)
1311
{
1312
int ret;
1313
mp3dec_map_info_t map_info;
1314
if ((ret = mp3dec_open_file(file_name, &map_info)))
1315
return ret;
1316
return mp3dec_iterate_mapinfo(&map_info, callback, user_data);
1317
}
1318
1319
int mp3dec_ex_open(mp3dec_ex_t *dec, const char *file_name, int flags)
1320
{
1321
int ret;
1322
if (!dec)
1323
return MP3D_E_PARAM;
1324
if ((ret = mp3dec_open_file(file_name, &dec->file)))
1325
return ret;
1326
return mp3dec_ex_open_mapinfo(dec, flags);
1327
}
1328
1329
void mp3dec_ex_close(mp3dec_ex_t *dec)
1330
{
1331
#ifdef MINIMP3_HAVE_RING
1332
if (dec->io)
1333
mp3dec_close_ring(&dec->file);
1334
#else
1335
if (dec->io && dec->file.buffer)
1336
free((void*)dec->file.buffer);
1337
#endif
1338
if (dec->is_file)
1339
mp3dec_close_file(&dec->file);
1340
if (dec->index.frames)
1341
free(dec->index.frames);
1342
memset(dec, 0, sizeof(*dec));
1343
}
1344
1345
#ifdef _WIN32
1346
int mp3dec_detect_w(const wchar_t *file_name)
1347
{
1348
int ret;
1349
mp3dec_map_info_t map_info;
1350
if ((ret = mp3dec_open_file_w(file_name, &map_info)))
1351
return ret;
1352
return mp3dec_detect_mapinfo(&map_info);
1353
}
1354
1355
int mp3dec_load_w(mp3dec_t *dec, const wchar_t *file_name, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data)
1356
{
1357
int ret;
1358
mp3dec_map_info_t map_info;
1359
if ((ret = mp3dec_open_file_w(file_name, &map_info)))
1360
return ret;
1361
return mp3dec_load_mapinfo(dec, &map_info, info, progress_cb, user_data);
1362
}
1363
1364
int mp3dec_iterate_w(const wchar_t *file_name, MP3D_ITERATE_CB callback, void *user_data)
1365
{
1366
int ret;
1367
mp3dec_map_info_t map_info;
1368
if ((ret = mp3dec_open_file_w(file_name, &map_info)))
1369
return ret;
1370
return mp3dec_iterate_mapinfo(&map_info, callback, user_data);
1371
}
1372
1373
int mp3dec_ex_open_w(mp3dec_ex_t *dec, const wchar_t *file_name, int flags)
1374
{
1375
int ret;
1376
if ((ret = mp3dec_open_file_w(file_name, &dec->file)))
1377
return ret;
1378
return mp3dec_ex_open_mapinfo(dec, flags);
1379
}
1380
#endif
1381
#else /* MINIMP3_NO_STDIO */
1382
void mp3dec_ex_close(mp3dec_ex_t *dec)
1383
{
1384
#ifdef MINIMP3_HAVE_RING
1385
if (dec->io)
1386
mp3dec_close_ring(&dec->file);
1387
#else
1388
if (dec->io && dec->file.buffer)
1389
free((void*)dec->file.buffer);
1390
#endif
1391
if (dec->index.frames)
1392
free(dec->index.frames);
1393
memset(dec, 0, sizeof(*dec));
1394
}
1395
#endif
1396
1397
#endif /* MINIMP3_IMPLEMENTATION && !_MINIMP3_EX_IMPLEMENTATION_GUARD */
1398
1399