ref: 45a1de9792aa8402af620bd1dc2b2d7bb9a3c62a
parent: 4b51e005b755ccfa7d0dba68ed24702802169c03
author: lieff <lieff@users.noreply.github.com>
date: Fri Aug 3 19:14:41 EDT 2018
high-level API passes test
--- a/minimp3_ex.h
+++ b/minimp3_ex.h
@@ -11,7 +11,7 @@
typedef struct
{
int16_t *buffer;
- size_t samples;
+ size_t samples; /* channels included, byte size = samples*sizeof(int16_t) */
int channels, hz, layer, avg_bitrate_kbps;
} mp3dec_file_info_t;
@@ -220,10 +220,12 @@
} while (frame_info.frame_bytes);
if (!samples)
return;
- size_t samples_bytes = samples*frame_info.channels*2;
- size_t allocated = (buf_size/frame_info.frame_bytes)*samples_bytes + MINIMP3_MAX_SAMPLES_PER_FRAME*2;
+ info->samples = samples*frame_info.channels;
+ size_t allocated = (buf_size/frame_info.frame_bytes)*info->samples*2 + MINIMP3_MAX_SAMPLES_PER_FRAME*2;
info->buffer = malloc(allocated);
- memcpy(info->buffer, pcm, samples_bytes);
+ memcpy(info->buffer, pcm, info->samples*2);
+ if (!info->buffer)
+ return;
/* save info */
info->channels = frame_info.channels;
info->hz = frame_info.hz;
@@ -233,24 +235,26 @@
/* decode rest frames */
do
{
- if ((allocated - samples_bytes) < MINIMP3_MAX_SAMPLES_PER_FRAME*2)
+ if ((allocated - info->samples*2) < MINIMP3_MAX_SAMPLES_PER_FRAME*2)
{
allocated *= 2;
info->buffer = realloc(info->buffer, allocated);
}
- samples = mp3dec_decode_frame(dec, buf, buf_size, (int16_t*)((int8_t *)info->buffer + samples_bytes), &frame_info);
+ samples = mp3dec_decode_frame(dec, buf, buf_size, info->buffer + info->samples, &frame_info);
if (samples)
{
- info->samples += samples;
+ if (info->hz != frame_info.hz || info->layer != frame_info.layer)
+ break;
+ info->samples += samples*frame_info.channels;
avg_bitrate_kbps += frame_info.bitrate_kbps;
- samples_bytes += samples*frame_info.channels*2;
+ frames++;
}
buf += frame_info.frame_bytes;
buf_size -= frame_info.frame_bytes;
} while (frame_info.frame_bytes);
/* reallocate to normal buffer size */
- if (allocated != samples_bytes)
- info->buffer = realloc(info->buffer, samples_bytes);
+ if (allocated != info->samples*2)
+ info->buffer = realloc(info->buffer, info->samples*2);
info->avg_bitrate_kbps = avg_bitrate_kbps/frames;
}
@@ -262,6 +266,7 @@
size_t id3v2size = mp3dec_skip_id3v2(buf, buf_size);
if (id3v2size > buf_size)
return;
+ const uint8_t *orig_buf = buf;
buf += id3v2size;
buf_size -= id3v2size;
do
@@ -274,7 +279,14 @@
continue;
if (!frame_size)
break;
- callback(user_data, buf + i, frame_size, i, &frame_info);
+ const uint8_t *hdr = buf;
+ frame_info.channels = HDR_IS_MONO(hdr) ? 1 : 2;
+ frame_info.hz = hdr_sample_rate_hz(hdr);
+ frame_info.layer = 4 - HDR_GET_LAYER(hdr);
+ frame_info.bitrate_kbps = hdr_bitrate_kbps(hdr);
+
+ if (callback(user_data, hdr, frame_size, hdr - orig_buf, &frame_info))
+ break;
buf += frame_size;
buf_size -= frame_size;
} while (1);
--- a/minimp3_test.c
+++ b/minimp3_test.c
@@ -2,7 +2,7 @@
/*#define MINIMP3_ONLY_SIMD*/
/*#define MINIMP3_NONSTANDARD_BUT_LOGICAL*/
#define MINIMP3_IMPLEMENTATION
-#include "minimp3.h"
+#include "minimp3_ex.h"
#include <stdio.h>
#include <math.h>
#include <string.h>
@@ -58,76 +58,81 @@
return data;
}
-static void decode_file(const unsigned char *buf_mp3, int mp3_size, const unsigned char *buf_ref, int ref_size, FILE *file_out, const int wave_out)
+#ifdef MP4_MODE
+typedef struct
{
- static mp3dec_t mp3d;
- mp3dec_frame_info_t info;
- int i, data_bytes, samples, total_samples = 0, maxdiff = 0;
- double MSE = 0.0, psnr;
+ mp3dec_t *mp3d;
+ mp3dec_file_info_t *info;
+ size_t allocated;
+} frames_iterate_data;
- if (mp3_size > 10 && !strncmp((char *)buf_mp3, "ID3", 3))
+static int frames_iterate_cb(void *user_data, const uint8_t *frame, int frame_size, size_t offset, mp3dec_frame_info_t *info)
+{
+ (void)offset;
+ frames_iterate_data *d = user_data;
+ d->info->channels = info->channels;
+ d->info->hz = info->hz;
+ d->info->layer = info->layer;
+ /*printf("%d %d %d\n", frame_size, (int)offset, info->channels);*/
+ if ((d->allocated - d->info->samples*2) < MINIMP3_MAX_SAMPLES_PER_FRAME*2)
{
- int id3v2size = (((buf_mp3[6] & 0x7f) << 21) | ((buf_mp3[7] & 0x7f) << 14) |
- ((buf_mp3[8] & 0x7f) << 7) | (buf_mp3[9] & 0x7f)) + 10;
- if (mp3_size >= id3v2size)
- {
- printf("info: skipping %d bytes of id3v2\n", id3v2size);
- buf_mp3 += id3v2size;
- mp3_size -= id3v2size;
- }
+ if (!d->allocated)
+ d->allocated = 1024*1024;
+ else
+ d->allocated *= 2;
+ d->info->buffer = realloc(d->info->buffer, d->allocated);
}
+ int samples = mp3dec_decode_frame(d->mp3d, frame, frame_size, d->info->buffer + d->info->samples, info);
+ if (samples)
+ {
+ d->info->samples += samples*info->channels;
+ }
+ return 0;
+}
+#endif
- mp3dec_init(&mp3d);
+static void decode_file(const char *input_file_name, const unsigned char *buf_ref, int ref_size, FILE *file_out, const int wave_out)
+{
+ mp3dec_t mp3d;
+ int i, data_bytes, total_samples = 0, maxdiff = 0;
+ double MSE = 0.0, psnr;
+
+ mp3dec_file_info_t info;
memset(&info, 0, sizeof(info));
+#ifdef MP4_MODE
+ frames_iterate_data d = { &mp3d, &info, 0 };
+ mp3dec_init(&mp3d);
+ if (mp3dec_iterate(input_file_name, frames_iterate_cb, &d))
+#else
+ if (mp3dec_load(&mp3d, input_file_name, &info))
+#endif
+ {
+ printf("error: file not found or read error");
+ exit(1);
+ }
#ifndef MINIMP3_NO_WAV
if (wave_out && file_out)
fwrite(wav_header(0, 0, 0, 0), 1, 44, file_out);
#endif
- do
+ if (info.samples)
{
- short pcm[MINIMP3_MAX_SAMPLES_PER_FRAME];
-#ifdef MP4_MODE
- int free_format_bytes = 0, frame_size = 0;
- i = mp3d_find_frame(buf_mp3, mp3_size, &free_format_bytes, &frame_size);
- buf_mp3 += i;
- mp3_size -= i;
- if (i && !frame_size)
+ total_samples += info.samples;
+ if (buf_ref)
{
- printf("warning: skipping %d bytes, frame_size=%d\n", i, frame_size);
- continue;
- }
- if (frame_size > mp3_size)
- {
- printf("error: demux mp3 frame failed: i=%d, frame_size=%d\n", i, frame_size);
- exit(1);
- }
- if (!frame_size)
- break;
- samples = mp3dec_decode_frame(&mp3d, buf_mp3, frame_size, pcm, &info);
-#else
- samples = mp3dec_decode_frame(&mp3d, buf_mp3, mp3_size, pcm, &info);
-#endif
- if (samples)
- {
- total_samples += samples*info.channels;
- if (buf_ref && ref_size >= samples*info.channels*2)
+ int max_samples = MINIMP3_MIN((size_t)ref_size/2, info.samples);
+ for (i = 0; i < max_samples; i++)
{
- for (i = 0; i < samples*info.channels; i++)
- {
- int MSEtemp = abs((int)pcm[i] - (int)(short)read16le(&buf_ref[i*sizeof(short)]));
- if (MSEtemp > maxdiff)
- maxdiff = MSEtemp;
- MSE += (float)MSEtemp*(float)MSEtemp;
- }
- buf_ref += samples*info.channels*2;
- ref_size -= samples*info.channels*2;
+ int MSEtemp = abs((int)info.buffer[i] - (int)(short)read16le(&buf_ref[i*sizeof(short)]));
+ if (MSEtemp > maxdiff)
+ maxdiff = MSEtemp;
+ MSE += (float)MSEtemp*(float)MSEtemp;
}
- if (file_out)
- fwrite(pcm, samples, 2*info.channels, file_out);
}
- buf_mp3 += info.frame_bytes;
- mp3_size -= info.frame_bytes;
- } while (info.frame_bytes);
+ if (file_out)
+ fwrite(info.buffer, info.samples, sizeof(int16_t), file_out);
+ free(info.buffer);
+ }
+
#ifndef LIBFUZZER
MSE /= total_samples ? total_samples : 1;
if (0 == MSE)
@@ -173,7 +178,7 @@
int main(int argc, char *argv[])
#endif
{
- int wave_out = 0, ref_size, mp3_size;
+ int wave_out = 0, ref_size;
char *ref_file_name = (argc > 2) ? argv[2] : NULL;
char *output_file_name = (argc > 3) ? argv[3] : NULL;
FILE *file_out = NULL;
@@ -200,17 +205,7 @@
printf("error: no file names given\n");
return 1;
}
- FILE *file_mp3 = fopen(input_file_name, "rb");
- unsigned char *buf_mp3 = preload(file_mp3, &mp3_size);
- if (file_mp3)
- fclose(file_mp3);
- if (!buf_mp3 || !mp3_size)
- {
- printf("error: no input data\n");
- return 1;
- }
- decode_file(buf_mp3, mp3_size, buf_ref, ref_size, file_out, wave_out);
- free(buf_mp3);
+ decode_file(input_file_name, buf_ref, ref_size, file_out, wave_out);
#ifdef __AFL_HAVE_MANUAL_CONTROL
}
#endif
--- a/scripts/build.sh
+++ b/scripts/build.sh
@@ -31,7 +31,7 @@
echo testing arm w/o neon...
arm-none-eabi-gcc -O2 -std=c89 -Wall -Wextra -Wmissing-prototypes -Werror -fno-asynchronous-unwind-tables -fno-stack-protector \
--mthumb -mcpu=cortex-m4 \
+-mthumb -mcpu=arm9e \
-ffunction-sections -fdata-sections -Wl,--gc-sections -o minimp3_arm minimp3_test.c --specs=rdimon.specs -lm
qemu-arm ./minimp3_arm