diff options
author | Lars-Dominik Braun <lars@6xq.net> | 2012-10-28 18:24:50 +0100 |
---|---|---|
committer | Lars-Dominik Braun <lars@6xq.net> | 2012-10-28 18:24:50 +0100 |
commit | dd6c620b53272e2eb4b091a835cd250309f04cad (patch) | |
tree | 26782b0908479ca6a12b8514d5928813ece30e56 | |
parent | 962dee5cdd3b468318916d9c8862bc4c3653c402 (diff) | |
download | pianobar-windows-dd6c620b53272e2eb4b091a835cd250309f04cad.tar.gz pianobar-windows-dd6c620b53272e2eb4b091a835cd250309f04cad.tar.bz2 pianobar-windows-dd6c620b53272e2eb4b091a835cd250309f04cad.zip |
player: Recover from AAC decoding error
Decoding errors are usually not fatal, so we can recover by skipping the
broken frame. This also fixes invalid memory reads caused by
sampleSizeCurr >= sampleSizeN. See issue #304.
-rw-r--r-- | src/player.c | 32 |
1 files changed, 23 insertions, 9 deletions
diff --git a/src/player.c b/src/player.c index 0e249dc..92524c7 100644 --- a/src/player.c +++ b/src/player.c @@ -28,6 +28,7 @@ THE SOFTWARE. #include <math.h> #include <stdint.h> #include <limits.h> +#include <assert.h> #include <arpa/inet.h> #include "player.h" @@ -135,17 +136,31 @@ static WaitressCbReturn_t BarPlayerAACCb (void *ptr, size_t size, NeAACDecFrameInfo frameInfo; size_t i; - while ((player->bufferFilled - player->bufferRead) > - player->sampleSize[player->sampleSizeCurr]) { + while (player->sampleSizeCurr < player->sampleSizeN && + (player->bufferFilled - player->bufferRead) >= + player->sampleSize[player->sampleSizeCurr]) { + /* going through this loop can take up to a few seconds => + * allow earlier thread abort */ + QUIT_PAUSE_CHECK; + /* decode frame */ aacDecoded = NeAACDecDecode(player->aacHandle, &frameInfo, - player->buffer + player->bufferRead, + &player->buffer[player->bufferRead], player->sampleSize[player->sampleSizeCurr]); + player->bufferRead += player->sampleSize[player->sampleSizeCurr]; + ++player->sampleSizeCurr; + if (frameInfo.error != 0) { + /* skip this frame, songPlayed will be slightly off if this + * happens */ BarUiMsg (player->settings, MSG_ERR, "Decoding error: %s\n", NeAACDecGetErrorMessage (frameInfo.error)); - break; + continue; } + /* assuming data in stsz atom is correct */ + assert (frameInfo.bytesconsumed == + player->sampleSize[player->sampleSizeCurr-1]); + for (i = 0; i < frameInfo.samples; i++) { aacDecoded[i] = applyReplayGain (aacDecoded[i], player->scale); } @@ -157,11 +172,10 @@ static WaitressCbReturn_t BarPlayerAACCb (void *ptr, size_t size, (unsigned long long int) BAR_PLAYER_MS_TO_S_FACTOR / (unsigned long long int) player->samplerate / (unsigned long long int) player->channels; - player->bufferRead += frameInfo.bytesconsumed; - player->sampleSizeCurr++; - /* going through this loop can take up to a few seconds => - * allow earlier thread abort */ - QUIT_PAUSE_CHECK; + } + if (player->sampleSizeCurr >= player->sampleSizeN) { + /* no more frames, drop data */ + player->bufferRead = player->bufferFilled; } } else { if (player->mode == PLAYER_INITIALIZED) { |