ref: f559dd18f024c594f5762c7427b1338cde004008
parent: 9773b3d093c0f697d9338b8d8cd9e37a4099d67b
author: lieff <[email protected]>
date: Sat Aug 4 15:12:51 EDT 2018
High-level API: +decoder with seek capability prototype +refactor file mapping code
--- a/minimp3_ex.h
+++ b/minimp3_ex.h
@@ -8,6 +8,10 @@
*/
#include "minimp3.h"
+#define MP3D_SEEK_TO_BYTE 0
+#define MP3D_SEEK_TO_SAMPLE 1
+#define MP3D_SEEK_TO_SAMPLE_INDEXED 2
+
typedef struct
{
int16_t *buffer;
@@ -15,6 +19,22 @@
int channels, hz, layer, avg_bitrate_kbps;
} mp3dec_file_info_t;
+typedef struct
+{
+ const uint8_t *buffer;
+ size_t size;
+} mp3dec_map_info_t;
+
+typedef struct
+{
+ mp3dec_t mp3d;
+ mp3dec_map_info_t file;
+ int seek_method;
+#ifndef MINIMP3_NO_STDIO
+ int is_file;
+#endif
+} mp3dec_ex_t;
+
typedef int (*MP3D_ITERATE_CB)(void *user_data, const uint8_t *frame, int frame_size, size_t offset, mp3dec_frame_info_t *info);
typedef int (*MP3D_PROGRESS_CB)(void *user_data, size_t file_size, size_t offset, mp3dec_frame_info_t *info);
@@ -26,10 +46,16 @@
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);
/* iterate through frames with optional decoding */
void mp3dec_iterate_buf(const uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data);
+/* decoder with seeking capability */
+int mp3dec_ex_open_buf(mp3dec_ex_t *dec, const uint8_t *buf, size_t buf_size, int seek_method);
+void mp3dec_ex_close(mp3dec_ex_t *dec);
+void mp3dec_ex_seek(mp3dec_ex_t *dec, size_t position);
+int mp3dec_ex_read(mp3dec_ex_t *dec, int16_t *buf, int samples);
#ifndef MINIMP3_NO_STDIO
/* stdio versions with file pre-load */
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);
#endif
#ifdef __cplusplus
@@ -161,6 +187,25 @@
} while (1);
}
+int mp3dec_ex_open_buf(mp3dec_ex_t *dec, const uint8_t *buf, size_t buf_size, int seek_method)
+{
+ memset(dec, 0, sizeof(*dec));
+ dec->file.buffer = buf;
+ dec->file.size = buf_size;
+ dec->seek_method = seek_method;
+ mp3dec_init(&dec->mp3d);
+ return 0;
+}
+
+/*void mp3dec_ex_seek(mp3dec_ex_t *dec, size_t position)
+{
+}
+
+int mp3dec_ex_read(mp3dec_ex_t *dec, int16_t *buf, int samples)
+{
+ return 0;
+}*/
+
#ifndef MINIMP3_NO_STDIO
#if defined(__linux__) || defined(__FreeBSD__)
@@ -176,66 +221,48 @@
#define MAP_POPULATE 0
#endif
-typedef struct
-{
- uint8_t *buffer;
- size_t size;
- int file;
-} mp3dec_map_info_t;
-
static void mp3dec_close_file(mp3dec_map_info_t *map_info)
{
if (map_info->buffer && MAP_FAILED != map_info->buffer)
- munmap(map_info->buffer, map_info->size);
- if (map_info->file)
- close(map_info->file);
+ munmap((void *)map_info->buffer, map_info->size);
map_info->buffer = 0;
- map_info->file = 0;
+ map_info->size = 0;
}
static int mp3dec_open_file(const char *file_name, mp3dec_map_info_t *map_info)
{
+ int file;
struct stat st;
memset(map_info, 0, sizeof(*map_info));
retry_open:
- map_info->file = open(file_name, O_RDONLY);
- if (map_info->file < 0 && (errno == EAGAIN || errno == EINTR))
+ file = open(file_name, O_RDONLY);
+ if (file < 0 && (errno == EAGAIN || errno == EINTR))
goto retry_open;
- if (map_info->file < 0 || fstat(map_info->file, &st) < 0)
+ if (file < 0 || fstat(file, &st) < 0)
{
- mp3dec_close_file(map_info);
+ close(file);
return -1;
}
map_info->size = st.st_size;
retry_mmap:
- map_info->buffer = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE | MAP_POPULATE, map_info->file, 0);
+ map_info->buffer = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE | MAP_POPULATE, file, 0);
if (MAP_FAILED == map_info->buffer && (errno == EAGAIN || errno == EINTR))
goto retry_mmap;
+ close(file);
if (MAP_FAILED == map_info->buffer)
- {
- mp3dec_close_file(map_info);
return -1;
- }
return 0;
}
#elif defined(_WIN32)
#include <windows.h>
-typedef struct
-{
- uint8_t *buffer;
- size_t size;
- HANDLE file;
-} mp3dec_map_info_t;
static void mp3dec_close_file(mp3dec_map_info_t *map_info)
{
if (map_info->buffer)
UnmapViewOfFile(map_info->buffer);
- if (INVALID_HANDLE_VALUE != map_info->file)
- CloseHandle(map_info->file);
map_info->buffer = 0;
- map_info->file = 0;
+ map_info->size = 0;
}
static int mp3dec_open_file(const char *file_name, mp3dec_map_info_t *map_info)
@@ -242,16 +269,16 @@
{
memset(map_info, 0, sizeof(*map_info));
- map_info->file = CreateFileA(file_name, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
- if (INVALID_HANDLE_VALUE == map_info->file)
- goto error;
+ HANDLE file = CreateFileA(file_name, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
+ if (INVALID_HANDLE_VALUE == file)
+ return -1;
LARGE_INTEGER s;
- s.LowPart = GetFileSize(map_info->file, (DWORD*)&s.HighPart);
+ s.LowPart = GetFileSize(file, (DWORD*)&s.HighPart);
if (s.LowPart == INVALID_FILE_SIZE && GetLastError() != NO_ERROR)
goto error;
map_info->size = s.QuadPart;
- HANDLE mapping = CreateFileMapping(map_info->file, NULL, PAGE_READONLY, 0, 0, NULL);
+ HANDLE mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
if (!mapping)
goto error;
map_info->buffer = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, s.QuadPart);
@@ -259,53 +286,49 @@
if (!map_info->buffer)
goto error;
+ CloseHandle(file);
return 0;
error:
mp3dec_close_file(map_info);
+ CloseHandle(file);
return -1;
}
#else
#include <stdio.h>
-typedef struct
-{
- uint8_t *buffer;
- FILE *file;
- size_t size;
-} mp3dec_map_info_t;
static void mp3dec_close_file(mp3dec_map_info_t *map_info)
{
if (map_info->buffer)
- free(map_info->buffer);
- if (map_info->file)
- fclose(map_info->file);
+ free((void *)map_info->buffer);
map_info->buffer = 0;
- map_info->file = 0;
+ map_info->size = 0;
}
static int mp3dec_open_file(const char *file_name, mp3dec_map_info_t *map_info)
{
memset(map_info, 0, sizeof(*map_info));
- map_info->file = fopen(file_name, "rb");
- if (!map_info->file)
+ FILE *file = fopen(file_name, "rb");
+ if (!file)
return -1;
- if (fseek(map_info->file, 0, SEEK_END))
+ if (fseek(file, 0, SEEK_END))
goto error;
- long size = ftell(map_info->file);
+ long size = ftell(file);
if (size < 0)
goto error;
map_info->size = (size_t)size;
- if (fseek(map_info->file, 0, SEEK_SET))
+ if (fseek(file, 0, SEEK_SET))
goto error;
map_info->buffer = (uint8_t *)malloc(map_info->size);
if (!map_info->buffer)
goto error;
- if (fread(map_info->buffer, 1, map_info->size, map_info->file) != map_info->size)
+ if (fread((void *)map_info->buffer, 1, map_info->size, file) != map_info->size)
goto error;
+ fclose(file);
return 0;
error:
mp3dec_close_file(map_info);
+ fclose(file);
return -1;
}
#endif
@@ -330,6 +353,33 @@
mp3dec_iterate_buf(map_info.buffer, map_info.size, callback, user_data);
mp3dec_close_file(&map_info);
return 0;
+}
+
+void mp3dec_ex_close(mp3dec_ex_t *dec)
+{
+ if (dec->is_file)
+ mp3dec_close_file(&dec->file);
+ else
+ free((void *)dec->file.buffer);
+ memset(dec, 0, sizeof(*dec));
+}
+
+int mp3dec_ex_open(mp3dec_ex_t *dec, const char *file_name, int seek_method)
+{
+ int ret;
+ memset(dec, 0, sizeof(*dec));
+ if ((ret = mp3dec_open_file(file_name, &dec->file)))
+ return ret;
+ dec->seek_method = seek_method;
+ dec->is_file = 1;
+ mp3dec_init(&dec->mp3d);
+ return 0;
+}
+#else
+void mp3dec_ex_close(mp3dec_ex_t *dec)
+{
+ free(dec->file.buffer);
+ memset(dec, 0, sizeof(*dec));
}
#endif