ref: 8dd466edc84f0e641f84ca79e8edb76b87554762
parent: a126b6ce7d9f81552e02fbe76d4fac276916992e
author: paulwilkins <[email protected]>
date: Wed Jun 24 07:36:51 EDT 2015
Changes to use of rectangular partitions. Changes to allow more use of rectangular partitions at speeds 1 and 2 for content classed by the first pass as animation and for blocks near the active image edge. This has quite a big impact in quality for the animated test sequence but also hurts encode speed for speed 2. For other content types the impact on both speed and quality is small. Added some plumbing for detection of internal vertical image edges. Change-Id: I3fc48de2349f8cb87946caaf0b06dbb0ea261a9a
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -2642,8 +2642,9 @@
}
// PARTITION_HORZ
- if (partition_horz_allowed && do_rect) {
- subsize = get_subsize(bsize, PARTITION_HORZ);
+ if (partition_horz_allowed &&
+ (do_rect || vp9_active_h_edge(cpi, mi_row, mi_step))) {
+ subsize = get_subsize(bsize, PARTITION_HORZ);
if (cpi->sf.adaptive_motion_search)
load_pred_mv(x, ctx);
if (cpi->sf.adaptive_pred_interp_filter && bsize == BLOCK_8X8 &&
@@ -2689,8 +2690,9 @@
restore_context(x, mi_row, mi_col, a, l, sa, sl, bsize);
}
// PARTITION_VERT
- if (partition_vert_allowed && do_rect) {
- subsize = get_subsize(bsize, PARTITION_VERT);
+ if (partition_vert_allowed &&
+ (do_rect || vp9_active_v_edge(cpi, mi_col, mi_step))) {
+ subsize = get_subsize(bsize, PARTITION_VERT);
if (cpi->sf.adaptive_motion_search)
load_pred_mv(x, ctx);
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -2906,16 +2906,13 @@
(cpi->twopass.this_frame_stats.inactive_zone_cols > 0));
}
-// Checks to see if a macro block is at the edge of the active image.
+// Checks to see if a super block is on a horizontal image edge.
// In most cases this is the "real" edge unless there are formatting
// bars embedded in the stream.
-int vp9_active_edge_sb(VP9_COMP *cpi,
- int mi_row, int mi_col) {
- int is_active_edge = 0;
+int vp9_active_h_edge(VP9_COMP *cpi, int mi_row, int mi_step) {
int top_edge = 0;
int bottom_edge = cpi->common.mi_rows;
- int left_edge = 0;
- int right_edge = cpi->common.mi_cols;
+ int is_active_h_edge = 0;
// For two pass account for any formatting bars detected.
if (cpi->oxcf.pass == 2) {
@@ -2929,14 +2926,47 @@
bottom_edge = MAX(top_edge, bottom_edge);
}
- if (((top_edge >= mi_row) && (top_edge < (mi_row + MI_BLOCK_SIZE))) ||
- ((bottom_edge >= mi_row) && (bottom_edge < (mi_row + MI_BLOCK_SIZE))) ||
- ((left_edge >= mi_col) && (left_edge < (mi_col + MI_BLOCK_SIZE))) ||
- ((right_edge >= mi_col) && (right_edge < (mi_col + MI_BLOCK_SIZE)))) {
- is_active_edge = 1;
+ if (((top_edge >= mi_row) && (top_edge < (mi_row + mi_step))) ||
+ ((bottom_edge >= mi_row) && (bottom_edge < (mi_row + mi_step)))) {
+ is_active_h_edge = 1;
}
+ return is_active_h_edge;
+}
- return is_active_edge;
+// Checks to see if a super block is on a vertical image edge.
+// In most cases this is the "real" edge unless there are formatting
+// bars embedded in the stream.
+int vp9_active_v_edge(VP9_COMP *cpi, int mi_col, int mi_step) {
+ int left_edge = 0;
+ int right_edge = cpi->common.mi_cols;
+ int is_active_v_edge = 0;
+
+ // For two pass account for any formatting bars detected.
+ if (cpi->oxcf.pass == 2) {
+ TWO_PASS *twopass = &cpi->twopass;
+
+ // The inactive region is specified in MBs not mi units.
+ // The image edge is in the following MB row.
+ left_edge += (int)(twopass->this_frame_stats.inactive_zone_cols * 2);
+
+ right_edge -= (int)(twopass->this_frame_stats.inactive_zone_cols * 2);
+ right_edge = MAX(left_edge, right_edge);
+ }
+
+ if (((left_edge >= mi_col) && (left_edge < (mi_col + mi_step))) ||
+ ((right_edge >= mi_col) && (right_edge < (mi_col + mi_step)))) {
+ is_active_v_edge = 1;
+ }
+ return is_active_v_edge;
+}
+
+// Checks to see if a super block is at the edge of the active image.
+// In most cases this is the "real" edge unless there are formatting
+// bars embedded in the stream.
+int vp9_active_edge_sb(VP9_COMP *cpi,
+ int mi_row, int mi_col) {
+ return vp9_active_h_edge(cpi, mi_row, MI_BLOCK_SIZE) ||
+ vp9_active_v_edge(cpi, mi_col, MI_BLOCK_SIZE);
}
void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi,
--- a/vp9/encoder/vp9_rdopt.h
+++ b/vp9/encoder/vp9_rdopt.h
@@ -55,6 +55,8 @@
int64_t best_rd_so_far);
int vp9_internal_image_edge(struct VP9_COMP *cpi);
+int vp9_active_h_edge(struct VP9_COMP *cpi, int mi_row, int mi_step);
+int vp9_active_v_edge(struct VP9_COMP *cpi, int mi_col, int mi_step);
int vp9_active_edge_sb(struct VP9_COMP *cpi, int mi_row, int mi_col);
void vp9_rd_pick_inter_mode_sub8x8(struct VP9_COMP *cpi,
--- a/vp9/encoder/vp9_speed_features.c
+++ b/vp9/encoder/vp9_speed_features.c
@@ -91,6 +91,7 @@
// If this is a two pass clip that fits the criteria for animated or
// graphics content then reset disable_split_mask for speeds 1-4.
+ // Also if the image edge is internal to the coded area.
if ((speed >= 1) && (cpi->oxcf.pass == 2) &&
((cpi->twopass.fr_content_type == FC_GRAPHICS_ANIMATION) ||
(vp9_internal_image_edge(cpi)))) {
@@ -115,7 +116,12 @@
sf->allow_skip_recode = 1;
if (speed >= 1) {
- sf->use_square_partition_only = !frame_is_intra_only(cm);
+ if ((cpi->twopass.fr_content_type == FC_GRAPHICS_ANIMATION) ||
+ vp9_internal_image_edge(cpi)) {
+ sf->use_square_partition_only = frame_is_boosted(cpi);
+ } else {
+ sf->use_square_partition_only = !frame_is_intra_only(cm);
+ }
sf->less_rectangular_check = 1;
sf->use_rd_breakout = 1;
@@ -155,6 +161,7 @@
}
if (speed >= 3) {
+ sf->use_square_partition_only = !frame_is_intra_only(cm);
sf->tx_size_search_method = frame_is_intra_only(cm) ? USE_FULL_RD
: USE_LARGESTALL;
sf->mv.subpel_search_method = SUBPEL_TREE_PRUNED;