#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)
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
int vp9_block_energy(VP9_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bs) {
double energy;
}
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;
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;
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);
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 &=
// 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;
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;
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) {
}
}
- 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;