Commit d92f3560 authored by David Barker's avatar David Barker

Make SEG_LVL_{SKIP,ZEROMV} blocks be single-ref-only

This patch modifies the interpretation of SEG_LVL_SKIP and
SEG_LVL_ZEROMV slightly, to fix a decoder crash and to save bits
in the intended use cases of these segment flags.

Previously, blocks using either of these segment flags could
signal reference frames just like any other block. But the mode
was implicitly taken to be ZEROMV. This worked fine in VP9, but
crashed for compound blocks in AV1 since those should use
ZERO_ZEROMV instead.

Now we make it so that SEG_LVL_SKIP and SEG_LVL_ZEROMV imply
that the block is single-reference. The reference to use is taken
from the SEG_LVL_REF_FRAME segment feature if that is present,
or is set to LAST_FRAME if not. See the attached bug report
for the reasoning behind this.

As a related change, we also teach the encoder how to deal with
the combination of SEG_LVL_SKIP + SEG_LVL_REF_FRAME.

BUG=aomedia:675

Change-Id: I5e657cbfc1f08395a0301cba701edfb1682502a5
parent 2e6f6a73
......@@ -1518,6 +1518,16 @@ static void read_ref_frames(AV1_COMMON *const cm, MACROBLOCKD *const xd,
ref_frame[0] = (MV_REFERENCE_FRAME)get_segdata(&cm->seg, segment_id,
SEG_LVL_REF_FRAME);
ref_frame[1] = NONE_FRAME;
}
#if CONFIG_SEGMENT_ZEROMV
else if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP) ||
segfeature_active(&cm->seg, segment_id, SEG_LVL_ZEROMV))
#else
else if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP))
#endif
{
ref_frame[0] = LAST_FRAME;
ref_frame[1] = NONE_FRAME;
} else {
const REFERENCE_MODE mode = read_block_reference_mode(cm, xd, r);
// FIXME(rbultje) I'm pretty sure this breaks segmentation ref frame coding
......@@ -2435,10 +2445,11 @@ static void read_inter_block_mode_info(AV1Decoder *const pbi,
#if CONFIG_SEGMENT_ZEROMV
if (segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP) ||
segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_ZEROMV)) {
segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_ZEROMV))
#else
if (segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
if (segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP))
#endif
{
mbmi->mode = ZEROMV;
if (bsize < BLOCK_8X8 && !unify_bsize) {
aom_internal_error(xd->error_info, AOM_CODEC_UNSUP_BITSTREAM,
......
......@@ -1006,6 +1006,16 @@ static void write_ref_frames(const AV1_COMMON *cm, const MACROBLOCKD *xd,
assert(!is_compound);
assert(mbmi->ref_frame[0] ==
get_segdata(&cm->seg, segment_id, SEG_LVL_REF_FRAME));
}
#if CONFIG_SEGMENT_ZEROMV
else if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP) ||
segfeature_active(&cm->seg, segment_id, SEG_LVL_ZEROMV))
#else
else if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP))
#endif
{
assert(!is_compound);
assert(mbmi->ref_frame[0] == LAST_FRAME);
} else {
// does the feature use compound prediction or not
// (if not specified at the frame/segment level)
......
......@@ -12200,7 +12200,10 @@ void av1_rd_pick_inter_mode_sb_seg_skip(const AV1_COMP *cpi,
mbmi->mode = ZEROMV;
mbmi->motion_mode = SIMPLE_TRANSLATION;
mbmi->uv_mode = UV_DC_PRED;
mbmi->ref_frame[0] = LAST_FRAME;
if (segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME))
mbmi->ref_frame[0] = get_segdata(&cm->seg, segment_id, SEG_LVL_REF_FRAME);
else
mbmi->ref_frame[0] = LAST_FRAME;
mbmi->ref_frame[1] = NONE_FRAME;
#if CONFIG_GLOBAL_MOTION
mbmi->mv[0].as_int =
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment