diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index e197bca16..4f44b43b9 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -2122,38 +2122,6 @@ static const BLOCK_SIZE max_partition_size[BLOCK_SIZES] = { 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. @@ -2252,7 +2220,7 @@ static void rd_auto_partition_range(VP9_COMP *cpi, const TileInfo *const tile, // 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 a85b70b99..61279f872 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -126,6 +126,7 @@ static void output_stats(FIRSTPASS_STATS *stats, 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 @@ static void zero_stats(FIRSTPASS_STATS *section) { 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 @@ static void accumulate_stats(FIRSTPASS_STATS *section, 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 @@ static void subtract_stats(FIRSTPASS_STATS *section, 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 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) { 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 00479322d..49f9da38e 100644 --- a/vp9/encoder/vp9_firstpass.h +++ b/vp9/encoder/vp9_firstpass.h @@ -53,6 +53,7 @@ typedef struct { 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 3a27e8989..409300b8f 100644 --- a/vp9/encoder/vp9_rdopt.c +++ b/vp9/encoder/vp9_rdopt.c @@ -2898,6 +2898,47 @@ static void rd_variance_adjustment(VP9_COMP *cpi, *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 @@ void vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, 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 @@ void vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, 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 459b0324b..16a8c68ee 100644 --- a/vp9/encoder/vp9_rdopt.h +++ b/vp9/encoder/vp9_rdopt.h @@ -54,6 +54,9 @@ void vp9_rd_pick_inter_mode_sb_seg_skip(struct VP9_COMP *cpi, 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 @@ void vp9_rd_pick_inter_mode_sub8x8(struct VP9_COMP *cpi, 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 6c6c4ed30..b3e5a0e4d 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 @@ 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. 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; }