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