]> granicus.if.org Git - libvpx/commitdiff
vp9-svc: Update layer_id of frame buffer idx last refreshed.
authorMarco Paniconi <marpan@google.com>
Mon, 14 May 2018 05:17:17 +0000 (22:17 -0700)
committerMarco Paniconi <marpan@google.com>
Mon, 14 May 2018 05:46:48 +0000 (22:46 -0700)
Remove some unused code and add parameter to keep track
of the layer_id of the frame buffer indices last refreshed.

This is useful for verifying constaints on spatial-temporal pattern,
for fixed/non-flexible mode.

Change-Id: I6957bb43157eb31df49dac1b8245facc043e4a49

vp9/encoder/vp9_encoder.c
vp9/encoder/vp9_svc_layercontext.c
vp9/encoder/vp9_svc_layercontext.h

index 0b72b2489a58d630a47b2f53d2460a0b2920fd10..997fae2bae6a29da3f234e739afffbf5ccd9dea0 100644 (file)
@@ -3024,23 +3024,28 @@ void vp9_update_reference_frames(VP9_COMP *cpi) {
     SVC *const svc = &cpi->svc;
     if (cm->frame_type == KEY_FRAME) {
       int i;
-      svc->ref_frame_index[cpi->lst_fb_idx] = svc->current_superframe;
-      svc->ref_frame_index[cpi->gld_fb_idx] = svc->current_superframe;
-      svc->ref_frame_index[cpi->alt_fb_idx] = svc->current_superframe;
       // On key frame update all reference frame slots.
       for (i = 0; i < REF_FRAMES; i++) {
+        svc->fb_idx_spatial_layer_id[i] = svc->spatial_layer_id;
+        svc->fb_idx_temporal_layer_id[i] = svc->temporal_layer_id;
         // LAST/GOLDEN/ALTREF is already updated above.
         if (i != cpi->lst_fb_idx && i != cpi->gld_fb_idx &&
             i != cpi->alt_fb_idx)
           ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[i], cm->new_fb_idx);
       }
     } else {
-      if (cpi->refresh_last_frame)
-        svc->ref_frame_index[cpi->lst_fb_idx] = svc->current_superframe;
-      if (cpi->refresh_golden_frame)
-        svc->ref_frame_index[cpi->gld_fb_idx] = svc->current_superframe;
-      if (cpi->refresh_alt_ref_frame)
-        svc->ref_frame_index[cpi->alt_fb_idx] = svc->current_superframe;
+      if (cpi->refresh_last_frame) {
+        svc->fb_idx_spatial_layer_id[cpi->lst_fb_idx] = svc->spatial_layer_id;
+        svc->fb_idx_temporal_layer_id[cpi->lst_fb_idx] = svc->temporal_layer_id;
+      }
+      if (cpi->refresh_golden_frame) {
+        svc->fb_idx_spatial_layer_id[cpi->gld_fb_idx] = svc->spatial_layer_id;
+        svc->fb_idx_temporal_layer_id[cpi->gld_fb_idx] = svc->temporal_layer_id;
+      }
+      if (cpi->refresh_alt_ref_frame) {
+        svc->fb_idx_spatial_layer_id[cpi->alt_fb_idx] = svc->spatial_layer_id;
+        svc->fb_idx_temporal_layer_id[cpi->alt_fb_idx] = svc->temporal_layer_id;
+      }
     }
     // Copy flags from encoder to SVC struct.
     vp9_copy_flags_ref_update_idx(cpi);
