From 8dd466edc84f0e641f84ca79e8edb76b87554762 Mon Sep 17 00:00:00 2001 From: paulwilkins Date: Wed, 24 Jun 2015 11:36:51 +0100 Subject: [PATCH] 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 --- vp9/encoder/vp9_encodeframe.c | 10 +++--- vp9/encoder/vp9_rdopt.c | 54 +++++++++++++++++++++++++------- vp9/encoder/vp9_rdopt.h | 2 ++ vp9/encoder/vp9_speed_features.c | 9 +++++- 4 files changed, 58 insertions(+), 17 deletions(-) diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index ca7359d65..e33fdb59e 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -2642,8 +2642,9 @@ static void rd_pick_partition(VP9_COMP *cpi, ThreadData *td, } // 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 @@ static void rd_pick_partition(VP9_COMP *cpi, ThreadData *td, 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); diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c index 409300b8f..9985f8947 100644 --- a/vp9/encoder/vp9_rdopt.c +++ b/vp9/encoder/vp9_rdopt.c @@ -2906,16 +2906,13 @@ int vp9_internal_image_edge(VP9_COMP *cpi) { (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 @@ int vp9_active_edge_sb(VP9_COMP *cpi, 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; +} + +// 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; +} - return is_active_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, diff --git a/vp9/encoder/vp9_rdopt.h b/vp9/encoder/vp9_rdopt.h index 16a8c68ee..00ee55c67 100644 --- a/vp9/encoder/vp9_rdopt.h +++ b/vp9/encoder/vp9_rdopt.h @@ -55,6 +55,8 @@ void vp9_rd_pick_inter_mode_sb_seg_skip(struct VP9_COMP *cpi, 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, diff --git a/vp9/encoder/vp9_speed_features.c b/vp9/encoder/vp9_speed_features.c index b3e5a0e4d..e544f9bb4 100644 --- a/vp9/encoder/vp9_speed_features.c +++ b/vp9/encoder/vp9_speed_features.c @@ -91,6 +91,7 @@ static void set_good_speed_feature_framesize_dependent(VP9_COMP *cpi, // 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 @@ static void set_good_speed_feature(VP9_COMP *cpi, VP9_COMMON *cm, 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 @@ static void set_good_speed_feature(VP9_COMP *cpi, VP9_COMMON *cm, } 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; -- GitLab