shithub: mp3dec

Download patch

ref: 4a08619d8df4e9c8cc3a353b9fd4a99c63c06779
parent: 8e89e558ae25b75b0ec3c3bdb250c8d0eeadb2eb
author: lieff <[email protected]>
date: Sun Feb 2 21:06:59 EST 2020

WIP mp3dec_ex API callback input support.

--- a/minimp3_ex.h
+++ b/minimp3_ex.h
@@ -13,6 +13,7 @@
 
 #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_RING_SIZE (128*1024)
 
 #define MP3D_E_MEMORY -1
 
@@ -19,7 +20,7 @@
 typedef struct
 {
     mp3d_sample_t *buffer;
-    size_t samples; /* channels included, byte size = samples*sizeof(int16_t) */
+    size_t samples; /* channels included, byte size = samples*sizeof(mp3d_sample_t) */
     int channels, hz, layer, avg_bitrate_kbps;
 } mp3dec_file_info_t;
 
@@ -41,7 +42,8 @@
     size_t num_frames, capacity;
 } mp3dec_index_t;
 
-/*typedef int (*MP3D_READ_CB)(void *buf, size_t size, void *user_data);*/
+typedef int (*MP3D_READ_CB)(void *buf, size_t size, void *user_data);
+typedef int (*MP3D_SEEK_CB)(size_t position);
 
 typedef struct
 {
@@ -72,10 +74,10 @@
 size_t mp3dec_iterate_buf(const 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, MP3D_READ_CB cb, void *user_data, uint64_t file_size, int seek_method);*/
+int mp3dec_ex_open_cb(mp3dec_ex_t *dec, MP3D_READ_CB read_cb, void *read_user_data, MP3D_SEEK_CB seek_cb, void *seek_user_data, int seek_method);
 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, int16_t *buf, size_t samples);
+size_t mp3dec_ex_read(mp3dec_ex_t *dec, mp3d_sample_t *buf, size_t 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);
@@ -373,7 +375,7 @@
     return 0;
 }
 
-size_t mp3dec_ex_read(mp3dec_ex_t *dec, int16_t *buf, size_t samples)
+size_t mp3dec_ex_read(mp3dec_ex_t *dec, mp3d_sample_t *buf, size_t samples)
 {
     size_t samples_requested = samples;
     mp3dec_frame_info_t frame_info;
@@ -381,7 +383,7 @@
     if (dec->buffer_consumed < dec->buffer_samples)
     {
         size_t to_copy = MINIMP3_MIN((size_t)(dec->buffer_samples - dec->buffer_consumed), samples);
-        memcpy(buf, dec->buffer + dec->buffer_consumed, to_copy*sizeof(int16_t));
+        memcpy(buf, dec->buffer + dec->buffer_consumed, to_copy*sizeof(mp3d_sample_t));
         buf += to_copy;
         dec->buffer_consumed += to_copy;
         samples -= to_copy;
@@ -404,7 +406,7 @@
                 dec->to_skip -= skip;
             }
             size_t to_copy = MINIMP3_MIN((size_t)(dec->buffer_samples - dec->buffer_consumed), samples);
-            memcpy(buf, dec->buffer + dec->buffer_consumed, to_copy*sizeof(int16_t));
+            memcpy(buf, dec->buffer + dec->buffer_consumed, to_copy*sizeof(mp3d_sample_t));
             buf += to_copy;
             dec->buffer_consumed += to_copy;
             samples -= to_copy;
@@ -428,6 +430,10 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <fcntl.h>
+#if !defined(_GNU_SOURCE)
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif
 #if !defined(MAP_POPULATE) && defined(__linux__)
 #define MAP_POPULATE 0x08000
 #elif !defined(MAP_POPULATE)
@@ -467,6 +473,98 @@
         return -1;
     return 0;
 }
