shithub: libvpx

Download patch

ref: 21ff7bdc72f0eb9ee3d13a4cc8067ad7484873bc
parent: 38f6232118a7aebdcc062ae0a10e59a32b6fdef8
author: Paul Wilkins <paulwilkins@google.com>
date: Tue Apr 16 14:59:39 EDT 2013

Adjustments to key frame sizing.

Adjustments take heavier account of the frame near a kf
in deciding boost and limit the total number that can contribute.
Also adjusted the minq calculations such that in most cases we
generate a smaller key frame.
Modified the code that accounts for how static the sequence is and
added some adjustment based on image size. This is still very
crude but smaller images tend to behave better with a larger
delta between KF Q and other frames than larger image formats.
Changes give sizable gains in overall PSNR  on all the test sets but the
biggest gains (~3%) were on the std-hd set.
The gains were smaller for SSIM but still significant.
Average PSNR results are mixed because this metric can very easily
be altered by having a very good / lossless coding of one or two frames.
Some of the YT and YT-HD clips in particular have blank lead ins and
allowing lossless coding of these appears to make a big difference to
average PSNR but it reality does not help much at all.

Change-Id: I6bfe485a1d330b47c783832f1717c95c535464ec

--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -38,7 +38,7 @@
 #define IIFACTOR   12.5
 #define IIKFACTOR1 12.5
 #define IIKFACTOR2 15.0
-#define RMAX       128.0
+#define RMAX       512.0
 #define GF_RMAX    96.0
 #define ERR_DIVISOR   150.0
 #define MIN_DECAY_FACTOR 0.1
@@ -2350,7 +2350,6 @@
   double decay_accumulator = 1.0;
   double zero_motion_accumulator = 1.0;
   double boost_score = 0;
-  double old_boost_score = 0.0;
   double loop_decay_rate;
 
   double kf_mod_err = 0.0;
@@ -2522,6 +2521,7 @@
   boost_score = 0.0;
   loop_decay_rate = 1.00;       // Starting decay rate
 
