Index: source/libvpx/vp9/encoder/vp9_encodeframe.c |
=================================================================== |
--- source/libvpx/vp9/encoder/vp9_encodeframe.c (revision 291087) |
+++ source/libvpx/vp9/encoder/vp9_encodeframe.c (working copy) |
@@ -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; |
} |