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.
unsigned int channels;
/** Current sample rate in Hz. */
unsigned int sample_rate;
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)
};
static size_t cb_read(void *buf, size_t size, size_t nmemb, void *datasource)
+#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);
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;
- 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);
- 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);
static void ogg_post_select(__a_unused struct sched *s, struct task *t)
{
struct filter_node *fn = container_of(t, struct filter_node, task);
char *buf;
ret = btr_node_status(btrn, fn->min_iqs, BTR_NT_INTERNAL);
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 */
goto out;
if (!pod->vf) {
if (ret <= 0)
goto out;
if (!pod->vf) {
if (ret <= 0)
buf = para_malloc(OGGDEC_OUTPUT_CHUNK_SIZE);
have = 0;
}
buf = para_malloc(OGGDEC_OUTPUT_CHUNK_SIZE);
have = 0;
}
+ pod->have_more = (ret > 0);
if (have > 0)
btr_add_output(buf, have, btrn);
else
if (have > 0)
btr_add_output(buf, have, btrn);
else