diff options
Diffstat (limited to 'vp9/encoder/vp9_encoder.c')
-rw-r--r-- | vp9/encoder/vp9_encoder.c | 115 |
1 files changed, 82 insertions, 33 deletions
diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index a4c77dd0a..65b660528 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -2307,26 +2307,43 @@ static void scale_and_extend_frame(const YV12_BUFFER_CONFIG *src, vp9_extend_frame_borders(dst); } +static int scale_down(VP9_COMP *cpi, int q) { + RATE_CONTROL *const rc = &cpi->rc; + GF_GROUP *const gf_group = &cpi->twopass.gf_group; + int scale = 0; + assert(frame_is_kf_gf_arf(cpi)); + + if (rc->frame_size_selector == UNSCALED && + q >= rc->rf_level_maxq[gf_group->rf_level[gf_group->index]]) { + const int max_size_thresh = (int)(rate_thresh_mult[SCALE_STEP1] + * MAX(rc->this_frame_target, rc->avg_frame_bandwidth)); + scale = rc->projected_frame_size > max_size_thresh ? 1 : 0; + } + return scale; +} + // Function to test for conditions that indicate we should loop // back and recode a frame. -static int recode_loop_test(const VP9_COMP *cpi, +static int recode_loop_test(VP9_COMP *cpi, int high_limit, int low_limit, int q, int maxq, int minq) { const RATE_CONTROL *const rc = &cpi->rc; const VP9EncoderConfig *const oxcf = &cpi->oxcf; + const int frame_is_kfgfarf = frame_is_kf_gf_arf(cpi); int force_recode = 0; - // Special case trap if maximum allowed frame size exceeded. - if (rc->projected_frame_size > rc->max_frame_bandwidth) { - force_recode = 1; - - // Is frame recode allowed. - // Yes if either recode mode 1 is selected or mode 2 is selected - // and the frame is a key frame, golden frame or alt_ref_frame - } else if ((cpi->sf.recode_loop == ALLOW_RECODE) || - ((cpi->sf.recode_loop == ALLOW_RECODE_KFARFGF) && - frame_is_kf_gf_arf(cpi))) { - // General over and under shoot tests + if ((cpi->sf.recode_loop == ALLOW_RECODE) || + (frame_is_kfgfarf && + (cpi->sf.recode_loop == ALLOW_RECODE_KFARFGF))) { + if (frame_is_kfgfarf && + (oxcf->resize_mode == RESIZE_DYNAMIC) && + scale_down(cpi, q)) { + // Code this group at a lower resolution. + cpi->resize_pending = 1; + return 1; + } + + // TODO(agrange) high_limit could be greater than the scale-down threshold. if ((rc->projected_frame_size > high_limit && q < maxq) || (rc->projected_frame_size < low_limit && q > minq)) { force_recode = 1; @@ -2557,13 +2574,15 @@ static void output_frame_level_debug_stats(VP9_COMP *cpi) { recon_err = vp9_get_y_sse(cpi->Source, get_frame_new_buffer(cm)); if (cpi->twopass.total_left_stats.coded_error != 0.0) - fprintf(f, "%10u %10d %10d %10d %10d" + fprintf(f, "%10u %dx%d %10d %10d %10d %10d" "%10"PRId64" %10"PRId64" %10"PRId64" %10"PRId64" %10d " "%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", - cpi->common.current_video_frame, cpi->rc.this_frame_target, + cpi->common.current_video_frame, + cm->width, cm->height, + cpi->rc.this_frame_target, cpi->rc.projected_frame_size, cpi->rc.projected_frame_size / cpi->common.MBs, (cpi->rc.projected_frame_size - cpi->rc.this_frame_target), @@ -2699,14 +2718,17 @@ static void init_motion_estimation(VP9_COMP *cpi) { void set_frame_size(VP9_COMP *cpi) { int ref_frame; VP9_COMMON *const cm = &cpi->common; - const VP9EncoderConfig *const oxcf = &cpi->oxcf; + VP9EncoderConfig *const oxcf = &cpi->oxcf; MACROBLOCKD *const xd = &cpi->td.mb.e_mbd; if (oxcf->pass == 2 && - cm->current_video_frame == 0 && - oxcf->resize_mode == RESIZE_FIXED && - oxcf->rc_mode == VPX_VBR) { - // Internal scaling is triggered on the first frame. + oxcf->rc_mode == VPX_VBR && + ((oxcf->resize_mode == RESIZE_FIXED && cm->current_video_frame == 0) || + (oxcf->resize_mode == RESIZE_DYNAMIC && cpi->resize_pending))) { + calculate_coded_size( + cpi, &oxcf->scaled_frame_width, &oxcf->scaled_frame_height); + + // There has been a change in frame size. vp9_set_size_literal(cpi, oxcf->scaled_frame_width, oxcf->scaled_frame_height); } @@ -2757,7 +2779,7 @@ void set_frame_size(VP9_COMP *cpi) { static void encode_without_recode_loop(VP9_COMP *cpi) { VP9_COMMON *const cm = &cpi->common; - int q, bottom_index, top_index; // Dummy variables. + int q = 0, bottom_index = 0, top_index = 0; // Dummy variables. vp9_clear_system_state(); @@ -2804,13 +2826,13 @@ static void encode_with_recode_loop(VP9_COMP *cpi, RATE_CONTROL *const rc = &cpi->rc; int bottom_index, top_index; int loop_count = 0; + int loop_at_this_size = 0; int loop = 0; int overshoot_seen = 0; int undershoot_seen = 0; int frame_over_shoot_limit; int frame_under_shoot_limit; int q = 0, q_low = 0, q_high = 0; - int frame_size_changed = 0; set_size_independent_vars(cpi); @@ -2819,19 +2841,31 @@ static void encode_with_recode_loop(VP9_COMP *cpi, set_frame_size(cpi); - if (loop_count == 0 || frame_size_changed != 0) { + if (loop_count == 0 || cpi->resize_pending != 0) { set_size_dependent_vars(cpi, &q, &bottom_index, &top_index); - q_low = bottom_index; - q_high = top_index; // TODO(agrange) Scale cpi->max_mv_magnitude if frame-size has changed. set_mv_search_params(cpi); + + // Reset the loop state for new frame size. + overshoot_seen = 0; + undershoot_seen = 0; + + // Reconfiguration for change in frame size has concluded. + cpi->resize_pending = 0; + + q_low = bottom_index; + q_high = top_index; + + loop_at_this_size = 0; } - // Decide frame size bounds - vp9_rc_compute_frame_size_bounds(cpi, rc->this_frame_target, - &frame_under_shoot_limit, - &frame_over_shoot_limit); + // Decide frame size bounds first time through. + if (loop_count == 0) { + vp9_rc_compute_frame_size_bounds(cpi, rc->this_frame_target, + &frame_under_shoot_limit, + &frame_over_shoot_limit); + } cpi->Source = vp9_scale_if_required(cm, cpi->un_scaled_source, &cpi->scaled_source); @@ -2944,6 +2978,20 @@ static void encode_with_recode_loop(VP9_COMP *cpi, int last_q = q; int retries = 0; + if (cpi->resize_pending == 1) { + // Change in frame size so go back around the recode loop. + cpi->rc.frame_size_selector = + SCALE_STEP1 - cpi->rc.frame_size_selector; + cpi->rc.next_frame_size_selector = cpi->rc.frame_size_selector; + +#if CONFIG_INTERNAL_STATS + ++cpi->tot_recode_hits; +#endif + ++loop_count; + loop = 1; + continue; + } + // Frame size out of permitted range: // Update correction factor & compute new Q to try... @@ -2956,7 +3004,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi, // Raise Qlow as to at least the current value q_low = q < q_high ? q + 1 : q_high; - if (undershoot_seen || loop_count > 1) { + if (undershoot_seen || loop_at_this_size > 1) { // Update rate_correction_factor unless vp9_rc_update_rate_correction_factors(cpi); @@ -2981,7 +3029,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi, // Frame is too small q_high = q > q_low ? q - 1 : q_low; - if (overshoot_seen || loop_count > 1) { + if (overshoot_seen || loop_at_this_size > 1) { vp9_rc_update_rate_correction_factors(cpi); q = (q_high + q_low) / 2; } else { @@ -3011,7 +3059,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi, // Clamp Q to upper and lower limits: q = clamp(q, q_low, q_high); - loop = q != last_q; + loop = (q != last_q); } else { loop = 0; } @@ -3023,10 +3071,11 @@ static void encode_with_recode_loop(VP9_COMP *cpi, loop = 0; if (loop) { - loop_count++; + ++loop_count; + ++loop_at_this_size; #if CONFIG_INTERNAL_STATS - cpi->tot_recode_hits++; + ++cpi->tot_recode_hits; #endif } } while (loop); |