ref: 9719597ec6d609e5ea535172bde809be67ce1b5a
parent: 0ae65c429d96f8cae1a959e7b51294ea90aaa427
author: lieff <[email protected]>
date: Wed Feb 5 20:45:48 EST 2020
mp3dec_ex: handle padding for mp3dec_ex_read + test decoded length
--- a/minimp3_ex.h
+++ b/minimp3_ex.h
@@ -50,7 +50,7 @@
mp3dec_t mp3d;
mp3dec_map_info_t file;
mp3dec_index_t index;
- uint64_t offset, samples, detected_samples, start_offset, end_offset;
+ uint64_t offset, samples, detected_samples, cur_sample, start_offset, end_offset;
mp3dec_frame_info_t info;
mp3d_sample_t buffer[MINIMP3_MAX_SAMPLES_PER_FRAME];
#ifndef MINIMP3_NO_STDIO
@@ -274,8 +274,8 @@
progress_cb(user_data, orig_buf_size, orig_buf_size - buf_size, &frame_info);
}
} while (frame_bytes);
- if (detected_samples)
- info->samples = detected_samples;
+ if (detected_samples && info->samples > detected_samples)
+ info->samples = detected_samples; /* cut padding */
/* reallocate to normal buffer size */
if (allocated != info->samples*sizeof(mp3d_sample_t))
info->buffer = (mp3d_sample_t*)realloc(info->buffer, info->samples*sizeof(mp3d_sample_t));
@@ -419,8 +419,10 @@
if (MP3D_SEEK_TO_BYTE == dec->seek_method)
{
dec->offset = position;
+ dec->cur_sample = 0;
return 0;
}
+ dec->cur_sample = position;
position += dec->start_delay;
if (0 == position)
{ /* optimize seek to zero, no index needed */
@@ -499,9 +501,17 @@
size_t samples_requested = samples;
mp3dec_frame_info_t frame_info;
memset(&frame_info, 0, sizeof(frame_info));
+ if (dec->detected_samples && dec->cur_sample >= dec->detected_samples)
+ return 0; /* at end of stream */
if (dec->buffer_consumed < dec->buffer_samples)
{
size_t to_copy = MINIMP3_MIN((size_t)(dec->buffer_samples - dec->buffer_consumed), samples);
+ if (dec->detected_samples)
+ { /* count decoded samples to properly cut padding */
+ if (dec->cur_sample + to_copy >= dec->detected_samples)
+ to_copy = dec->detected_samples - dec->cur_sample;
+ dec->cur_sample += to_copy;
+ }
memcpy(buf, dec->buffer + dec->buffer_consumed, to_copy*sizeof(mp3d_sample_t));
buf += to_copy;
dec->buffer_consumed += to_copy;
@@ -509,6 +519,8 @@
}
while (samples)
{
+ if (dec->detected_samples && dec->cur_sample >= dec->detected_samples)
+ break;
const uint8_t *dec_buf = dec->file.buffer + dec->offset;
uint64_t buf_size = end_offset - dec->offset;
if (!buf_size)
@@ -525,6 +537,12 @@
dec->to_skip -= skip;
}
size_t to_copy = MINIMP3_MIN((size_t)(dec->buffer_samples - dec->buffer_consumed), samples);
+ if (dec->detected_samples)
+ { /* ^ handle padding */
+ if (dec->cur_sample + to_copy >= dec->detected_samples)
+ to_copy = dec->detected_samples - dec->cur_sample;
+ dec->cur_sample += to_copy;
+ }
memcpy(buf, dec->buffer + dec->buffer_consumed, to_copy*sizeof(mp3d_sample_t));
buf += to_copy;
dec->buffer_consumed += to_copy;
--- a/minimp3_test.c
+++ b/minimp3_test.c
@@ -121,6 +121,7 @@
info.samples = dec.samples;
info.buffer = malloc(dec.samples*sizeof(int16_t));
info.hz = dec.info.hz;
+ info.layer = dec.info.layer;
info.channels = dec.info.channels;
if (position < 0)
{
@@ -142,6 +143,12 @@
printf("error: mp3dec_ex_read() readed less than expected\n");
exit(1);
}
+ readed = mp3dec_ex_read(&dec, info.buffer, 1);
+ if (readed)
+ {
+ printf("error: mp3dec_ex_read() readed more than expected\n");
+ exit(1);
+ }
mp3dec_ex_close(&dec);
} else
{
@@ -172,7 +179,13 @@
total_samples += info.samples;
if (buf_ref)
{
- int max_samples = MINIMP3_MIN((size_t)ref_size/2, info.samples);
+ size_t ref_samples = ref_size/2;
+ if (ref_samples != info.samples && (ref_samples + 1152) != info.samples && (ref_samples + 2304) != info.samples && 3 == info.layer)
+ { /* some standard vectors are for some reason a little shorter */
+ printf("error: reference and produced number of samples do not match (%d/%d)\n", (int)ref_samples, (int)info.samples);
+ exit(1);
+ }
+ int max_samples = MINIMP3_MIN(ref_samples, info.samples);
for (i = 0; i < max_samples; i++)
{
int MSEtemp = abs((int)buffer[i] - (int)(int16_t)read16le(&buf_ref[i*sizeof(int16_t)]));
@@ -195,7 +208,7 @@
printf("rate=%d samples=%d max_diff=%d PSNR=%f\n", info.hz, total_samples, maxdiff, psnr);
if (psnr < 96)
{
- printf("PSNR compliance failed\n");
+ printf("error: PSNR compliance failed\n");
exit(1);
}
#endif