History

mp3dec_ex: implement mp3dec_load_cb, improve test

lieff committed 6 years ago

Commit ea70d0b1 parent 682006f3 files · +175 −42Browse files

Unified · Split

3 files
  1. minimp3_ex.h +95 −23
  2. minimp3_test.c +64 −13
  3. scripts/build.sh +16 −6
minimp3_ex.h+95−23
@@ -81,7 +81,7 @@ extern "C" { · 80 unmodified lines
8181 #endif
8282
8383 /* decode whole buffer block */
84−void 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);
84+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);
8585 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);
8686 /* iterate through frames */
8787 size_t mp3dec_iterate_buf(const uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data);
@@ -134,8 +134,9 @@ static void mp3dec_skip_id3v1(const uint8_t *buf, size_t *pbuf_size) · 46 unmodified lines
134134
135135 static size_t mp3dec_skip_id3v2(const uint8_t *buf, size_t buf_size)
136136 {
137+#define MINIMP3_ID3_DETECT_SIZE 10
137138 #ifndef MINIMP3_NOSKIP_ID3V2
138− if (buf_size >= 10 && !memcmp(buf, "ID3", 3) && !((buf[5] & 15) || (buf[6] & 0x80) || (buf[7] & 0x80) || (buf[8] & 0x80) || (buf[9] & 0x80)))
139+ 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)))
139140 {
140141 size_t id3v2size = (((buf[6] & 0x7f) << 21) | ((buf[7] & 0x7f) << 14) | ((buf[8] & 0x7f) << 7) | (buf[9] & 0x7f)) + 10;
141142 if ((buf[5] & 16))
@@ -210,7 +211,12 @@ static int mp3dec_check_vbrtag(const uint8_t *frame, int frame_size, uint32_t *f · 68 unmodified lines
210211 return 1;
211212 }
212213
213−void 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)
214+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)
215+{
216+ return mp3dec_load_cb(dec, 0, (uint8_t *)buf, buf_size, info, progress_cb, user_data);
217+}
218+
219+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)
214220 {
215221 uint64_t detected_samples = 0;
216222 size_t orig_buf_size = buf_size;
@@ -218,24 +224,64 @@ void mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_ · 1 unmodified line
218224 mp3dec_frame_info_t frame_info;
219225 memset(info, 0, sizeof(*info));
220226 memset(&frame_info, 0, sizeof(frame_info));
227+
221228 /* skip id3 */
222− mp3dec_skip_id3(&buf, &buf_size);
223− if (!buf_size)
224− return;
229+ size_t filled, consumed;
230+ int eof;
231+ if (io)
232+ {
233+ io->seek(0, io->seek_data);
234+ filled = io->read(buf, MINIMP3_ID3_DETECT_SIZE, io->read_data), consumed = 0, eof = 0;
235+ if (MINIMP3_ID3_DETECT_SIZE != filled)
236+ return 0;
237+ size_t id3v2size = mp3dec_skip_id3v2(buf, filled);
238+ if (id3v2size)
239+ {
240+ io->seek(id3v2size, io->seek_data);
241+ filled = io->read(buf, buf_size, io->read_data);
242+ } else
243+ filled += io->read(buf + MINIMP3_ID3_DETECT_SIZE, buf_size - MINIMP3_ID3_DETECT_SIZE, io->read_data);
244+ if (filled < MINIMP3_BUF_SIZE)
245+ mp3dec_skip_id3v1(buf, &filled);
246+ } else
247+ {
248+ mp3dec_skip_id3((const uint8_t **)&buf, &buf_size);
249+ if (!buf_size)
250+ return 0;
251+ }
225252 /* try to make allocation size assumption by first frame or vbr tag */
226253 mp3dec_init(dec);
227254 int samples;
228255 do
229256 {
230257 uint32_t frames;
231− int delay, padding, free_format_bytes = 0, frame_size = 0;
232− int i = mp3d_find_frame(buf, buf_size, &free_format_bytes, &frame_size);
233− buf += i;
234− buf_size -= i;
258+ int i, delay, padding, free_format_bytes = 0, frame_size = 0;
259+ if (io)
260+ {
261+ if (!eof && filled - consumed < MINIMP3_BUF_SIZE)
262+ { /* keep minimum 10 consecutive mp3 frames (~16KB) worst case */
263+ memmove(buf, buf + consumed, filled - consumed);
264+ filled -= consumed;
265+ consumed = 0;
266+ size_t readed = io->read(buf + filled, buf_size - filled, io->read_data);
267+ if (readed != (buf_size - filled))
268+ eof = 1;
269+ filled += readed;
270+ if (eof)
271+ mp3dec_skip_id3v1(buf, &filled);
272+ }
273+ i = mp3d_find_frame(buf + consumed, filled - consumed, &free_format_bytes, &frame_size);
274+ consumed += i;
275+ } else
276+ {
277+ i = mp3d_find_frame(buf, buf_size, &free_format_bytes, &frame_size);
278+ buf += i;
279+ buf_size -= i;
280+ }
235281 if (i && !frame_size)
236282 continue;
237283 if (!frame_size)
238− return;
284+ return 0;
239285 const uint8_t *hdr = buf;
240286 frame_info.channels = HDR_IS_MONO(hdr) ? 1 : 2;
241287 frame_info.hz = hdr_sample_rate_hz(hdr);
@@ -253,9 +299,15 @@ void mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_ · 11 unmodified lines
253299 if (padding > 0 && detected_samples >= (uint64_t)padding)
254300 detected_samples -= padding;
255301 if (!detected_samples)
256− return;
257− buf += frame_size;
258− buf_size -= frame_size;
302+ return 0;
303+ if (io)
304+ {
305+ consumed += frame_size;
306+ } else
307+ {
308+ buf += frame_size;
309+ buf_size -= frame_size;
310+ }
259311 }
260312 break;
261313 } while(1);
@@ -266,14 +318,13 @@ void mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_ · 4 unmodified lines
266318 allocated += (buf_size/frame_info.frame_bytes)*samples*sizeof(mp3d_sample_t);
267319 info->buffer = (mp3d_sample_t*)malloc(allocated);
268320 if (!info->buffer)
269− return;
321+ return MP3D_E_MEMORY;
270322 /* save info */
271323 info->channels = frame_info.channels;
272324 info->hz = frame_info.hz;
273325 info->layer = frame_info.layer;
274326 /* decode all frames */
275327 size_t avg_bitrate_kbps = 0, frames = 0;
276− int frame_bytes;
277328 do
278329 {
279330 if ((allocated - info->samples*sizeof(mp3d_sample_t)) < MINIMP3_MAX_SAMPLES_PER_FRAME*sizeof(mp3d_sample_t))
@@ -281,10 +332,28 @@ void mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_ · 1 unmodified line
281332 allocated *= 2;
282333 info->buffer = (mp3d_sample_t*)realloc(info->buffer, allocated);
283334 }
284− samples = mp3dec_decode_frame(dec, buf, MINIMP3_MIN(buf_size, (size_t)INT_MAX), info->buffer + info->samples, &frame_info);
285− frame_bytes = frame_info.frame_bytes;
286− buf += frame_bytes;
287− buf_size -= frame_bytes;
335+ if (io)
336+ {
337+ if (!eof && filled - consumed < MINIMP3_BUF_SIZE)
338+ { /* keep minimum 10 consecutive mp3 frames (~16KB) worst case */
339+ memmove(buf, buf + consumed, filled - consumed);
340+ filled -= consumed;
341+ consumed = 0;
342+ size_t readed = io->read(buf + filled, buf_size - filled, io->read_data);
343+ if (readed != (buf_size - filled))
344+ eof = 1;
345+ filled += readed;
346+ if (eof)
347+ mp3dec_skip_id3v1(buf, &filled);
348+ }
349+ samples = mp3dec_decode_frame(dec, buf + consumed, filled - consumed, info->buffer + info->samples, &frame_info);
350+ consumed += frame_info.frame_bytes;
351+ } else
352+ {
353+ samples = mp3dec_decode_frame(dec, buf, MINIMP3_MIN(buf_size, (size_t)INT_MAX), info->buffer + info->samples, &frame_info);
354+ buf += frame_info.frame_bytes;
355+ buf_size -= frame_info.frame_bytes;
356+ }
288357 if (samples)
289358 {
290359 if (info->hz != frame_info.hz || info->layer != frame_info.layer)
@@ -309,7 +378,7 @@ void mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_ · 18 unmodified lines
309378 if (progress_cb)
310379 progress_cb(user_data, orig_buf_size, orig_buf_size - buf_size, &frame_info);
311380 }
312− } while (frame_bytes);
381+ } while (frame_info.frame_bytes);
313382 if (detected_samples && info->samples > detected_samples)
314383 info->samples = detected_samples; /* cut padding */
315384 /* reallocate to normal buffer size */
@@ -317,6 +386,7 @@ void mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_ · 1 unmodified line
317386 info->buffer = (mp3d_sample_t*)realloc(info->buffer, info->samples*sizeof(mp3d_sample_t));
318387 if (frames)
319388 info->avg_bitrate_kbps = avg_bitrate_kbps/frames;
389+ return 0;
320390 }
321391
322392 size_t mp3dec_iterate_buf(const uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data)
@@ -363,11 +433,13 @@ uint64_t mp3dec_iterate_cb(mp3dec_io_t *io, uint8_t *buf, size_t buf_size, MP3D_ · 40 unmodified lines
363433 if (buf_size < MINIMP3_BUF_SIZE)
364434 return 0;
365435 io->seek(0, io->seek_data);
366− size_t filled = io->read(buf, 10, io->read_data), consumed = 0;
436+ size_t filled = io->read(buf, MINIMP3_ID3_DETECT_SIZE, io->read_data), consumed = 0;
367437 uint64_t readed = 0, frames = 0;
368438 mp3dec_frame_info_t frame_info;
369439 int eof = 0;
370440 memset(&frame_info, 0, sizeof(frame_info));
441+ if (MINIMP3_ID3_DETECT_SIZE != filled)
442+ return 0;
371443 size_t id3v2size = mp3dec_skip_id3v2(buf, filled);
372444 if (id3v2size)
373445 {
@@ -375,7 +447,7 @@ uint64_t mp3dec_iterate_cb(mp3dec_io_t *io, uint8_t *buf, size_t buf_size, MP3D_ · 1 unmodified line
375447 filled = io->read(buf, buf_size, io->read_data);
376448 readed += id3v2size;
377449 } else
378− filled += io->read(buf + 10, buf_size - 10, io->read_data);
450+ filled += io->read(buf + MINIMP3_ID3_DETECT_SIZE, buf_size - MINIMP3_ID3_DETECT_SIZE, io->read_data);
379451 if (filled < MINIMP3_BUF_SIZE)
380452 mp3dec_skip_id3v1(buf, &filled);
381453 do
minimp3_test.c+64−13
@@ -14,10 +14,15 @@ · 13 unmodified lines
1414 #include <strings.h>
1515 #endif
1616
17−#define MODE_LOAD 0
18−#define MODE_ITERATE 1
19−#define MODE_STREAM 2
20−#define MODE_STREAM_CB 3
17+#define MODE_LOAD 0
18+#define MODE_LOAD_BUF 1
19+#define MODE_LOAD_CB 2
20+#define MODE_ITERATE 3
21+#define MODE_ITERATE_BUF 4
22+#define MODE_ITERATE_CB 5
23+#define MODE_STREAM 6
24+#define MODE_STREAM_BUF 7
25+#define MODE_STREAM_CB 8
2126
2227 static int16_t read16le(const void *p)
2328 {
@@ -115,31 +120,75 @@ static void decode_file(const char *input_file_name, const unsigned char *buf_re · 91 unmodified lines
115120 int no_std_vec = strstr(input_file_name, "nonstandard") || strstr(input_file_name, "ILL");
116121 double MSE = 0.0, psnr;
117122
123+ mp3dec_io_t io;
118124 mp3dec_file_info_t info;
119125 memset(&info, 0, sizeof(info));
126+ io.read = read_cb;
127+ io.seek = seek_cb;
120128 if (MODE_LOAD == mode)
121129 {
122130 res = mp3dec_load(&mp3d, input_file_name, &info, 0, 0);
131+ } else if (MODE_LOAD_BUF == mode)
132+ {
133+ int size = 0;
134+ FILE *file = fopen(input_file_name, "rb");
135+ uint8_t *buf = preload(file, &size);
136+ fclose(file);
137+ res = buf ? mp3dec_load_buf(&mp3d, buf, size, &info, 0, 0) : -1;
138+ free(buf);
139+ } else if (MODE_LOAD_CB == mode)
140+ {
141+ uint8_t *io_buf = malloc(MINIMP3_IO_SIZE);
142+ FILE *file = fopen(input_file_name, "rb");
143+ io.read_data = io.seek_data = file;
144+ res = file ? mp3dec_load_cb(&mp3d, &io, io_buf, MINIMP3_IO_SIZE, &info, 0, 0) : -1;
145+ fclose((FILE*)io.read_data);
146+ free(io_buf);
123147 } else if (MODE_ITERATE == mode)
124148 {
125149 frames_iterate_data d = { &mp3d, &info, 0 };
126150 mp3dec_init(&mp3d);
127151 res = mp3dec_iterate(input_file_name, frames_iterate_cb, &d) > 0 ? 0 : -1;
128− } else if (MODE_STREAM == mode || MODE_STREAM_CB == mode)
152+ } else if (MODE_ITERATE_BUF == mode)
153+ {
154+ int size = 0;
155+ FILE *file = fopen(input_file_name, "rb");
156+ uint8_t *buf = preload(file, &size);
157+ fclose(file);
158+ frames_iterate_data d = { &mp3d, &info, 0 };
159+ mp3dec_init(&mp3d);
160+ res = mp3dec_iterate_buf(buf, size, frames_iterate_cb, &d) > 0 ? 0 : -1;
161+ free(buf);
162+ } else if (MODE_ITERATE_CB == mode)
163+ {
164+ uint8_t *io_buf = malloc(MINIMP3_IO_SIZE);
165+ FILE *file = fopen(input_file_name, "rb");
166+ io.read_data = io.seek_data = file;
167+ frames_iterate_data d = { &mp3d, &info, 0 };
168+ mp3dec_init(&mp3d);
169+ res = mp3dec_iterate_cb(&io, io_buf, MINIMP3_IO_SIZE, frames_iterate_cb, &d) > 0 ? 0 : -1;
170+ fclose((FILE*)io.read_data);
171+ free(io_buf);
172+ } else if (MODE_STREAM == mode || MODE_STREAM_BUF == mode || MODE_STREAM_CB == mode)
129173 {
130174 mp3dec_ex_t dec;
131− mp3dec_io_t io;
132175 size_t readed;
133− if (MODE_STREAM_CB == mode)
176+ uint8_t *buf;
177+ if (MODE_STREAM == mode)
178+ {
179+ res = mp3dec_ex_open(&dec, input_file_name, MP3D_SEEK_TO_SAMPLE);
180+ } else if (MODE_STREAM_BUF == mode)
181+ {
182+ int size = 0;
183+ FILE *file = fopen(input_file_name, "rb");
184+ buf = preload(file, &size);
185+ fclose(file);
186+ res = mp3dec_ex_open_buf(&dec, buf, size, MP3D_SEEK_TO_SAMPLE);
187+ } else if (MODE_STREAM_CB == mode)
134188 {
135189 FILE *file = fopen(input_file_name, "rb");
136− io.read = read_cb;
137− io.seek = seek_cb;
138190 io.read_data = io.seek_data = file;
139191 res = file ? mp3dec_ex_open_cb(&dec, &io, MP3D_SEEK_TO_SAMPLE) : -1;
140− } else
141− {
142− res = mp3dec_ex_open(&dec, input_file_name, MP3D_SEEK_TO_SAMPLE);
143192 }
144193 if (res)
145194 {
@@ -184,6 +233,8 @@ static void decode_file(const char *input_file_name, const unsigned char *buf_re · 38 unmodified lines
184233 exit(1);
185234 }
186235 mp3dec_ex_close(&dec);
236+ if (MODE_STREAM_BUF == mode)
237+ free(buf);
187238 if (MODE_STREAM_CB == mode)
188239 fclose((FILE*)io.read_data);
189240 } else
@@ -217,7 +268,7 @@ static void decode_file(const char *input_file_name, const unsigned char *buf_re · 27 unmodified lines
217268 int len_match = ref_samples == info.samples;
218269 int relaxed_len_match = len_match || (ref_samples + 1152) == info.samples || (ref_samples + 2304) == info.samples;
219270 int seek_len_match = (ref_samples <= info.samples) || (ref_samples + 2304) >= info.samples;
220− if ((((!relaxed_len_match && 2 != mode && 3 != mode) || !seek_len_match) && 3 == info.layer && !no_std_vec) || (no_std_vec && !len_match))
271+ if ((((!relaxed_len_match && MODE_STREAM != mode && MODE_STREAM_BUF != mode && MODE_STREAM_CB != mode) || !seek_len_match) && 3 == info.layer && !no_std_vec) || (no_std_vec && !len_match))
221272 { /* some standard vectors are for some reason a little shorter */
222273 printf("error: reference and produced number of samples do not match (%d/%d)\n", (int)ref_samples, (int)info.samples);
223274 exit(1);
scripts/build.sh+16−6
@@ -11,17 +11,22 @@ CFLAGS="-O2 -std=c89 -Wall -Wextra -Wmissing-prototypes -Werror -fno-asynchronou · 10 unmodified lines
1111
1212 echo testing mp4 mode...
1313 gcc $CFLAGS -DMP4_MODE -o minimp3 minimp3_test.c -lm
14−scripts/test_mode.sh 1 0
14+scripts/test_mode.sh 3 0
1515
1616 echo testing stream mode...
17−scripts/test_mode.sh 2 -1
17+scripts/test_mode.sh 6 -1
1818
1919 echo testing coverage x86 w sse...
2020 gcc -coverage -O0 -m32 -std=c89 -msse2 -DMINIMP3_TEST -DMINIMP3_NO_WAV -o minimp3 minimp3_test.c -lm
2121 scripts/test.sh
2222 scripts/test_mode.sh 1 0
23−scripts/test_mode.sh 2 -1
24−scripts/test_mode.sh 3 -1
23+scripts/test_mode.sh 2 0
24+scripts/test_mode.sh 3 0
25+scripts/test_mode.sh 4 0
26+scripts/test_mode.sh 5 0
27+scripts/test_mode.sh 6 -1
28+scripts/test_mode.sh 7 -1
29+scripts/test_mode.sh 8 -1
2530 set +e
2631 ./minimp3
2732 ./minimp3 do_not_exist
@@ -40,8 +45,13 @@ echo testing x64 with float output... · 12 unmodified lines
4045 gcc $CFLAGS -DMINIMP3_FLOAT_OUTPUT -o minimp3 minimp3_test.c -lm
4146 scripts/test.sh
4247 scripts/test_mode.sh 1 0
43−scripts/test_mode.sh 2 -1
44−scripts/test_mode.sh 3 -1
48+scripts/test_mode.sh 2 0
49+scripts/test_mode.sh 3 0
50+scripts/test_mode.sh 4 0
51+scripts/test_mode.sh 5 0
52+scripts/test_mode.sh 6 -1
53+scripts/test_mode.sh 7 -1
54+scripts/test_mode.sh 8 -1
4555
4656 echo testing arm w/o neon...
4757 arm-none-eabi-gcc $CFLAGS -mthumb -mcpu=arm9e -o minimp3_arm minimp3_test.c --specs=rdimon.specs -lm

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t