+  // Scan through the kf group collating various stats.
   for (i = 0; i < cpi->twopass.frames_to_key; i++) {
     double r;
 
@@ -2528,16 +2528,6 @@
     if (EOF == input_stats(cpi, &next_frame))
       break;
 
-    if (next_frame.intra_error > cpi->twopass.kf_intra_err_min)
-      r = (IIKFACTOR2 * next_frame.intra_error /
-           DOUBLE_DIVIDE_CHECK(next_frame.coded_error));
-    else
-      r = (IIKFACTOR2 * cpi->twopass.kf_intra_err_min /
-           DOUBLE_DIVIDE_CHECK(next_frame.coded_error));
-
-    if (r > RMAX)
-      r = RMAX;
-
     // Monitor for static sections.
     if ((next_frame.pcnt_inter - next_frame.pcnt_motion) <
         zero_motion_accumulator) {
@@ -2545,22 +2535,28 @@
         (next_frame.pcnt_inter - next_frame.pcnt_motion);
     }
 
-    // How fast is prediction quality decaying
-    if (!detect_flash(cpi, 0)) {
-      loop_decay_rate = get_prediction_decay_rate(cpi, &next_frame);
-      decay_accumulator = decay_accumulator * loop_decay_rate;
-      decay_accumulator = decay_accumulator < MIN_DECAY_FACTOR
-                            ? MIN_DECAY_FACTOR : decay_accumulator;
-    }
+    // For the first few frames collect data to decide kf boost.
+    if (i <= (cpi->max_gf_interval * 2)) {
+      if (next_frame.intra_error > cpi->twopass.kf_intra_err_min)
+        r = (IIKFACTOR2 * next_frame.intra_error /
+             DOUBLE_DIVIDE_CHECK(next_frame.coded_error));
+      else
+        r = (IIKFACTOR2 * cpi->twopass.kf_intra_err_min /
+             DOUBLE_DIVIDE_CHECK(next_frame.coded_error));
 
-    boost_score += (decay_accumulator * r);
+      if (r > RMAX)
+        r = RMAX;
 
-    if ((i > MIN_GF_INTERVAL) &&
-        ((boost_score - old_boost_score) < 6.25)) {
-      break;
-    }
+      // How fast is prediction quality decaying
+      if (!detect_flash(cpi, 0)) {
+        loop_decay_rate = get_prediction_decay_rate(cpi, &next_frame);
+        decay_accumulator = decay_accumulator * loop_decay_rate;
+        decay_accumulator = decay_accumulator < MIN_DECAY_FACTOR
+                              ? MIN_DECAY_FACTOR : decay_accumulator;
+      }
 
-    old_boost_score = boost_score;
+      boost_score += (decay_accumulator * r);
+    }
   }
 
   {
@@ -2590,8 +2586,8 @@
     int allocation_chunks;
     int alt_kf_bits;
 
-    if (kf_boost < (cpi->twopass.frames_to_key * 5))
-      kf_boost = (cpi->twopass.frames_to_key * 5);
+    if (kf_boost < (cpi->twopass.frames_to_key * 3))
+      kf_boost = (cpi->twopass.frames_to_key * 3);
 
     if (kf_boost < 300) // Min KF boost
       kf_boost = 300;
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -177,15 +177,16 @@
 
 
     kf_low_motion_minq[i] = calculate_minq_index(maxq,
-                                                 0.0000003,
-                                                 -0.000015,
-                                                 0.074,
+                                                 0.000001,
+                                                 -0.0004,
+                                                 0.15,
                                                  0.0);
     kf_high_motion_minq[i] = calculate_minq_index(maxq,
-                                                  0.0000004,
-                                                  -0.000125,
-                                                  0.14,
+                                                  0.000002,
+                                                  -0.0012,
+                                                  0.5,
                                                   0.0);
+
     gf_low_motion_minq[i] = calculate_minq_index(maxq,
                                                  0.0000015,
                                                  -0.0009,
@@ -2757,31 +2758,7 @@
   q = cpi->active_worst_quality;
 
   if (cm->frame_type == KEY_FRAME) {
-#if CONFIG_MULTIPLE_ARF
-    double current_q;
-#endif
-    int high = 2000;
-    int low = 400;
-
-    if (cpi->kf_boost > high) {
-      cpi->active_best_quality = kf_low_motion_minq[q];
-    } else if (cpi->kf_boost < low) {
-      cpi->active_best_quality = kf_high_motion_minq[q];
-    } else {
-      const int gap = high - low;
-      const int offset = high - cpi->kf_boost;
-      const int qdiff = kf_high_motion_minq[q] - kf_low_motion_minq[q];
-      const int adjustment = ((offset * qdiff) + (gap >> 1)) / gap;
-
-      cpi->active_best_quality = kf_low_motion_minq[q] + adjustment;
-    }
-
-    // Make an adjustment based on the % static
-    // The main impact of this is at lower Q to prevent overly large key
-    // frames unless a lot of the image is static.
-    if (cpi->kf_zeromotion_pct < 64)
-      cpi->active_best_quality += 4 - (cpi->kf_zeromotion_pct >> 4);
-
+#if !CONFIG_MULTIPLE_ARF
     // Special case for key frames forced because we have reached
     // the maximum key frame interval. Here force the Q to a range
     // based on the ambient Q to reduce the risk of popping
@@ -2794,8 +2771,43 @@
                                     (last_boosted_q * 0.75));
 
       cpi->active_best_quality = MAX(qindex + delta_qindex, cpi->best_quality);
+    } else {
+      int high = 5000;
+      int low = 400;
+      double q_adj_factor = 1.0;
+      double q_val;
+
+      // Baseline value derived from cpi->active_worst_quality and kf boost
+      if (cpi->kf_boost > high) {
+        cpi->active_best_quality = kf_low_motion_minq[q];
+      } else if (cpi->kf_boost < low) {
+        cpi->active_best_quality = kf_high_motion_minq[q];
+      } else {
+        const int gap = high - low;
+        const int offset = high - cpi->kf_boost;
+        const int qdiff = kf_high_motion_minq[q] - kf_low_motion_minq[q];
+        const int adjustment = ((offset * qdiff) + (gap >> 1)) / gap;
+
+        cpi->active_best_quality = kf_low_motion_minq[q] + adjustment;
+      }
+
+
+      // Allow somewhat lower kf minq with small image formats.
+      if ((cm->width * cm->height) <= (352 * 288)) {
+        q_adj_factor -= 0.25;
+      }
+
+      // Make a further adjustment based on the kf zero motion measure.
+      q_adj_factor += 0.05 - (0.001 * (double)cpi->kf_zeromotion_pct);
+
+      // Convert the adjustment factor to a qindex delta on active_best_quality.
+      q_val = vp9_convert_qindex_to_q(cpi->active_best_quality);
+      cpi->active_best_quality +=
+        compute_qdelta(cpi, q_val, (q_val * q_adj_factor));
     }
-#if CONFIG_MULTIPLE_ARF
+#else
+    double current_q;
+
     // Force the KF quantizer to be 30% of the active_worst_quality.
     current_q = vp9_convert_qindex_to_q(cpi->active_worst_quality);
     cpi->active_best_quality = cpi->active_worst_quality