@@ -3729,10 +3734,12 @@ static void encode_without_recode_loop(VP9_COMP *cpi, size_t *size,
 
   suppress_active_map(cpi);
 
-  // For SVC on non-zero spatial layer: check for disabling inter-layer
-  // prediction.
-  if (cpi->use_svc && cpi->svc.spatial_layer_id > 0)
-    vp9_svc_constrain_inter_layer_pred(cpi);
+  if (cpi->use_svc) {
+    // On non-zero spatial layer, check for disabling inter-layer
+    // prediction.
+    if (cpi->svc.spatial_layer_id > 0) vp9_svc_constrain_inter_layer_pred(cpi);
+    vp9_svc_assert_constraints_pattern(cpi);
+  }
 
   // Variance adaptive and in frame q adjustment experiments are mutually
   // exclusive.
index 07d1995a8659993e52944fae7ab2a556be29978e..aec877ac8073efdf27efe5978f23bd80eba907c5 100644 (file)
@@ -41,7 +41,10 @@ void vp9_init_layer_context(VP9_COMP *const cpi) {
   svc->disable_inter_layer_pred = INTER_LAYER_PRED_ON;
   svc->framedrop_mode = CONSTRAINED_LAYER_DROP;
 
-  for (i = 0; i < REF_FRAMES; ++i) svc->ref_frame_index[i] = -1;
+  for (i = 0; i < REF_FRAMES; ++i) {
+    svc->fb_idx_spatial_layer_id[i] = -1;
+    svc->fb_idx_temporal_layer_id[i] = -1;
+  }
   for (sl = 0; sl < oxcf->ss_number_layers; ++sl) {
     svc->last_layer_dropped[sl] = 0;
     svc->drop_spatial_layer[sl] = 0;
@@ -940,3 +943,45 @@ void vp9_svc_constrain_inter_layer_pred(VP9_COMP *const cpi) {
     }
   }
 }
+
+void vp9_svc_assert_constraints_pattern(VP9_COMP *const cpi) {
+  SVC *const svc = &cpi->svc;
+  // For fixed/non-flexible mode, and with CONSTRAINED frame drop
+  // mode (default), the folllowing constraint are expected.
+  if (svc->temporal_layering_mode != VP9E_TEMPORAL_LAYERING_MODE_BYPASS &&
+      svc->framedrop_mode == CONSTRAINED_LAYER_DROP) {
+    if (!cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame) {
+      // On non-key frames: LAST is always temporal reference, GOLDEN is
+      // spatial reference.
+      if (svc->temporal_layer_id == 0)
+        // Base temporal only predicts from base temporal.
+        assert(svc->fb_idx_temporal_layer_id[cpi->lst_fb_idx] == 0);
+      else
+        // Non-base temporal only predicts from lower temporal layer.
+        assert(svc->fb_idx_temporal_layer_id[cpi->lst_fb_idx] <
+               svc->temporal_layer_id);
+      if (svc->spatial_layer_id > 0) {
+        // Non-base spatial only predicts from lower spatial layer with same
+        // temporal_id.
+        assert(svc->fb_idx_spatial_layer_id[cpi->gld_fb_idx] ==
+               svc->spatial_layer_id - 1);
+        assert(svc->fb_idx_temporal_layer_id[cpi->gld_fb_idx] ==
+               svc->temporal_layer_id);
+      }
+    } else if (svc->spatial_layer_id > 0) {
+      // Only 1 reference for frame whose base is key; reference may be LAST
+      // or GOLDEN, so we check both.
+      if (cpi->ref_frame_flags & VP9_LAST_FLAG) {
+        assert(svc->fb_idx_spatial_layer_id[cpi->lst_fb_idx] ==
+               svc->spatial_layer_id - 1);
+        assert(svc->fb_idx_temporal_layer_id[cpi->lst_fb_idx] ==
+               svc->temporal_layer_id);
+      } else if (cpi->ref_frame_flags & VP9_GOLD_FLAG) {
+        assert(svc->fb_idx_spatial_layer_id[cpi->gld_fb_idx] ==
+               svc->spatial_layer_id - 1);
+        assert(svc->fb_idx_temporal_layer_id[cpi->gld_fb_idx] ==
+               svc->temporal_layer_id);
+      }
+    }
+  }
+}
index 6177170493180c370c38959dc1523d508e52beb6..99ec9e97be36a5ef63fb5b66085a7b6aea188af5 100644 (file)
@@ -96,7 +96,6 @@ typedef struct SVC {
   int lst_fb_idx[VPX_MAX_LAYERS];
   int gld_fb_idx[VPX_MAX_LAYERS];
   int alt_fb_idx[VPX_MAX_LAYERS];
-  int ref_frame_index[REF_FRAMES];
   int force_zero_mode_spatial_ref;
   int current_superframe;
   int non_reference_frame;
@@ -142,6 +141,11 @@ typedef struct SVC {
   // Keep track of the frame buffer index updated/refreshed on the base
   // temporal superframe.
   uint8_t fb_idx_upd_tl0[VPX_SS_MAX_LAYERS];
+
+  // Keep track of the spatial and temporal layer id of the frame that last
+  // updated the frame buffer index.
+  uint8_t fb_idx_spatial_layer_id[REF_FRAMES];
+  uint8_t fb_idx_temporal_layer_id[REF_FRAMES];
 } SVC;
 
 struct VP9_COMP;
@@ -201,6 +205,8 @@ void vp9_svc_check_reset_layer_rc_flag(struct VP9_COMP *const cpi);
 
 void vp9_svc_constrain_inter_layer_pred(struct VP9_COMP *const cpi);
 
+void vp9_svc_assert_constraints_pattern(struct VP9_COMP *const cpi);
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif