ref: 066b02c2d8926222ff547679b900573de7415713
parent: 2f7eb1e9544b0b6f4ed3ff244d6869192b76fb4e
author: Boyuan Xiao <boyuan.xiao@argondesign.com>
date: Mon Oct 15 12:37:54 EDT 2018
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.
--- a/src/decode.c
+++ b/src/decode.c
@@ -3090,6 +3090,13 @@
// 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 @@
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;