Merge branch 't/decoder_fixes'
authorAndre Noll <maan@systemlinux.org>
Tue, 26 Jun 2012 20:07:55 +0000 (22:07 +0200)
committerAndre Noll <maan@systemlinux.org>
Tue, 26 Jun 2012 20:11:07 +0000 (22:11 +0200)
97dbfe wmadec: Only decode one superframe at a time.
d6e017 flacdec: Only process a single flac audio frame.
1e1968 flacdec_close(): Be liberal in what you accept.
3f96f9 oggdec: Fix EOF handling on repositioning.
c7e2f7 oggdec: Realloc buffer to save memory.
634e75 oggdec: Do not decode more than necessary.

These changes are well tested and there are no known problems.

NEWS
flacdec_filter.c
oggdec_filter.c
wmadec_filter.c

diff --git a/NEWS b/NEWS
index fa8e024..df54a64 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,7 @@
          support this feature, data is sent as a multiplexed stream.
        - The --no_default_filters option of para_filter has been
          removed.
+       - Several fixes and latency improvements to various decoders.
        - Documentation improvements.
 
 ------------------------------------------
index 40246f2..e8baa6b 100644 (file)
@@ -234,27 +234,25 @@ static void flacdec_post_select(__a_unused struct sched *s, struct task *t)
                ret = flacdec_init(fn);
                goto out;
        }
-       pfd->unconsumed = 0;
-       for (;;) {
-               if (output_queue_full(btrn)) {
-                       pfd->have_more = true;
-                       break;
-               }
-               pfd->have_more = false;
-               FLAC__StreamDecoderState state;
-               FLAC__stream_decoder_process_single(pfd->decoder);
-               state = FLAC__stream_decoder_get_state(pfd->decoder);
-               //PARA_CRIT_LOG("state: %s\n", FLAC__stream_decoder_get_resolved_state_string(pfd->decoder));
-               ret = -E_FLACDEC_EOF;
-               if (state == FLAC__STREAM_DECODER_END_OF_STREAM)
-                       goto out;
-               if (state == FLAC__STREAM_DECODER_ABORTED) {
-                       FLAC__stream_decoder_flush(pfd->decoder);
-                       fn->min_iqs = pfd->unconsumed + 1;
-                       break;
-               }
-               fn->min_iqs = 0;
+       if (output_queue_full(btrn)) {
+               pfd->have_more = true;
+               ret = 1;
+               goto out;
        }
+       pfd->have_more = false;
+       FLAC__StreamDecoderState state;
+       FLAC__stream_decoder_process_single(pfd->decoder);
+       state = FLAC__stream_decoder_get_state(pfd->decoder);
+       ret = -E_FLACDEC_EOF;
+       if (state == FLAC__STREAM_DECODER_END_OF_STREAM)
+               goto out;
+       if (state == FLAC__STREAM_DECODER_ABORTED) {
+               FLAC__stream_decoder_flush(pfd->decoder);
+               fn->min_iqs = pfd->unconsumed + 1;
+               ret = 1;
+               goto out;
+       }
+       fn->min_iqs = 0;
        ret = 1;
 out:
        t->error = ret;
@@ -264,10 +262,17 @@ out:
 
 static void flacdec_close(struct filter_node *fn)
 {
-       struct private_flacdec_data *pfd = fn->private_data;
+       struct private_flacdec_data *pfd;
 
-       FLAC__stream_decoder_finish(pfd->decoder);
-       FLAC__stream_decoder_delete(pfd->decoder);
+       if (!fn)
+               return;
+       pfd = fn->private_data;
+       if (!pfd)
+               return;
+       if (pfd->decoder) {
+               FLAC__stream_decoder_finish(pfd->decoder);
+               FLAC__stream_decoder_delete(pfd->decoder);
+       }
        free(pfd);
        fn->private_data = NULL;
 }
index 79716a3..9498313 100644 (file)
@@ -208,10 +208,16 @@ static void ogg_post_select(__a_unused struct sched *s, struct task *t)
        char *buf;
 
        ret = btr_node_status(btrn, fn->min_iqs, BTR_NT_INTERNAL);
-       if (ret < 0 && ret != -E_BTR_EOF) /* fatal error */
-               goto out;
-       if (ret <= 0 && !pod->have_more) /* nothing to do */
+       if (ret < 0) {
+               if (ret != -E_BTR_EOF) /* fatal error */
+                       goto out;
+               if (fn->min_iqs == 0 && !pod->have_more) /* EOF */
+                       goto out;
+               /* last ov_read() returned OV_HOLE */
+       } else if (ret == 0 && !pod->have_more) /* nothing to do */
                goto out;
+       if (btr_get_output_queue_size(btrn) > OGGDEC_MAX_OUTPUT_SIZE)
+               return;
        if (!pod->vf) {
                if (ret <= 0)
                        goto out;
@@ -239,9 +245,11 @@ static void ogg_post_select(__a_unused struct sched *s, struct task *t)
                have = 0;
        }
        pod->have_more = (ret > 0);
-       if (have > 0)
+       if (have > 0) {
+               if (have < OGGDEC_OUTPUT_CHUNK_SIZE)
+                       buf = para_realloc(buf, have);
                btr_add_output(buf, have, btrn);
-       else
+       else
                free(buf);
        if (ret == OV_HOLE) /* avoid buffer underruns */
                fn->min_iqs = 9000;
index be72610..e58754f 100644 (file)
@@ -1214,11 +1214,11 @@ static int wmadec_execute(struct btr_node *btrn, const char *cmd, char **result)
 static void wmadec_post_select(__a_unused struct sched *s, struct task *t)
 {
        struct filter_node *fn = container_of(t, struct filter_node, task);
-       int ret, converted;
+       int ret, converted, out_size;
        struct private_wmadec_data *pwd = fn->private_data;
        struct btr_node *btrn = fn->btrn;
        size_t len;
-       char *in;
+       char *in, *out;
 
 next_buffer:
        converted = 0;
@@ -1247,22 +1247,20 @@ next_buffer:
                goto success;
        }
        fn->min_iqs = WMA_FRAME_SKIP + pwd->ahi.block_align;
-       for (;;) {
-               char *out;
-               int out_size = WMA_OUTPUT_BUFFER_SIZE;
-               if (converted + fn->min_iqs > len)
-                       break;
-               out = para_malloc(WMA_OUTPUT_BUFFER_SIZE);
-               ret = wma_decode_superframe(pwd, out,
-                       &out_size, (uint8_t *)in + converted + WMA_FRAME_SKIP,
-                       len - WMA_FRAME_SKIP);
-               if (ret < 0) {
-                       free(out);
-                       goto err;
-               }
-               btr_add_output(out, out_size, btrn);
-               converted += ret + WMA_FRAME_SKIP;
+       if (fn->min_iqs > len)
+               goto success;
+       out_size = WMA_OUTPUT_BUFFER_SIZE;
+       out = para_malloc(out_size);
+       ret = wma_decode_superframe(pwd, out, &out_size,
+               (uint8_t *)in + WMA_FRAME_SKIP, len - WMA_FRAME_SKIP);
+       if (ret < 0) {
+               free(out);
+               goto err;
        }
+       out = para_realloc(out, out_size);
+       if (out_size > 0)
+               btr_add_output(out, out_size, btrn);
+       converted += ret + WMA_FRAME_SKIP;
 success:
        btr_consume(btrn, converted);
        return;