ref: 4400b0137e4b1b54f3c2ff54dfb1163d69983ce6
parent: 4d2ec89de0b9915bc93bcb5199855506e055b437
parent: b99749b540f865cf5b8b32604d918c0760a3071a
author: Paul Wilkins <paulwilkins@google.com>
date: Fri Jun 29 10:16:52 EDT 2018
Merge "Enhanced partition experiment."
--- a/vp9/encoder/vp9_aq_variance.c
+++ b/vp9/encoder/vp9_aq_variance.c
@@ -19,6 +19,7 @@
#include "vp9/encoder/vp9_ratectrl.h"
#include "vp9/encoder/vp9_rd.h"
+#include "vp9/encoder/vp9_encodeframe.h"
#include "vp9/encoder/vp9_segmentation.h"
#define ENERGY_MIN (-4)
@@ -190,6 +191,40 @@
unsigned int var = block_variance(cpi, x, bs);
vpx_clear_system_state();
return log(var + 1.0);
+}
+
+// Get the range of sub block energy values;
+void vp9_get_sub_block_energy(VP9_COMP *cpi, MACROBLOCK *mb, int mi_row,
+ int mi_col, BLOCK_SIZE bsize, int *min_e,
+ int *max_e) {
+ VP9_COMMON *const cm = &cpi->common;
+ const int bw = num_8x8_blocks_wide_lookup[bsize];
+ const int bh = num_8x8_blocks_high_lookup[bsize];
+ const int xmis = VPXMIN(cm->mi_cols - mi_col, bw);
+ const int ymis = VPXMIN(cm->mi_rows - mi_row, bh);
+ int x, y;
+
+ if (xmis < bw || ymis < bh) {
+ vp9_setup_src_planes(mb, cpi->Source, mi_row, mi_col);
+ *min_e = vp9_block_energy(cpi, mb, bsize);
+ *max_e = *min_e;
+ } else {
+ int energy;
+ *min_e = ENERGY_MAX;
+ *max_e = ENERGY_MIN;
+
+ for (y = 0; y < ymis; ++y) {
+ for (x = 0; x < xmis; ++x) {
+ vp9_setup_src_planes(mb, cpi->Source, mi_row + y, mi_col + x);
+ energy = vp9_block_energy(cpi, mb, BLOCK_8X8);
+ *min_e = VPXMIN(*min_e, energy);
+ *max_e = VPXMAX(*max_e, energy);
+ }
+ }
+ }
+
+ // Re-instate source pointers back to what they should have been on entry.
+ vp9_setup_src_planes(mb, cpi->Source, mi_row, mi_col);
}
#define DEFAULT_E_MIDPOINT 10.0
--- a/vp9/encoder/vp9_aq_variance.h
+++ b/vp9/encoder/vp9_aq_variance.h
@@ -20,7 +20,11 @@
unsigned int vp9_vaq_segment_id(int energy);
void vp9_vaq_frame_setup(VP9_COMP *cpi);
+void vp9_get_sub_block_energy(VP9_COMP *cpi, MACROBLOCK *mb, int mi_row,
+ int mi_col, BLOCK_SIZE bsize, int *min_e,
+ int *max_e);
int vp9_block_energy(VP9_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bs);
+
double vp9_log_block_var(VP9_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bs);
#ifdef __cplusplus
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -1903,13 +1903,22 @@
}
if (aq_mode == VARIANCE_AQ) {
- const int energy =
- bsize <= BLOCK_16X16 ? x->mb_energy : vp9_block_energy(cpi, x, bsize);
-
if (cm->frame_type == KEY_FRAME || cpi->refresh_alt_ref_frame ||
cpi->force_update_segmentation ||
(cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref)) {
- mi->segment_id = vp9_vaq_segment_id(energy);
+ int min_energy;
+ int max_energy;
+
+ // Get sub block energy range
+ if (bsize >= BLOCK_32X32) {
+ vp9_get_sub_block_energy(cpi, x, mi_row, mi_col, bsize, &min_energy,
+ &max_energy);
+ } else {
+ min_energy = bsize <= BLOCK_16X16 ? x->mb_energy
+ : vp9_block_energy(cpi, x, bsize);
+ }
+
+ mi->segment_id = vp9_vaq_segment_id(min_energy);
} else {
const uint8_t *const map =
cm->seg.update_map ? cpi->segmentation_map : cm->last_frame_seg_map;
@@ -3529,6 +3538,7 @@
int64_t dist_breakout_thr = cpi->sf.partition_search_breakout_thr.dist;
int rate_breakout_thr = cpi->sf.partition_search_breakout_thr.rate;
+ int must_split = 0;
(void)*tp_orig;
@@ -3535,9 +3545,9 @@
assert(num_8x8_blocks_wide_lookup[bsize] ==
num_8x8_blocks_high_lookup[bsize]);
- // Adjust dist breakout threshold according to the partition size.
dist_breakout_thr >>=
8 - (b_width_log2_lookup[bsize] + b_height_log2_lookup[bsize]);
+
rate_breakout_thr *= num_pels_log2_lookup[bsize];
vp9_rd_cost_init(&this_rdc);
@@ -3561,10 +3571,18 @@
set_partition_range(cm, xd, mi_row, mi_col, bsize, &min_size, &max_size);
}
+ // Get sub block energy range
+ if (bsize >= BLOCK_16X16) {
+ int min_energy, max_energy;
+ vp9_get_sub_block_energy(cpi, x, mi_row, mi_col, bsize, &min_energy,
+ &max_energy);
+ must_split = (min_energy < -3) && (max_energy - min_energy > 2);
+ }
+
// Determine partition types in search according to the speed features.
// The threshold set here has to be of square block size.
if (cpi->sf.auto_min_max_partition_size) {
- partition_none_allowed &= (bsize <= max_size && bsize >= min_size);
+ partition_none_allowed &= (bsize <= max_size);
partition_horz_allowed &=
((bsize <= max_size && bsize > min_size) || force_horz_split);
partition_vert_allowed &=
@@ -3767,7 +3785,7 @@
// PARTITION_SPLIT
// TODO(jingning): use the motion vectors given by the above search as
// the starting point of motion search in the following partition type check.
- if (do_split) {
+ if (do_split || must_split) {
subsize = get_subsize(bsize, PARTITION_SPLIT);
if (bsize == BLOCK_8X8) {
i = 4;
@@ -3778,7 +3796,8 @@
if (sum_rdc.rate == INT_MAX) sum_rdc.rdcost = INT64_MAX;
} else {
- for (i = 0; i < 4 && sum_rdc.rdcost < best_rdc.rdcost; ++i) {
+ for (i = 0; (i < 4) && ((sum_rdc.rdcost < best_rdc.rdcost) || must_split);
+ ++i) {
const int x_idx = (i & 1) * mi_step;
const int y_idx = (i >> 1) * mi_step;
@@ -3790,6 +3809,13 @@
pc_tree->split[i]->index = i;
rd_pick_partition(cpi, td, tile_data, tp, mi_row + y_idx,
mi_col + x_idx, subsize, &this_rdc,
+ // A must split test here increases the number of sub
+ // partitions but hurts metrics results quite a bit,
+ // so this extra test is commented out pending
+ // further tests on whether it adds much in terms of
+ // visual quality.
+ // (must_split) ? best_rdc.rdcost
+ // : best_rdc.rdcost - sum_rdc.rdcost,
best_rdc.rdcost - sum_rdc.rdcost, pc_tree->split[i]);
if (this_rdc.rate == INT_MAX) {
@@ -3803,12 +3829,13 @@
}
}
- if (sum_rdc.rdcost < best_rdc.rdcost && i == 4) {
+ if (((sum_rdc.rdcost < best_rdc.rdcost) || must_split) && i == 4) {
sum_rdc.rdcost += RDCOST(x->rdmult, x->rddiv,
cpi->partition_cost[pl][PARTITION_SPLIT], 0);
sum_rdc.rate += cpi->partition_cost[pl][PARTITION_SPLIT];
- if (sum_rdc.rdcost < best_rdc.rdcost) {
+ if ((sum_rdc.rdcost < best_rdc.rdcost) ||
+ (must_split && (sum_rdc.dist < best_rdc.dist))) {
best_rdc = sum_rdc;
pc_tree->partitioning = PARTITION_SPLIT;