]> granicus.if.org Git - libvpx/commitdiff
vp9-svc: Allow second temporal reference for next highest layer.
authorMarco Paniconi <marpan@google.com>
Thu, 7 Jun 2018 17:52:09 +0000 (10:52 -0700)
committerMarco Paniconi <marpan@google.com>
Thu, 7 Jun 2018 19:26:42 +0000 (12:26 -0700)
When inter-layer prediction is disabled on INTER frames, allow
for next highest resolution to have second temporal reference.
Current code allowed for only top/highest spatial layer.

Change-Id: I102137273e3e4d57512a13d95e8ccb9c5b0a7b4b

vp9/encoder/vp9_ratectrl.c
vp9/encoder/vp9_svc_layercontext.c
vp9/encoder/vp9_svc_layercontext.h

index 968e181eee3b12e4c53e68420daf5e0bb0d717c5..e3d1b3713bdeb8e1c2c020e9b4cc44a722c32a92 100644 (file)
@@ -1879,8 +1879,11 @@ void vp9_rc_get_svc_params(VP9_COMP *cpi) {
     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;
       cpi->ext_refresh_alt_ref_frame = 1;
-      cpi->alt_fb_idx = svc->buffer_longterm_ref.idx;
+      if (svc->number_spatial_layers == 3) index = svc->spatial_layer_id - 1;
+      assert(index >= 0);
+      cpi->alt_fb_idx = svc->buffer_longterm_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
index a72083b61fec59b818864f9467a1e102440c365f..c606125b2babf18cd8784151d9539676400f9453 100644 (file)
@@ -62,8 +62,10 @@ void vp9_init_layer_context(VP9_COMP *const cpi) {
   }
   svc->max_consec_drop = INT_MAX;
 
-  svc->buffer_longterm_ref.idx = 7;
-  svc->buffer_longterm_ref.is_used = 0;
+  svc->buffer_longterm_ref[1].idx = 7;
+  svc->buffer_longterm_ref[0].idx = 6;
+  svc->buffer_longterm_ref[1].is_used = 0;
+  svc->buffer_longterm_ref[0].is_used = 0;
 
   if (cpi->oxcf.error_resilient_mode == 0 && cpi->oxcf.pass == 2) {
     if (vpx_realloc_frame_buffer(&cpi->svc.empty_frame.img, SMALL_FRAME_WIDTH,
@@ -714,10 +716,14 @@ int vp9_one_pass_cbr_svc_start_layer(VP9_COMP *const cpi) {
     }
   }
 
-  if (cpi->lst_fb_idx == svc->buffer_longterm_ref.idx ||
-      cpi->gld_fb_idx == svc->buffer_longterm_ref.idx ||
-      cpi->alt_fb_idx == svc->buffer_longterm_ref.idx)
-    svc->buffer_longterm_ref.is_used = 1;
+  if (cpi->lst_fb_idx == svc->buffer_longterm_ref[0].idx ||
+      cpi->gld_fb_idx == svc->buffer_longterm_ref[0].idx ||
+      cpi->alt_fb_idx == svc->buffer_longterm_ref[0].idx)
+    svc->buffer_longterm_ref[0].is_used = 1;
+  if (cpi->lst_fb_idx == svc->buffer_longterm_ref[1].idx ||
+      cpi->gld_fb_idx == svc->buffer_longterm_ref[1].idx ||
+      cpi->alt_fb_idx == svc->buffer_longterm_ref[1].idx)
+    svc->buffer_longterm_ref[1].is_used = 1;
 
   // For the fixed (non-flexible/bypass) SVC mode:
   // If long term temporal reference is enabled at the sequence level
@@ -725,21 +731,25 @@ int vp9_one_pass_cbr_svc_start_layer(VP9_COMP *const cpi) {
   // we can use golden as a second temporal reference
   // (since the spatial/inter-layer reference is disabled).
   // We check that the fb_idx for this reference (buffer_longterm_ref.idx) is
-  // unused (slot 7 should be available for 3-3 layer system).
+  // unused (slot 7 and 6 should be available for 3-3 layer system).
   // For now usage of this second temporal reference will only be used for
-  // highest spatial layer.
+  // highest and next to highest spatial layer (i.e., top and middle layer for
+  // 3 spatial layers).
   svc->use_longterm_ref_current_layer = 0;
-  if (svc->use_longterm_ref && !svc->buffer_longterm_ref.is_used &&
+  if (svc->use_longterm_ref && !svc->buffer_longterm_ref[0].is_used &&
+      !svc->buffer_longterm_ref[1].is_used &&
       svc->temporal_layering_mode != VP9E_TEMPORAL_LAYERING_MODE_BYPASS &&
       svc->disable_inter_layer_pred != INTER_LAYER_PRED_ON &&
       svc->number_spatial_layers <= 3 && svc->number_temporal_layers <= 3 &&
-      svc->spatial_layer_id == svc->number_spatial_layers - 1) {
+      svc->spatial_layer_id >= svc->number_spatial_layers - 2) {
     // Enable the second (long-term) temporal reference at the frame-level.
     svc->use_longterm_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.
-      cpi->gld_fb_idx = svc->buffer_longterm_ref.idx;
+      int index = svc->spatial_layer_id;
+      if (svc->number_spatial_layers == 3) index = svc->spatial_layer_id - 1;
+      cpi->gld_fb_idx = svc->buffer_longterm_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;
index c766c201658924049da1d3999d64c4db6141ddfe..b7a4e2769e2a32b8037adb315ef26c49204cc05d 100644 (file)
@@ -106,7 +106,8 @@ typedef struct SVC {
   int use_longterm_ref;
   // Frame level flag to enable second (long term) temporal reference.
   int use_longterm_ref_current_layer;
-  BUFFER_LONGTERM_REF buffer_longterm_ref;
+  // Allow second reference for at most 2 top highest resolution layers.
+  BUFFER_LONGTERM_REF buffer_longterm_ref[2];
   int current_superframe;
   int non_reference_frame;
   int use_base_mv;