shithub: libvpx

Download patch

ref: 704028d435d0e9ba445f961502e2083da8ed80f4
parent: 8b989f5b23a8a7d3337f486622001f58a0443184
author: Paul Wilkins <paulwilkins@google.com>
date: Mon Oct 7 15:20:10 EDT 2013

Experimental rate control change.

When the codec in VBR (or cq) mode hits its max q limits and is
struggling to hit a target bandwidth, the bit target per frame collapses.

In the first instance normal frames cap out at the maximum allowed
Q and then the ARF and GFs do the same. This latter behavior is not
generally desirable as GFs and ARFs are only effective from a quality
and data rate perspective if they have at lease some level of -Q delta
compared to the surrounding frames.

In this patch I define a separate max Q for GFs and ARFs that is
derived from but somewhat lower than that defined for normal frames.
In effect there is a minimum Q delta that will always be available for
GFs and ARFs regardless of the target rate and MAXQ setting.

This may of course mean that the absolute lowest rate obtainable for
a given clip is somewhat higher.

Change-Id: I268868b28401900d0cd87e51e609cd3b784ab54a

--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -787,6 +787,7 @@
         sf->adaptive_motion_search = 1;
         sf->auto_mv_step_size = 1;
         sf->adaptive_rd_thresh = 2;
+        sf->recode_loop = 2;
       }
       if (speed == 2) {
         sf->use_square_partition_only = !(cpi->common.frame_type == KEY_FRAME ||
@@ -2610,7 +2611,8 @@
 }
 #endif
 
-static int pick_q_and_adjust_q_bounds(VP9_COMP *cpi) {
+static int pick_q_and_adjust_q_bounds(VP9_COMP *cpi,
+                                      int * bottom_index, int * top_index) {
   // Set an active best quality and if necessary active worst quality
   int q = cpi->active_worst_quality;
   VP9_COMMON *const cm = &cpi->common;
@@ -2617,7 +2619,7 @@
 
   if (cm->frame_type == KEY_FRAME) {
 #if !CONFIG_MULTIPLE_ARF
-    // Handle the special case for key frames forced when we have reached
+    // Handle the special case for key frames forced when we have75 reached
     // the maximum key frame interval. Here force the Q to a range
     // based on the ambient Q to reduce the risk of popping.
     if (cpi->this_key_frame_forced) {
@@ -2663,12 +2665,13 @@
     cpi->active_best_quality = cpi->active_worst_quality
         + compute_qdelta(cpi, current_q, current_q * 0.3);
 #endif
-  } else if (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame) {
+  } else if (!cpi->is_src_frame_alt_ref &&
+             (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
     int high = 2000;
     int low = 400;
 
     // Use the lower of cpi->active_worst_quality and recent
-    // average Q as basis for GF/ARF Q limit unless last frame was
+    // average Q as basis for GF/ARF best Q limit unless last frame was
     // a key frame.
     if (cpi->frames_since_key > 1 &&
         cpi->avg_frame_qindex < cpi->active_worst_quality) {
@@ -2709,14 +2712,10 @@
         }
       }
     } else {
-      if (!cpi->refresh_alt_ref_frame) {
-        cpi->active_best_quality = inter_minq[q];
-      } else {
         cpi->active_best_quality = get_active_quality(q, cpi->gfu_boost,
                                                       low, high,
                                                       gf_low_motion_minq,
                                                       gf_high_motion_minq);
-      }
     }
   } else {
     if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
@@ -2732,7 +2731,7 @@
       cpi->active_best_quality = inter_minq[q];
 #endif
 
-      // For the constant/constrained quality mode we don't want
+      // For the constrained quality mode we don't want
       // q to fall below the cq level.
       if ((cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) &&
           (cpi->active_best_quality < cpi->cq_target_quality)) {
@@ -2760,14 +2759,28 @@
   if (cpi->active_worst_quality < cpi->active_best_quality)
     cpi->active_worst_quality = cpi->active_best_quality;
 
-  // Special case code to try and match quality with forced key frames
+  // Limit Q range for the adaptive loop.
+  if (cm->frame_type == KEY_FRAME && !cpi->this_key_frame_forced) {
+    *top_index = cpi->active_best_quality;
+  } else if (!cpi->is_src_frame_alt_ref &&
+             (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
+    *top_index =
+      (cpi->active_worst_quality + cpi->active_best_quality * 3) / 4;
+  } else {
+    *top_index = cpi->active_worst_quality;
+  }
+  *bottom_index = cpi->active_best_quality;
+
   if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
     q = cpi->active_best_quality;
+  // Special case code to try and match quality with forced key frames
   } else if ((cm->frame_type == KEY_FRAME) && cpi->this_key_frame_forced) {
     q = cpi->last_boosted_qindex;
   } else {
     // Determine initial Q to try
     q = vp9_regulate_q(cpi, cpi->this_frame_target);
+    if (q > *top_index)
+      q = *top_index;
   }
 
   return q;
@@ -2906,8 +2919,11 @@
 
   vp9_clear_system_state();
 
-  q = pick_q_and_adjust_q_bounds(cpi);
+  q = pick_q_and_adjust_q_bounds(cpi, &bottom_index, &top_index);
 
+  q_high = top_index;
+  q_low  = bottom_index;
+
   vp9_compute_frame_size_bounds(cpi, &frame_under_shoot_limit,
                                 &frame_over_shoot_limit);
 
@@ -2930,16 +2946,9 @@
     q_high = q;
 
     printf("frame:%d q:%d\n", cm->current_video_frame, q);
-  } else {
-#endif
-    // Limit Q range for the adaptive loop.
-    bottom_index = cpi->active_best_quality;
-    top_index    = cpi->active_worst_quality;
-    q_low  = cpi->active_best_quality;
-    q_high = cpi->active_worst_quality;
-#if CONFIG_MULTIPLE_ARF
   }
 #endif
+
   loop_count = 0;
   vp9_zero(cpi->rd_tx_select_threshes);
 
@@ -3030,10 +3039,10 @@
       frame_over_shoot_limit = 1;
     active_worst_qchanged = 0;
 
-    // Special case handling for forced key frames
     if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
       loop = 0;
     } else {
+      // Special case handling for forced key frames
       if ((cm->frame_type == KEY_FRAME) && cpi->this_key_frame_forced) {
         int last_q = q;
         int kf_err = vp9_calc_ss_err(cpi->Source,