shithub: libvpx

Download patch

ref: 997db6fc3f67aa499574e362b37adf4b07534ff7
parent: 90d21bb28e2def7f43d5e59305c08b684a14b594
parent: eca93642e28102e5e30d6499f9661b89e8fdc27b
author: Pengchong Jin <pengchong@google.com>
date: Fri Aug 15 15:51:04 EDT 2014

Merge "Add a speed feature to give the tighter search range"

--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -1723,7 +1723,8 @@
 // function so repeat calls can accumulate a min and max of more than one sb64.
 static void get_sb_partition_size_range(MACROBLOCKD *xd, MODE_INFO **mi_8x8,
                                         BLOCK_SIZE *min_block_size,
-                                        BLOCK_SIZE *max_block_size ) {
+                                        BLOCK_SIZE *max_block_size,
+                                        int bs_hist[BLOCK_SIZES]) {
   int sb_width_in_blocks = MI_BLOCK_SIZE;
   int sb_height_in_blocks  = MI_BLOCK_SIZE;
   int i, j;
@@ -1734,6 +1735,7 @@
     for (j = 0; j < sb_width_in_blocks; ++j) {
       MODE_INFO * mi = mi_8x8[index+j];
       BLOCK_SIZE sb_type = mi ? mi->mbmi.sb_type : 0;
+      bs_hist[sb_type]++;
       *min_block_size = MIN(*min_block_size, sb_type);
       *max_block_size = MAX(*max_block_size, sb_type);
     }
@@ -1766,6 +1768,9 @@
   int bh, bw;
   BLOCK_SIZE min_size = BLOCK_4X4;
   BLOCK_SIZE max_size = BLOCK_64X64;
+  int i = 0;
+  int bs_hist[BLOCK_SIZES] = {0};
+
   // Trap case where we do not have a prediction.
   if (left_in_image || above_in_image || cm->frame_type != KEY_FRAME) {
     // Default "min to max" and "max to min"
@@ -1778,22 +1783,51 @@
     if (cm->frame_type != KEY_FRAME) {
       MODE_INFO **const prev_mi =
           &cm->prev_mi_grid_visible[mi_row * xd->mi_stride + mi_col];
-      get_sb_partition_size_range(xd, prev_mi, &min_size, &max_size);
+      get_sb_partition_size_range(xd, prev_mi, &min_size, &max_size, bs_hist);
     }
     // Find the min and max partition sizes used in the left SB64
     if (left_in_image) {
       MODE_INFO **left_sb64_mi = &mi[-MI_BLOCK_SIZE];
-      get_sb_partition_size_range(xd, left_sb64_mi, &min_size, &max_size);
+      get_sb_partition_size_range(xd, left_sb64_mi, &min_size, &max_size,
+                                  bs_hist);
     }
     // Find the min and max partition sizes used in the above SB64.
     if (above_in_image) {
       MODE_INFO **above_sb64_mi = &mi[-xd->mi_stride * MI_BLOCK_SIZE];
-      get_sb_partition_size_range(xd, above_sb64_mi, &min_size, &max_size);
+      get_sb_partition_size_range(xd, above_sb64_mi, &min_size, &max_size,
+                                  bs_hist);
     }
+
     // adjust observed min and max
     if (cpi->sf.auto_min_max_partition_size == RELAXED_NEIGHBORING_MIN_MAX) {
       min_size = min_partition_size[min_size];
       max_size = max_partition_size[max_size];
+    } else if (cpi->sf.auto_min_max_partition_size ==
+               CONSTRAIN_NEIGHBORING_MIN_MAX) {
+      // adjust the search range based on the histogram of the observed
+      // partition sizes from left, above the previous co-located blocks
+      int sum = 0;
+      int first_moment = 0;
+      int second_moment = 0;
+      int var_unnormalized = 0;
+
+      for (i = 0; i < BLOCK_SIZES; i++) {
+        sum += bs_hist[i];
+        first_moment += bs_hist[i] * i;
+        second_moment += bs_hist[i] * i * i;
+      }
+
+      // if variance is small enough,
+      // adjust the range around its mean size, which gives a tighter range
+      var_unnormalized = second_moment - first_moment * first_moment / sum;
+      if (var_unnormalized <= 4 * sum) {
+        int mean = first_moment / sum;
+        min_size = min_partition_size[mean];
+        max_size = max_partition_size[mean];
+      } else {
+        min_size = min_partition_size[min_size];
+        max_size = max_partition_size[max_size];
+      }
     }
   }
 
@@ -1810,6 +1844,7 @@
       next_square_size[max_size] < min_size) {
      min_size = next_square_size[max_size];
   }
+
   *min_block_size = min_size;
   *max_block_size = max_size;
 }
--- a/vp9/encoder/vp9_speed_features.c
+++ b/vp9/encoder/vp9_speed_features.c
@@ -102,7 +102,7 @@
                                  FLAG_SKIP_INTRA_LOWVAR;
     sf->disable_filter_search_var_thresh = 100;
     sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
-    sf->auto_min_max_partition_size = RELAXED_NEIGHBORING_MIN_MAX;
+    sf->auto_min_max_partition_size = CONSTRAIN_NEIGHBORING_MIN_MAX;
     sf->use_lastframe_partitioning = LAST_FRAME_PARTITION_LOW_MOTION;
     sf->adjust_partitioning_from_last_frame = 1;
   }
--- a/vp9/encoder/vp9_speed_features.h
+++ b/vp9/encoder/vp9_speed_features.h
@@ -63,7 +63,8 @@
 typedef enum {
   NOT_IN_USE = 0,
   RELAXED_NEIGHBORING_MIN_MAX = 1,
-  STRICT_NEIGHBORING_MIN_MAX = 2
+  CONSTRAIN_NEIGHBORING_MIN_MAX = 2,
+  STRICT_NEIGHBORING_MIN_MAX = 3
 } AUTO_MIN_MAX_MODE;
 
 typedef enum {