shithub: libvpx

Download patch

ref: a1af335f448923e2f9edadb7c02c549f06306256
parent: 7d526c1654ed972e4083c89f17fbb8f92782dfb0
author: paulwilkins <paulwilkins@google.com>
date: Fri May 19 11:08:15 EDT 2017

Further refactoring of mod error calculation.

Further refactoring to support alternative error distributions.

Change-Id: I0f7fa3fd6f3baa4b0a1e53c6aa3be63966e97b82

--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -235,16 +235,21 @@
   return fclamp(active_pct, MIN_ACTIVE_AREA, MAX_ACTIVE_AREA);
 }
 
+// Get the average weighted error for the clip (or corpus)
+static double get_distribution_av_err(TWO_PASS *const twopass) {
+  const double av_weight =
+      twopass->total_stats.weight / twopass->total_stats.count;
+  return (twopass->total_stats.coded_error * av_weight) /
+         twopass->total_stats.count;
+}
+
 // Calculate a modified Error used in distributing bits between easier and
 // harder frames.
 #define ACT_AREA_CORRECTION 0.5
 static double calculate_mod_frame_score(const VP9_COMP *cpi,
-                                        const TWO_PASS *twopass,
                                         const VP9EncoderConfig *oxcf,
-                                        const FIRSTPASS_STATS *this_frame) {
-  const FIRSTPASS_STATS *const stats = &twopass->total_stats;
-  const double av_weight = stats->weight / stats->count;
-  const double av_err = (stats->coded_error * av_weight) / stats->count;
+                                        const FIRSTPASS_STATS *this_frame,
+                                        const double av_err) {
   double modified_score =
       av_err * pow(this_frame->coded_error * this_frame->weight /
                        DOUBLE_DIVIDE_CHECK(av_err),
@@ -263,10 +268,8 @@
 static double calculate_norm_frame_score(const VP9_COMP *cpi,
                                          const TWO_PASS *twopass,
                                          const VP9EncoderConfig *oxcf,
-                                         const FIRSTPASS_STATS *this_frame) {
-  const FIRSTPASS_STATS *const stats = &twopass->total_stats;
-  const double av_weight = stats->weight / stats->count;
-  const double av_err = (stats->coded_error * av_weight) / stats->count;
+                                         const FIRSTPASS_STATS *this_frame,
+                                         const double av_err) {
   double modified_score =
       av_err * pow(this_frame->coded_error * this_frame->weight /
                        DOUBLE_DIVIDE_CHECK(av_err),
@@ -1713,12 +1716,13 @@
   // to provide a linear basis for bit allocation. I.e a frame A with a score
   // that is double that of frame B will be allocated 2x as many bits.
   {
-    const FIRSTPASS_STATS *s = twopass->stats_in;
     double modified_score_total = 0.0;
+    const FIRSTPASS_STATS *s = twopass->stats_in;
+    const double av_err = get_distribution_av_err(twopass);
 
     // The first scan is unclamped and gives a raw average.
     while (s < twopass->stats_in_end) {
-      modified_score_total += calculate_mod_frame_score(cpi, twopass, oxcf, s);
+      modified_score_total += calculate_mod_frame_score(cpi, oxcf, s, av_err);
       ++s;
     }
 
@@ -1730,10 +1734,11 @@
     // Second scan using clamps based on the previous cycle average.
     // This may modify the total and average somewhat but we dont bother with
     // further itterations.
-    s = twopass->stats_in;
     modified_score_total = 0.0;
+    s = twopass->stats_in;
     while (s < twopass->stats_in_end) {
-      modified_score_total += calculate_norm_frame_score(cpi, twopass, oxcf, s);
+      modified_score_total +=
+          calculate_norm_frame_score(cpi, twopass, oxcf, s, av_err);
       ++s;
     }
     twopass->normalized_score_left = modified_score_total;
@@ -2350,6 +2355,7 @@
   double mv_in_out_thresh;
   double abs_mv_in_out_thresh;
   double sr_accumulator = 0.0;
+  const double av_err = get_distribution_av_err(twopass);
   unsigned int allow_alt_ref = is_altref_enabled(cpi);
 
   int f_boost = 0;
@@ -2372,7 +2378,8 @@
   vp9_zero(next_frame);
 
   // Load stats for the current frame.
-  mod_frame_err = calculate_norm_frame_score(cpi, twopass, oxcf, this_frame);
+  mod_frame_err =
+      calculate_norm_frame_score(cpi, twopass, oxcf, this_frame, av_err);
 
   // Note the error of the frame at the start of the group. This will be
   // the GF frame error if we code a normal gf.
@@ -2438,7 +2445,8 @@
     ++i;
 
     // Accumulate error score of frames in this gf group.
-    mod_frame_err = calculate_norm_frame_score(cpi, twopass, oxcf, this_frame);
+    mod_frame_err =
+        calculate_norm_frame_score(cpi, twopass, oxcf, this_frame, av_err);
     gf_group_err += mod_frame_err;
     gf_group_raw_error += this_frame->coded_error;
     gf_group_noise += this_frame->frame_noise_energy;
@@ -2548,7 +2556,7 @@
     for (j = 0; j < new_gf_interval - rc->baseline_gf_interval; ++j) {
       if (EOF == input_stats(twopass, this_frame)) break;
       gf_group_err +=
-          calculate_norm_frame_score(cpi, twopass, oxcf, this_frame);
+          calculate_norm_frame_score(cpi, twopass, oxcf, this_frame, av_err);
       gf_group_raw_error += this_frame->coded_error;
       gf_group_noise += this_frame->frame_noise_energy;
       gf_group_skip_pct += this_frame->intra_skip_pct;
@@ -2769,7 +2777,7 @@
   double kf_group_err = 0.0;
   double recent_loop_decay[FRAMES_TO_CHECK_DECAY];
   double sr_accumulator = 0.0;
-
+  const double av_err = get_distribution_av_err(twopass);
   vp9_zero(next_frame);
 
   cpi->common.frame_type = KEY_FRAME;
@@ -2793,7 +2801,8 @@
   twopass->kf_group_bits = 0;          // Total bits available to kf group
   twopass->kf_group_error_left = 0.0;  // Group modified error score.
 
-  kf_mod_err = calculate_norm_frame_score(cpi, twopass, oxcf, this_frame);
+  kf_mod_err =
+      calculate_norm_frame_score(cpi, twopass, oxcf, this_frame, av_err);
 
   // Initialize the decay rates for the recent frames to check
   for (j = 0; j < FRAMES_TO_CHECK_DECAY; ++j) recent_loop_decay[j] = 1.0;
@@ -2803,7 +2812,8 @@
   while (twopass->stats_in < twopass->stats_in_end &&
          rc->frames_to_key < cpi->oxcf.key_freq) {
     // Accumulate kf group error.
-    kf_group_err += calculate_norm_frame_score(cpi, twopass, oxcf, this_frame);
+    kf_group_err +=
+        calculate_norm_frame_score(cpi, twopass, oxcf, this_frame, av_err);
 
     // Load the next frame's stats.
     last_frame = *this_frame;
@@ -2864,7 +2874,7 @@
     // Rescan to get the correct error data for the forced kf group.
     for (i = 0; i < rc->frames_to_key; ++i) {
       kf_group_err +=
-          calculate_norm_frame_score(cpi, twopass, oxcf, &tmp_frame);
+          calculate_norm_frame_score(cpi, twopass, oxcf, &tmp_frame, av_err);
       input_stats(twopass, &tmp_frame);
     }
     rc->next_key_frame_forced = 1;
@@ -2882,7 +2892,7 @@
     for (j = 0; j < new_frame_to_key - rc->frames_to_key; ++j) {
       if (EOF == input_stats(twopass, this_frame)) break;
       kf_group_err +=
-          calculate_norm_frame_score(cpi, twopass, oxcf, this_frame);
+          calculate_norm_frame_score(cpi, twopass, oxcf, this_frame, av_err);
     }
     rc->frames_to_key = new_frame_to_key;
   }
@@ -2890,7 +2900,8 @@
   // Special case for the last key frame of the file.
   if (twopass->stats_in >= twopass->stats_in_end) {
     // Accumulate kf group error.
-    kf_group_err += calculate_norm_frame_score(cpi, twopass, oxcf, this_frame);
+    kf_group_err +=
+        calculate_norm_frame_score(cpi, twopass, oxcf, this_frame, av_err);
   }
 
   // Calculate the number of bits that should be assigned to the kf group.