diff options
Diffstat (limited to 'vp9')
-rw-r--r-- | vp9/common/vp9_thread_common.c | 3 | ||||
-rw-r--r-- | vp9/decoder/vp9_decodemv.c | 5 | ||||
-rw-r--r-- | vp9/encoder/vp9_aq_cyclicrefresh.c | 46 | ||||
-rw-r--r-- | vp9/encoder/vp9_aq_cyclicrefresh.h | 8 | ||||
-rw-r--r-- | vp9/encoder/vp9_encodeframe.c | 47 | ||||
-rw-r--r-- | vp9/encoder/vp9_encoder.c | 9 | ||||
-rw-r--r-- | vp9/encoder/vp9_firstpass.c | 6 | ||||
-rw-r--r-- | vp9/encoder/vp9_pickmode.c | 1 | ||||
-rw-r--r-- | vp9/encoder/vp9_ratectrl.c | 20 |
9 files changed, 116 insertions, 29 deletions
diff --git a/vp9/common/vp9_thread_common.c b/vp9/common/vp9_thread_common.c index 27a3212ca..7a3871c41 100644 --- a/vp9/common/vp9_thread_common.c +++ b/vp9/common/vp9_thread_common.c @@ -382,6 +382,9 @@ void vp9_accumulate_frame_counts(VP9_COMMON *cm, FRAME_COUNTS *counts, cm->counts.tx.p8x8[i][j] += counts->tx.p8x8[i][j]; } + for (i = 0; i < TX_SIZES; i++) + cm->counts.tx.tx_totals[i] += counts->tx.tx_totals[i]; + for (i = 0; i < SKIP_CONTEXTS; i++) for (j = 0; j < 2; j++) cm->counts.skip[i][j] += counts->skip[i][j]; diff --git a/vp9/decoder/vp9_decodemv.c b/vp9/decoder/vp9_decodemv.c index 37bdfe058..072f6b7b7 100644 --- a/vp9/decoder/vp9_decodemv.c +++ b/vp9/decoder/vp9_decodemv.c @@ -122,11 +122,10 @@ static void copy_segment_id(const VP9_COMMON *cm, last_segment_ids[mi_offset + y * cm->mi_cols + x] : 0; } -static int read_intra_segment_id(VP9_COMMON *const cm, MACROBLOCKD *const xd, +static int read_intra_segment_id(VP9_COMMON *const cm, BLOCK_SIZE bsize, int mi_row, int mi_col, vp9_reader *r) { struct segmentation *const seg = &cm->seg; - const BLOCK_SIZE bsize = xd->mi[0].src_mi->mbmi.sb_type; int segment_id; if (!seg->enabled) @@ -199,7 +198,7 @@ static void read_intra_frame_mode_info(VP9_COMMON *const cm, const BLOCK_SIZE bsize = mbmi->sb_type; int i; - mbmi->segment_id = read_intra_segment_id(cm, xd, mi_row, mi_col, r); + mbmi->segment_id = read_intra_segment_id(cm, bsize, mi_row, mi_col, r); mbmi->skip = read_skip(cm, xd, counts, mbmi->segment_id, r); mbmi->tx_size = read_tx_size(cm, xd, counts, 1, r); mbmi->ref_frame[0] = INTRA_FRAME; diff --git a/vp9/encoder/vp9_aq_cyclicrefresh.c b/vp9/encoder/vp9_aq_cyclicrefresh.c index 154068052..44a6f9877 100644 --- a/vp9/encoder/vp9_aq_cyclicrefresh.c +++ b/vp9/encoder/vp9_aq_cyclicrefresh.c @@ -47,6 +47,7 @@ struct CYCLIC_REFRESH { int16_t motion_thresh; // Rate target ratio to set q delta. double rate_ratio_qdelta; + double low_content_avg; }; CYCLIC_REFRESH *vp9_cyclic_refresh_alloc(int mi_rows, int mi_cols) { @@ -244,7 +245,7 @@ void vp9_cyclic_refresh_update_segment(VP9_COMP *const cpi, } // Update the actual number of blocks that were applied the segment delta q. -void vp9_cyclic_refresh_update_actual_count(struct VP9_COMP *const cpi) { +void vp9_cyclic_refresh_postencode(VP9_COMP *const cpi) { VP9_COMMON *const cm = &cpi->common; CYCLIC_REFRESH *const cr = cpi->cyclic_refresh; unsigned char *const seg_map = cpi->segmentation_map; @@ -257,6 +258,47 @@ void vp9_cyclic_refresh_update_actual_count(struct VP9_COMP *const cpi) { } } +// Set golden frame update interval, for non-svc 1 pass CBR mode. +void vp9_cyclic_refresh_set_golden_update(VP9_COMP *const cpi) { + RATE_CONTROL *const rc = &cpi->rc; + CYCLIC_REFRESH *const cr = cpi->cyclic_refresh; + // Set minimum gf_interval for GF update to a multiple (== 2) of refresh + // period. Depending on past encoding stats, GF flag may be reset and update + // may not occur until next baseline_gf_interval. + if (cr->percent_refresh > 0) + rc->baseline_gf_interval = 2 * (100 / cr->percent_refresh); + else + rc->baseline_gf_interval = 20; +} + +// Update some encoding stats (from the just encoded frame), and if the golden +// reference is to be updated check if we should NOT update the golden ref. +void vp9_cyclic_refresh_check_golden_update(VP9_COMP *const cpi) { + VP9_COMMON *const cm = &cpi->common; + CYCLIC_REFRESH *const cr = cpi->cyclic_refresh; + int mi_row, mi_col; + double fraction_low = 0.0; + int low_content_frame = 0; + for (mi_row = 0; mi_row < cm->mi_rows; mi_row++) + for (mi_col = 0; mi_col < cm->mi_cols; mi_col++) { + if (cr->map[mi_row * cm->mi_cols + mi_col] < 1) + low_content_frame++; + } + fraction_low = + (double)low_content_frame / (cm->mi_rows * cm->mi_cols); + // Update average. + cr->low_content_avg = (fraction_low + 3 * cr->low_content_avg) / 4; + if (cpi->refresh_golden_frame == 1) { + // Don't update golden reference if the amount of low_content for the + // current encoded frame is small, or if the recursive average of the + // low_content over the update interval window falls below threshold. + if (fraction_low < 0.8 || cr->low_content_avg < 0.7) + cpi->refresh_golden_frame = 0; + // Reset for next internal. + cr->low_content_avg = fraction_low; + } +} + // Update the segmentation map, and related quantities: cyclic refresh map, // refresh sb_index, and target number of blocks to be refreshed. // The map is set to either 0/CR_SEGMENT_ID_BASE (no refresh) or to @@ -347,6 +389,8 @@ void vp9_cyclic_refresh_setup(VP9_COMP *const cpi) { CYCLIC_REFRESH *const cr = cpi->cyclic_refresh; struct segmentation *const seg = &cm->seg; const int apply_cyclic_refresh = apply_cyclic_refresh_bitrate(cm, rc); + if (cm->current_video_frame == 0) + cr->low_content_avg = 0.0; // Don't apply refresh on key frame or enhancement layer frames. if (!apply_cyclic_refresh || (cm->frame_type == KEY_FRAME) || diff --git a/vp9/encoder/vp9_aq_cyclicrefresh.h b/vp9/encoder/vp9_aq_cyclicrefresh.h index dc1b968a2..048a0ed35 100644 --- a/vp9/encoder/vp9_aq_cyclicrefresh.h +++ b/vp9/encoder/vp9_aq_cyclicrefresh.h @@ -62,7 +62,13 @@ void vp9_cyclic_refresh_update_segment(struct VP9_COMP *const cpi, void vp9_cyclic_refresh_update__map(struct VP9_COMP *const cpi); // Update the actual number of blocks that were applied the segment delta q. -void vp9_cyclic_refresh_update_actual_count(struct VP9_COMP *const cpi); +void vp9_cyclic_refresh_postencode(struct VP9_COMP *const cpi); + +// Set golden frame update interval, for non-svc 1 pass CBR mode. +void vp9_cyclic_refresh_set_golden_update(struct VP9_COMP *cpi); + +// Check if we should not update golden reference, based on past refresh stats. +void vp9_cyclic_refresh_check_golden_update(struct VP9_COMP *const cpi); // Set/update global/frame level refresh parameters. void vp9_cyclic_refresh_update_parameters(struct VP9_COMP *const cpi); diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index 933b049d4..5c841cfdc 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -563,32 +563,51 @@ static void choose_partitioning(VP9_COMP *cpi, if (!is_key_frame) { MB_MODE_INFO *mbmi = &xd->mi[0].src_mi->mbmi; unsigned int uv_sad; + const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, LAST_FRAME); #if GLOBAL_MOTION - unsigned int y_sad; + const YV12_BUFFER_CONFIG *yv12_g = get_ref_frame_buffer(cpi, GOLDEN_FRAME); + unsigned int y_sad, y_sad_g; BLOCK_SIZE bsize; + if (mi_row + 4 < cm->mi_rows && mi_col + 4 < cm->mi_cols) + bsize = BLOCK_64X64; + else if (mi_row + 4 < cm->mi_rows && mi_col + 4 >= cm->mi_cols) + bsize = BLOCK_32X64; + else if (mi_row + 4 >= cm->mi_rows && mi_col + 4 < cm->mi_cols) + bsize = BLOCK_64X32; + else + bsize = BLOCK_32X32; #endif - const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, LAST_FRAME); assert(yv12 != NULL); +#if GLOBAL_MOTION + if (yv12_g && yv12_g != yv12) { + vp9_setup_pre_planes(xd, 0, yv12_g, mi_row, mi_col, + &cm->frame_refs[GOLDEN_FRAME - 1].sf); + y_sad_g = cpi->fn_ptr[bsize].sdf(x->plane[0].src.buf, + x->plane[0].src.stride, + xd->plane[0].pre[0].buf, + xd->plane[0].pre[0].stride); + } else { + y_sad_g = UINT_MAX; + } +#endif vp9_setup_pre_planes(xd, 0, yv12, mi_row, mi_col, - &cm->frame_refs[LAST_FRAME - 1].sf); + &cm->frame_refs[LAST_FRAME - 1].sf); mbmi->ref_frame[0] = LAST_FRAME; mbmi->ref_frame[1] = NONE; mbmi->sb_type = BLOCK_64X64; mbmi->mv[0].as_int = 0; mbmi->interp_filter = BILINEAR; - #if GLOBAL_MOTION - if (mi_row + 4 < cm->mi_rows && mi_col + 4 < cm->mi_cols) - bsize = BLOCK_64X64; - else if (mi_row + 4 < cm->mi_rows && mi_col + 4 >= cm->mi_cols) - bsize = BLOCK_32X64; - else if (mi_row + 4 >= cm->mi_rows && mi_col + 4 < cm->mi_cols) - bsize = BLOCK_64X32; - else - bsize = BLOCK_32X32; - y_sad = vp9_int_pro_motion_estimation(cpi, x, bsize); - x->pred_mv[LAST_FRAME] = mbmi->mv[0].as_mv; + if (y_sad_g < y_sad) { + vp9_setup_pre_planes(xd, 0, yv12_g, mi_row, mi_col, + &cm->frame_refs[GOLDEN_FRAME - 1].sf); + mbmi->ref_frame[0] = GOLDEN_FRAME; + mbmi->mv[0].as_int = 0; + y_sad = y_sad_g; + } else { + x->pred_mv[LAST_FRAME] = mbmi->mv[0].as_mv; + } #endif vp9_build_inter_predictors_sb(xd, mi_row, mi_col, BLOCK_64X64); diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index 249c2363d..32bf88061 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -2843,6 +2843,14 @@ static void encode_without_recode_loop(VP9_COMP *cpi) { // transform / motion compensation build reconstruction frame vp9_encode_frame(cpi); + // Update some stats from cyclic refresh, and check if we should not update + // golden reference, for non-SVC 1 pass CBR. + if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ && + cm->frame_type != KEY_FRAME && + !cpi->use_svc && + (cpi->oxcf.pass == 0 && cpi->oxcf.rc_mode == VPX_CBR)) + vp9_cyclic_refresh_check_golden_update(cpi); + // Update the skip mb flag probabilities based on the distribution // seen in the last encoder iteration. // update_base_skip_probs(cpi); @@ -3220,7 +3228,6 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, TX_SIZE t; set_ext_overrides(cpi); - vp9_clear_system_state(); // Set the arf sign bias for this frame. diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index 6c8bbdb6d..046c64170 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -2621,11 +2621,13 @@ void vp9_twopass_postencode_update(VP9_COMP *cpi) { ++twopass->gf_group.index; // If the rate control is drifting consider adjustment to min or maxq. - if ((cpi->oxcf.rc_mode == VPX_VBR) && + if ((cpi->oxcf.rc_mode != VPX_Q) && (cpi->twopass.gf_zeromotion_pct < VLOW_MOTION_THRESHOLD) && !cpi->rc.is_src_frame_alt_ref) { const int maxq_adj_limit = rc->worst_quality - twopass->active_worst_quality; + const int minq_adj_limit = + (cpi->oxcf.rc_mode == VPX_CQ) ? 0 : MINQ_ADJ_LIMIT; // Undershoot. if (rc->rate_error_estimate > cpi->oxcf.under_shoot_pct) { @@ -2650,7 +2652,7 @@ void vp9_twopass_postencode_update(VP9_COMP *cpi) { --twopass->extend_maxq; } - twopass->extend_minq = clamp(twopass->extend_minq, 0, MINQ_ADJ_LIMIT); + twopass->extend_minq = clamp(twopass->extend_minq, 0, minq_adj_limit); twopass->extend_maxq = clamp(twopass->extend_maxq, 0, maxq_adj_limit); } } diff --git a/vp9/encoder/vp9_pickmode.c b/vp9/encoder/vp9_pickmode.c index dedec5f54..6c2576add 100644 --- a/vp9/encoder/vp9_pickmode.c +++ b/vp9/encoder/vp9_pickmode.c @@ -1052,6 +1052,7 @@ void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, mode_idx[INTRA_FRAME][mbmi->mode]; PREDICTION_MODE this_mode; for (ref_frame = LAST_FRAME; ref_frame <= GOLDEN_FRAME; ++ref_frame) { + if (best_ref_frame != ref_frame) continue; for (this_mode = NEARESTMV; this_mode <= NEWMV; ++this_mode) { THR_MODES thr_mode_idx = mode_idx[ref_frame][INTER_OFFSET(this_mode)]; int *freq_fact = &tile_data->thresh_freq_fact[bsize][thr_mode_idx]; diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index f33fe5100..626c6e9af 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -377,7 +377,7 @@ static double get_rate_correction_factor(const VP9_COMP *cpi) { rcf = rc->rate_correction_factors[INTER_NORMAL]; } rcf *= rcf_mult[rc->frame_size_selector]; - return rcf > MAX_BPB_FACTOR ? MAX_BPB_FACTOR : rcf; + return fclamp(rcf, MIN_BPB_FACTOR, MAX_BPB_FACTOR); } static void set_rate_correction_factor(VP9_COMP *cpi, double factor) { @@ -386,6 +386,8 @@ static void set_rate_correction_factor(VP9_COMP *cpi, double factor) { // Normalize RCF to account for the size-dependent scaling factor. factor /= rcf_mult[cpi->rc.frame_size_selector]; + factor = fclamp(factor, MIN_BPB_FACTOR, MAX_BPB_FACTOR); + if (cpi->common.frame_type == KEY_FRAME) { rc->rate_correction_factors[KF_STD] = factor; } else if (cpi->oxcf.pass == 2) { @@ -1050,7 +1052,7 @@ static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi, // Extension to max or min Q if undershoot or overshoot is outside // the permitted range. - if ((cpi->oxcf.rc_mode == VPX_VBR) && + if ((cpi->oxcf.rc_mode != VPX_Q) && (cpi->twopass.gf_zeromotion_pct < VLOW_MOTION_THRESHOLD)) { if (frame_is_intra_only(cm) || (!rc->is_src_frame_alt_ref && @@ -1229,7 +1231,7 @@ void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) { const int qindex = cm->base_qindex; if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ && cm->seg.enabled) { - vp9_cyclic_refresh_update_actual_count(cpi); + vp9_cyclic_refresh_postencode(cpi); } // Update rate control heuristics @@ -1535,7 +1537,10 @@ void vp9_rc_get_one_pass_cbr_params(VP9_COMP *cpi) { cm->frame_type = INTER_FRAME; } if (rc->frames_till_gf_update_due == 0) { - rc->baseline_gf_interval = DEFAULT_GF_INTERVAL; + if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ) + vp9_cyclic_refresh_set_golden_update(cpi); + else + rc->baseline_gf_interval = DEFAULT_GF_INTERVAL; rc->frames_till_gf_update_due = rc->baseline_gf_interval; // NOTE: frames_till_gf_update_due must be <= frames_to_key. if (rc->frames_till_gf_update_due > rc->frames_to_key) @@ -1595,11 +1600,12 @@ int vp9_compute_qdelta_by_rate(const RATE_CONTROL *rc, FRAME_TYPE frame_type, // Convert the q target to an index for (i = rc->best_quality; i < rc->worst_quality; ++i) { - target_index = i; - if (vp9_rc_bits_per_mb(frame_type, i, 1.0, bit_depth) <= target_bits_per_mb) + if (vp9_rc_bits_per_mb(frame_type, i, 1.0, bit_depth) <= + target_bits_per_mb) { + target_index = i; break; + } } - return target_index - qindex; } |