+
+static void mp3dec_close_ring(mp3dec_map_info_t *map_info)
+{
+#if defined(__linux__) && defined(_GNU_SOURCE)
+    if (map_info->buffer && MAP_FAILED != map_info->buffer)
+        munmap((void *)map_info->buffer, map_info->size*2);
+#esle
+    if (map_info->buffer)
+    {
+        shmdt(map_info->buffer);
+        shmdt(map_info->buffer + map_info->size);
+    }
+#endif
+    map_info->buffer = 0;
+    map_info->size   = 0;
+}
+
+static int mp3dec_open_ring(mp3dec_map_info_t *map_info, size_t size)
+{
+    int memfd, page_size;
+#if defined(__linux__) && defined(_GNU_SOURCE)
+    int res;
+#endif
+    memset(map_info, 0, sizeof(*map_info));
+
+#ifdef _SC_PAGESIZE
+    page_size = sysconf( _SC_PAGESIZE );
+#else
+    page_size = getpagesize();
+#endif
+    map_info->size = (size + page_size - 1)/page_size*page_size;
+
+#if defined(__linux__) && defined(_GNU_SOURCE)
+    memfd = memfd_create("mp3_ring", 0);
+    if (memfd < 0)
+        return -1;
+
+retry_ftruncate:
+    res = ftruncate(memfd, size);
+    if (res && (errno == EAGAIN || errno == EINTR))
+        goto retry_ftruncate;
+    if (res)
+        goto error;
+
+retry_mmap:
+    map_info->buffer = (const uint8_t *)mmap(NULL, map_info->size*2, PROT_NONE, MAP_PRIVATE, -1, 0);
+    if (MAP_FAILED == map_info->buffer && (errno == EAGAIN || errno == EINTR))
+        goto retry_mmap;
+    if (MAP_FAILED == map_info->buffer)
+        goto error;
+retry_mmap2:
+    map_info->buffer = (const uint8_t *)mmap((void *)map_info->buffer, map_info->size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, memfd, 0);
+    if (MAP_FAILED == map_info->buffer && (errno == EAGAIN || errno == EINTR))
+        goto retry_mmap2;
+    if (MAP_FAILED == map_info->buffer)
+        goto error;
+retry_mmap3:
+    map_info->buffer = (const uint8_t *)mmap((void *)map_info->buffer + map_info->size, map_info->size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, memfd, 0);
+    if (MAP_FAILED == map_info->buffer && (errno == EAGAIN || errno == EINTR))
+        goto retry_mmap3;
+    if (MAP_FAILED == map_info->buffer)
+        goto error;
+
+    close(memfd);
+    return 0;
+error:
+    close(memfd);
+    mp3dec_close_ring(map_info);
+    return -1;
+#else
+    memfd = shmget(IPC_PRIVATE, map_info->size, IPC_CREAT | 0700);
+    if (memfd < 0)
+        return -1;
+retry_mmap:
+    map_info->buffer = (const uint8_t *)mmap(NULL, map_info->size*2, PROT_NONE, MAP_PRIVATE, -1, 0);
+    if (MAP_FAILED == map_info->buffer && (errno == EAGAIN || errno == EINTR))
+        goto retry_mmap;
+    if (MAP_FAILED == map_info->buffer)
+        goto error;
+    if (map_info->buffer != shmat(memfd, map_info->buffer, 0))
+        goto error;
+    if ((map_info->buffer + map_info->size) != shmat(memfd, map_info->buffer + map_info->size, 0))
+        goto error;
+    if (shmctl(memfd, IPC_RMID, NULL) < 0)
+        return -1;
+    return 0;
+error:
+    shmctl(memfd, IPC_RMID, NULL);
+    mp3dec_close_ring(map_info);
+    return -1;
+#endif
+}
 #elif defined(_WIN32)
 #include <windows.h>
 
@@ -475,7 +573,7 @@
     if (map_info->buffer)
         UnmapViewOfFile(map_info->buffer);
     map_info->buffer = 0;
-    map_info->size = 0;
+    map_info->size   = 0;
 }
 
 static int mp3dec_open_file(const char *file_name, mp3dec_map_info_t *map_info)
@@ -495,7 +593,7 @@
     mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
     if (!mapping)
         goto error;
-    map_info->buffer = (const uint8_t*) MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, s.QuadPart);
+    map_info->buffer = (const uint8_t*)MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, s.QuadPart);
     CloseHandle(mapping);
     if (!map_info->buffer)
         goto error;
@@ -507,8 +605,41 @@
     CloseHandle(file);
     return -1;
 }
+
+static void mp3dec_close_ring(mp3dec_map_info_t *map_info)
+{
+    if (map_info->buffer)
+    {
+        UnmapViewOfFile(map_info->buffer);
+        UnmapViewOfFile(map_info->buffer + map_info->size);
+    }
+    map_info->buffer = 0;
+    map_info->size   = 0;
+}
+
+static int mp3dec_open_ring(mp3dec_map_info_t *map_info, size_t size)
+{
+    map_info->size = size;
+    HANDLE hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, NULL);
+    if (INVALID_HANDLE_VALUE == hMap)
+        return -1;
+    map_info->buffer = (const uint8_t *)VirtualAlloc(0, size*2, MEM_RESERVE, PAGE_READWRITE);
+    if (!map_info->buffer)
+        goto error;
+    if (!MapViewOfFileEx(hMap, FILE_MAP_ALL_ACCESS, 0, 0, size, (LPVOID)map_info->buffer))
+        goto error;
+    if (!MapViewOfFileEx(hMap, FILE_MAP_ALL_ACCESS, 0, 0, size, (LPVOID)(map_info->buffer + size)))
+        goto error;
+    CloseHandle(hMap);
+    return 0;
+error:
+    mp3dec_close_ring(map_info);
+    CloseHandle(hMap);
+    return -1;
+}
 #else
 #include <stdio.h>
+#define MINIMP3_NO_RING
 
 static void mp3dec_close_file(mp3dec_map_info_t *map_info)
 {
@@ -586,6 +717,22 @@
     ret = mp3dec_ex_open_buf(dec, dec->file.buffer, dec->file.size, seek_method);
     dec->is_file = 1;
     return ret;
+}
+
+int mp3dec_ex_open_cb(mp3dec_ex_t *dec, MP3D_READ_CB read_cb, void *read_user_data, MP3D_SEEK_CB seek_cb, void *seek_user_data, int seek_method)
+{
+    memset(dec, 0, sizeof(*dec));
+#ifndef MINIMP3_NO_RING
+    mp3dec_open_ring(&dec->file, MINIMP3_RING_SIZE);
+#endif
+    dec->seek_method = seek_method;
+    mp3dec_init(&dec->mp3d);
+    /* TODO */
+    (void)read_cb;
+    (void)read_user_data;
+    (void)seek_cb;
+    (void)seek_user_data;
+    return 0;
 }
 #else /* MINIMP3_NO_STDIO */
 void mp3dec_ex_close(mp3dec_ex_t *dec)