Change speed and rd features for formatting bars. Change speed features / behavior for split mode when there is an internal active edge (e.g. formatting bars). Remove some threshold constraints in rd code near the active edge of the image. Add some plumbing for left and right active edge detection. Patch set 5. Limit rd pass through for sub 8x8 to internal active edges. This takes away any speed penalty for most clips but keeps the enhanced edge coding for the more critical case of internal image edges Change-Id: If644e4762874de4fe9cbb0a66211953fa74c13a5
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index 02d986e..ca7359d 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c
@@ -2123,38 +2123,6 @@ BLOCK_64X64 }; -// Checks to see if a macro 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. -static int active_edge_sb(VP9_COMP *cpi, - int mi_row, int mi_col) { - int is_active_edge = 0; - int top_edge = 0; - int bottom_edge = cpi->common.mi_rows; - int left_edge = 0; - int right_edge = cpi->common.mi_cols; - - // 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. - top_edge += (int)(twopass->this_frame_stats.inactive_zone_rows * 2); - - bottom_edge -= (int)(twopass->this_frame_stats.inactive_zone_rows * 2); - 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; - } - - return is_active_edge; -} // Look at all the mode_info entries for blocks that are part of this // partition and find the min and max values for sb_type. @@ -2253,7 +2221,7 @@ // Test for blocks at the edge of the active image. // This may be the actual edge of the image or where there are formatting // bars. - if (active_edge_sb(cpi, mi_row, mi_col)) { + if (vp9_active_edge_sb(cpi, mi_row, mi_col)) { min_size = BLOCK_4X4; } else { min_size = MIN(cpi->sf.rd_auto_partition_min_limit,
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index a85b70b..61279f8 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c
@@ -126,6 +126,7 @@ stats->pcnt_neutral, stats->intra_skip_pct, stats->inactive_zone_rows, + stats->inactive_zone_cols, stats->MVr, stats->mvr_abs, stats->MVc, @@ -164,6 +165,7 @@ section->pcnt_neutral = 0.0; section->intra_skip_pct = 0.0; section->inactive_zone_rows = 0.0; + section->inactive_zone_cols = 0.0; section->MVr = 0.0; section->mvr_abs = 0.0; section->MVc = 0.0; @@ -191,6 +193,7 @@ section->pcnt_neutral += frame->pcnt_neutral; section->intra_skip_pct += frame->intra_skip_pct; section->inactive_zone_rows += frame->inactive_zone_rows; + section->inactive_zone_cols += frame->inactive_zone_cols; section->MVr += frame->MVr; section->mvr_abs += frame->mvr_abs; section->MVc += frame->MVc; @@ -216,6 +219,7 @@ section->pcnt_neutral -= frame->pcnt_neutral; section->intra_skip_pct -= frame->intra_skip_pct; section->inactive_zone_rows -= frame->inactive_zone_rows; + section->inactive_zone_cols -= frame->inactive_zone_cols; section->MVr -= frame->MVr; section->mvr_abs -= frame->mvr_abs; section->MVc -= frame->MVc; @@ -1050,6 +1054,7 @@ fps.pcnt_neutral = (double)neutral_count / num_mbs; fps.intra_skip_pct = (double)intra_skip_count / num_mbs; fps.inactive_zone_rows = (double)image_data_start_row; + fps.inactive_zone_cols = (double)0; // TODO(paulwilkins): fix if (mvcount > 0) { fps.MVr = (double)sum_mvr / mvcount;
diff --git a/vp9/encoder/vp9_firstpass.h b/vp9/encoder/vp9_firstpass.h index 0047932..49f9da3 100644 --- a/vp9/encoder/vp9_firstpass.h +++ b/vp9/encoder/vp9_firstpass.h
@@ -53,6 +53,7 @@ double pcnt_neutral; double intra_skip_pct; double inactive_zone_rows; // Image mask rows top and bottom. + double inactive_zone_cols; // Image mask columns at left and right edges. double MVr; double mvr_abs; double MVc;
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c index 3a27e89..409300b 100644 --- a/vp9/encoder/vp9_rdopt.c +++ b/vp9/encoder/vp9_rdopt.c
@@ -2898,6 +2898,47 @@ *this_rd += (*this_rd * var_factor) / 100; } + +// Do we have an internal image edge (e.g. formatting bars). +int vp9_internal_image_edge(VP9_COMP *cpi) { + return (cpi->oxcf.pass == 2) && + ((cpi->twopass.this_frame_stats.inactive_zone_rows > 0) || + (cpi->twopass.this_frame_stats.inactive_zone_cols > 0)); +} + +// Checks to see if a macro 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) { + int is_active_edge = 0; + int top_edge = 0; + int bottom_edge = cpi->common.mi_rows; + int left_edge = 0; + int right_edge = cpi->common.mi_cols; + + // 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. + top_edge += (int)(twopass->this_frame_stats.inactive_zone_rows * 2); + + bottom_edge -= (int)(twopass->this_frame_stats.inactive_zone_rows * 2); + 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; + } + + return is_active_edge; +} + void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, TileDataEnc *tile_data, MACROBLOCK *x, @@ -3751,13 +3792,15 @@ int skip_uv; PREDICTION_MODE mode_uv = DC_PRED; const int intra_cost_penalty = vp9_get_intra_cost_penalty( - cm->base_qindex, cm->y_dc_delta_q, cm->bit_depth); + cm->base_qindex, cm->y_dc_delta_q, cm->bit_depth); int_mv seg_mvs[4][MAX_REF_FRAMES]; b_mode_info best_bmodes[4]; int best_skip2 = 0; int ref_frame_skip_mask[2] = { 0 }; int64_t mask_filter = 0; int64_t filter_cache[SWITCHABLE_FILTER_CONTEXTS]; + int internal_active_edge = + vp9_active_edge_sb(cpi, mi_row, mi_col) && vp9_internal_image_edge(cpi); x->skip_encode = sf->skip_encode_frame && x->q_index < QIDX_SKIP_THRESH; memset(x->zcoeff_blk[TX_4X4], 0, 4); @@ -3843,7 +3886,8 @@ continue; // Test best rd so far against threshold for trying this mode. - if (rd_less_than_thresh(best_rd, + if (!internal_active_edge && + rd_less_than_thresh(best_rd, rd_opt->threshes[segment_id][bsize][ref_index], tile_data->thresh_freq_fact[bsize][ref_index])) continue;
diff --git a/vp9/encoder/vp9_rdopt.h b/vp9/encoder/vp9_rdopt.h index 459b032..16a8c68 100644 --- a/vp9/encoder/vp9_rdopt.h +++ b/vp9/encoder/vp9_rdopt.h
@@ -54,6 +54,9 @@ PICK_MODE_CONTEXT *ctx, int64_t best_rd_so_far); +int vp9_internal_image_edge(struct VP9_COMP *cpi); +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, struct TileDataEnc *tile_data, struct macroblock *x, @@ -61,6 +64,7 @@ struct RD_COST *rd_cost, BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx, int64_t best_rd_so_far); + #ifdef __cplusplus } // extern "C" #endif
diff --git a/vp9/encoder/vp9_speed_features.c b/vp9/encoder/vp9_speed_features.c index 6c6c4ed..b3e5a0e 100644 --- a/vp9/encoder/vp9_speed_features.c +++ b/vp9/encoder/vp9_speed_features.c
@@ -12,6 +12,8 @@ #include "vp9/encoder/vp9_encoder.h" #include "vp9/encoder/vp9_speed_features.h" +#include "vp9/encoder/vp9_rdopt.h" + // Intra only frames, golden frames (except alt ref overlays) and // alt ref frames tend to be coded at a higher than ambient quality @@ -90,7 +92,8 @@ // 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. if ((speed >= 1) && (cpi->oxcf.pass == 2) && - (cpi->twopass.fr_content_type == FC_GRAPHICS_ANIMATION)) { + ((cpi->twopass.fr_content_type == FC_GRAPHICS_ANIMATION) || + (vp9_internal_image_edge(cpi)))) { sf->disable_split_mask = DISABLE_COMPOUND_SPLIT; }