]> granicus.if.org Git - libvpx/commitdiff
vp9: Reset rc flags on some configuration changes.
authorMarco <marpan@google.com>
Fri, 8 Dec 2017 01:24:41 +0000 (17:24 -0800)
committerMarco <marpan@google.com>
Wed, 13 Dec 2017 18:41:38 +0000 (10:41 -0800)
For large dynamic changes in target avg_frame_bandwidth, or
a change in resolution, via the update in change_config()),
reset the under/overshoot flags (rc_1_frame, rc_2_frame)
to prevent constraining the QP for the first few frames
following the change.

For SVC use the spatial stream avg_frame_bandwidth in
reset condition.

For the avg_frame_bandwidth condition, use fairly large
threshold (~50%) for now in reset.

This allows for better/faster QP response if, for example,
application dynamically changes bitrate by large amount.

Change-Id: Ib6e3761732d956949d79c9247e50dba744a535c0

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

index e840155b19dcbb068a962fdadc83162c39f3056b..c9f69ef77cff5504e23feb54dc346aa9316ad784 100644 (file)
@@ -1853,6 +1853,8 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) {
            cm->mi_rows * cm->mi_cols * sizeof(*cpi->consec_zero_mv));
     if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ)
       vp9_cyclic_refresh_reset_resize(cpi);
+    rc->rc_1_frame = 0;
+    rc->rc_2_frame = 0;
   }
 
   if ((cpi->svc.number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) ||
@@ -1863,6 +1865,21 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) {
                                            (int)cpi->oxcf.target_bandwidth);
   }
 
+  // Check for resetting the rc flags (rc_1_frame, rc_2_frame) if the
+  // configuration change has a large change in avg_frame_bandwidth.
+  // For SVC check for resetting based on spatial layer average bandwidth.
+  if (cm->current_video_frame > 0) {
+    if (cpi->use_svc) {
+      vp9_svc_check_reset_layer_rc_flag(cpi);
+    } else {
+      if (rc->avg_frame_bandwidth > (3 * rc->last_avg_frame_bandwidth >> 1) ||
+          rc->avg_frame_bandwidth < (rc->last_avg_frame_bandwidth >> 1)) {
+        rc->rc_1_frame = 0;
+        rc->rc_2_frame = 0;
+      }
+    }
+  }
+
   cpi->alt_ref_source = NULL;
   rc->is_src_frame_alt_ref = 0;
 
index 3f7fb1e885aac19cc7ed2f56872d87ea3589c36b..b7f3a0e897b967b05a80f930cb2ce8e20c65a57a 100644 (file)
@@ -1488,6 +1488,8 @@ void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) {
     cpi->rc.last_frame_is_src_altref = cpi->rc.is_src_frame_alt_ref;
   }
   if (cm->frame_type != KEY_FRAME) rc->reset_high_source_sad = 0;
+
+  rc->last_avg_frame_bandwidth = rc->avg_frame_bandwidth;
 }
 
 void vp9_rc_postencode_update_drop_frame(VP9_COMP *cpi) {
index 8a785c99494ba5598afea4fa8796b07c5180c744..c1b210677e2019779cfb2c7d13b66c038c5378e8 100644 (file)
@@ -152,6 +152,8 @@ typedef struct {
   int rc_2_frame;
   int q_1_frame;
   int q_2_frame;
+  // Keep track of the last target average frame bandwidth.
+  int last_avg_frame_bandwidth;
 
   // Auto frame-scaling variables.
   FRAME_SCALE_LEVEL frame_size_selector;
index e0d3bad8b3697425b5accaa6d08e8de235435381..45a1d142dbb6430c386afc0a5c5108b234518e2c 100644 (file)
@@ -862,3 +862,26 @@ void vp9_svc_reset_key_frame(VP9_COMP *const cpi) {
   vp9_update_temporal_layer_framerate(cpi);
   vp9_restore_layer_context(cpi);
 }
+
+void vp9_svc_check_reset_layer_rc_flag(VP9_COMP *const cpi) {
+  SVC *svc = &cpi->svc;
+  int sl, tl;
+  for (sl = 0; sl < svc->number_spatial_layers; ++sl) {
+    // Check for reset based on avg_frame_bandwidth for spatial layer sl.
+    int layer = LAYER_IDS_TO_IDX(sl, svc->number_temporal_layers - 1,
+                                 svc->number_temporal_layers);
+    LAYER_CONTEXT *lc = &svc->layer_context[layer];
+    RATE_CONTROL *lrc = &lc->rc;
+    if (lrc->avg_frame_bandwidth > (3 * lrc->last_avg_frame_bandwidth >> 1) ||
+        lrc->avg_frame_bandwidth < (lrc->last_avg_frame_bandwidth >> 1)) {
+      // Reset for all temporal layers with spatial layer sl.
+      for (tl = 0; tl < svc->number_temporal_layers; ++tl) {
+        int layer = LAYER_IDS_TO_IDX(sl, tl, svc->number_temporal_layers);
+        LAYER_CONTEXT *lc = &svc->layer_context[layer];
+        RATE_CONTROL *lrc = &lc->rc;
+        lrc->rc_1_frame = 0;
+        lrc->rc_2_frame = 0;
+      }
+    }
+  }
+}
index 16d1d6bb1e5a455925dd3d8a7abecafbc1c12ab8..b7cdfd9623d1a315d911a497ef28d1dceb7e193f 100644 (file)
@@ -154,6 +154,8 @@ void vp9_free_svc_cyclic_refresh(struct VP9_COMP *const cpi);
 
 void vp9_svc_reset_key_frame(struct VP9_COMP *const cpi);
 
+void vp9_svc_check_reset_layer_rc_flag(struct VP9_COMP *const cpi);
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif