shithub: libvpx

Download patch

ref: 2626b1545e4b5493729850d14185b0ec00a21383
parent: e32f0bf2399bfba4cda1f04f56bc2b05a2d34354
author: Marco Paniconi <marpan@google.com>
date: Thu Jun 7 11:07:57 EDT 2018

vp9-svc: Adjust some logic on gf temporal reference.

For the feature of using second temporal reference (when
inter-layer is off): move the buffer_idx assignement and
refresh flag settings further down to vp9_rc_get_svc_params(),
since is_key_frame is set there for every frame/layer.
Otherwise it was using the setting from the previous frame/layer.

This makes the refresh more consistent for both layers for
2 spatial layers case.

Small/negligible change in metrics.

Change-Id: I88279243bc27898448e8891dba38143d936cf6d5

--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -1873,27 +1873,42 @@
     }
   }
   // If long term termporal feature is enabled, set the period of the update.
-  // The update/refresh of this reference frame  is always on base temporal
+  // The update/refresh of this reference frame is always on base temporal
   // layer frame.
-  if (svc->use_gf_temporal_ref_current_layer && svc->temporal_layer_id == 0) {
-    if (svc->layer_context[svc->temporal_layer_id].is_key_frame) {
-      // On key frame we update the buffer index used for long term reference.
-      // Use the alt_ref since it is not used or updated on key frames.
+  if (svc->use_gf_temporal_ref_current_layer) {
+    // Only use gf long-term prediction on non-key superframes.
+    if (!svc->layer_context[svc->temporal_layer_id].is_key_frame) {
+      // Use golden for this reference, which will be used for prediction.
       int index = svc->spatial_layer_id;
-      cpi->ext_refresh_alt_ref_frame = 1;
       if (svc->number_spatial_layers == 3) index = svc->spatial_layer_id - 1;
       assert(index >= 0);
-      cpi->alt_fb_idx = svc->buffer_gf_temporal_ref[index].idx;
-    } else if (rc->frames_till_gf_update_due == 0) {
-      // Set perdiod of next update. Make it a multiple of 10, as the cyclic
-      // refresh is typically ~10%, and we'd like the update to happen after
-      // a few cylces of the refresh (so it better quality frame). Note the
-      // cyclic refresh for SVC only operates on base temporal layer frames.
-      // Choose 20 as perdiod for now (2 cycles).
-      rc->baseline_gf_interval = 20;
-      rc->frames_till_gf_update_due = rc->baseline_gf_interval;
-      cpi->ext_refresh_golden_frame = 1;
-      rc->gfu_boost = DEFAULT_GF_BOOST;
+      cpi->gld_fb_idx = svc->buffer_gf_temporal_ref[index].idx;
+      // Enable prediction off LAST (last reference) and golden (which will
+      // generally be further behind/long-term reference).
+      cpi->ref_frame_flags = VP9_LAST_FLAG | VP9_GOLD_FLAG;
+    }
+    // Check for update/refresh of reference: only refresh on base temporal
+    // layer.
+    if (svc->temporal_layer_id == 0) {
+      if (svc->layer_context[svc->temporal_layer_id].is_key_frame) {
+        // On key frame we update the buffer index used for long term reference.
+        // Use the alt_ref since it is not used or updated on key frames.
+        int index = svc->spatial_layer_id;
+        if (svc->number_spatial_layers == 3) index = svc->spatial_layer_id - 1;
+        assert(index >= 0);
+        cpi->alt_fb_idx = svc->buffer_gf_temporal_ref[index].idx;
+        cpi->ext_refresh_alt_ref_frame = 1;
+      } else if (rc->frames_till_gf_update_due == 0) {
+        // Set perdiod of next update. Make it a multiple of 10, as the cyclic
+        // refresh is typically ~10%, and we'd like the update to happen after
+        // a few cylces of the refresh (so it better quality frame). Note the
+        // cyclic refresh for SVC only operates on base temporal layer frames.
+        // Choose 20 as perdiod for now (2 cycles).
+        rc->baseline_gf_interval = 20;
+        rc->frames_till_gf_update_due = rc->baseline_gf_interval;
+        cpi->ext_refresh_golden_frame = 1;
+        rc->gfu_boost = DEFAULT_GF_BOOST;
+      }
     }
   } else if (!svc->use_gf_temporal_ref) {
     rc->frames_till_gf_update_due = INT_MAX;
--- a/vp9/encoder/vp9_svc_layercontext.c
+++ b/vp9/encoder/vp9_svc_layercontext.c
@@ -744,16 +744,6 @@
       svc->spatial_layer_id >= svc->number_spatial_layers - 2) {
     // Enable the second (long-term) temporal reference at the frame-level.
     svc->use_gf_temporal_ref_current_layer = 1;
-    // Only used for prediction for on non-key superframes.
-    if (!svc->layer_context[svc->temporal_layer_id].is_key_frame) {
-      // Use golden for this reference which will be used for prediction.
-      int index = svc->spatial_layer_id;
-      if (svc->number_spatial_layers == 3) index = svc->spatial_layer_id - 1;
-      cpi->gld_fb_idx = svc->buffer_gf_temporal_ref[index].idx;
-      // Enable prediction off LAST (last reference) and golden (which will
-      // generally be further behind/long-term reference).
-      cpi->ref_frame_flags = VP9_LAST_FLAG | VP9_GOLD_FLAG;
-    }
   }
 
   // Reset the drop flags for all spatial layers, on the base layer.