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
38typedef 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
45typedef struct
46{
47 const uint8_t *buffer;
48 size_t size;
49} mp3dec_map_info_t;
50
51typedef struct
52{
53 uint64_t sample;
54 uint64_t offset;
55} mp3dec_frame_t;
56
57typedef struct
58{
59 mp3dec_frame_t *frames;
60 size_t num_frames, capacity;
61} mp3dec_index_t;
62
63typedef size_t (*MP3D_READ_CB)(void *buf, size_t size, void *user_data);
64typedef int (*MP3D_SEEK_CB)(uint64_t position, void *user_data);
65
66typedef 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
74typedef 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
90typedef 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);
91typedef int (*MP3D_PROGRESS_CB)(void *user_data, size_t file_size, uint64_t offset, mp3dec_frame_info_t *info);
92
93#ifdef __cplusplus
94extern "C" {
95#endif
96
97/* detect mp3/mpa format */
98int mp3dec_detect_buf(const uint8_t *buf, size_t buf_size);
99int mp3dec_detect_cb(mp3dec_io_t *io, uint8_t *buf, size_t buf_size);
100/* decode whole buffer block */
101int 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);
102int 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 */
104int mp3dec_iterate_buf(const uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data);
105int 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 */
107int mp3dec_ex_open_buf(mp3dec_ex_t *dec, const uint8_t *buf, size_t buf_size, int flags);
108int mp3dec_ex_open_cb(mp3dec_ex_t *dec, mp3dec_io_t *io, int flags);
109void mp3dec_ex_close(mp3dec_ex_t *dec);
110int mp3dec_ex_seek(mp3dec_ex_t *dec, uint64_t position);
111size_t mp3dec_ex_read_frame(mp3dec_ex_t *dec, mp3d_sample_t **buf, mp3dec_frame_info_t *frame_info, size_t max_samples);
112size_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 */
115int mp3dec_detect(const char *file_name);
116int mp3dec_load(mp3dec_t *dec, const char *file_name, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data);
117int mp3dec_iterate(const char *file_name, MP3D_ITERATE_CB callback, void *user_data);
118int mp3dec_ex_open(mp3dec_ex_t *dec, const char *file_name, int flags);
119#ifdef _WIN32
120int mp3dec_detect_w(const wchar_t *file_name);
121int mp3dec_load_w(mp3dec_t *dec, const wchar_t *file_name, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data);
122int mp3dec_iterate_w(const wchar_t *file_name, MP3D_ITERATE_CB callback, void *user_data);
123int 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
137static 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
161static 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
176static 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
193static 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
240int 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
245int 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
283int 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
288int 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 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
502int 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 ret = callback(user_data, hdr, frame_size, free_format_bytes, buf_size, hdr - orig_buf, &frame_info);
533 if (ret != 0)
534 return ret;
535 }
536 buf += frame_size;
537 buf_size -= frame_size;
538 } while (1);
539 return 0;
540}
541
542int mp3dec_iterate_cb(mp3dec_io_t *io, uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data)
543{
544 if (!io || !buf || (size_t)-1 == buf_size || buf_size < MINIMP3_BUF_SIZE || !callback)
545 return MP3D_E_PARAM;
546 size_t filled = io->read(buf, MINIMP3_ID3_DETECT_SIZE, io->read_data), consumed = 0;
547 uint64_t readed = 0;
548 mp3dec_frame_info_t frame_info;
549 int eof = 0;
550 memset(&frame_info, 0, sizeof(frame_info));
551 if (filled > MINIMP3_ID3_DETECT_SIZE)
552 return MP3D_E_IOERROR;
553 if (MINIMP3_ID3_DETECT_SIZE != filled)
554 return 0;
555 size_t id3v2size = mp3dec_skip_id3v2(buf, filled);
556 if (id3v2size)
557 {
558 if (io->seek(id3v2size, io->seek_data))
559 return MP3D_E_IOERROR;
560 filled = io->read(buf, buf_size, io->read_data);
561 if (filled > buf_size)
562 return MP3D_E_IOERROR;
563 readed += id3v2size;
564 } else
565 {
566 readed = io->read(buf + MINIMP3_ID3_DETECT_SIZE, buf_size - MINIMP3_ID3_DETECT_SIZE, io->read_data);
567 if (readed > (buf_size - MINIMP3_ID3_DETECT_SIZE))
568 return MP3D_E_IOERROR;
569 filled += readed;
570 }
571 if (filled < MINIMP3_BUF_SIZE)
572 mp3dec_skip_id3v1(buf, &filled);
573 do
574 {
575 int free_format_bytes = 0, frame_size = 0, ret;
576 int i = mp3d_find_frame(buf + consumed, filled - consumed, &free_format_bytes, &frame_size);
577 if (i && !frame_size)
578 {
579 consumed += i;
580 continue;
581 }
582 if (!frame_size)
583 break;
584 const uint8_t *hdr = buf + consumed + i;
585 frame_info.channels = HDR_IS_MONO(hdr) ? 1 : 2;
586 frame_info.hz = hdr_sample_rate_hz(hdr);
587 frame_info.layer = 4 - HDR_GET_LAYER(hdr);
588 frame_info.bitrate_kbps = hdr_bitrate_kbps(hdr);
589 frame_info.frame_bytes = frame_size;
590
591 readed += i;
592 if (callback)
593 {
594 ret = callback(user_data, hdr, frame_size, free_format_bytes, filled - consumed, readed, &frame_info);
595 if (ret != 0)
596 return ret;
597 }
598 readed += frame_size;
599 consumed += i + frame_size;
600 if (!eof && filled - consumed < MINIMP3_BUF_SIZE)
601 { /* keep minimum 10 consecutive mp3 frames (~16KB) worst case */
602 memmove(buf, buf + consumed, filled - consumed);
603 filled -= consumed;
604 consumed = 0;
605 readed = io->read(buf + filled, buf_size - filled, io->read_data);
606 if (readed > (buf_size - filled))
607 return MP3D_E_IOERROR;
608 if (readed != (buf_size - filled))
609 eof = 1;
610 filled += readed;
611 if (eof)
612 mp3dec_skip_id3v1(buf, &filled);
613 }
614 } while (1);
615 return 0;
616}
617
618static 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)
619{
620 mp3dec_frame_t *idx_frame;
621 mp3dec_ex_t *dec = (mp3dec_ex_t *)user_data;
622 if (!dec->index.frames && !dec->start_offset)
623 { /* detect VBR tag and try to avoid full scan */
624 uint32_t frames;
625 int delay, padding;
626 dec->info = *info;
627 dec->start_offset = dec->offset = offset;
628 dec->end_offset = offset + buf_size;
629 dec->free_format_bytes = free_format_bytes; /* should not change */
630 if (3 == dec->info.layer)
631 {
632 int ret = mp3dec_check_vbrtag(frame, frame_size, &frames, &delay, &padding);
633 if (ret)
634 dec->start_offset = dec->offset = offset + frame_size;
635 if (ret > 0)
636 {
637 padding *= info->channels;
638 dec->start_delay = dec->to_skip = delay*info->channels;
639 dec->samples = hdr_frame_samples(frame)*info->channels*(uint64_t)frames;
640 if (dec->samples >= (uint64_t)dec->start_delay)
641 dec->samples -= dec->start_delay;
642 if (padding > 0 && dec->samples >= (uint64_t)padding)
643 dec->samples -= padding;
644 dec->detected_samples = dec->samples;
645 dec->vbr_tag_found = 1;
646 return MP3D_E_USER;
647 } else if (ret < 0)
648 return 0;
649 }
650 }
651 if (dec->flags & MP3D_DO_NOT_SCAN)
652 return MP3D_E_USER;
653 if (dec->index.num_frames + 1 > dec->index.capacity)
654 {
655 if (!dec->index.capacity)
656 dec->index.capacity = 4096;
657 else
658 dec->index.capacity *= 2;
659 mp3dec_frame_t *alloc_buf = (mp3dec_frame_t *)realloc((void*)dec->index.frames, sizeof(mp3dec_frame_t)*dec->index.capacity);
660 if (!alloc_buf)
661 return MP3D_E_MEMORY;
662 dec->index.frames = alloc_buf;
663 }
664 idx_frame = &dec->index.frames[dec->index.num_frames++];
665 idx_frame->offset = offset;
666 idx_frame->sample = dec->samples;
667 if (!dec->buffer_samples && dec->index.num_frames < 256)
668 { /* for some cutted mp3 frames, bit-reservoir not filled and decoding can't be started from first frames */
669 /* try to decode up to 255 first frames till samples starts to decode */
670 dec->buffer_samples = mp3dec_decode_frame(&dec->mp3d, frame, MINIMP3_MIN(buf_size, (size_t)INT_MAX), dec->buffer, info);
671 dec->samples += dec->buffer_samples*info->channels;
672 } else
673 dec->samples += hdr_frame_samples(frame)*info->channels;
674 return 0;
675}
676
677int mp3dec_ex_open_buf(mp3dec_ex_t *dec, const uint8_t *buf, size_t buf_size, int flags)
678{
679 if (!dec || !buf || (size_t)-1 == buf_size || (flags & (~MP3D_FLAGS_MASK)))
680 return MP3D_E_PARAM;
681 memset(dec, 0, sizeof(*dec));
682 dec->file.buffer = buf;
683 dec->file.size = buf_size;
684 dec->flags = flags;
685 mp3dec_init(&dec->mp3d);
686 int ret = mp3dec_iterate_buf(dec->file.buffer, dec->file.size, mp3dec_load_index, dec);
687 if (ret && MP3D_E_USER != ret)
688 return ret;
689 mp3dec_init(&dec->mp3d);
690 dec->buffer_samples = 0;
691 dec->indexes_built = !(dec->vbr_tag_found || (flags & MP3D_DO_NOT_SCAN));
692 dec->flags &= (~MP3D_DO_NOT_SCAN);
693 return 0;
694}
695
696#ifndef MINIMP3_SEEK_IDX_LINEAR_SEARCH
697static size_t mp3dec_idx_binary_search(mp3dec_index_t *idx, uint64_t position)
698{
699 size_t end = idx->num_frames, start = 0, index = 0;
700 while (start <= end)
701 {
702 size_t mid = (start + end) / 2;
703 if (idx->frames[mid].sample >= position)
704 { /* move left side. */
705 if (idx->frames[mid].sample == position)
706 return mid;
707 end = mid - 1;
708 } else
709 { /* move to right side */
710 index = mid;
711 start = mid + 1;
712 if (start == idx->num_frames)
713 break;
714 }
715 }
716 return index;
717}
718#endif
719
720int mp3dec_ex_seek(mp3dec_ex_t *dec, uint64_t position)
721{
722 size_t i;
723 if (!dec)
724 return MP3D_E_PARAM;
725 if (!(dec->flags & MP3D_SEEK_TO_SAMPLE))
726 {
727 if (dec->io)
728 {
729 dec->offset = position;
730 } else
731 {
732 dec->offset = MINIMP3_MIN(position, dec->file.size);
733 }
734 dec->cur_sample = 0;
735 goto do_exit;
736 }
737 dec->cur_sample = position;
738 position += dec->start_delay;
739 if (0 == position)
740 { /* optimize seek to zero, no index needed */
741seek_zero:
742 dec->offset = dec->start_offset;
743 dec->to_skip = 0;
744 goto do_exit;
745 }
746 if (!dec->indexes_built)
747 { /* no index created yet (vbr tag used to calculate track length or MP3D_DO_NOT_SCAN open flag used) */
748 dec->indexes_built = 1;
749 dec->samples = 0;
750 dec->buffer_samples = 0;
751 if (dec->io)
752 {
753 if (dec->io->seek(dec->start_offset, dec->io->seek_data))
754 return MP3D_E_IOERROR;
755 int ret = mp3dec_iterate_cb(dec->io, (uint8_t *)dec->file.buffer, dec->file.size, mp3dec_load_index, dec);
756 if (ret && MP3D_E_USER != ret)
757 return ret;
758 } else
759 {
760 int ret = mp3dec_iterate_buf(dec->file.buffer + dec->start_offset, dec->file.size - dec->start_offset, mp3dec_load_index, dec);
761 if (ret && MP3D_E_USER != ret)
762 return ret;
763 }
764 for (i = 0; i < dec->index.num_frames; i++)
765 dec->index.frames[i].offset += dec->start_offset;
766 dec->samples = dec->detected_samples;
767 }
768 if (!dec->index.frames)
769 goto seek_zero; /* no frames in file - seek to zero */
770#ifdef MINIMP3_SEEK_IDX_LINEAR_SEARCH
771 for (i = 0; i < dec->index.num_frames; i++)
772 {
773 if (dec->index.frames[i].sample >= position)
774 break;
775 }
776#else
777 i = mp3dec_idx_binary_search(&dec->index, position);
778#endif
779 if (i)
780 {
781 int to_fill_bytes = 511;
782 int skip_frames = MINIMP3_PREDECODE_FRAMES
783#ifdef MINIMP3_SEEK_IDX_LINEAR_SEARCH
784 + ((dec->index.frames[i].sample == position) ? 0 : 1)
785#endif
786 ;
787 i -= MINIMP3_MIN(i, (size_t)skip_frames);
788 if (3 == dec->info.layer)
789 {
790 while (i && to_fill_bytes)
791 { /* make sure bit-reservoir is filled when we start decoding */
792 bs_t bs[1];
793 L3_gr_info_t gr_info[4];
794 int frame_bytes, frame_size;
795 const uint8_t *hdr;
796 if (dec->io)
797 {
798 hdr = dec->file.buffer;
799 if (dec->io->seek(dec->index.frames[i - 1].offset, dec->io->seek_data))
800 return MP3D_E_IOERROR;
801 size_t readed = dec->io->read((uint8_t *)hdr, HDR_SIZE, dec->io->read_data);
802 if (readed != HDR_SIZE)
803 return MP3D_E_IOERROR;
804 frame_size = hdr_frame_bytes(hdr, dec->free_format_bytes) + hdr_padding(hdr);
805 readed = dec->io->read((uint8_t *)hdr + HDR_SIZE, frame_size - HDR_SIZE, dec->io->read_data);
806 if (readed != (size_t)(frame_size - HDR_SIZE))
807 return MP3D_E_IOERROR;
808 bs_init(bs, hdr + HDR_SIZE, frame_size - HDR_SIZE);
809 } else
810 {
811 hdr = dec->file.buffer + dec->index.frames[i - 1].offset;
812 frame_size = hdr_frame_bytes(hdr, dec->free_format_bytes) + hdr_padding(hdr);
813 bs_init(bs, hdr + HDR_SIZE, frame_size - HDR_SIZE);
814 }
815 if (HDR_IS_CRC(hdr))
816 get_bits(bs, 16);
817 i--;
818 if (L3_read_side_info(bs, gr_info, hdr) < 0)
819 break; /* frame not decodable, we can start from here */
820 frame_bytes = (bs->limit - bs->pos)/8;
821 to_fill_bytes -= MINIMP3_MIN(to_fill_bytes, frame_bytes);
822 }
823 }
824 }
825 dec->offset = dec->index.frames[i].offset;
826 dec->to_skip = position - dec->index.frames[i].sample;
827 while ((i + 1) < dec->index.num_frames && !dec->index.frames[i].sample && !dec->index.frames[i + 1].sample)
828 { /* skip not decodable first frames */
829 const uint8_t *hdr;
830 if (dec->io)
831 {
832 hdr = dec->file.buffer;
833 if (dec->io->seek(dec->index.frames[i].offset, dec->io->seek_data))
834 return MP3D_E_IOERROR;
835 size_t readed = dec->io->read((uint8_t *)hdr, HDR_SIZE, dec->io->read_data);
836 if (readed != HDR_SIZE)
837 return MP3D_E_IOERROR;
838 } else
839 hdr = dec->file.buffer + dec->index.frames[i].offset;
840 dec->to_skip += hdr_frame_samples(hdr)*dec->info.channels;
841 i++;
842 }
843do_exit:
844 if (dec->io)
845 {
846 if (dec->io->seek(dec->offset, dec->io->seek_data))
847 return MP3D_E_IOERROR;
848 }
849 dec->buffer_samples = 0;
850 dec->buffer_consumed = 0;
851 dec->input_consumed = 0;
852 dec->input_filled = 0;
853 dec->last_error = 0;
854 mp3dec_init(&dec->mp3d);
855 return 0;
856}
857
858size_t mp3dec_ex_read_frame(mp3dec_ex_t *dec, mp3d_sample_t **buf, mp3dec_frame_info_t *frame_info, size_t max_samples)
859{
860 if (!dec || !buf || !frame_info)
861 {
862 if (dec)
863 dec->last_error = MP3D_E_PARAM;
864 return 0;
865 }
866 if (dec->detected_samples && dec->cur_sample >= dec->detected_samples)
867 return 0; /* at end of stream */
868 if (dec->last_error)
869 return 0; /* error eof state, seek can reset it */
870 *buf = NULL;
871 uint64_t end_offset = dec->end_offset ? dec->end_offset : dec->file.size;
872 int eof = 0;
873 while (dec->buffer_consumed == dec->buffer_samples)
874 {
875 const uint8_t *dec_buf;
876 if (dec->io)
877 {
878 if (!eof && (dec->input_filled - dec->input_consumed) < MINIMP3_BUF_SIZE)
879 { /* keep minimum 10 consecutive mp3 frames (~16KB) worst case */
880 memmove((uint8_t*)dec->file.buffer, (uint8_t*)dec->file.buffer + dec->input_consumed, dec->input_filled - dec->input_consumed);
881 dec->input_filled -= dec->input_consumed;
882 dec->input_consumed = 0;
883 size_t readed = dec->io->read((uint8_t*)dec->file.buffer + dec->input_filled, dec->file.size - dec->input_filled, dec->io->read_data);
884 if (readed > (dec->file.size - dec->input_filled))
885 {
886 dec->last_error = MP3D_E_IOERROR;
887 readed = 0;
888 }
889 if (readed != (dec->file.size - dec->input_filled))
890 eof = 1;
891 dec->input_filled += readed;
892 if (eof)
893 mp3dec_skip_id3v1((uint8_t*)dec->file.buffer, &dec->input_filled);
894 }
895 dec_buf = dec->file.buffer + dec->input_consumed;
896 if (!(dec->input_filled - dec->input_consumed))
897 return 0;
898 dec->buffer_samples = mp3dec_decode_frame(&dec->mp3d, dec_buf, dec->input_filled - dec->input_consumed, dec->buffer, frame_info);
899 dec->input_consumed += frame_info->frame_bytes;
900 } else
901 {
902 dec_buf = dec->file.buffer + dec->offset;
903 uint64_t buf_size = end_offset - dec->offset;
904 if (!buf_size)
905 return 0;
906 dec->buffer_samples = mp3dec_decode_frame(&dec->mp3d, dec_buf, MINIMP3_MIN(buf_size, (uint64_t)INT_MAX), dec->buffer, frame_info);
907 }
908 dec->buffer_consumed = 0;
909 if (dec->info.hz != frame_info->hz || dec->info.layer != frame_info->layer)
910 {
911return_e_decode:
912 dec->last_error = MP3D_E_DECODE;
913 return 0;
914 }
915 if (dec->buffer_samples)
916 {
917 dec->buffer_samples *= frame_info->channels;
918 if (dec->to_skip)
919 {
920 size_t skip = MINIMP3_MIN(dec->buffer_samples, dec->to_skip);
921 dec->buffer_consumed += skip;
922 dec->to_skip -= skip;
923 }
924 if (
925#ifdef MINIMP3_ALLOW_MONO_STEREO_TRANSITION
926 !(dec->flags & MP3D_ALLOW_MONO_STEREO_TRANSITION) &&
927#endif
928 dec->buffer_consumed != dec->buffer_samples && dec->info.channels != frame_info->channels)
929 {
930 goto return_e_decode;
931 }
932 } else if (dec->to_skip)
933 { /* In mp3 decoding not always can start decode from any frame because of bit reservoir,
934 count skip samples for such frames */
935 int frame_samples = hdr_frame_samples(dec_buf)*frame_info->channels;
936 dec->to_skip -= MINIMP3_MIN(frame_samples, dec->to_skip);
937 }
938 dec->offset += frame_info->frame_bytes;
939 }
940 size_t out_samples = MINIMP3_MIN((size_t)(dec->buffer_samples - dec->buffer_consumed), max_samples);
941 if (dec->detected_samples)
942 { /* count decoded samples to properly cut padding */
943 if (dec->cur_sample + out_samples >= dec->detected_samples)
944 out_samples = dec->detected_samples - dec->cur_sample;
945 }
946 dec->cur_sample += out_samples;
947 *buf = dec->buffer + dec->buffer_consumed;
948 dec->buffer_consumed += out_samples;
949 return out_samples;
950}
951
952size_t mp3dec_ex_read(mp3dec_ex_t *dec, mp3d_sample_t *buf, size_t samples)
953{
954 if (!dec || !buf)
955 {
956 if (dec)
957 dec->last_error = MP3D_E_PARAM;
958 return 0;
959 }
960 mp3dec_frame_info_t frame_info;
961 memset(&frame_info, 0, sizeof(frame_info));
962 size_t samples_requested = samples;
963 while (samples)
964 {
965 mp3d_sample_t *buf_frame = NULL;
966 size_t read_samples = mp3dec_ex_read_frame(dec, &buf_frame, &frame_info, samples);
967 if (!read_samples)
968 {
969 break;
970 }
971 memcpy(buf, buf_frame, read_samples * sizeof(mp3d_sample_t));
972 buf += read_samples;
973 samples -= read_samples;
974 }
975 return samples_requested - samples;
976}
977
978int mp3dec_ex_open_cb(mp3dec_ex_t *dec, mp3dec_io_t *io, int flags)
979{
980 if (!dec || !io || (flags & (~MP3D_FLAGS_MASK)))
981 return MP3D_E_PARAM;
982 memset(dec, 0, sizeof(*dec));
983#ifdef MINIMP3_HAVE_RING
984 int ret;
985 if (ret = mp3dec_open_ring(&dec->file, MINIMP3_IO_SIZE))
986 return ret;
987#else
988 dec->file.size = MINIMP3_IO_SIZE;
989 dec->file.buffer = (const uint8_t*)malloc(dec->file.size);
990 if (!dec->file.buffer)
991 return MP3D_E_MEMORY;
992#endif
993 dec->flags = flags;
994 dec->io = io;
995 mp3dec_init(&dec->mp3d);
996 if (io->seek(0, io->seek_data))
997 return MP3D_E_IOERROR;
998 int ret = mp3dec_iterate_cb(io, (uint8_t *)dec->file.buffer, dec->file.size, mp3dec_load_index, dec);
999 if (ret && MP3D_E_USER != ret)
1000 return ret;
1001 if (dec->io->seek(dec->start_offset, dec->io->seek_data))
1002 return MP3D_E_IOERROR;
1003 mp3dec_init(&dec->mp3d);
1004 dec->buffer_samples = 0;
1005 dec->indexes_built = !(dec->vbr_tag_found || (flags & MP3D_DO_NOT_SCAN));
1006 dec->flags &= (~MP3D_DO_NOT_SCAN);
1007 return 0;
1008}
1009
1010
1011#ifndef MINIMP3_NO_STDIO
1012
1013#if defined(__linux__) || defined(__FreeBSD__)
1014#include <errno.h>
1015#include <sys/mman.h>
1016#include <sys/types.h>
1017#include <sys/stat.h>
1018#include <unistd.h>
1019#include <fcntl.h>
1020#if !defined(_GNU_SOURCE)
1021#include <sys/ipc.h>
1022#include <sys/shm.h>
1023#endif
1024#if !defined(MAP_POPULATE) && defined(__linux__)
1025#define MAP_POPULATE 0x08000
1026#elif !defined(MAP_POPULATE)
1027#define MAP_POPULATE 0
1028#endif
1029
1030static void mp3dec_close_file(mp3dec_map_info_t *map_info)
1031{
1032 if (map_info->buffer && MAP_FAILED != map_info->buffer)
1033 munmap((void *)map_info->buffer, map_info->size);
1034 map_info->buffer = 0;
1035 map_info->size = 0;
1036}
1037
1038static int mp3dec_open_file(const char *file_name, mp3dec_map_info_t *map_info)
1039{
1040 if (!file_name)
1041 return MP3D_E_PARAM;
1042 int file;
1043 struct stat st;
1044 memset(map_info, 0, sizeof(*map_info));
1045retry_open:
1046 file = open(file_name, O_RDONLY);
1047 if (file < 0 && (errno == EAGAIN || errno == EINTR))
1048 goto retry_open;
1049 if (file < 0 || fstat(file, &st) < 0)
1050 {
1051 close(file);
1052 return MP3D_E_IOERROR;
1053 }
1054
1055 map_info->size = st.st_size;
1056retry_mmap:
1057 map_info->buffer = (const uint8_t *)mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE | MAP_POPULATE, file, 0);
1058 if (MAP_FAILED == map_info->buffer && (errno == EAGAIN || errno == EINTR))
1059 goto retry_mmap;
1060 close(file);
1061 if (MAP_FAILED == map_info->buffer)
1062 return MP3D_E_IOERROR;
1063 return 0;
1064}
1065
1066#if MINIMP3_ENABLE_RING && defined(__linux__) && defined(_GNU_SOURCE)
1067#define MINIMP3_HAVE_RING
1068static void mp3dec_close_ring(mp3dec_map_info_t *map_info)
1069{
1070#if defined(__linux__) && defined(_GNU_SOURCE)
1071 if (map_info->buffer && MAP_FAILED != map_info->buffer)
1072 munmap((void *)map_info->buffer, map_info->size*2);
1073#else
1074 if (map_info->buffer)
1075 {
1076 shmdt(map_info->buffer);
1077 shmdt(map_info->buffer + map_info->size);
1078 }
1079#endif
1080 map_info->buffer = 0;
1081 map_info->size = 0;
1082}
1083
1084static int mp3dec_open_ring(mp3dec_map_info_t *map_info, size_t size)
1085{
1086 int memfd, page_size;
1087#if defined(__linux__) && defined(_GNU_SOURCE)
1088 void *buffer;
1089 int res;
1090#endif
1091 memset(map_info, 0, sizeof(*map_info));
1092
1093#ifdef _SC_PAGESIZE
1094 page_size = sysconf(_SC_PAGESIZE);
1095#else
1096 page_size = getpagesize();
1097#endif
1098 map_info->size = (size + page_size - 1)/page_size*page_size;
1099
1100#if defined(__linux__) && defined(_GNU_SOURCE)
1101 memfd = memfd_create("mp3_ring", 0);
1102 if (memfd < 0)
1103 return MP3D_E_MEMORY;
1104
1105retry_ftruncate:
1106 res = ftruncate(memfd, map_info->size);
1107 if (res && (errno == EAGAIN || errno == EINTR))
1108 goto retry_ftruncate;
1109 if (res)
1110 goto error;
1111
1112retry_mmap:
1113 map_info->buffer = (const uint8_t *)mmap(NULL, map_info->size*2, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
1114 if (MAP_FAILED == map_info->buffer && (errno == EAGAIN || errno == EINTR))
1115 goto retry_mmap;
1116 if (MAP_FAILED == map_info->buffer || !map_info->buffer)
1117 goto error;
1118retry_mmap2:
1119 buffer = mmap((void *)map_info->buffer, map_info->size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, memfd, 0);
1120 if (MAP_FAILED == map_info->buffer && (errno == EAGAIN || errno == EINTR))
1121 goto retry_mmap2;
1122 if (MAP_FAILED == map_info->buffer || buffer != (void *)map_info->buffer)
1123 goto error;
1124retry_mmap3:
1125 buffer = mmap((void *)map_info->buffer + map_info->size, map_info->size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, memfd, 0);
1126 if (MAP_FAILED == map_info->buffer && (errno == EAGAIN || errno == EINTR))
1127 goto retry_mmap3;
1128 if (MAP_FAILED == map_info->buffer || buffer != (void *)(map_info->buffer + map_info->size))
1129 goto error;
1130
1131 close(memfd);
1132 return 0;
1133error:
1134 close(memfd);
1135 mp3dec_close_ring(map_info);
1136 return MP3D_E_MEMORY;
1137#else
1138 memfd = shmget(IPC_PRIVATE, map_info->size, IPC_CREAT | 0700);
1139 if (memfd < 0)
1140 return MP3D_E_MEMORY;
1141retry_mmap:
1142 map_info->buffer = (const uint8_t *)mmap(NULL, map_info->size*2, PROT_NONE, MAP_PRIVATE, -1, 0);
1143 if (MAP_FAILED == map_info->buffer && (errno == EAGAIN || errno == EINTR))
1144 goto retry_mmap;
1145 if (MAP_FAILED == map_info->buffer)
1146 goto error;
1147 if (map_info->buffer != shmat(memfd, map_info->buffer, 0))
1148 goto error;
1149 if ((map_info->buffer + map_info->size) != shmat(memfd, map_info->buffer + map_info->size, 0))
1150 goto error;
1151 if (shmctl(memfd, IPC_RMID, NULL) < 0)
1152 return MP3D_E_MEMORY;
1153 return 0;
1154error:
1155 shmctl(memfd, IPC_RMID, NULL);
1156 mp3dec_close_ring(map_info);
1157 return MP3D_E_MEMORY;
1158#endif
1159}
1160#endif /*MINIMP3_ENABLE_RING*/
1161#elif defined(_WIN32)
1162#include <windows.h>
1163
1164static void mp3dec_close_file(mp3dec_map_info_t *map_info)
1165{
1166 if (map_info->buffer)
1167 UnmapViewOfFile(map_info->buffer);
1168 map_info->buffer = 0;
1169 map_info->size = 0;
1170}
1171
1172static int mp3dec_open_file_h(HANDLE file, mp3dec_map_info_t *map_info)
1173{
1174 memset(map_info, 0, sizeof(*map_info));
1175
1176 HANDLE mapping = NULL;
1177 LARGE_INTEGER s;
1178 s.LowPart = GetFileSize(file, (DWORD*)&s.HighPart);
1179 if (s.LowPart == INVALID_FILE_SIZE && GetLastError() != NO_ERROR)
1180 goto error;
1181 map_info->size = s.QuadPart;
1182
1183 mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
1184 if (!mapping)
1185 goto error;
1186 map_info->buffer = (const uint8_t*)MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, s.QuadPart);
1187 CloseHandle(mapping);
1188 if (!map_info->buffer)
1189 goto error;
1190
1191 CloseHandle(file);
1192 return 0;
1193error:
1194 mp3dec_close_file(map_info);
1195 CloseHandle(file);
1196 return MP3D_E_IOERROR;
1197}
1198
1199static int mp3dec_open_file(const char *file_name, mp3dec_map_info_t *map_info)
1200{
1201 if (!file_name)
1202 return MP3D_E_PARAM;
1203 HANDLE file = CreateFileA(file_name, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
1204 if (INVALID_HANDLE_VALUE == file)
1205 return MP3D_E_IOERROR;
1206 return mp3dec_open_file_h(file, map_info);
1207}
1208
1209static int mp3dec_open_file_w(const wchar_t *file_name, mp3dec_map_info_t *map_info)
1210{
1211 if (!file_name)
1212 return MP3D_E_PARAM;
1213 HANDLE file = CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
1214 if (INVALID_HANDLE_VALUE == file)
1215 return MP3D_E_IOERROR;
1216 return mp3dec_open_file_h(file, map_info);
1217}
1218#else
1219#include <stdio.h>
1220
1221static void mp3dec_close_file(mp3dec_map_info_t *map_info)
1222{
1223 if (map_info->buffer)
1224 free((void *)map_info->buffer);
1225 map_info->buffer = 0;
1226 map_info->size = 0;
1227}
1228
1229static int mp3dec_open_file(const char *file_name, mp3dec_map_info_t *map_info)
1230{
1231 if (!file_name)
1232 return MP3D_E_PARAM;
1233 memset(map_info, 0, sizeof(*map_info));
1234 FILE *file = fopen(file_name, "rb");
1235 if (!file)
1236 return MP3D_E_IOERROR;
1237 int res = MP3D_E_IOERROR;
1238 long size = -1;
1239 if (fseek(file, 0, SEEK_END))
1240 goto error;
1241 size = ftell(file);
1242 if (size < 0)
1243 goto error;
1244 map_info->size = (size_t)size;
1245 if (fseek(file, 0, SEEK_SET))
1246 goto error;
1247 map_info->buffer = (uint8_t *)malloc(map_info->size);
1248 if (!map_info->buffer)
1249 {
1250 res = MP3D_E_MEMORY;
1251 goto error;
1252 }
1253 if (fread((void *)map_info->buffer, 1, map_info->size, file) != map_info->size)
1254 goto error;
1255 fclose(file);
1256 return 0;
1257error:
1258 mp3dec_close_file(map_info);
1259 fclose(file);
1260 return res;
1261}
1262#endif
1263
1264static int mp3dec_detect_mapinfo(mp3dec_map_info_t *map_info)
1265{
1266 int ret = mp3dec_detect_buf(map_info->buffer, map_info->size);
1267 mp3dec_close_file(map_info);
1268 return ret;
1269}
1270
1271static 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)
1272{
1273 int ret = mp3dec_load_buf(dec, map_info->buffer, map_info->size, info, progress_cb, user_data);
1274 mp3dec_close_file(map_info);
1275 return ret;
1276}
1277
1278static int mp3dec_iterate_mapinfo(mp3dec_map_info_t *map_info, MP3D_ITERATE_CB callback, void *user_data)
1279{
1280 int ret = mp3dec_iterate_buf(map_info->buffer, map_info->size, callback, user_data);
1281 mp3dec_close_file(map_info);
1282 return ret;
1283}
1284
1285static int mp3dec_ex_open_mapinfo(mp3dec_ex_t *dec, int flags)
1286{
1287 int ret = mp3dec_ex_open_buf(dec, dec->file.buffer, dec->file.size, flags);
1288 dec->is_file = 1;
1289 if (ret)
1290 mp3dec_ex_close(dec);
1291 return ret;
1292}
1293
1294int mp3dec_detect(const char *file_name)
1295{
1296 int ret;
1297 mp3dec_map_info_t map_info;
1298 if ((ret = mp3dec_open_file(file_name, &map_info)))
1299 return ret;
1300 return mp3dec_detect_mapinfo(&map_info);
1301}
1302
1303int mp3dec_load(mp3dec_t *dec, const char *file_name, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data)
1304{
1305 int ret;
1306 mp3dec_map_info_t map_info;
1307 if ((ret = mp3dec_open_file(file_name, &map_info)))
1308 return ret;
1309 return mp3dec_load_mapinfo(dec, &map_info, info, progress_cb, user_data);
1310}
1311
1312int mp3dec_iterate(const char *file_name, MP3D_ITERATE_CB callback, void *user_data)
1313{
1314 int ret;
1315 mp3dec_map_info_t map_info;
1316 if ((ret = mp3dec_open_file(file_name, &map_info)))
1317 return ret;
1318 return mp3dec_iterate_mapinfo(&map_info, callback, user_data);
1319}
1320
1321int mp3dec_ex_open(mp3dec_ex_t *dec, const char *file_name, int flags)
1322{
1323 int ret;
1324 if (!dec)
1325 return MP3D_E_PARAM;
1326 if ((ret = mp3dec_open_file(file_name, &dec->file)))
1327 return ret;
1328 return mp3dec_ex_open_mapinfo(dec, flags);
1329}
1330
1331void mp3dec_ex_close(mp3dec_ex_t *dec)
1332{
1333#ifdef MINIMP3_HAVE_RING
1334 if (dec->io)
1335 mp3dec_close_ring(&dec->file);
1336#else
1337 if (dec->io && dec->file.buffer)
1338 free((void*)dec->file.buffer);
1339#endif
1340 if (dec->is_file)
1341 mp3dec_close_file(&dec->file);
1342 if (dec->index.frames)
1343 free(dec->index.frames);
1344 memset(dec, 0, sizeof(*dec));
1345}
1346
1347#ifdef _WIN32
1348int mp3dec_detect_w(const wchar_t *file_name)
1349{
1350 int ret;
1351 mp3dec_map_info_t map_info;
1352 if ((ret = mp3dec_open_file_w(file_name, &map_info)))
1353 return ret;
1354 return mp3dec_detect_mapinfo(&map_info);
1355}
1356
1357int mp3dec_load_w(mp3dec_t *dec, const wchar_t *file_name, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data)
1358{
1359 int ret;
1360 mp3dec_map_info_t map_info;
1361 if ((ret = mp3dec_open_file_w(file_name, &map_info)))
1362 return ret;
1363 return mp3dec_load_mapinfo(dec, &map_info, info, progress_cb, user_data);
1364}
1365
1366int mp3dec_iterate_w(const wchar_t *file_name, MP3D_ITERATE_CB callback, void *user_data)
1367{
1368 int ret;
1369 mp3dec_map_info_t map_info;
1370 if ((ret = mp3dec_open_file_w(file_name, &map_info)))
1371 return ret;
1372 return mp3dec_iterate_mapinfo(&map_info, callback, user_data);
1373}
1374
1375int mp3dec_ex_open_w(mp3dec_ex_t *dec, const wchar_t *file_name, int flags)
1376{
1377 int ret;
1378 if ((ret = mp3dec_open_file_w(file_name, &dec->file)))
1379 return ret;
1380 return mp3dec_ex_open_mapinfo(dec, flags);
1381}
1382#endif
1383#else /* MINIMP3_NO_STDIO */
1384void mp3dec_ex_close(mp3dec_ex_t *dec)
1385{
1386#ifdef MINIMP3_HAVE_RING
1387 if (dec->io)
1388 mp3dec_close_ring(&dec->file);
1389#else
1390 if (dec->io && dec->file.buffer)
1391 free((void*)dec->file.buffer);
1392#endif
1393 if (dec->index.frames)
1394 free(dec->index.frames);
1395 memset(dec, 0, sizeof(*dec));
1396}
1397#endif
1398
1399#endif /* MINIMP3_IMPLEMENTATION && !_MINIMP3_EX_IMPLEMENTATION_GUARD */
1400