mp3dec: Handle decode errors gracefully.
authorAndre Noll <maan@systemlinux.org>
Sun, 7 Aug 2011 10:33:03 +0000 (12:33 +0200)
committerAndre Noll <maan@systemlinux.org>
Tue, 9 Aug 2011 21:11:48 +0000 (23:11 +0200)
Currently decoding damaged mp3 files leads to very audible artefacts
even if only a single frame is corrupt. This patch instructs the mp3
decoder to synchronize the stream on decode errors and to continue the
decode process. Only on fatal errors the input buffer is discarded.

mp3dec_filter.c

index d262b25..6982f26 100644 (file)
@@ -80,7 +80,7 @@ static void mp3dec_post_select(__a_unused struct sched *s, struct task *t)
        int i, ret;
        struct private_mp3dec_data *pmd = fn->private_data;
        struct btr_node *btrn = fn->btrn;
-       size_t loaded, used, len, iqs;
+       size_t loaded = 0, used, len, iqs;
        char *inbuffer, *outbuffer;
 
 next_buffer:
@@ -112,25 +112,27 @@ next_frame:
                                goto err;
                        }
                        fn->min_iqs += 100;
+               }
+               if (loaded == 0)
                        goto next_buffer;
-               } else if (pmd->stream.error != MAD_ERROR_LOSTSYNC)
-                       PARA_DEBUG_LOG("header decode: %s\n",
-                               mad_stream_errorstr(&pmd->stream));
-               goto next_buffer;
+               return;
        }
        fn->min_iqs = 0;
        pmd->sample_rate = pmd->frame.header.samplerate;
        pmd->channels = MAD_NCHANNELS(&pmd->frame.header);
+decode:
        ret = mad_frame_decode(&pmd->frame, &pmd->stream);
        if (ret != 0) {
-               PARA_INFO_LOG("frame decode: %s\n", mad_stream_errorstr(&pmd->stream));
-               used = used_mad_buffer_bytes(&pmd->stream, len);
                ret = handle_decode_error(pmd);
-               btr_consume(btrn, used);
                if (ret < 0)
                        goto err;
-               if (ret == 0)
-                       goto next_buffer;
+               mad_stream_sync(&pmd->stream);
+               if (pmd->stream.error == MAD_ERROR_BUFLEN)
+                       return;
+               if (pmd->stream.error != MAD_ERROR_BADDATAPTR)
+                       goto decode;
+               used = used_mad_buffer_bytes(&pmd->stream, len);
+               btr_consume(btrn, used);
                return;
        }
        mad_synth_frame(&pmd->synth, &pmd->frame);