From: Andre Noll Date: Sun, 29 May 2011 10:27:43 +0000 (+0200) Subject: oggdec: Take internal state into account. X-Git-Tag: v0.4.8~3^2 X-Git-Url: http://git.tue.mpg.de/?a=commitdiff_plain;h=4e5c01fe757de01edfc6aee72697d6765ae0e1a9;p=paraslash.git oggdec: Take internal state into account. It is incorrect to look only at the node status of the oggdec buffer tree node and do nothing if the status is zero. In case the previous call to ogg_post_select() returned early because it hit the maximal output buffer size limit, the node status is zero if there is no more input available, but ov_read() will nevertheless return data which should be fed to the children of the decoder node as soon as possible. Fix this by remembering whether we hit the limit. --- diff --git a/oggdec_filter.c b/oggdec_filter.c index 0fa56f11..32ffdef9 100644 --- a/oggdec_filter.c +++ b/oggdec_filter.c @@ -36,6 +36,8 @@ struct private_oggdec_data { unsigned int channels; /** Current sample rate in Hz. */ unsigned int sample_rate; + /** Whether everything was decoded during the previous iteration. */ + bool have_more; }; static size_t cb_read(void *buf, size_t size, size_t nmemb, void *datasource) @@ -177,22 +179,26 @@ out: return ret; } +#define OGGDEC_MAX_OUTPUT_SIZE (96 * 1024) +#define OGGDEC_OUTPUT_CHUNK_SIZE (32 * 1024) + static void ogg_pre_select(struct sched *s, struct task *t) { struct filter_node *fn = container_of(t, struct filter_node, task); + struct private_oggdec_data *pod = fn->private_data; + struct btr_node *btrn = fn->btrn; int ret; - t->error = 0; - ret = btr_node_status(fn->btrn, fn->min_iqs, BTR_NT_INTERNAL); + ret = btr_node_status(btrn, fn->min_iqs, BTR_NT_INTERNAL); if (ret != 0) - sched_min_delay(s); - else - sched_request_timeout_ms(100, s); + return sched_min_delay(s); + if (!pod->have_more) + return; + if (btr_get_output_queue_size(btrn) > OGGDEC_MAX_OUTPUT_SIZE) + return; + sched_min_delay(s); } -#define OGGDEC_MAX_OUTPUT_SIZE (128 * 1024) -#define OGGDEC_OUTPUT_CHUNK_SIZE (32 * 1024) - static void ogg_post_select(__a_unused struct sched *s, struct task *t) { struct filter_node *fn = container_of(t, struct filter_node, task); @@ -202,7 +208,9 @@ 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) + if (ret < 0 && ret != -E_BTR_EOF) /* fatal error */ + goto out; + if (ret <= 0 && !pod->have_more) /* nothing to do */ goto out; if (!pod->vf) { if (ret <= 0) @@ -230,6 +238,7 @@ static void ogg_post_select(__a_unused struct sched *s, struct task *t) buf = para_malloc(OGGDEC_OUTPUT_CHUNK_SIZE); have = 0; } + pod->have_more = (ret > 0); if (have > 0) btr_add_output(buf, have, btrn); else