Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/videolan/dav1d.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src/lib.c
diff options
context:
space:
mode:
authorRonald S. Bultje <rsbultje@gmail.com>2022-02-03 23:29:06 +0300
committerJames Almer <jamrial@gmail.com>2022-02-04 01:37:56 +0300
commitf9844476372719fd1acc2a6dec51ca65fa74bbcf (patch)
treec507bfd5f66dd77049dde404ef961e938c4c9d17 /src/lib.c
parent0dc1d3539ceae7d5c2efc3163f7a14b83eea26fc (diff)
Output only latest spatial layer if --alllayers 0
Right now, --alllayers 0 will only output operating points that exactly match the largest one in the sequence header. However, in certain cases, the largest one might not be available, and a smaller one should be returned to the user instead. This matches update_frame_buffers() in aomdec to output only the latest frame if --alllayers 0 is specified. Signed-off-by: James Almer <jamrial@gmail.com>
Diffstat (limited to 'src/lib.c')
-rw-r--r--src/lib.c55
1 files changed, 35 insertions, 20 deletions
diff --git a/src/lib.c b/src/lib.c
index 41aaf61..3a255cd 100644
--- a/src/lib.c
+++ b/src/lib.c
@@ -313,34 +313,46 @@ static int has_grain(const Dav1dPicture *const pic)
fgdata->num_uv_points[1];
}
-static int output_image(Dav1dContext *const c, Dav1dPicture *const out,
- Dav1dThreadPicture *const in)
+static int output_image(Dav1dContext *const c, Dav1dPicture *const out)
{
+ int res = 0;
+
+ Dav1dThreadPicture *const in = c->all_layers ? &c->out : &c->cache;
if (!c->apply_grain || !has_grain(&in->p)) {
dav1d_picture_move_ref(out, &in->p);
dav1d_thread_picture_unref(in);
- return 0;
+ goto end;
}
- int res = dav1d_apply_grain(c, out, &in->p);
+ res = dav1d_apply_grain(c, out, &in->p);
dav1d_thread_picture_unref(in);
+end:
+ if (!c->all_layers && c->out.p.data[0]) {
+ dav1d_thread_picture_move_ref(in, &c->out);
+ }
return res;
}
-static int output_picture_ready(Dav1dContext *const c) {
-
- if (!c->out.p.data[0]) return 0;
-
- // skip lower spatial layers
- if (c->operating_point_idc && !c->all_layers) {
- const int max_spatial_id = ulog2(c->operating_point_idc >> 8);
- if (max_spatial_id > c->out.p.frame_hdr->spatial_id) {
- dav1d_thread_picture_unref(&c->out);
+static int output_picture_ready(Dav1dContext *const c, const int drain) {
+ if (!c->all_layers) {
+ if (c->out.p.data[0] && c->cache.p.data[0]) {
+ const unsigned spatial_mask = c->operating_point_idc >> 8;
+ const int max_spatial_id = spatial_mask ? ulog2(spatial_mask) : 0;
+ if (max_spatial_id == c->cache.p.frame_hdr->spatial_id ||
+ c->out.flags & PICTURE_FLAG_NEW_TEMPORAL_UNIT)
+ return 1;
+ dav1d_thread_picture_unref(&c->cache);
+ dav1d_thread_picture_move_ref(&c->cache, &c->out);
+ return 0;
+ } else if (c->cache.p.data[0] && drain) {
+ return 1;
+ } else if (c->out.p.data[0]) {
+ dav1d_thread_picture_move_ref(&c->cache, &c->out);
return 0;
}
}
- return 1;
+ return !!c->out.p.data[0];
}
static int drain_picture(Dav1dContext *const c, Dav1dPicture *const out) {
@@ -376,11 +388,14 @@ static int drain_picture(Dav1dContext *const c, Dav1dPicture *const out) {
c->event_flags |= dav1d_picture_get_event_flags(out_delayed);
}
dav1d_thread_picture_unref(out_delayed);
- if (output_picture_ready(c))
- return output_image(c, out, &c->out);
+ if (output_picture_ready(c, 0))
+ return output_image(c, out);
}
} while (++drain_count < c->n_fc);
+ if (output_picture_ready(c, 1))
+ return output_image(c, out);
+
return DAV1D_ERR(EAGAIN);
}
@@ -389,7 +404,7 @@ static int gen_picture(Dav1dContext *const c)
int res;
Dav1dData *const in = &c->in;
- if (output_picture_ready(c))
+ if (output_picture_ready(c, 0))
return 0;
while (in->sz > 0) {
@@ -402,7 +417,7 @@ static int gen_picture(Dav1dContext *const c)
in->data += res;
if (!in->sz) dav1d_data_unref_internal(in);
}
- if (output_picture_ready(c))
+ if (output_picture_ready(c, 0))
break;
if (res < 0)
return res;
@@ -442,8 +457,8 @@ int dav1d_get_picture(Dav1dContext *const c, Dav1dPicture *const out)
if (res < 0)
return res;
- if (output_picture_ready(c))
- return output_image(c, out, &c->out);
+ if (output_picture_ready(c, drain && c->n_fc == 1))
+ return output_image(c, out);
if (c->n_fc > 1 && drain)
return drain_picture(c, out);