ref: 7718c4644edeef78cdbc6fb93397ea3f9f4c736e
parent: b735b80b743d5bb85059e8fb87efd0375bc5bc65
author: Janne Grunau <janne-vlc@jannau.net>
date: Tue Dec 4 18:45:16 EST 2018
frame-mt: drain delayed pictures fully before returning -EAGAIN Fixes #211, dav1d_get_picture starts draining delayed pictures when it gets called multiple times without dav1d_send_data call in between.
--- a/src/internal.h
+++ b/src/internal.h
@@ -119,6 +119,7 @@
int operating_point;
unsigned operating_point_idc;
int all_layers;
+ int drain;
};
struct Dav1dFrameContext {
--- a/src/lib.c
+++ b/src/lib.c
@@ -222,6 +222,8 @@
validate_input_or_ret(in != NULL, -EINVAL);
validate_input_or_ret(in->data == NULL || in->sz, -EINVAL);
+ c->drain = 0;
+
if (c->in.data)
return -EAGAIN;
dav1d_data_move_ref(&c->in, in);
@@ -275,6 +277,35 @@
return 0;
}
+static int drain_picture(Dav1dContext *const c, Dav1dPicture *const out) {
+ unsigned drain_count = 0;
+ do {
+ const unsigned next = c->frame_thread.next;
+ Dav1dFrameContext *const f = &c->fc[next];
+ pthread_mutex_lock(&f->frame_thread.td.lock);
+ while (f->n_tile_data > 0)
+ pthread_cond_wait(&f->frame_thread.td.cond,
+ &f->frame_thread.td.lock);
+ pthread_mutex_unlock(&f->frame_thread.td.lock);
+ Dav1dThreadPicture *const out_delayed =
+ &c->frame_thread.out_delayed[next];
+ if (++c->frame_thread.next == c->n_fc)
+ c->frame_thread.next = 0;
+ if (out_delayed->p.data[0]) {
+ const unsigned progress =
+ atomic_load_explicit(&out_delayed->progress[1],
+ memory_order_relaxed);
+ if (out_delayed->visible && progress != FRAME_ERROR)
+ dav1d_picture_ref(&c->out, &out_delayed->p);
+ dav1d_thread_picture_unref(out_delayed);
+ if (c->out.data[0])
+ return output_image(c, out, &c->out);
+ }
+ } while (++drain_count < c->n_fc);
+
+ return -EAGAIN;
+}
+
int dav1d_get_picture(Dav1dContext *const c, Dav1dPicture *const out)
{
int res;
@@ -282,36 +313,13 @@
validate_input_or_ret(c != NULL, -EINVAL);
validate_input_or_ret(out != NULL, -EINVAL);
+ const int drain = c->drain;
+ c->drain = 1;
+
Dav1dData *const in = &c->in;
if (!in->data) {
if (c->n_fc == 1) return -EAGAIN;
-
- // flush
- unsigned flush_count = 0;
- do {
- const unsigned next = c->frame_thread.next;
- Dav1dFrameContext *const f = &c->fc[next];
-
- pthread_mutex_lock(&f->frame_thread.td.lock);
- while (f->n_tile_data > 0)
- pthread_cond_wait(&f->frame_thread.td.cond,
- &f->frame_thread.td.lock);
- pthread_mutex_unlock(&f->frame_thread.td.lock);
- Dav1dThreadPicture *const out_delayed =
- &c->frame_thread.out_delayed[next];
- if (++c->frame_thread.next == c->n_fc)
- c->frame_thread.next = 0;
- if (out_delayed->p.data[0]) {
- const unsigned progress = atomic_load_explicit(&out_delayed->progress[1],
- memory_order_relaxed);
- if (out_delayed->visible && progress != FRAME_ERROR)
- dav1d_picture_ref(&c->out, &out_delayed->p);
- dav1d_thread_picture_unref(out_delayed);
- if (c->out.data[0])
- return output_image(c, out, &c->out);
- }
- } while (++flush_count < c->n_fc);
- return -EAGAIN;
+ return drain_picture(c, out);
}
while (in->sz > 0) {
@@ -333,11 +341,15 @@
if (c->out.data[0])
return output_image(c, out, &c->out);
+ if (c->n_fc > 1 && drain)
+ return drain_picture(c, out);
+
return -EAGAIN;
}
void dav1d_flush(Dav1dContext *const c) {
dav1d_data_unref(&c->in);
+ c->drain = 0;
if (c->n_fc == 1) return;