From 18d3f76152de5745678f34a10c9a4acf1778a9fb Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Mon, 24 Mar 2025 08:16:37 -0700 Subject: [PATCH] Bug Fix: Fix minimp3 streaming support The streaming support was breaking because initial packet detection was failing due to bit reservoir errors. Instead, detect consecutive sync frames in the initial read buffer, then attempt to sync to a decodable frame in the first block of data, otherwise give up. Signed-off-by: Christopher Snowhill --- Plugins/minimp3/MP3Decoder.h | 4 ++-- Plugins/minimp3/MP3Decoder.m | 38 ++++++++++++++++++++++++------------ 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/Plugins/minimp3/MP3Decoder.h b/Plugins/minimp3/MP3Decoder.h index b6051f6a6..a687f7a1f 100644 --- a/Plugins/minimp3/MP3Decoder.h +++ b/Plugins/minimp3/MP3Decoder.h @@ -15,11 +15,11 @@ #import "Plugin.h" -#define INPUT_BUFFER_SIZE 16 * 1024 +//#define INPUT_BUFFER_SIZE 16 * 1024 // superceded by MINIMP3_BUF_SIZE, which has been altered @interface MP3Decoder : NSObject { BOOL seekable; - unsigned char _decoder_buffer[INPUT_BUFFER_SIZE]; + unsigned char _decoder_buffer[MINIMP3_BUF_SIZE]; size_t _decoder_buffer_filled; mp3dec_ex_t _decoder_ex; diff --git a/Plugins/minimp3/MP3Decoder.m b/Plugins/minimp3/MP3Decoder.m index 19a13f87c..2910cd8e9 100644 --- a/Plugins/minimp3/MP3Decoder.m +++ b/Plugins/minimp3/MP3Decoder.m @@ -161,20 +161,28 @@ static int mp3_seek_callback(uint64_t position, void *user_data) { } bitrate = (double)((_fileSize - id3_length) * 8) / ((double)totalFrames / (double)_decoder_info.hz) / 1000.0; } else { - _decoder_buffer_filled = [source read:_decoder_buffer amount:INPUT_BUFFER_SIZE]; - inputEOF = _decoder_buffer_filled < INPUT_BUFFER_SIZE; + _decoder_buffer_filled = [source read:_decoder_buffer amount:MINIMP3_BUF_SIZE]; + inputEOF = _decoder_buffer_filled < MINIMP3_BUF_SIZE; mp3dec_init(&_decoder_ex.mp3d); - int samples = mp3dec_decode_frame(&_decoder_ex.mp3d, _decoder_buffer, (int)_decoder_buffer_filled, &_decoder_buffer_output[0], &_decoder_info); - if(!samples) + int error = mp3dec_detect_buf(_decoder_buffer, _decoder_buffer_filled); + if(error) return NO; - size_t bytes_read = _decoder_info.frame_bytes; - if(bytes_read >= _decoder_buffer_filled) { - _decoder_buffer_filled = 0; - } else { - _decoder_buffer_filled -= bytes_read; - memmove(&_decoder_buffer[0], &_decoder_buffer[bytes_read], _decoder_buffer_filled); + + for(;;) { + error = mp3dec_decode_frame(&_decoder_ex.mp3d, _decoder_buffer, (int)_decoder_buffer_filled, &_decoder_buffer_output[0], &_decoder_info); + if(_decoder_info.frame_bytes > _decoder_buffer_filled) { + break; + } + _decoder_buffer_filled -= _decoder_info.frame_bytes; + memmove(&_decoder_buffer[0], &_decoder_buffer[_decoder_info.frame_bytes], _decoder_buffer_filled); + if(error) { + break; + } } - samples_filled = samples; + if(!error) { + return NO; + } + samples_filled = error; bitrate = _decoder_info.bitrate_kbps; } @@ -243,7 +251,7 @@ static int mp3_seek_callback(uint64_t position, void *user_data) { inputEOF = YES; } } else { - size_t bytesRemain = INPUT_BUFFER_SIZE - _decoder_buffer_filled; + size_t bytesRemain = MINIMP3_BUF_SIZE - _decoder_buffer_filled; ssize_t bytesRead = [_source read:&_decoder_buffer[_decoder_buffer_filled] amount:bytesRemain]; if(bytesRead < 0 || bytesRead < bytesRemain) { inputEOF = YES; @@ -254,8 +262,12 @@ static int mp3_seek_callback(uint64_t position, void *user_data) { int samples = mp3dec_decode_frame(&_decoder_ex.mp3d, &_decoder_buffer[0], (int)_decoder_buffer_filled, &_decoder_buffer_output[0], &_decoder_info); if(samples > 0) { samples_filled = samples; - } else { + } + if(_decoder_info.frame_bytes > _decoder_buffer_filled) { inputEOF = YES; + } else { + _decoder_buffer_filled -= _decoder_info.frame_bytes; + memmove(&_decoder_buffer[0], &_decoder_buffer[_decoder_info.frame_bytes], _decoder_buffer_filled); } }