summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLars-Dominik Braun <lars@6xq.net>2012-10-28 18:24:50 +0100
committerLars-Dominik Braun <lars@6xq.net>2012-10-28 18:24:50 +0100
commitdd6c620b53272e2eb4b091a835cd250309f04cad (patch)
tree26782b0908479ca6a12b8514d5928813ece30e56 /src
parent962dee5cdd3b468318916d9c8862bc4c3653c402 (diff)
downloadpianobar-dd6c620b53272e2eb4b091a835cd250309f04cad.tar.gz
pianobar-dd6c620b53272e2eb4b091a835cd250309f04cad.tar.bz2
pianobar-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.
Diffstat (limited to 'src')
-rw-r--r--src/player.c32
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) {