vp9-svc: Fix in choose_partitioning for different scaling.
authorMarco Paniconi <marpan@google.com>
Tue, 3 Apr 2018 22:50:19 +0000 (15:50 -0700)
committerMarco Paniconi <marpan@google.com>
Tue, 3 Apr 2018 23:21:44 +0000 (16:21 -0700)
In the SVC encoder LAST ref frame should be the last temporal
reference at the same resolution. This is the case for the default/fixed
patterns, but may not be the case for arbitrary pattern in flexible mode.

Add check that the LAST reference frame has same resolution as the current frame.
If the reference scale for LAST is different from current treat the current
frame as key frame just for the purpose of superblock partitioning.
This avoids potential segfault in vp9_int_pro_motion_estimation() for different
scaled reference.

Change-Id: I4276ff616de46cd4e12c73316f85ae313f170242

vp9/encoder/vp9_encodeframe.c

index bf87a26..1646435 100644 (file)
@@ -1255,13 +1255,17 @@ static int choose_partitioning(VP9_COMP *cpi, const TileInfo *const tile,
   int segment_id;
   int sb_offset = (cm->mi_stride >> 3) * (mi_row >> 3) + (mi_col >> 3);
 
-  // For SVC: check if LAST frame is NULL and if so treat this frame as a key
-  // frame, for the purpose of the superblock partitioning. This can happen
-  // (LAST is NULL) in some cases where enhancement spatial layers are enabled
-  // dyanmically in the stream and the only reference is the spatial
+  // For SVC: check if LAST frame is NULL or if the resolution of LAST is
+  // different than the current frame resolution, and if so, treat this frame
+  // as a key frame, for the purpose of the superblock partitioning.
+  // LAST == NULL can happen in some cases where enhancement spatial layers are
+  // enabled dyanmically in the stream and the only reference is the spatial
   // reference (GOLDEN).
   if (cpi->use_svc) {
-    if (get_ref_frame_buffer(cpi, LAST_FRAME) == NULL) is_key_frame = 1;
+    const YV12_BUFFER_CONFIG *const ref = get_ref_frame_buffer(cpi, LAST_FRAME);
+    if (ref == NULL || ref->y_crop_height != cm->height ||
+        ref->y_crop_width != cm->width)
+      is_key_frame = 1;
   }
 
   set_offsets(cpi, tile, x, mi_row, mi_col, BLOCK_64X64);