X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=flacdec_filter.c;h=bbacb3dad87025073b5bf8e99dc1ea8fa6bf5800;hp=9a83c599744b6b632d95a0e42f607ee15e9a3614;hb=99708bef7ad12ccb9399186f6055004d11bcf3db;hpb=d16fe3df649cb48d5ffa26187da3dad4c3066646 diff --git a/flacdec_filter.c b/flacdec_filter.c index 9a83c599..bbacb3da 100644 --- a/flacdec_filter.c +++ b/flacdec_filter.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Andre Noll + * Copyright (C) 2011 Andre Noll * * Licensed under the GPL v2. For licencing details see COPYING. */ @@ -25,7 +25,7 @@ struct private_flacdec_data { * We can not consume directly what was copied by the read callback * because we might need to feed unconsumend bytes to the decoder again * after the read callback ran out of data and returned ABORT. So we - * track how many bytes are unconsumed so far. + * track how many bytes have been fed to libflac but are unconsumed so far. */ size_t unconsumed; }; @@ -63,6 +63,16 @@ static FLAC__StreamDecoderReadStatus read_cb( } if (*bytes > 0) return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; + /** + * Nothing was copied. If the input queue of the btrn is smaller than + * the minimal input queue size, our parent must have been gone, so + * we're not going to get more input. Since our remaining data is not + * sufficient do decode a single frame, we have an EOF condition. + */ + if (btr_get_input_queue_size(btrn) < fn->min_iqs) { + assert(btr_no_parent(btrn)); + return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; + } /* * We are kind of screwed here. Returning CONTINUE with a byte count of * zero leads to an endless loop, so we must return either EOF or @@ -144,7 +154,7 @@ static FLAC__StreamDecoderWriteStatus write_cb( write_int16_host_endian(outbuffer + 4 * k + 2, right); } } - btr_add_output(outbuffer, n * 4, btrn); + btr_add_output(outbuffer, n * channels * 2, btrn); flac_consume(fn); return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; } @@ -200,9 +210,9 @@ static bool output_queue_full(struct btr_node *btrn) return btr_get_output_queue_size(btrn) > FLACDEC_MAX_OUTPUT_SIZE; } -static void flacdec_pre_select(struct sched *s, struct task *t) +static void flacdec_pre_select(struct sched *s, void *context) { - struct filter_node *fn = container_of(t, struct filter_node, task); + struct filter_node *fn = context; struct private_flacdec_data *pfd = fn->private_data; struct btr_node *btrn = fn->btrn; int ret; @@ -216,15 +226,16 @@ static void flacdec_pre_select(struct sched *s, struct task *t) return sched_min_delay(s); } -static void flacdec_post_select(__a_unused struct sched *s, struct task *t) +static int flacdec_post_select(__a_unused struct sched *s, void *context) { - struct filter_node *fn = container_of(t, struct filter_node, task); + struct filter_node *fn = context; struct private_flacdec_data *pfd = fn->private_data; struct btr_node *btrn = fn->btrn; int ret; + FLAC__StreamDecoderState state; if (output_queue_full(btrn)) - return; + return 0; ret = btr_node_status(btrn, fn->min_iqs, BTR_NT_INTERNAL); if (ret < 0 && ret != -E_BTR_EOF) /* fatal error */ goto out; @@ -234,40 +245,46 @@ 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__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); + pfd->unconsumed = 0; /* feed unconsumed bytes again */ + fn->min_iqs = btr_get_input_queue_size(btrn) + 1; + ret = 1; + goto out; + } + pfd->have_more = true; + fn->min_iqs = 0; ret = 1; out: - t->error = ret; if (ret < 0) - btr_remove_node(btrn); + btr_remove_node(&fn->btrn); + return ret; } 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; }