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
diff options
context:
space:
mode:
authorBoyuan Xiao <boyuan.xiao@argondesign.com>2018-10-15 18:37:54 +0300
committerRonald S. Bultje <rsbultje@gmail.com>2018-11-14 17:12:05 +0300
commit066b02c2d8926222ff547679b900573de7415713 (patch)
treef61376b1b8f32c0ed29341e0b8c3d64fa4a465a9
parent2f7eb1e9544b0b6f4ed3ff244d6869192b76fb4e (diff)
Segmentation map reference logic
The previous code raised an error if !segmentation.update_map but the reference frame didn't yield any segmentation data. (The first "goto error" that the patch removes happens if the reference frame was the right size but had no segmentation data; the second happens if the reference frame was the wrong size). This doesn't match the logic in the description of load_previous_segment_ids in section 6.8.2 of the spec. This patch allows such streams, allocating and zeroing cur_segmap in this case. It is still an error for a stream to signal a temporal update but not to have valid segmentation data from the ref frame - that's the error case that the patch puts back in.
-rw-r--r--src/decode.c40
1 files changed, 27 insertions, 13 deletions
diff --git a/src/decode.c b/src/decode.c
index ca8ea63..7438998 100644
--- a/src/decode.c
+++ b/src/decode.c
@@ -3090,6 +3090,13 @@ int dav1d_submit_frame(Dav1dContext *const c) {
// segmap
if (f->frame_hdr.segmentation.enabled) {
+
+ // By default, the previous segmentation map is not initialised.
+ f->prev_segmap_ref = NULL;
+ f->prev_segmap = NULL;
+
+ // We might need a previous frame's segmentation map. This
+ // happens if there is either no update or a temporal update.
if (f->frame_hdr.segmentation.temporal || !f->frame_hdr.segmentation.update_map) {
const int pri_ref = f->frame_hdr.primary_ref_frame;
assert(pri_ref != PRIMARY_REF_NONE);
@@ -3097,30 +3104,37 @@ int dav1d_submit_frame(Dav1dContext *const c) {
const int ref_h = ((f->refp[pri_ref].p.p.h + 7) >> 3) << 1;
if (ref_w == f->bw && ref_h == f->bh) {
f->prev_segmap_ref = c->refs[f->frame_hdr.refidx[pri_ref]].segmap;
- if (f->prev_segmap_ref == NULL) {
- res = -EINVAL;
- goto error;
+ if (f->prev_segmap_ref) {
+ dav1d_ref_inc(f->prev_segmap_ref);
+ f->prev_segmap = f->prev_segmap_ref->data;
}
- dav1d_ref_inc(f->prev_segmap_ref);
- f->prev_segmap = f->prev_segmap_ref->data;
- } else {
- f->prev_segmap_ref = NULL;
- f->prev_segmap = NULL;
}
- } else {
- f->prev_segmap_ref = NULL;
- f->prev_segmap = NULL;
+ // It is an error to signal a temporal update if the
+ // previous frame was the wrong size or had no
+ // segmentation data.
+ if (f->frame_hdr.segmentation.temporal && !f->prev_segmap_ref) {
+ res = -EINVAL;
+ goto error;
+ }
}
+
if (f->frame_hdr.segmentation.update_map) {
+ // We're updating an existing map, but need somewhere to
+ // put the new values. Allocate them here (the data
+ // actually gets set elsewhere)
f->cur_segmap_ref = dav1d_ref_create(f->b4_stride * 32 * f->sb128h);
f->cur_segmap = f->cur_segmap_ref->data;
} else if (f->prev_segmap_ref) {
+ // We're not updating an existing map, and we have a valid
+ // reference. Use that.
f->cur_segmap_ref = f->prev_segmap_ref;
dav1d_ref_inc(f->cur_segmap_ref);
f->cur_segmap = f->prev_segmap_ref->data;
} else {
- res = -EINVAL;
- goto error;
+ // We need to make a new map. Allocate one here and zero it out.
+ f->cur_segmap_ref = dav1d_ref_create(f->b4_stride * 32 * f->sb128h);
+ f->cur_segmap = f->cur_segmap_ref->data;
+ memset(f->cur_segmap_ref->data, 0, f->b4_stride * 32 * f->sb128h);
}
} else {
f->cur_segmap = NULL;