shithub: mp3dec

Download patch

ref: 4e4702c945707858222f49ffe4bc4ac7f5c17ae1
parent: edd3ce5805803f3121dd05fe5a929f8976ab2f72
author: lieff <[email protected]>
date: Thu Feb 27 20:31:04 EST 2020

mp3dec_ex: do not decode empty frame with vbrtag,
if it's valid, but there no frames flag, just skip it.

--- a/minimp3_ex.h
+++ b/minimp3_ex.h
@@ -191,7 +191,7 @@
         return 0;
     int flags = tag[7];
     if (!((flags & FRAMES_FLAG)))
-        return 0;
+        return -1;
     tag += 8;
     *frames = (uint32_t)(tag[0] << 24) | (tag[1] << 16) | (tag[2] << 8) | tag[3];
     tag += 4;
@@ -308,7 +308,8 @@
         frame_info.bitrate_kbps = hdr_bitrate_kbps(hdr);
         frame_info.frame_bytes = frame_size;
         samples = hdr_frame_samples(hdr)*frame_info.channels;
-        if (mp3dec_check_vbrtag(hdr, frame_size, &frames, &delay, &padding))
+        int ret = mp3dec_check_vbrtag(hdr, frame_size, &frames, &delay, &padding);
+        if (ret > 0)
         {
             padding *= frame_info.channels;
             to_skip = delay*frame_info.channels;
@@ -319,6 +320,9 @@
                 detected_samples -= padding;
             if (!detected_samples)
                 return 0;
+        }
+        if (ret)
+        {
             if (io)
             {
                 consumed += frame_size;
@@ -552,7 +556,10 @@
         dec->start_offset = dec->offset = offset;
         dec->end_offset   = offset + buf_size;
         dec->free_format_bytes = free_format_bytes; /* should not change */
-        if (mp3dec_check_vbrtag(frame, frame_size, &frames, &delay, &padding))
+        int ret = mp3dec_check_vbrtag(frame, frame_size, &frames, &delay, &padding);
+        if (ret)
+            dec->start_offset = dec->offset = offset + frame_size;
+        if (ret > 0)
         {
             padding *= info->channels;
             dec->start_delay = dec->to_skip = delay*info->channels;
@@ -562,10 +569,10 @@
             if (padding > 0 && dec->samples >= (uint64_t)padding)
                 dec->samples -= padding;
             dec->detected_samples = dec->samples;
-            dec->start_offset = dec->offset = offset + frame_size;
             dec->vbr_tag_found = 1;
             return MP3D_E_USER;
-        }
+        } else if (ret < 0)
+            return 0;
     }
     if (dec->index.num_frames + 1 > dec->index.capacity)
     {
--- a/scripts/build.sh
+++ b/scripts/build.sh
@@ -95,6 +95,10 @@
 [[ "$(./minimp3 -m 8 -s 1 -e 5 vectors/l3-nonstandard-vbrtag-only.bit)" != "error: mp3dec_ex_seek()=-3 failed" ]] && echo fail && exit 1 || echo pass
 [[ "$(./minimp3 -m 6 -s 1 -f 2 vectors/l3-nonstandard-sin1k0db_lame_vbrtag.bit)" != "error: mp3dec_ex_seek()=-2 failed" ]] && echo fail && exit 1 || echo pass
 [[ "$(./minimp3 vectors/l3-nonstandard-vbrtag-empty.bit)" != "rate=0 samples=0 max_diff=0 PSNR=99.000000" ]] && echo fail && exit 1 || echo pass
+# Currently vbrtag with no frames flag treated as no vbrtag, not sure if any software produce such files.
+# Delay and padding usage can be implemented if such software/files exists.
+[[ "$(./minimp3 vectors/l3-nonstandard-vbrtag-noframes.bit)" != "rate=44100 samples=0 max_diff=0 PSNR=99.000000" ]] && echo fail && exit 1 || echo pass
+[[ "$(./minimp3 -m 6 vectors/l3-nonstandard-vbrtag-noframes.bit)" != "rate=44100 samples=0 max_diff=0 PSNR=99.000000" ]] && echo fail && exit 1 || echo pass
 set -e
 
 ./minimp3 -m 6 -s 215 -b vectors/l3-sin1k0db.bit vectors/l3-sin1k0db.pcm
binary files /dev/null b/vectors/l3-nonstandard-vbrtag-noframes.bit differ