diff options
Diffstat (limited to 'vp9/encoder')
-rw-r--r-- | vp9/encoder/vp9_aq_cyclicrefresh.c | 28 | ||||
-rw-r--r-- | vp9/encoder/vp9_aq_cyclicrefresh.h | 3 | ||||
-rw-r--r-- | vp9/encoder/vp9_avg.c | 29 | ||||
-rw-r--r-- | vp9/encoder/vp9_bitstream.c | 14 | ||||
-rw-r--r-- | vp9/encoder/vp9_encodeframe.c | 31 | ||||
-rw-r--r-- | vp9/encoder/vp9_encoder.c | 5 | ||||
-rw-r--r-- | vp9/encoder/vp9_encoder.h | 1 | ||||
-rw-r--r-- | vp9/encoder/vp9_ethread.c | 34 | ||||
-rw-r--r-- | vp9/encoder/vp9_firstpass.c | 95 | ||||
-rw-r--r-- | vp9/encoder/vp9_firstpass.h | 11 | ||||
-rw-r--r-- | vp9/encoder/vp9_pickmode.c | 13 | ||||
-rw-r--r-- | vp9/encoder/vp9_quantize.c | 2 | ||||
-rw-r--r-- | vp9/encoder/vp9_rdopt.c | 27 | ||||
-rw-r--r-- | vp9/encoder/vp9_resize.c | 20 | ||||
-rw-r--r-- | vp9/encoder/vp9_speed_features.c | 61 | ||||
-rw-r--r-- | vp9/encoder/vp9_svc_layercontext.c | 1 | ||||
-rw-r--r-- | vp9/encoder/vp9_tokenize.c | 6 | ||||
-rw-r--r-- | vp9/encoder/x86/vp9_avg_intrin_sse2.c | 9 |
18 files changed, 265 insertions, 125 deletions
diff --git a/vp9/encoder/vp9_aq_cyclicrefresh.c b/vp9/encoder/vp9_aq_cyclicrefresh.c index 4b1c95957..df70d48f8 100644 --- a/vp9/encoder/vp9_aq_cyclicrefresh.c +++ b/vp9/encoder/vp9_aq_cyclicrefresh.c @@ -48,6 +48,8 @@ struct CYCLIC_REFRESH { int16_t motion_thresh; // Rate target ratio to set q delta. double rate_ratio_qdelta; + // Boost factor for rate target ratio, for segment CR_SEGMENT_ID_BOOST2. + double rate_boost_fac; double low_content_avg; int qindex_delta_seg1; int qindex_delta_seg2; @@ -420,18 +422,30 @@ static void cyclic_refresh_update_map(VP9_COMP *const cpi) { cr->sb_index = i; } -// Set/update global/frame level cyclic refresh parameters. +// Set cyclic refresh parameters. void vp9_cyclic_refresh_update_parameters(VP9_COMP *const cpi) { const RATE_CONTROL *const rc = &cpi->rc; + const VP9_COMMON *const cm = &cpi->common; CYCLIC_REFRESH *const cr = cpi->cyclic_refresh; cr->percent_refresh = 10; + cr->max_qdelta_perc = 50; + cr->time_for_refresh = 0; // Use larger delta-qp (increase rate_ratio_qdelta) for first few (~4) - // periods of the refresh cycle, after a key frame. This corresponds to ~40 - // frames with cr->percent_refresh = 10. - if (rc->frames_since_key < 40) + // periods of the refresh cycle, after a key frame. + if (rc->frames_since_key < 4 * cr->percent_refresh) cr->rate_ratio_qdelta = 3.0; else cr->rate_ratio_qdelta = 2.0; + // Adjust some parameters for low resolutions at low bitrates. + if (cm->width <= 352 && + cm->height <= 288 && + rc->avg_frame_bandwidth < 3400) { + cr->motion_thresh = 4; + cr->rate_boost_fac = 1.25; + } else { + cr->motion_thresh = 32; + cr->rate_boost_fac = 1.7; + } } // Setup cyclic background refresh: set delta q and segmentation map. @@ -460,8 +474,6 @@ void vp9_cyclic_refresh_setup(VP9_COMP *const cpi) { int qindex2; const double q = vp9_convert_qindex_to_q(cm->base_qindex, cm->bit_depth); vp9_clear_system_state(); - cr->max_qdelta_perc = 50; - cr->time_for_refresh = 0; // Set rate threshold to some multiple (set to 2 for now) of the target // rate (target is given by sb64_target_rate and scaled by 256). cr->thresh_rate_sb = ((int64_t)(rc->sb64_target_rate) << 8) << 2; @@ -469,7 +481,7 @@ void vp9_cyclic_refresh_setup(VP9_COMP *const cpi) { // q will not exceed 457, so (q * q) is within 32bit; see: // vp9_convert_qindex_to_q(), vp9_ac_quant(), ac_qlookup*[]. cr->thresh_dist_sb = ((int64_t)(q * q)) << 2; - cr->motion_thresh = 32; + // Set up segmentation. // Clear down the segment map. vp9_enable_segmentation(&cm->seg); @@ -505,7 +517,7 @@ void vp9_cyclic_refresh_setup(VP9_COMP *const cpi) { // Set a more aggressive (higher) q delta for segment BOOST2. qindex_delta = compute_deltaq(cpi, cm->base_qindex, MIN(CR_MAX_RATE_TARGET_RATIO, - CR_BOOST2_FAC * cr->rate_ratio_qdelta)); + cr->rate_boost_fac * cr->rate_ratio_qdelta)); cr->qindex_delta_seg2 = qindex_delta; vp9_set_segdata(seg, CR_SEGMENT_ID_BOOST2, SEG_LVL_ALT_Q, qindex_delta); diff --git a/vp9/encoder/vp9_aq_cyclicrefresh.h b/vp9/encoder/vp9_aq_cyclicrefresh.h index 21f114b5e..99bb98ec8 100644 --- a/vp9/encoder/vp9_aq_cyclicrefresh.h +++ b/vp9/encoder/vp9_aq_cyclicrefresh.h @@ -27,9 +27,6 @@ extern "C" { // Maximum rate target ratio for setting segment delta-qp. #define CR_MAX_RATE_TARGET_RATIO 4.0 -// Boost factor for rate target ratio, for segment CR_SEGMENT_ID_BOOST2. -#define CR_BOOST2_FAC 1.7 - struct VP9_COMP; struct CYCLIC_REFRESH; diff --git a/vp9/encoder/vp9_avg.c b/vp9/encoder/vp9_avg.c index b9987c1ce..437356681 100644 --- a/vp9/encoder/vp9_avg.c +++ b/vp9/encoder/vp9_avg.c @@ -29,6 +29,8 @@ unsigned int vp9_avg_4x4_c(const uint8_t *s, int p) { return (sum + 8) >> 4; } +// src_diff: first pass, 9 bit, dynamic range [-255, 255] +// second pass, 12 bit, dynamic range [-2040, 2040] static void hadamard_col8(const int16_t *src_diff, int src_stride, int16_t *coeff) { int16_t b0 = src_diff[0 * src_stride] + src_diff[1 * src_stride]; @@ -65,15 +67,18 @@ void vp9_hadamard_8x8_c(int16_t const *src_diff, int src_stride, int16_t buffer[64]; int16_t *tmp_buf = &buffer[0]; for (idx = 0; idx < 8; ++idx) { - hadamard_col8(src_diff, src_stride, tmp_buf); + hadamard_col8(src_diff, src_stride, tmp_buf); // src_diff: 9 bit + // dynamic range [-255, 255] tmp_buf += 8; ++src_diff; } tmp_buf = &buffer[0]; for (idx = 0; idx < 8; ++idx) { - hadamard_col8(tmp_buf, 8, coeff); - coeff += 8; + hadamard_col8(tmp_buf, 8, coeff); // tmp_buf: 12 bit + // dynamic range [-2040, 2040] + coeff += 8; // coeff: 15 bit + // dynamic range [-16320, 16320] ++tmp_buf; } } @@ -83,26 +88,28 @@ void vp9_hadamard_16x16_c(int16_t const *src_diff, int src_stride, int16_t *coeff) { int idx; for (idx = 0; idx < 4; ++idx) { + // src_diff: 9 bit, dynamic range [-255, 255] int16_t const *src_ptr = src_diff + (idx >> 1) * 8 * src_stride + (idx & 0x01) * 8; vp9_hadamard_8x8_c(src_ptr, src_stride, coeff + idx * 64); } + // coeff: 15 bit, dynamic range [-16320, 16320] for (idx = 0; idx < 64; ++idx) { int16_t a0 = coeff[0]; int16_t a1 = coeff[64]; int16_t a2 = coeff[128]; int16_t a3 = coeff[192]; - int16_t b0 = a0 + a1; - int16_t b1 = a0 - a1; - int16_t b2 = a2 + a3; - int16_t b3 = a2 - a3; + int16_t b0 = (a0 + a1) >> 1; // (a0 + a1): 16 bit, [-32640, 32640] + int16_t b1 = (a0 - a1) >> 1; // b0-b3: 15 bit, dynamic range + int16_t b2 = (a2 + a3) >> 1; // [-16320, 16320] + int16_t b3 = (a2 - a3) >> 1; - coeff[0] = (b0 + b2) >> 1; - coeff[64] = (b1 + b3) >> 1; - coeff[128] = (b0 - b2) >> 1; - coeff[192] = (b1 - b3) >> 1; + coeff[0] = b0 + b2; // 16 bit, [-32640, 32640] + coeff[64] = b1 + b3; + coeff[128] = b0 - b2; + coeff[192] = b1 - b3; ++coeff; } diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c index 9b493d7d2..1ebdd066b 100644 --- a/vp9/encoder/vp9_bitstream.c +++ b/vp9/encoder/vp9_bitstream.c @@ -93,7 +93,7 @@ static void write_selected_tx_size(const VP9_COMMON *cm, static int write_skip(const VP9_COMMON *cm, const MACROBLOCKD *xd, int segment_id, const MODE_INFO *mi, vp9_writer *w) { - if (vp9_segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)) { + if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)) { return 1; } else { const int skip = mi->mbmi.skip; @@ -207,10 +207,10 @@ static void write_ref_frames(const VP9_COMMON *cm, const MACROBLOCKD *xd, // If segment level coding of this signal is disabled... // or the segment allows multiple reference frame options - if (vp9_segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME)) { + if (segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME)) { assert(!is_compound); assert(mbmi->ref_frame[0] == - vp9_get_segdata(&cm->seg, segment_id, SEG_LVL_REF_FRAME)); + get_segdata(&cm->seg, segment_id, SEG_LVL_REF_FRAME)); } else { // does the feature use compound prediction or not // (if not specified at the frame/segment level) @@ -264,7 +264,7 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, const MODE_INFO *mi, skip = write_skip(cm, xd, segment_id, mi, w); - if (!vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) + if (!segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) vp9_write(w, is_inter, vp9_get_intra_inter_prob(cm, xd)); if (bsize >= BLOCK_8X8 && cm->tx_mode == TX_MODE_SELECT && @@ -293,7 +293,7 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, const MODE_INFO *mi, write_ref_frames(cm, xd, w); // If segment skip is not enabled code the mode. - if (!vp9_segfeature_active(seg, segment_id, SEG_LVL_SKIP)) { + if (!segfeature_active(seg, segment_id, SEG_LVL_SKIP)) { if (bsize >= BLOCK_8X8) { write_inter_mode(w, mode, inter_probs); } @@ -790,10 +790,10 @@ static void encode_segmentation(VP9_COMMON *cm, MACROBLOCKD *xd, for (i = 0; i < MAX_SEGMENTS; i++) { for (j = 0; j < SEG_LVL_MAX; j++) { - const int active = vp9_segfeature_active(seg, i, j); + const int active = segfeature_active(seg, i, j); vp9_wb_write_bit(wb, active); if (active) { - const int data = vp9_get_segdata(seg, i, j); + const int data = get_segdata(seg, i, j); const int data_max = vp9_seg_feature_data_max(j); if (vp9_is_segfeature_signed(j)) { diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index 49e888768..5299244d9 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -370,6 +370,7 @@ static void sum_2_variances(const var *a, const var *b, var *r) { static void fill_variance_tree(void *data, BLOCK_SIZE bsize) { variance_node node; + memset(&node, 0, sizeof(node)); tree_to_node(data, bsize, &node); sum_2_variances(node.split[0], node.split[1], &node.part_variances->horz[0]); sum_2_variances(node.split[2], node.split[3], &node.part_variances->horz[1]); @@ -1050,7 +1051,7 @@ static void update_state(VP9_COMP *cpi, ThreadData *td, if (!output_enabled) return; - if (!vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) { + if (!segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) { for (i = 0; i < TX_MODES; i++) rdc->tx_select_diff[i] += ctx->tx_rd_diff[i]; } @@ -1247,7 +1248,7 @@ static void rd_pick_sb_modes(VP9_COMP *cpi, vp9_rd_pick_intra_mode_sb(cpi, x, rd_cost, bsize, ctx, best_rd); } else { if (bsize >= BLOCK_8X8) { - if (vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) + if (segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) vp9_rd_pick_inter_mode_sb_seg_skip(cpi, tile_data, x, rd_cost, bsize, ctx, best_rd); else @@ -1290,8 +1291,8 @@ static void update_stats(VP9_COMMON *cm, ThreadData *td) { if (!frame_is_intra_only(cm)) { FRAME_COUNTS *const counts = td->counts; const int inter_block = is_inter_block(mbmi); - const int seg_ref_active = vp9_segfeature_active(&cm->seg, mbmi->segment_id, - SEG_LVL_REF_FRAME); + const int seg_ref_active = segfeature_active(&cm->seg, mbmi->segment_id, + SEG_LVL_REF_FRAME); if (!seg_ref_active) { counts->intra_inter[vp9_get_intra_inter_context(xd)][inter_block]++; // If the segment reference feature is enabled we have only a single @@ -1316,7 +1317,7 @@ static void update_stats(VP9_COMMON *cm, ThreadData *td) { } } if (inter_block && - !vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) { + !segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) { const int mode_ctx = mbmi->mode_context[mbmi->ref_frame[0]]; if (bsize >= BLOCK_8X8) { const PREDICTION_MODE mode = mbmi->mode; @@ -1563,7 +1564,7 @@ static void set_fixed_partitioning(VP9_COMP *cpi, const TileInfo *const tile, } } -const struct { +static const struct { int row; int col; } coord_lookup[16] = { @@ -2848,7 +2849,7 @@ static void encode_rd_sb_row(VP9_COMP *cpi, const uint8_t *const map = seg->update_map ? cpi->segmentation_map : cm->last_frame_seg_map; int segment_id = vp9_get_segment_id(cm, map, BLOCK_64X64, mi_row, mi_col); - seg_skip = vp9_segfeature_active(seg, segment_id, SEG_LVL_SKIP); + seg_skip = segfeature_active(seg, segment_id, SEG_LVL_SKIP); } x->source_variance = UINT_MAX; @@ -2908,7 +2909,7 @@ static void init_encode_frame_mb_context(VP9_COMP *cpi) { static int check_dual_ref_flags(VP9_COMP *cpi) { const int ref_flags = cpi->ref_frame_flags; - if (vp9_segfeature_active(&cpi->common.seg, 1, SEG_LVL_REF_FRAME)) { + if (segfeature_active(&cpi->common.seg, 1, SEG_LVL_REF_FRAME)) { return 0; } else { return (!!(ref_flags & VP9_GOLD_FLAG) + !!(ref_flags & VP9_LAST_FLAG) @@ -2983,7 +2984,7 @@ static void nonrd_pick_sb_modes(VP9_COMP *cpi, if (cm->frame_type == KEY_FRAME) hybrid_intra_mode_search(cpi, x, rd_cost, bsize, ctx); - else if (vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) + else if (segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) set_mode_info_seg_skip(x, cm->tx_mode, rd_cost, bsize); else if (bsize >= BLOCK_8X8) vp9_pick_inter_mode(cpi, x, tile_data, mi_row, mi_col, @@ -3598,7 +3599,7 @@ static void encode_nonrd_sb_row(VP9_COMP *cpi, const uint8_t *const map = seg->update_map ? cpi->segmentation_map : cm->last_frame_seg_map; int segment_id = vp9_get_segment_id(cm, map, BLOCK_64X64, mi_row, mi_col); - seg_skip = vp9_segfeature_active(seg, segment_id, SEG_LVL_SKIP); + seg_skip = segfeature_active(seg, segment_id, SEG_LVL_SKIP); if (seg_skip) { partition_search_type = FIXED_PARTITION; } @@ -3785,9 +3786,13 @@ void vp9_init_tile_data(VP9_COMP *cpi) { TOKENEXTRA *pre_tok = cpi->tile_tok[0][0]; int tile_tok = 0; - if (cpi->tile_data == NULL) { + if (cpi->tile_data == NULL || cpi->allocated_tiles < tile_cols * tile_rows) { + if (cpi->tile_data != NULL) + vpx_free(cpi->tile_data); CHECK_MEM_ERROR(cm, cpi->tile_data, vpx_malloc(tile_cols * tile_rows * sizeof(*cpi->tile_data))); + cpi->allocated_tiles = tile_cols * tile_rows; + for (tile_row = 0; tile_row < tile_rows; ++tile_row) for (tile_col = 0; tile_col < tile_cols; ++tile_col) { TileDataEnc *tile_data = @@ -4156,8 +4161,8 @@ static void encode_superblock(VP9_COMP *cpi, ThreadData *td, MODE_INFO **mi_8x8 = xd->mi; MODE_INFO *mi = mi_8x8[0]; MB_MODE_INFO *mbmi = &mi->mbmi; - const int seg_skip = vp9_segfeature_active(&cm->seg, mbmi->segment_id, - SEG_LVL_SKIP); + const int seg_skip = segfeature_active(&cm->seg, mbmi->segment_id, + SEG_LVL_SKIP); const int mis = cm->mi_stride; const int mi_width = num_8x8_blocks_wide_lookup[bsize]; const int mi_height = num_8x8_blocks_high_lookup[bsize]; diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index b79bc00d2..ba38d640d 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -2872,7 +2872,7 @@ static void output_frame_level_debug_stats(VP9_COMP *cpi) { "%7.2lf %7.2lf %7.2lf %7.2lf %7.2lf" "%6d %6d %5d %5d %5d " "%10"PRId64" %10.3lf" - "%10lf %8u %10"PRId64" %10d %10d\n", + "%10lf %8u %10"PRId64" %10d %10d %10d\n", cpi->common.current_video_frame, cm->width, cm->height, cpi->rc.source_alt_ref_pending, @@ -2901,7 +2901,8 @@ static void output_frame_level_debug_stats(VP9_COMP *cpi) { cpi->twopass.bits_left / (1 + cpi->twopass.total_left_stats.coded_error), cpi->tot_recode_hits, recon_err, cpi->rc.kf_boost, - cpi->twopass.kf_zeromotion_pct); + cpi->twopass.kf_zeromotion_pct, + cpi->twopass.fr_content_type); fclose(f); diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h index 6ce4a67cd..4d2a186e8 100644 --- a/vp9/encoder/vp9_encoder.h +++ b/vp9/encoder/vp9_encoder.h @@ -306,6 +306,7 @@ typedef struct VP9_COMP { YV12_BUFFER_CONFIG scaled_last_source; TileDataEnc *tile_data; + int allocated_tiles; // Keep track of memory allocated for tiles. // For a still frame, this flag is set to 1 to skip partition search. int partition_search_skippable_frame; diff --git a/vp9/encoder/vp9_ethread.c b/vp9/encoder/vp9_ethread.c index 8700ccdae..4ae3fbc54 100644 --- a/vp9/encoder/vp9_ethread.c +++ b/vp9/encoder/vp9_ethread.c @@ -54,6 +54,18 @@ static int enc_worker_hook(EncWorkerData *const thread_data, void *unused) { return 0; } +static int get_max_tile_cols(VP9_COMP *cpi) { + const int aligned_width = ALIGN_POWER_OF_TWO(cpi->oxcf.width, MI_SIZE_LOG2); + int mi_cols = aligned_width >> MI_SIZE_LOG2; + int min_log2_tile_cols, max_log2_tile_cols; + int log2_tile_cols; + + vp9_get_tile_n_bits(mi_cols, &min_log2_tile_cols, &max_log2_tile_cols); + log2_tile_cols = clamp(cpi->oxcf.tile_columns, + min_log2_tile_cols, max_log2_tile_cols); + return (1 << log2_tile_cols); +} + void vp9_encode_tiles_mt(VP9_COMP *cpi) { VP9_COMMON *const cm = &cpi->common; const int tile_cols = 1 << cm->log2_tile_cols; @@ -65,20 +77,30 @@ void vp9_encode_tiles_mt(VP9_COMP *cpi) { // Only run once to create threads and allocate thread data. if (cpi->num_workers == 0) { + int allocated_workers = num_workers; + + // While using SVC, we need to allocate threads according to the highest + // resolution. + if (cpi->use_svc) { + int max_tile_cols = get_max_tile_cols(cpi); + allocated_workers = MIN(cpi->oxcf.max_threads, max_tile_cols); + } + CHECK_MEM_ERROR(cm, cpi->workers, - vpx_malloc(num_workers * sizeof(*cpi->workers))); + vpx_malloc(allocated_workers * sizeof(*cpi->workers))); CHECK_MEM_ERROR(cm, cpi->tile_thr_data, - vpx_calloc(num_workers, sizeof(*cpi->tile_thr_data))); + vpx_calloc(allocated_workers, + sizeof(*cpi->tile_thr_data))); - for (i = 0; i < num_workers; i++) { + for (i = 0; i < allocated_workers; i++) { VP9Worker *const worker = &cpi->workers[i]; EncWorkerData *thread_data = &cpi->tile_thr_data[i]; ++cpi->num_workers; winterface->init(worker); - if (i < num_workers - 1) { + if (i < allocated_workers - 1) { thread_data->cpi = cpi; // Allocate thread data. @@ -154,7 +176,7 @@ void vp9_encode_tiles_mt(VP9_COMP *cpi) { // Set the starting tile for each thread. thread_data->start = i; - if (i == num_workers - 1) + if (i == cpi->num_workers - 1) winterface->execute(worker); else winterface->launch(worker); @@ -171,7 +193,7 @@ void vp9_encode_tiles_mt(VP9_COMP *cpi) { EncWorkerData *const thread_data = (EncWorkerData*)worker->data1; // Accumulate counters. - if (i < num_workers - 1) { + if (i < cpi->num_workers - 1) { vp9_accumulate_frame_counts(cm, thread_data->td->counts, 0); accumulate_rd_opt(&cpi->td, thread_data->td); } diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index 856a6655c..3d7843ea7 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -113,8 +113,8 @@ static void output_stats(FIRSTPASS_STATS *stats, fpfile = fopen("firstpass.stt", "a"); fprintf(fpfile, "%12.0lf %12.4lf %12.0lf %12.0lf %12.0lf %12.4lf %12.4lf" - "%12.4lf %12.4lf %12.4lf %12.4lf %12.4lf %12.4lf %12.4lf" - "%12.4lf %12.0lf %12.0lf %12.0lf %12.4lf\n", + "%12.4lf %12.4lf %12.4lf %12.4lf %12.4lf %12.4lf %12.4lf %12.4lf" + "%12.4lf %12.4lf %12.0lf %12.0lf %12.0lf %12.4lf\n", stats->frame, stats->weight, stats->intra_error, @@ -124,6 +124,8 @@ static void output_stats(FIRSTPASS_STATS *stats, stats->pcnt_motion, stats->pcnt_second_ref, stats->pcnt_neutral, + stats->intra_skip_pct, + stats->inactive_zone_rows, stats->MVr, stats->mvr_abs, stats->MVc, @@ -160,7 +162,9 @@ static void zero_stats(FIRSTPASS_STATS *section) { section->pcnt_motion = 0.0; section->pcnt_second_ref = 0.0; section->pcnt_neutral = 0.0; - section->MVr = 0.0; + section->intra_skip_pct = 0.0; + section->inactive_zone_rows = 0.0; + section->MVr = 0.0; section->mvr_abs = 0.0; section->MVc = 0.0; section->mvc_abs = 0.0; @@ -185,7 +189,9 @@ static void accumulate_stats(FIRSTPASS_STATS *section, section->pcnt_motion += frame->pcnt_motion; section->pcnt_second_ref += frame->pcnt_second_ref; section->pcnt_neutral += frame->pcnt_neutral; - section->MVr += frame->MVr; + section->intra_skip_pct += frame->intra_skip_pct; + section->inactive_zone_rows += frame->inactive_zone_rows; + section->MVr += frame->MVr; section->mvr_abs += frame->mvr_abs; section->MVc += frame->MVc; section->mvc_abs += frame->mvc_abs; @@ -208,7 +214,9 @@ static void subtract_stats(FIRSTPASS_STATS *section, section->pcnt_motion -= frame->pcnt_motion; section->pcnt_second_ref -= frame->pcnt_second_ref; section->pcnt_neutral -= frame->pcnt_neutral; - section->MVr -= frame->MVr; + section->intra_skip_pct -= frame->intra_skip_pct; + section->inactive_zone_rows -= frame->inactive_zone_rows; + section->MVr -= frame->MVr; section->mvr_abs -= frame->mvr_abs; section->MVc -= frame->MVc; section->mvc_abs -= frame->mvc_abs; @@ -453,6 +461,8 @@ static void set_first_pass_params(VP9_COMP *cpi) { cpi->rc.frames_to_key = INT_MAX; } +#define UL_INTRA_THRESH 50 +#define INVALID_ROW -1 void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) { int mb_row, mb_col; MACROBLOCK *const x = &cpi->td.mb; @@ -477,6 +487,8 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) { int second_ref_count = 0; const int intrapenalty = INTRA_MODE_PENALTY; double neutral_count; + int intra_skip_count = 0; + int image_data_start_row = INVALID_ROW; int new_mv_count = 0; int sum_in_vectors = 0; MV lastmv = {0, 0}; @@ -636,6 +648,18 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) { (bsize >= BLOCK_16X16 ? TX_16X16 : TX_8X8) : TX_4X4; vp9_encode_intra_block_plane(x, bsize, 0); this_error = vpx_get_mb_ss(x->plane[0].src_diff); + + // Keep a record of blocks that have almost no intra error residual + // (i.e. are in effect completely flat and untextured in the intra + // domain). In natural videos this is uncommon, but it is much more + // common in animations, graphics and screen content, so may be used + // as a signal to detect these types of content. + if (this_error < UL_INTRA_THRESH) { + ++intra_skip_count; + } else if ((mb_col > 0) && (image_data_start_row == INVALID_ROW)) { + image_data_start_row = mb_row; + } + #if CONFIG_VP9_HIGHBITDEPTH if (cm->use_highbitdepth) { switch (cm->bit_depth) { @@ -963,6 +987,18 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) { vp9_clear_system_state(); } + // Clamp the image start to rows/2. This number of rows is discarded top + // and bottom as dead data so rows / 2 means the frame is blank. + if ((image_data_start_row > cm->mb_rows / 2) || + (image_data_start_row == INVALID_ROW)) { + image_data_start_row = cm->mb_rows / 2; + } + // Exclude any image dead zone + if (image_data_start_row > 0) { + intra_skip_count = + MAX(0, intra_skip_count - (image_data_start_row * cm->mb_cols * 2)); + } + { FIRSTPASS_STATS fps; // The minimum error here insures some bit allocation to frames even @@ -987,6 +1023,8 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) { fps.pcnt_inter = (double)intercount / num_mbs; fps.pcnt_second_ref = (double)second_ref_count / num_mbs; 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; if (mvcount > 0) { fps.MVr = (double)sum_mvr / mvcount; @@ -1108,21 +1146,25 @@ static double calc_correction_factor(double err_per_mb, static int get_twopass_worst_quality(const VP9_COMP *cpi, const double section_err, + double inactive_zone, int section_target_bandwidth, double group_weight_factor) { const RATE_CONTROL *const rc = &cpi->rc; const VP9EncoderConfig *const oxcf = &cpi->oxcf; + inactive_zone = fclamp(inactive_zone, 0.0, 1.0); + if (section_target_bandwidth <= 0) { return rc->worst_quality; // Highest value allowed } else { const int num_mbs = (cpi->oxcf.resize_mode != RESIZE_NONE) ? cpi->initial_mbs : cpi->common.MBs; - const double err_per_mb = section_err / num_mbs; + const int active_mbs = MAX(1, num_mbs - (int)(num_mbs * inactive_zone)); + const double av_err_per_mb = section_err / active_mbs; const double speed_term = 1.0 + 0.04 * oxcf->speed; - const double ediv_size_correction = num_mbs / EDIV_SIZE_FACTOR; + const double ediv_size_correction = (double)num_mbs / EDIV_SIZE_FACTOR; const int target_norm_bits_per_mb = ((uint64_t)section_target_bandwidth << - BPER_MB_NORMBITS) / num_mbs; + BPER_MB_NORMBITS) / active_mbs; int q; int is_svc_upper_layer = 0; @@ -1135,7 +1177,7 @@ static int get_twopass_worst_quality(const VP9_COMP *cpi, // content at the given rate. for (q = rc->best_quality; q < rc->worst_quality; ++q) { const double factor = - calc_correction_factor(err_per_mb, + calc_correction_factor(av_err_per_mb, ERR_DIVISOR - ediv_size_correction, is_svc_upper_layer ? SVC_FACTOR_PT_LOW : FACTOR_PT_LOW, FACTOR_PT_HIGH, q, @@ -1414,6 +1456,8 @@ static double calc_frame_boost(VP9_COMP *cpi, const int num_mbs = (cpi->oxcf.resize_mode != RESIZE_NONE) ? cpi->initial_mbs : cpi->common.MBs; + // TODO(paulwilkins): correct for dead zone + // Underlying boost factor is based on inter error ratio. frame_boost = (BASELINE_ERR_PER_MB * num_mbs) / DOUBLE_DIVIDE_CHECK(this_frame->coded_error); @@ -1779,6 +1823,8 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { #if GROUP_ADAPTIVE_MAXQ double gf_group_raw_error = 0.0; #endif + double gf_group_skip_pct = 0.0; + double gf_group_inactive_zone_rows = 0.0; double gf_first_frame_err = 0.0; double mod_frame_err = 0.0; @@ -1828,6 +1874,8 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { #if GROUP_ADAPTIVE_MAXQ gf_group_raw_error -= this_frame->coded_error; #endif + gf_group_skip_pct -= this_frame->intra_skip_pct; + gf_group_inactive_zone_rows -= this_frame->inactive_zone_rows; } // Motion breakout threshold for loop below depends on image size. @@ -1872,6 +1920,8 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { #if GROUP_ADAPTIVE_MAXQ gf_group_raw_error += this_frame->coded_error; #endif + gf_group_skip_pct += this_frame->intra_skip_pct; + gf_group_inactive_zone_rows += this_frame->inactive_zone_rows; if (EOF == input_stats(twopass, &next_frame)) break; @@ -1974,6 +2024,8 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { #if GROUP_ADAPTIVE_MAXQ gf_group_raw_error += this_frame->coded_error; #endif + gf_group_skip_pct += this_frame->intra_skip_pct; + gf_group_inactive_zone_rows += this_frame->inactive_zone_rows; } rc->baseline_gf_interval = new_gf_interval; } @@ -1996,6 +2048,12 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { const int vbr_group_bits_per_frame = (int)(gf_group_bits / rc->baseline_gf_interval); const double group_av_err = gf_group_raw_error / rc->baseline_gf_interval; + const double group_av_skip_pct = + gf_group_skip_pct / rc->baseline_gf_interval; + const double group_av_inactive_zone = + ((gf_group_inactive_zone_rows * 2) / + (rc->baseline_gf_interval * (double)cm->mb_rows)); + int tmp_q; // rc factor is a weight factor that corrects for local rate control drift. double rc_factor = 1.0; @@ -2007,7 +2065,9 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { (double)(100 - rc->rate_error_estimate) / 100.0); } tmp_q = - get_twopass_worst_quality(cpi, group_av_err, vbr_group_bits_per_frame, + get_twopass_worst_quality(cpi, group_av_err, + (group_av_skip_pct + group_av_inactive_zone), + vbr_group_bits_per_frame, twopass->kfgroup_inter_fraction * rc_factor); twopass->active_worst_quality = MAX(tmp_q, twopass->active_worst_quality >> 1); @@ -2546,10 +2606,17 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { // Special case code for first frame. const int section_target_bandwidth = (int)(twopass->bits_left / frames_left); + const double section_length = twopass->total_left_stats.count; const double section_error = - twopass->total_left_stats.coded_error / twopass->total_left_stats.count; + twopass->total_left_stats.coded_error / section_length; + const double section_intra_skip = + twopass->total_left_stats.intra_skip_pct / section_length; + const double section_inactive_zone = + (twopass->total_left_stats.inactive_zone_rows * 2) / + ((double)cm->mb_rows * section_length); const int tmp_q = get_twopass_worst_quality(cpi, section_error, + section_intra_skip + section_inactive_zone, section_target_bandwidth, DEFAULT_GRP_WEIGHT); twopass->active_worst_quality = tmp_q; @@ -2565,6 +2632,12 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { if (EOF == input_stats(twopass, &this_frame)) return; + // Set the frame content type flag. + if (this_frame.intra_skip_pct >= FC_ANIMATION_THRESH) + twopass->fr_content_type = FC_GRAPHICS_ANIMATION; + else + twopass->fr_content_type = FC_NORMAL; + // Keyframe and section processing. if (rc->frames_to_key == 0 || (cpi->frame_flags & FRAMEFLAGS_KEY)) { FIRSTPASS_STATS this_frame_copy; diff --git a/vp9/encoder/vp9_firstpass.h b/vp9/encoder/vp9_firstpass.h index 4a0385506..00479322d 100644 --- a/vp9/encoder/vp9_firstpass.h +++ b/vp9/encoder/vp9_firstpass.h @@ -51,6 +51,8 @@ typedef struct { double pcnt_motion; double pcnt_second_ref; double pcnt_neutral; + double intra_skip_pct; + double inactive_zone_rows; // Image mask rows top and bottom. double MVr; double mvr_abs; double MVc; @@ -73,6 +75,13 @@ typedef enum { FRAME_UPDATE_TYPES = 5 } FRAME_UPDATE_TYPE; +#define FC_ANIMATION_THRESH 0.15 +typedef enum { + FC_NORMAL = 0, + FC_GRAPHICS_ANIMATION = 1, + FRAME_CONTENT_TYPES = 2 +} FRAME_CONTENT_TYPE; + typedef struct { unsigned char index; RATE_FACTOR_LEVEL rf_level[(MAX_LAG_BUFFERS * 2) + 1]; @@ -103,6 +112,8 @@ typedef struct { uint8_t *this_frame_mb_stats; FIRSTPASS_MB_STATS firstpass_mb_stats; #endif + // An indication of the content type of the current frame + FRAME_CONTENT_TYPE fr_content_type; // Projected total bits available for a key frame group of frames int64_t kf_group_bits; diff --git a/vp9/encoder/vp9_pickmode.c b/vp9/encoder/vp9_pickmode.c index 2c7883183..2479b6e73 100644 --- a/vp9/encoder/vp9_pickmode.c +++ b/vp9/encoder/vp9_pickmode.c @@ -1179,7 +1179,8 @@ void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, if (cm->use_prev_frame_mvs) vp9_find_mv_refs(cm, xd, tile_info, xd->mi[0], ref_frame, - candidates, mi_row, mi_col, NULL, NULL); + candidates, mi_row, mi_col, NULL, NULL, + xd->mi[0]->mbmi.mode_context); else const_motion[ref_frame] = mv_refs_rt(cm, xd, tile_info, xd->mi[0], @@ -1658,7 +1659,8 @@ void vp9_pick_inter_mode_sub8x8(VP9_COMP *cpi, MACROBLOCK *x, vp9_setup_pred_block(xd, yv12_mb[ref_frame], yv12, mi_row, mi_col, sf, sf); vp9_find_mv_refs(cm, xd, tile_info, xd->mi[0], ref_frame, - candidates, mi_row, mi_col, NULL, NULL); + candidates, mi_row, mi_col, NULL, NULL, + xd->mi[0]->mbmi.mode_context); vp9_find_best_ref_mvs(xd, cm->allow_high_precision_mv, candidates, &dummy_mv[0], &dummy_mv[1]); @@ -1690,8 +1692,8 @@ void vp9_pick_inter_mode_sub8x8(VP9_COMP *cpi, MACROBLOCK *x, // If the segment reference frame feature is enabled.... // then do nothing if the current ref frame is not allowed.. - if (vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME) && - vp9_get_segdata(seg, segment_id, SEG_LVL_REF_FRAME) != (int)ref_frame) + if (segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME) && + get_segdata(seg, segment_id, SEG_LVL_REF_FRAME) != (int)ref_frame) continue; mbmi->ref_frame[0] = ref_frame; @@ -1732,7 +1734,8 @@ void vp9_pick_inter_mode_sub8x8(VP9_COMP *cpi, MACROBLOCK *x, b_mv[NEWMV].as_int = INVALID_MV; vp9_append_sub8x8_mvs_for_idx(cm, xd, tile_info, i, 0, mi_row, mi_col, &b_mv[NEARESTMV], - &b_mv[NEARMV]); + &b_mv[NEARMV], + xd->mi[0]->mbmi.mode_context); for (this_mode = NEARESTMV; this_mode <= NEWMV; ++this_mode) { int b_rate = 0; diff --git a/vp9/encoder/vp9_quantize.c b/vp9/encoder/vp9_quantize.c index db5460b6c..e6e17c073 100644 --- a/vp9/encoder/vp9_quantize.c +++ b/vp9/encoder/vp9_quantize.c @@ -678,7 +678,7 @@ void vp9_init_plane_quantizers(VP9_COMP *cpi, MACROBLOCK *x) { x->plane[i].quant_thred[1] = x->plane[i].zbin[1] * x->plane[i].zbin[1]; } - x->skip_block = vp9_segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP); + x->skip_block = segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP); x->q_index = qindex; x->errorperbit = rdmult >> 6; diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c index 9fa258c61..162d4de5f 100644 --- a/vp9/encoder/vp9_rdopt.c +++ b/vp9/encoder/vp9_rdopt.c @@ -1804,7 +1804,8 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x, frame_mv[ZEROMV][frame].as_int = 0; vp9_append_sub8x8_mvs_for_idx(cm, xd, tile, i, ref, mi_row, mi_col, &frame_mv[NEARESTMV][frame], - &frame_mv[NEARMV][frame]); + &frame_mv[NEARMV][frame], + xd->mi[0]->mbmi.mode_context); } // search for the best motion vector on this segment @@ -2119,8 +2120,8 @@ static void estimate_ref_frame_costs(const VP9_COMMON *cm, unsigned int *ref_costs_single, unsigned int *ref_costs_comp, vp9_prob *comp_mode_p) { - int seg_ref_active = vp9_segfeature_active(&cm->seg, segment_id, - SEG_LVL_REF_FRAME); + int seg_ref_active = segfeature_active(&cm->seg, segment_id, + SEG_LVL_REF_FRAME); if (seg_ref_active) { memset(ref_costs_single, 0, MAX_REF_FRAMES * sizeof(*ref_costs_single)); memset(ref_costs_comp, 0, MAX_REF_FRAMES * sizeof(*ref_costs_comp)); @@ -2220,7 +2221,7 @@ static void setup_buffer_inter(VP9_COMP *cpi, MACROBLOCK *x, // Gets an initial list of candidate vectors from neighbours and orders them vp9_find_mv_refs(cm, xd, tile, mi, ref_frame, candidates, mi_row, mi_col, - NULL, NULL); + NULL, NULL, xd->mi[0]->mbmi.mode_context); // Candidate refinement carried out at encoder and decoder vp9_find_best_ref_mvs(xd, cm->allow_high_precision_mv, candidates, @@ -3006,8 +3007,8 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, } // If the segment reference frame feature is enabled.... // then do nothing if the current ref frame is not allowed.. - if (vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME) && - vp9_get_segdata(seg, segment_id, SEG_LVL_REF_FRAME) != (int)ref_frame) { + if (segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME) && + get_segdata(seg, segment_id, SEG_LVL_REF_FRAME) != (int)ref_frame) { ref_frame_skip_mask[0] |= (1 << ref_frame); ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK; } @@ -3016,7 +3017,7 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, // Disable this drop out case if the ref frame // segment level feature is enabled for this segment. This is to // prevent the possibility that we end up unable to pick any mode. - if (!vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) { + if (!segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) { // Only consider ZEROMV/ALTREF_FRAME for alt ref frame, // unless ARNR filtering is enabled in which case we want // an unfiltered alternative. We allow near/nearest as well @@ -3195,7 +3196,7 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, // Do not allow compound prediction if the segment level reference frame // feature is in use as in this case there can only be one reference. - if (vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) + if (segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) continue; if ((mode_search_skip_flags & FLAG_SKIP_COMP_BESTINTRA) && @@ -3637,7 +3638,7 @@ void vp9_rd_pick_inter_mode_sb_seg_skip(VP9_COMP *cpi, rd_cost->rate = INT_MAX; - assert(vp9_segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)); + assert(segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)); mbmi->mode = ZEROMV; mbmi->uv_mode = DC_PRED; @@ -3849,7 +3850,7 @@ void vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, continue; // Do not allow compound prediction if the segment level reference frame // feature is in use as in this case there can only be one reference. - if (vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) + if (segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) continue; if ((sf->mode_search_skip_flags & FLAG_SKIP_COMP_BESTINTRA) && @@ -3874,13 +3875,13 @@ void vp9_rd_pick_inter_mode_sub8x8(VP9_COMP *cpi, // If the segment reference frame feature is enabled.... // then do nothing if the current ref frame is not allowed.. - if (vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME) && - vp9_get_segdata(seg, segment_id, SEG_LVL_REF_FRAME) != (int)ref_frame) { + if (segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME) && + get_segdata(seg, segment_id, SEG_LVL_REF_FRAME) != (int)ref_frame) { continue; // Disable this drop out case if the ref frame // segment level feature is enabled for this segment. This is to // prevent the possibility that we end up unable to pick any mode. - } else if (!vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) { + } else if (!segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) { // Only consider ZEROMV/ALTREF_FRAME for alt ref frame, // unless ARNR filtering is enabled in which case we want // an unfiltered alternative. We allow near/nearest as well diff --git a/vp9/encoder/vp9_resize.c b/vp9/encoder/vp9_resize.c index bca5b1326..f46cad804 100644 --- a/vp9/encoder/vp9_resize.c +++ b/vp9/encoder/vp9_resize.c @@ -29,7 +29,7 @@ typedef int16_t interp_kernel[INTERP_TAPS]; // Filters for interpolation (0.5-band) - note this also filters integer pels. -const interp_kernel vp9_filteredinterp_filters500[(1 << SUBPEL_BITS)] = { +static const interp_kernel filteredinterp_filters500[(1 << SUBPEL_BITS)] = { {-3, 0, 35, 64, 35, 0, -3, 0}, {-3, -1, 34, 64, 36, 1, -3, 0}, {-3, -1, 32, 64, 38, 1, -3, 0}, @@ -65,7 +65,7 @@ const interp_kernel vp9_filteredinterp_filters500[(1 << SUBPEL_BITS)] = { }; // Filters for interpolation (0.625-band) - note this also filters integer pels. -const interp_kernel vp9_filteredinterp_filters625[(1 << SUBPEL_BITS)] = { +static const interp_kernel filteredinterp_filters625[(1 << SUBPEL_BITS)] = { {-1, -8, 33, 80, 33, -8, -1, 0}, {-1, -8, 30, 80, 35, -8, -1, 1}, {-1, -8, 28, 80, 37, -7, -2, 1}, @@ -101,7 +101,7 @@ const interp_kernel vp9_filteredinterp_filters625[(1 << SUBPEL_BITS)] = { }; // Filters for interpolation (0.75-band) - note this also filters integer pels. -const interp_kernel vp9_filteredinterp_filters750[(1 << SUBPEL_BITS)] = { +static const interp_kernel filteredinterp_filters750[(1 << SUBPEL_BITS)] = { {2, -11, 25, 96, 25, -11, 2, 0}, {2, -11, 22, 96, 28, -11, 2, 0}, {2, -10, 19, 95, 31, -11, 2, 0}, @@ -137,7 +137,7 @@ const interp_kernel vp9_filteredinterp_filters750[(1 << SUBPEL_BITS)] = { }; // Filters for interpolation (0.875-band) - note this also filters integer pels. -const interp_kernel vp9_filteredinterp_filters875[(1 << SUBPEL_BITS)] = { +static const interp_kernel filteredinterp_filters875[(1 << SUBPEL_BITS)] = { {3, -8, 13, 112, 13, -8, 3, 0}, {3, -7, 10, 112, 17, -9, 3, -1}, {2, -6, 7, 111, 21, -9, 3, -1}, @@ -173,7 +173,7 @@ const interp_kernel vp9_filteredinterp_filters875[(1 << SUBPEL_BITS)] = { }; // Filters for interpolation (full-band) - no filtering for integer pixels -const interp_kernel vp9_filteredinterp_filters1000[(1 << SUBPEL_BITS)] = { +static const interp_kernel filteredinterp_filters1000[(1 << SUBPEL_BITS)] = { {0, 0, 0, 128, 0, 0, 0, 0}, {0, 1, -3, 128, 3, -1, 0, 0}, {-1, 2, -6, 127, 7, -2, 1, 0}, @@ -215,15 +215,15 @@ static const int16_t vp9_down2_symodd_half_filter[] = {64, 35, 0, -3}; static const interp_kernel *choose_interp_filter(int inlength, int outlength) { int outlength16 = outlength * 16; if (outlength16 >= inlength * 16) - return vp9_filteredinterp_filters1000; + return filteredinterp_filters1000; else if (outlength16 >= inlength * 13) - return vp9_filteredinterp_filters875; + return filteredinterp_filters875; else if (outlength16 >= inlength * 11) - return vp9_filteredinterp_filters750; + return filteredinterp_filters750; else if (outlength16 >= inlength * 9) - return vp9_filteredinterp_filters625; + return filteredinterp_filters625; else - return vp9_filteredinterp_filters500; + return filteredinterp_filters500; } static void interpolate(const uint8_t *const input, int inlength, diff --git a/vp9/encoder/vp9_speed_features.c b/vp9/encoder/vp9_speed_features.c index 4b206ba7b..6c6c4ed30 100644 --- a/vp9/encoder/vp9_speed_features.c +++ b/vp9/encoder/vp9_speed_features.c @@ -19,9 +19,33 @@ static int frame_is_boosted(const VP9_COMP *cpi) { return frame_is_kf_gf_arf(cpi) || vp9_is_upper_layer_key_frame(cpi); } -static void set_good_speed_feature_framesize_dependent(VP9_COMMON *cm, +// Sets a partition size down to which the auto partition code will always +// search (can go lower), based on the image dimensions. The logic here +// is that the extent to which ringing artefacts are offensive, depends +// partly on the screen area that over which they propogate. Propogation is +// limited by transform block size but the screen area take up by a given block +// size will be larger for a small image format stretched to full screen. +static BLOCK_SIZE set_partition_min_limit(VP9_COMMON *const cm) { + unsigned int screen_area = (cm->width * cm->height); + + // Select block size based on image format size. + if (screen_area < 1280 * 720) { + // Formats smaller in area than 720P + return BLOCK_4X4; + } else if (screen_area < 1920 * 1080) { + // Format >= 720P and < 1080P + return BLOCK_8X8; + } else { + // Formats 1080P and up + return BLOCK_16X16; + } +} + +static void set_good_speed_feature_framesize_dependent(VP9_COMP *cpi, SPEED_FEATURES *sf, int speed) { + VP9_COMMON *const cm = &cpi->common; + if (speed >= 1) { if (MIN(cm->width, cm->height) >= 720) { sf->disable_split_mask = cm->show_frame ? DISABLE_ALL_SPLIT @@ -45,6 +69,7 @@ static void set_good_speed_feature_framesize_dependent(VP9_COMMON *cm, sf->partition_search_breakout_dist_thr = (1 << 22); sf->partition_search_breakout_rate_thr = 100; } + sf->rd_auto_partition_min_limit = set_partition_min_limit(cm); } if (speed >= 3) { @@ -62,6 +87,13 @@ static void set_good_speed_feature_framesize_dependent(VP9_COMMON *cm, } } + // 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)) { + sf->disable_split_mask = DISABLE_COMPOUND_SPLIT; + } + if (speed >= 4) { if (MIN(cm->width, cm->height) >= 720) { sf->partition_search_breakout_dist_thr = (1 << 26); @@ -72,29 +104,6 @@ static void set_good_speed_feature_framesize_dependent(VP9_COMMON *cm, } } -// Sets a partition size down to which the auto partition code will always -// search (can go lower), based on the image dimensions. The logic here -// is that the extent to which ringing artefacts are offensive, depends -// partly on the screen area that over which they propogate. Propogation is -// limited by transform block size but the screen area take up by a given block -// size will be larger for a small image format stretched to full screen. -static BLOCK_SIZE set_partition_min_limit(VP9_COMP *cpi) { - VP9_COMMON *const cm = &cpi->common; - unsigned int screen_area = (cm->width * cm->height); - - // Select block size based on image format size. - if (screen_area < 1280 * 720) { - // Formats smaller in area than 720P - return BLOCK_4X4; - } else if (screen_area < 1920 * 1080) { - // Format >= 720P and < 1080P - return BLOCK_8X8; - } else { - // Formats 1080P and up - return BLOCK_16X16; - } -} - static void set_good_speed_feature(VP9_COMP *cpi, VP9_COMMON *cm, SPEED_FEATURES *sf, int speed) { const int boosted = frame_is_boosted(cpi); @@ -139,7 +148,6 @@ static void set_good_speed_feature(VP9_COMP *cpi, VP9_COMMON *cm, sf->disable_filter_search_var_thresh = 100; sf->comp_inter_joint_search_thresh = BLOCK_SIZES; sf->auto_min_max_partition_size = RELAXED_NEIGHBORING_MIN_MAX; - sf->rd_auto_partition_min_limit = set_partition_min_limit(cpi); sf->allow_partition_search_skip = 1; } @@ -383,7 +391,6 @@ static void set_rt_speed_feature(VP9_COMP *cpi, SPEED_FEATURES *sf, void vp9_set_speed_features_framesize_dependent(VP9_COMP *cpi) { SPEED_FEATURES *const sf = &cpi->sf; - VP9_COMMON *const cm = &cpi->common; const VP9EncoderConfig *const oxcf = &cpi->oxcf; RD_OPT *const rd = &cpi->rd; int i; @@ -391,7 +398,7 @@ void vp9_set_speed_features_framesize_dependent(VP9_COMP *cpi) { if (oxcf->mode == REALTIME) { set_rt_speed_feature_framesize_dependent(cpi, sf, oxcf->speed); } else if (oxcf->mode == GOOD) { - set_good_speed_feature_framesize_dependent(cm, sf, oxcf->speed); + set_good_speed_feature_framesize_dependent(cpi, sf, oxcf->speed); } if (sf->disable_split_mask == DISABLE_ALL_SPLIT) { diff --git a/vp9/encoder/vp9_svc_layercontext.c b/vp9/encoder/vp9_svc_layercontext.c index cb1b0df4c..1b35ac9b6 100644 --- a/vp9/encoder/vp9_svc_layercontext.c +++ b/vp9/encoder/vp9_svc_layercontext.c @@ -152,7 +152,6 @@ void vp9_update_layer_context_change_config(VP9_COMP *const cpi, } } else { int layer_end; - float bitrate_alloc = 1.0; if (svc->number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) { layer_end = svc->number_temporal_layers; diff --git a/vp9/encoder/vp9_tokenize.c b/vp9/encoder/vp9_tokenize.c index 35920313a..181a99ce8 100644 --- a/vp9/encoder/vp9_tokenize.c +++ b/vp9/encoder/vp9_tokenize.c @@ -484,7 +484,7 @@ static INLINE void add_token_no_extra(TOKENEXTRA **t, static INLINE int get_tx_eob(const struct segmentation *seg, int segment_id, TX_SIZE tx_size) { const int eob_max = 16 << (tx_size << 1); - return vp9_segfeature_active(seg, segment_id, SEG_LVL_SKIP) ? 0 : eob_max; + return segfeature_active(seg, segment_id, SEG_LVL_SKIP) ? 0 : eob_max; } static void tokenize_b(int plane, int block, BLOCK_SIZE plane_bsize, @@ -615,8 +615,8 @@ void vp9_tokenize_sb(VP9_COMP *cpi, ThreadData *td, TOKENEXTRA **t, MACROBLOCKD *const xd = &x->e_mbd; MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi; const int ctx = vp9_get_skip_context(xd); - const int skip_inc = !vp9_segfeature_active(&cm->seg, mbmi->segment_id, - SEG_LVL_SKIP); + const int skip_inc = !segfeature_active(&cm->seg, mbmi->segment_id, + SEG_LVL_SKIP); struct tokenize_b_args arg = {cpi, td, t}; if (mbmi->skip) { if (!dry_run) diff --git a/vp9/encoder/x86/vp9_avg_intrin_sse2.c b/vp9/encoder/x86/vp9_avg_intrin_sse2.c index 56a91ed2d..4531d794a 100644 --- a/vp9/encoder/x86/vp9_avg_intrin_sse2.c +++ b/vp9/encoder/x86/vp9_avg_intrin_sse2.c @@ -264,17 +264,18 @@ void vp9_hadamard_16x16_sse2(int16_t const *src_diff, int src_stride, __m128i b2 = _mm_add_epi16(coeff2, coeff3); __m128i b3 = _mm_sub_epi16(coeff2, coeff3); + b0 = _mm_srai_epi16(b0, 1); + b1 = _mm_srai_epi16(b1, 1); + b2 = _mm_srai_epi16(b2, 1); + b3 = _mm_srai_epi16(b3, 1); + coeff0 = _mm_add_epi16(b0, b2); coeff1 = _mm_add_epi16(b1, b3); - coeff0 = _mm_srai_epi16(coeff0, 1); - coeff1 = _mm_srai_epi16(coeff1, 1); _mm_store_si128((__m128i *)coeff, coeff0); _mm_store_si128((__m128i *)(coeff + 64), coeff1); coeff2 = _mm_sub_epi16(b0, b2); coeff3 = _mm_sub_epi16(b1, b3); - coeff2 = _mm_srai_epi16(coeff2, 1); - coeff3 = _mm_srai_epi16(coeff3, 1); _mm_store_si128((__m128i *)(coeff + 128), coeff2); _mm_store_si128((__m128i *)(coeff + 192), coeff3); |