shithub: mp3dec

Download patch

ref: 2ed89a6d88755846503bf1d69ab4482dec66f9f4
parent: cf99374896971c78e79eb74ee22468155f47eb69
author: lieff <lieff@users.noreply.github.com>
date: Tue Feb 18 21:16:58 EST 2020

mp3dec_ex: return MP3D_E_DECODE in case of transitions errors

--- a/minimp3_ex.h
+++ b/minimp3_ex.h
@@ -20,7 +20,8 @@
 #define MP3D_E_PARAM   -1
 #define MP3D_E_MEMORY  -2
 #define MP3D_E_IOERROR -3
-#define MP3D_E_USER    -4
+#define MP3D_E_USER    -4  /* can be used to stop processing from callbacks without indicating specific error */
+#define MP3D_E_DECODE  -5  /* decode error which can't be safely skipped, such as sample rate, layer and channels change */
 
 typedef struct
 {
@@ -230,7 +231,7 @@
 
     /* skip id3 */
     size_t filled, consumed;
-    int eof;
+    int eof, ret = 0;
     if (io)
     {
         if (io->seek(0, io->seek_data))
@@ -375,13 +376,19 @@
         if (samples)
         {
             if (info->hz != frame_info.hz || info->layer != frame_info.layer)
+            {
+                ret = MP3D_E_DECODE;
                 break;
+            }
             if (info->channels && info->channels != frame_info.channels)
+            {
 #ifdef MINIMP3_ALLOW_MONO_STEREO_TRANSITION
                 info->channels = 0; /* mark file with mono-stereo transition */
 #else
+                ret = MP3D_E_DECODE;
                 break;
 #endif
+            }
             samples *= frame_info.channels;
             if (to_skip)
             {
@@ -395,9 +402,9 @@
             frames++;
             if (progress_cb)
             {
-                int ret = progress_cb(user_data, orig_buf_size, orig_buf_size - buf_size, &frame_info);
+                ret = progress_cb(user_data, orig_buf_size, orig_buf_size - buf_size, &frame_info);
                 if (ret)
-                    return ret;
+                    break;
             }
         }
     } while (frame_info.frame_bytes);
@@ -408,7 +415,7 @@
         info->buffer = (mp3d_sample_t*)realloc(info->buffer, info->samples*sizeof(mp3d_sample_t));
     if (frames)
         info->avg_bitrate_kbps = avg_bitrate_kbps/frames;
-    return 0;
+    return ret;
 }
 
 int mp3dec_iterate_buf(const uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data)
@@ -805,6 +812,15 @@
             dec->buffer_samples = mp3dec_decode_frame(&dec->mp3d, dec_buf, MINIMP3_MIN(buf_size, (uint64_t)INT_MAX), dec->buffer, &frame_info);
         }
         dec->buffer_consumed = 0;
+        if (dec->info.hz != frame_info.hz || dec->info.layer != frame_info.layer
+#ifndef MINIMP3_ALLOW_MONO_STEREO_TRANSITION
+            || dec->info.channels != frame_info.channels
+#endif
+            )
+        {
+            dec->last_error = MP3D_E_DECODE;
+            break;
+        }
         if (dec->buffer_samples)
         {
             dec->buffer_samples *= frame_info.channels;
--- a/minimp3_test.c
+++ b/minimp3_test.c
@@ -200,7 +200,7 @@
             io.read_data = io.seek_data = file;
             res = file ? mp3dec_ex_open_cb(&dec, &io, MP3D_SEEK_TO_SAMPLE) : -1;
         }
-        if (res)
+        if (res && MP3D_E_DECODE != res)
         {
             printf("error: mp3dec_ex_open() failed\n");
             exit(1);