shithub: libvpx

Download patch

ref: f362bf981c4648b426aa2a0735d4fb6bda4136c0
parent: af355dacd568dfe5c109ae2d6d22104f94cdcf7f
author: Marco Paniconi <marpan@google.com>
date: Mon May 7 18:54:48 EDT 2018

vp9-svc: Fix when whole superframe is dropped.

When the whole superframe is dropped (due to rate control),
don't increment the temporal layer counter.

This is a temporary fix to prevent an issue where temporal
prediction pattern is possibly broken.

Updated svc_datarate tests to handle this case.

Change-Id: Icac44fdc9d0f08a957776c937584db4b2c7927c7

--- a/test/encode_test_driver.cc
+++ b/test/encode_test_driver.cc
@@ -201,7 +201,7 @@
       PreEncodeFrameHook(video, encoder.get());
       encoder->EncodeFrame(video, frame_flags_);
 
-      PostEncodeFrameHook();
+      PostEncodeFrameHook(encoder.get());
 
       CxDataIterator iter = encoder->GetCxData();
 
--- a/test/encode_test_driver.h
+++ b/test/encode_test_driver.h
@@ -226,7 +226,7 @@
   virtual void PreEncodeFrameHook(VideoSource * /*video*/,
                                   Encoder * /*encoder*/) {}
 
-  virtual void PostEncodeFrameHook() {}
+  virtual void PostEncodeFrameHook(Encoder * /*encoder*/) {}
 
   // Hook to be called on every compressed data packet.
   virtual void FramePktHook(const vpx_codec_cx_pkt_t * /*pkt*/) {}
--- a/test/svc_datarate_test.cc
+++ b/test/svc_datarate_test.cc
@@ -297,7 +297,10 @@
     duration_ = 0;
   }
 
-  virtual void PostEncodeFrameHook() {
+  virtual void PostEncodeFrameHook(::libvpx_test::Encoder *encoder) {
+    vpx_svc_layer_id_t layer_id;
+    encoder->Control(VP9E_GET_SVC_LAYER_ID, &layer_id);
+    temporal_layer_id_ = layer_id.temporal_layer_id;
     for (int sl = 0; sl < number_spatial_layers_; ++sl) {
       for (int tl = temporal_layer_id_; tl < number_temporal_layers_; ++tl) {
         const int layer = sl * number_temporal_layers_ + tl;
@@ -848,7 +851,7 @@
                       layer_target_avg_bandwidth_, bits_in_buffer_model_);
   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
   CheckLayerRateTargeting(&cfg_, number_spatial_layers_,
-                          number_temporal_layers_, file_datarate_, 0.75, 1.2);
+                          number_temporal_layers_, file_datarate_, 0.75, 1.45);
 #if CONFIG_VP9_DECODER
   // The non-reference frames are expected to be mismatched frames as the
   // encoder will avoid loopfilter on these frames.
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -4560,8 +4560,18 @@
       if (cpi->use_svc) {
         cpi->svc.last_layer_dropped[cpi->svc.spatial_layer_id] = 1;
         cpi->svc.drop_spatial_layer[cpi->svc.spatial_layer_id] = 1;
-        vp9_inc_frame_in_layer(cpi);
         cpi->svc.skip_enhancement_layer = 1;
+        if (cpi->svc.framedrop_mode != CONSTRAINED_LAYER_DROP ||
+            cpi->svc.drop_spatial_layer[0] == 0) {
+          // For the case of CONSTRAINED_LAYER_DROP where the base is dropped
+          // (drop_spatial_layer[0] == 1), which means full superframe dropped,
+          // we don't increment the svc frame counters. In particular temporal
+          // layer counter (which is incremented in vp9_inc_frame_in_layer())
+          // won't be incremented, so on a dropped frame we try the same
+          // temporal_layer_id on next incoming frame. This is to avoid an
+          // issue with temporal alignement with full superframe dropping.
+          vp9_inc_frame_in_layer(cpi);
+        }
         if (cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 1) {
           int i;
           int all_layers_drop = 1;