tempv_signaling: Simplify test for whether prev_frame works for mvs
For some background, see this previous change in Gerrit[0]. What's
going on here is that we only want to use a previous frame for motion
vector prediction if the encoded sizes match. When scaling with
superres, this means the size before upscaling.
To check this correctly, we need to check prev_frame's width/height
and compare it with the current frame. Without superres, prev_frame's
width/height is stored in y_crop_width/y_crop_height so we can check
that way. With superres, those numbers are after the scaling, so can't
be compared with cm->width and cm->height.
The previous code worked around this by comparing with cm->last_width
and cm->last_height. That works because these are the width/height for
the last encoded and shown frame and that frame *is* prev_frame if
last_show_frame is true. Since this is the only case when we want to
use prev_frame, they are the numbers we need.
This patch simplifies the logic by storing the width/height in
RefCntBuffer before any scaling and then checking that they match.
The check for whether we can use motion vectors from a previous frame
is factored out into a pair of inline functions in the
header. frame_might_use_prev_frame_mvs() is true if it's possible that
this frame could use motion vectors from a previous frame. This
doesn't use knowledge of what prev_frame is: it just checks we're not
in error resilient mode and aren't a keyframe. When this is true, a
flag is signaled in the bitstream to say whether we actually want to
use motion vectors from the previous frame.
The second function, frame_can_use_prev_frame_mvs, is true if the
current frame / previous frame pair is suitable for sharing motion
vectors. This is a stricter test: the previous frame needs to be
have been shown and not to have been intra_only, and it needs to have
the same width/height as the current frame.
If the re-assignment of prev_frame (just before the calls to
frame_can_use_prev_frame_mvs()) were removed in some way, we could
probably combine the two functions and often save a bit per frame
header.
The other slight tidy-up in the patch is to move re-allocation of the
mvs buffer into onyxc_int.h: the code that did the allocation was
duplicated between the encoder and decoder.
[0] https://aomedia-review.googlesource.com/c/13806
BUG=aomedia:78
Change-Id: If25227fa24222fc05c56529c2ac9ddf1e1c36a84
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index 07e4ea4..4bd7558 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -3132,15 +3132,6 @@
}
#endif // CONFIG_FRAME_SUPERRES
-static void resize_mv_buffer(AV1_COMMON *cm) {
- aom_free(cm->cur_frame->mvs);
- cm->cur_frame->mi_rows = cm->mi_rows;
- cm->cur_frame->mi_cols = cm->mi_cols;
- CHECK_MEM_ERROR(cm, cm->cur_frame->mvs,
- (MV_REF *)aom_calloc(cm->mi_rows * cm->mi_cols,
- sizeof(*cm->cur_frame->mvs)));
-}
-
static void resize_context_buffers(AV1_COMMON *cm, int width, int height) {
#if CONFIG_SIZE_LIMIT
if (width > DECODE_WIDTH_LIMIT || height > DECODE_HEIGHT_LIMIT)
@@ -3167,10 +3158,10 @@
cm->width = width;
cm->height = height;
}
- if (cm->cur_frame->mvs == NULL || cm->mi_rows > cm->cur_frame->mi_rows ||
- cm->mi_cols > cm->cur_frame->mi_cols) {
- resize_mv_buffer(cm);
- }
+
+ ensure_mv_buffer(cm->cur_frame, cm);
+ cm->cur_frame->width = cm->width;
+ cm->cur_frame->height = cm->height;
}
static void setup_frame_size(AV1_COMMON *cm, struct aom_read_bit_buffer *rb) {
@@ -4572,9 +4563,6 @@
#if CONFIG_PALETTE || CONFIG_INTRABC
if (cm->intra_only) cm->allow_screen_content_tools = aom_rb_read_bit(rb);
#endif // CONFIG_PALETTE || CONFIG_INTRABC
-#if CONFIG_TEMPMV_SIGNALING
- if (cm->intra_only || cm->error_resilient_mode) cm->use_prev_frame_mvs = 0;
-#endif
if (cm->error_resilient_mode) {
cm->reset_frame_context = RESET_FRAME_CONTEXT_ALL;
} else {
@@ -4663,9 +4651,10 @@
cm->allow_high_precision_mv = aom_rb_read_bit(rb);
cm->interp_filter = read_frame_interp_filter(rb);
#if CONFIG_TEMPMV_SIGNALING
- if (!cm->error_resilient_mode) {
+ if (frame_might_use_prev_frame_mvs(cm))
cm->use_prev_frame_mvs = aom_rb_read_bit(rb);
- }
+ else
+ cm->use_prev_frame_mvs = 0;
#endif
for (i = 0; i < INTER_REFS_PER_FRAME; ++i) {
RefBuffer *const ref_buf = &cm->frame_refs[i];
@@ -5333,16 +5322,7 @@
#endif // CONFIG_EXT_REFS || CONFIG_TEMPMV_SIGNALING
#if CONFIG_TEMPMV_SIGNALING
- if (cm->use_prev_frame_mvs) {
- assert(!cm->error_resilient_mode && cm->prev_frame);
-#if CONFIG_FRAME_SUPERRES
- assert(cm->width == cm->last_width && cm->height == cm->last_height);
-#else
- assert(cm->width == last_fb_ref_buf->buf->y_crop_width &&
- cm->height == last_fb_ref_buf->buf->y_crop_height);
-#endif // CONFIG_FRAME_SUPERRES
- assert(!cm->prev_frame->intra_only);
- }
+ if (cm->use_prev_frame_mvs) assert(frame_can_use_prev_frame_mvs(cm));
#else
cm->use_prev_frame_mvs = !cm->error_resilient_mode && cm->prev_frame &&
#if CONFIG_FRAME_SUPERRES