ref: a3d51712098ba68ed08c2b7c48934505d4b19b22
parent: 60fd217a7e76f72bd552b70c04a29a8f6301940e
author: lieff <[email protected]>
date: Fri Apr 24 10:23:32 EDT 2020
MP3D_DO_NOT_SCAN support for mp3dec_ex_open. Which guarantees file will not be scanned to detect it's length, but mp3dec_ex_t::samples will not be filled if vbr-tag absent.
--- a/minimp3_ex.h
+++ b/minimp3_ex.h
@@ -8,15 +8,19 @@
*/
#include "minimp3.h"
-#define MP3D_SEEK_TO_BYTE 0
-#define MP3D_SEEK_TO_SAMPLE 1
+/* flags for mp3dec_ex_open_* functions */
+#define MP3D_SEEK_TO_BYTE 0 /* mp3dec_ex_seek seeks to byte in stream */
+#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) */
+#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 */
+/* compile-time config */
#define MINIMP3_PREDECODE_FRAMES 2 /* frames to pre-decode and skip after seek (to fill internal structures) */
/*#define MINIMP3_SEEK_IDX_LINEAR_SEARCH*/ /* define to use linear index search instead of binary search on seek */
#define MINIMP3_IO_SIZE (128*1024) /* io buffer size for streaming functions, must be greater than MINIMP3_BUF_SIZE */
#define MINIMP3_BUF_SIZE (16*1024) /* buffer which can hold minimum 10 consecutive mp3 frames (~16KB) worst case */
-#define MINIMP3_ENABLE_RING 0 /* enable hardware magic ring buffer if available, to make less input buffer memmove(s) in callback IO mode */
+#define MINIMP3_ENABLE_RING 0 /* WIP enable hardware magic ring buffer if available, to make less input buffer memmove(s) in callback IO mode */
+/* return error codes */
#define MP3D_E_PARAM -1
#define MP3D_E_MEMORY -2
#define MP3D_E_IOERROR -3
@@ -69,7 +73,7 @@
mp3dec_frame_info_t info;
mp3d_sample_t buffer[MINIMP3_MAX_SAMPLES_PER_FRAME];
size_t input_consumed, input_filled;
- int is_file, seek_method, vbr_tag_found;
+ int is_file, flags, vbr_tag_found;
int free_format_bytes;
int buffer_samples, buffer_consumed, to_skip, start_delay;
int last_error;
@@ -92,8 +96,8 @@
int mp3dec_iterate_buf(const uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data);
int mp3dec_iterate_cb(mp3dec_io_t *io, uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data);
/* streaming decoder with seeking capability */
-int mp3dec_ex_open_buf(mp3dec_ex_t *dec, const uint8_t *buf, size_t buf_size, int seek_method);
-int mp3dec_ex_open_cb(mp3dec_ex_t *dec, mp3dec_io_t *io, int seek_method);
+int mp3dec_ex_open_buf(mp3dec_ex_t *dec, const uint8_t *buf, size_t buf_size, int flags);
+int mp3dec_ex_open_cb(mp3dec_ex_t *dec, mp3dec_io_t *io, int flags);
void mp3dec_ex_close(mp3dec_ex_t *dec);
int mp3dec_ex_seek(mp3dec_ex_t *dec, uint64_t position);
size_t mp3dec_ex_read(mp3dec_ex_t *dec, mp3d_sample_t *buf, size_t samples);
@@ -102,12 +106,12 @@
int mp3dec_detect(const char *file_name);
int mp3dec_load(mp3dec_t *dec, const char *file_name, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data);
int mp3dec_iterate(const char *file_name, MP3D_ITERATE_CB callback, void *user_data);
-int mp3dec_ex_open(mp3dec_ex_t *dec, const char *file_name, int seek_method);
+int mp3dec_ex_open(mp3dec_ex_t *dec, const char *file_name, int flags);
#ifdef _WIN32
int mp3dec_detect_w(const wchar_t *file_name);
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);
int mp3dec_iterate_w(const wchar_t *file_name, MP3D_ITERATE_CB callback, void *user_data);
-int mp3dec_ex_open_w(mp3dec_ex_t *dec, const wchar_t *file_name, int seek_method);
+int mp3dec_ex_open_w(mp3dec_ex_t *dec, const wchar_t *file_name, int flags);
#endif
#endif
@@ -631,6 +635,8 @@
return 0;
}
}
+ if (dec->flags & MP3D_DO_NOT_SCAN)
+ return MP3D_E_USER;
if (dec->index.num_frames + 1 > dec->index.capacity)
{
if (!dec->index.capacity)
@@ -655,14 +661,14 @@
return 0;
}
-int mp3dec_ex_open_buf(mp3dec_ex_t *dec, const uint8_t *buf, size_t buf_size, int seek_method)
+int mp3dec_ex_open_buf(mp3dec_ex_t *dec, const uint8_t *buf, size_t buf_size, int flags)
{
- if (!dec || !buf || (size_t)-1 == buf_size || !(MP3D_SEEK_TO_BYTE == seek_method || MP3D_SEEK_TO_SAMPLE == seek_method))
+ if (!dec || !buf || (size_t)-1 == buf_size || (flags & (~3)))
return MP3D_E_PARAM;
memset(dec, 0, sizeof(*dec));
dec->file.buffer = buf;
dec->file.size = buf_size;
- dec->seek_method = seek_method;
+ dec->flags = flags;
mp3dec_init(&dec->mp3d);
int ret = mp3dec_iterate_buf(dec->file.buffer, dec->file.size, mp3dec_load_index, dec);
if (ret && MP3D_E_USER != ret)
@@ -701,7 +707,7 @@
size_t i;
if (!dec)
return MP3D_E_PARAM;
- if (MP3D_SEEK_TO_BYTE == dec->seek_method)
+ if (!(dec->flags & MP3D_SEEK_TO_SAMPLE))
{
if (dec->io)
{
@@ -1212,9 +1218,9 @@
return ret;
}
-static int mp3dec_ex_open_mapinfo(mp3dec_ex_t *dec, int seek_method)
+static int mp3dec_ex_open_mapinfo(mp3dec_ex_t *dec, int flags)
{
- int ret = mp3dec_ex_open_buf(dec, dec->file.buffer, dec->file.size, seek_method);
+ int ret = mp3dec_ex_open_buf(dec, dec->file.buffer, dec->file.size, flags);
dec->is_file = 1;
if (ret)
mp3dec_ex_close(dec);
@@ -1248,7 +1254,7 @@
return mp3dec_iterate_mapinfo(&map_info, callback, user_data);
}
-int mp3dec_ex_open(mp3dec_ex_t *dec, const char *file_name, int seek_method)
+int mp3dec_ex_open(mp3dec_ex_t *dec, const char *file_name, int flags)
{
int ret;
if (!dec)
@@ -1255,12 +1261,12 @@
return MP3D_E_PARAM;
if ((ret = mp3dec_open_file(file_name, &dec->file)))
return ret;
- return mp3dec_ex_open_mapinfo(dec, seek_method);
+ return mp3dec_ex_open_mapinfo(dec, flags);
}
-int mp3dec_ex_open_cb(mp3dec_ex_t *dec, mp3dec_io_t *io, int seek_method)
+int mp3dec_ex_open_cb(mp3dec_ex_t *dec, mp3dec_io_t *io, int flags)
{
- if (!dec || !io || !(MP3D_SEEK_TO_BYTE == seek_method || MP3D_SEEK_TO_SAMPLE == seek_method))
+ if (!dec || !io || (flags & (~3)))
return MP3D_E_PARAM;
memset(dec, 0, sizeof(*dec));
#ifdef MINIMP3_HAVE_RING
@@ -1273,7 +1279,7 @@
if (!dec->file.buffer)
return MP3D_E_MEMORY;
#endif
- dec->seek_method = seek_method;
+ dec->flags = flags;
dec->io = io;
mp3dec_init(&dec->mp3d);
if (io->seek(0, io->seek_data))
@@ -1332,12 +1338,12 @@
return mp3dec_iterate_mapinfo(&map_info, callback, user_data);
}
-int mp3dec_ex_open_w(mp3dec_ex_t *dec, const wchar_t *file_name, int seek_method)
+int mp3dec_ex_open_w(mp3dec_ex_t *dec, const wchar_t *file_name, int flags)
{
int ret;
if ((ret = mp3dec_open_file_w(file_name, &dec->file)))
return ret;
- return mp3dec_ex_open_mapinfo(dec, seek_method);
+ return mp3dec_ex_open_mapinfo(dec, flags);
}
#endif
#else /* MINIMP3_NO_STDIO */
--- a/minimp3_test.c
+++ b/minimp3_test.c
@@ -512,18 +512,19 @@
ASSERT(MP3D_E_PARAM == ret);
ret = mp3dec_ex_open_buf(&dec, buf, (size_t)-1, MP3D_SEEK_TO_SAMPLE);
ASSERT(MP3D_E_PARAM == ret);
- ret = mp3dec_ex_open_buf(&dec, buf, size, MP3D_SEEK_TO_SAMPLE + 1);
+ ret = mp3dec_ex_open_buf(&dec, buf, size, MP3D_SEEK_TO_SAMPLE | (1 << 2));
ASSERT(MP3D_E_PARAM == ret);
ret = mp3dec_ex_open_buf(&dec, buf, 0, MP3D_SEEK_TO_SAMPLE);
ASSERT(0 == ret);
ret = mp3dec_ex_read(&dec, (mp3d_sample_t*)buf, 10);
ASSERT(0 == ret);
+ mp3dec_ex_close(&dec);
ret = mp3dec_ex_open_cb(0, &io, MP3D_SEEK_TO_SAMPLE);
ASSERT(MP3D_E_PARAM == ret);
ret = mp3dec_ex_open_cb(&dec, 0, MP3D_SEEK_TO_SAMPLE);
ASSERT(MP3D_E_PARAM == ret);
- ret = mp3dec_ex_open_cb(&dec, &io, MP3D_SEEK_TO_SAMPLE + 1);
+ ret = mp3dec_ex_open_cb(&dec, &io, MP3D_SEEK_TO_SAMPLE | (1 << 2));
ASSERT(MP3D_E_PARAM == ret);
ret = mp3dec_ex_seek(0, 0);
@@ -561,7 +562,7 @@
ASSERT(MP3D_E_PARAM == ret);
ret = mp3dec_ex_open(&dec, 0, MP3D_SEEK_TO_SAMPLE);
ASSERT(MP3D_E_PARAM == ret);
- ret = mp3dec_ex_open(&dec, input_file_name, MP3D_SEEK_TO_SAMPLE + 1);
+ ret = mp3dec_ex_open(&dec, input_file_name, MP3D_SEEK_TO_SAMPLE | (1 << 2));
ASSERT(MP3D_E_PARAM == ret);
ret = mp3dec_ex_open(&dec, "not_foud", MP3D_SEEK_TO_SAMPLE);
ASSERT(MP3D_E_IOERROR == ret);
@@ -574,6 +575,7 @@
ret = mp3dec_ex_open_cb(&dec, &io, MP3D_SEEK_TO_SAMPLE);
ASSERT(0 == ret);
ASSERT(5 == io_num);
+ ASSERT(725760 == dec.samples); /* num samples detected */
fail_io_num = 5;
mp3d_sample_t sample;
size_t readed = mp3dec_ex_read(&dec, &sample, 1);
@@ -588,8 +590,15 @@
readed = mp3dec_ex_read(&dec, &sample, 1);
ASSERT(1 == readed);
mp3dec_ex_close(&dec);
- fclose((FILE*)io.read_data);
+ ret = mp3dec_ex_open_cb(&dec, &io, MP3D_SEEK_TO_SAMPLE | MP3D_DO_NOT_SCAN);
+ ASSERT(0 == ret);
+ ASSERT(0 == dec.samples); /* num samples do not detected because of MP3D_DO_NOT_SCAN */
+ readed = mp3dec_ex_read(&dec, &sample, 1);
+ ASSERT(1 == readed);
+ mp3dec_ex_close(&dec);
+
+ fclose((FILE*)io.read_data);
printf("passed\n");
return 0;
}