diff options
author | Angie Chiang <angiebird@google.com> | 2019-10-22 18:17:51 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2019-10-22 18:17:51 +0000 |
commit | 96d584e1b8049570e8c93cd5177d28a7d78b890c (patch) | |
tree | a9d586aed23a5108703c67aabef2232882aff368 | |
parent | 062a43acb6b474e2663b3e639ef251ca9f3b360f (diff) | |
parent | b2e498000ff52b27a62cd14a5b586ba0fefc9914 (diff) | |
download | libvpx-96d584e1b8049570e8c93cd5177d28a7d78b890c.tar libvpx-96d584e1b8049570e8c93cd5177d28a7d78b890c.tar.gz libvpx-96d584e1b8049570e8c93cd5177d28a7d78b890c.tar.bz2 libvpx-96d584e1b8049570e8c93cd5177d28a7d78b890c.zip |
Merge changes I00697e9a,I9dfc2ba3,I73619051,Ib4d37667
* changes:
Refactor kf_group_err in find_next_key_frame
Simplify the logics in find_next_key_frame
Add get_gop_coding_frame_num()
Localize zero_motion_accumulator
-rw-r--r-- | vp9/encoder/vp9_firstpass.c | 324 |
1 files changed, 163 insertions, 161 deletions
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index 76c45b81c..a6b2ce3c2 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -2477,6 +2477,122 @@ static void adjust_group_arnr_filter(VP9_COMP *cpi, double section_noise, #define ARF_ABS_ZOOM_THRESH 4.0 #define MAX_GF_BOOST 5400 + +static int get_gop_coding_frame_num( + int *use_alt_ref, const FRAME_INFO *frame_info, + const FIRST_PASS_INFO *first_pass_info, const RATE_CONTROL *rc, + int gf_start_show_idx, int active_min_gf_interval, + int active_max_gf_interval, double gop_intra_factor, int kf_zeromotion_pct, + int lag_in_frames) { + double loop_decay_rate = 1.00; + double mv_ratio_accumulator = 0.0; + double this_frame_mv_in_out = 0.0; + double mv_in_out_accumulator = 0.0; + double abs_mv_in_out_accumulator = 0.0; + double sr_accumulator = 0.0; + // Motion breakout threshold for loop below depends on image size. + double mv_ratio_accumulator_thresh = + (frame_info->frame_height + frame_info->frame_width) / 4.0; + double zero_motion_accumulator = 1.0; + int gop_coding_frames; + + *use_alt_ref = 1; + gop_coding_frames = 0; + while (gop_coding_frames < rc->static_scene_max_gf_interval && + gop_coding_frames < rc->frames_to_key) { + const FIRSTPASS_STATS *next_next_frame; + const FIRSTPASS_STATS *next_frame; + int flash_detected; + ++gop_coding_frames; + + next_frame = fps_get_frame_stats(first_pass_info, + gf_start_show_idx + gop_coding_frames); + if (next_frame == NULL) { + break; + } + + // Test for the case where there is a brief flash but the prediction + // quality back to an earlier frame is then restored. + next_next_frame = fps_get_frame_stats( + first_pass_info, gf_start_show_idx + gop_coding_frames + 1); + flash_detected = detect_flash_from_frame_stats(next_next_frame); + + // Update the motion related elements to the boost calculation. + accumulate_frame_motion_stats( + next_frame, &this_frame_mv_in_out, &mv_in_out_accumulator, + &abs_mv_in_out_accumulator, &mv_ratio_accumulator); + + // Monitor for static sections. + if ((rc->frames_since_key + gop_coding_frames - 1) > 1) { + zero_motion_accumulator = + VPXMIN(zero_motion_accumulator, + get_zero_motion_factor(frame_info, next_frame)); + } + + // Accumulate the effect of prediction quality decay. + if (!flash_detected) { + double last_loop_decay_rate = loop_decay_rate; + loop_decay_rate = get_prediction_decay_rate(frame_info, next_frame); + + // Break clause to detect very still sections after motion. For example, + // a static image after a fade or other transition. + if (gop_coding_frames > rc->min_gf_interval && loop_decay_rate >= 0.999 && + last_loop_decay_rate < 0.9) { + int still_interval = 5; + if (check_transition_to_still(first_pass_info, + gf_start_show_idx + gop_coding_frames, + still_interval)) { + *use_alt_ref = 0; + break; + } + } + + // Update the accumulator for second ref error difference. + // This is intended to give an indication of how much the coded error is + // increasing over time. + if (gop_coding_frames == 1) { + sr_accumulator += next_frame->coded_error; + } else { + sr_accumulator += + (next_frame->sr_coded_error - next_frame->coded_error); + } + } + + // Break out conditions. + // Break at maximum of active_max_gf_interval unless almost totally + // static. + // + // Note that the addition of a test of rc->source_alt_ref_active is + // deliberate. The effect of this is that after a normal altref group even + // if the material is static there will be one normal length GF group + // before allowing longer GF groups. The reason for this is that in cases + // such as slide shows where slides are separated by a complex transition + // such as a fade, the arf group spanning the transition may not be coded + // at a very high quality and hence this frame (with its overlay) is a + // poor golden frame to use for an extended group. + if ((gop_coding_frames >= active_max_gf_interval) && + ((zero_motion_accumulator < 0.995) || (rc->source_alt_ref_active))) { + break; + } + if ( + // Don't break out with a very short interval. + (gop_coding_frames >= active_min_gf_interval) && + // If possible dont break very close to a kf + ((rc->frames_to_key - gop_coding_frames) >= rc->min_gf_interval) && + (gop_coding_frames & 0x01) && (!flash_detected) && + ((mv_ratio_accumulator > mv_ratio_accumulator_thresh) || + (abs_mv_in_out_accumulator > ARF_ABS_ZOOM_THRESH) || + (sr_accumulator > gop_intra_factor * next_frame->intra_error))) { + break; + } + } + *use_alt_ref &= zero_motion_accumulator < 0.995; + *use_alt_ref &= kf_zeromotion_pct < STATIC_KF_GROUP_THRESH; + *use_alt_ref &= gop_coding_frames < lag_in_frames; + *use_alt_ref &= gop_coding_frames >= rc->min_gf_interval; + return gop_coding_frames; +} + static void define_gf_group(VP9_COMP *cpi, int gf_start_show_idx) { VP9_COMMON *const cm = &cpi->common; RATE_CONTROL *const rc = &cpi->rc; @@ -2485,8 +2601,7 @@ static void define_gf_group(VP9_COMP *cpi, int gf_start_show_idx) { const FRAME_INFO *frame_info = &cpi->frame_info; const FIRST_PASS_INFO *first_pass_info = &twopass->first_pass_info; const FIRSTPASS_STATS *const start_pos = twopass->stats_in; - int i; - int j; + int gop_coding_frames; double gf_group_err = 0.0; double gf_group_raw_error = 0.0; @@ -2496,9 +2611,8 @@ static void define_gf_group(VP9_COMP *cpi, int gf_start_show_idx) { double gf_group_inter = 0.0; double gf_group_motion = 0.0; - double zero_motion_accumulator = 1.0; - - unsigned int allow_alt_ref = is_altref_enabled(cpi); + int allow_alt_ref = is_altref_enabled(cpi); + int use_alt_ref; int active_max_gf_interval; int active_min_gf_interval; @@ -2565,6 +2679,7 @@ static void define_gf_group(VP9_COMP *cpi, int gf_start_show_idx) { if (cpi->multi_layer_arf) { int layers = 0; int max_layers = VPXMIN(MAX_ARF_LAYERS, cpi->oxcf.enable_auto_arf); + int i; // Adapt the intra_error factor to active_max_gf_interval limit. for (i = active_max_gf_interval; i > 0; i >>= 1) ++layers; @@ -2573,120 +2688,28 @@ static void define_gf_group(VP9_COMP *cpi, int gf_start_show_idx) { gop_intra_factor += (layers * 0.25); } - i = 0; { - double loop_decay_rate = 1.00; - double mv_ratio_accumulator = 0.0; - double this_frame_mv_in_out = 0.0; - double mv_in_out_accumulator = 0.0; - double abs_mv_in_out_accumulator = 0.0; - double sr_accumulator = 0.0; - // Motion breakout threshold for loop below depends on image size. - double mv_ratio_accumulator_thresh = - (cpi->initial_height + cpi->initial_width) / 4.0; - - while (i < rc->static_scene_max_gf_interval && i < rc->frames_to_key) { - const FIRSTPASS_STATS *next_next_frame; - const FIRSTPASS_STATS *next_frame; - int flash_detected; - ++i; - - next_frame = fps_get_frame_stats(first_pass_info, gf_start_show_idx + i); - if (next_frame == NULL) { - break; - } - - // Test for the case where there is a brief flash but the prediction - // quality back to an earlier frame is then restored. - next_next_frame = - fps_get_frame_stats(first_pass_info, gf_start_show_idx + i + 1); - flash_detected = detect_flash_from_frame_stats(next_next_frame); - - // Update the motion related elements to the boost calculation. - accumulate_frame_motion_stats( - next_frame, &this_frame_mv_in_out, &mv_in_out_accumulator, - &abs_mv_in_out_accumulator, &mv_ratio_accumulator); - - // Monitor for static sections. - if ((rc->frames_since_key + i - 1) > 1) { - zero_motion_accumulator = - VPXMIN(zero_motion_accumulator, - get_zero_motion_factor(frame_info, next_frame)); - } - - // Accumulate the effect of prediction quality decay. - if (!flash_detected) { - double last_loop_decay_rate = loop_decay_rate; - loop_decay_rate = get_prediction_decay_rate(frame_info, next_frame); - - // Break clause to detect very still sections after motion. For example, - // a static image after a fade or other transition. - if (i > rc->min_gf_interval && loop_decay_rate >= 0.999 && - last_loop_decay_rate < 0.9) { - int still_interval = 5; - if (check_transition_to_still(first_pass_info, gf_start_show_idx + i, - still_interval)) { - allow_alt_ref = 0; - break; - } - } - - // Update the accumulator for second ref error difference. - // This is intended to give an indication of how much the coded error is - // increasing over time. - if (i == 1) { - sr_accumulator += next_frame->coded_error; - } else { - sr_accumulator += - (next_frame->sr_coded_error - next_frame->coded_error); - } - } - - // Break out conditions. - // Break at maximum of active_max_gf_interval unless almost totally - // static. - // - // Note that the addition of a test of rc->source_alt_ref_active is - // deliberate. The effect of this is that after a normal altref group even - // if the material is static there will be one normal length GF group - // before allowing longer GF groups. The reason for this is that in cases - // such as slide shows where slides are separated by a complex transition - // such as a fade, the arf group spanning the transition may not be coded - // at a very high quality and hence this frame (with its overlay) is a - // poor golden frame to use for an extended group. - if ((i >= active_max_gf_interval) && - ((zero_motion_accumulator < 0.995) || (rc->source_alt_ref_active))) { - break; - } - if ( - // Don't break out with a very short interval. - (i >= active_min_gf_interval) && - // If possible dont break very close to a kf - ((rc->frames_to_key - i) >= rc->min_gf_interval) && (i & 0x01) && - (!flash_detected) && - ((mv_ratio_accumulator > mv_ratio_accumulator_thresh) || - (abs_mv_in_out_accumulator > ARF_ABS_ZOOM_THRESH) || - (sr_accumulator > gop_intra_factor * next_frame->intra_error))) { - break; - } - } + gop_coding_frames = get_gop_coding_frame_num( + &use_alt_ref, frame_info, first_pass_info, rc, gf_start_show_idx, + active_min_gf_interval, active_max_gf_interval, gop_intra_factor, + twopass->kf_zeromotion_pct, cpi->oxcf.lag_in_frames); + use_alt_ref &= allow_alt_ref; } // Was the group length constrained by the requirement for a new KF? - rc->constrained_gf_group = (i >= rc->frames_to_key) ? 1 : 0; + rc->constrained_gf_group = (gop_coding_frames >= rc->frames_to_key) ? 1 : 0; // Should we use the alternate reference frame. - if ((zero_motion_accumulator < 0.995) && allow_alt_ref && - (twopass->kf_zeromotion_pct < STATIC_KF_GROUP_THRESH) && - (i < cpi->oxcf.lag_in_frames) && (i >= rc->min_gf_interval)) { - const int f_frames = (rc->frames_to_key - i >= i - 1) - ? i - 1 - : VPXMAX(0, rc->frames_to_key - i); - const int b_frames = i - 1; + if (use_alt_ref) { + const int f_frames = + (rc->frames_to_key - gop_coding_frames >= gop_coding_frames - 1) + ? gop_coding_frames - 1 + : VPXMAX(0, rc->frames_to_key - gop_coding_frames); + const int b_frames = gop_coding_frames - 1; const int avg_inter_frame_qindex = rc->avg_frame_qindex[INTER_FRAME]; // TODO(angiebird): figure out why arf's location is assigned this way - const int arf_show_idx = - VPXMIN(gf_start_show_idx + i + 1, fps_get_num_frames(first_pass_info)); + const int arf_show_idx = VPXMIN(gf_start_show_idx + gop_coding_frames + 1, + fps_get_num_frames(first_pass_info)); // Calculate the boost for alt ref. rc->gfu_boost = @@ -2694,7 +2717,7 @@ static void define_gf_group(VP9_COMP *cpi, int gf_start_show_idx) { b_frames, avg_inter_frame_qindex); rc->source_alt_ref_pending = 1; } else { - const int f_frames = i - 1; + const int f_frames = gop_coding_frames - 1; const int b_frames = 0; const int avg_inter_frame_qindex = rc->avg_frame_qindex[INTER_FRAME]; // TODO(angiebird): figure out why arf's location is assigned this way @@ -2718,25 +2741,27 @@ static void define_gf_group(VP9_COMP *cpi, int gf_start_show_idx) { rc->arf_active_best_quality_adjustment_factor = LAST_ALR_ACTIVE_BEST_QUALITY_ADJUSTMENT_FACTOR + (1.0 - LAST_ALR_ACTIVE_BEST_QUALITY_ADJUSTMENT_FACTOR) * - (rc->frames_to_key - i) / - (VPXMAX(1, ((rc->frames_to_key + rc->frames_since_key) / 2 - i))); + (rc->frames_to_key - gop_coding_frames) / + (VPXMAX(1, ((rc->frames_to_key + rc->frames_since_key) / 2 - + gop_coding_frames))); rc->arf_increase_active_best_quality = 1; - } else if ((rc->frames_to_key - i) > 0) { + } else if ((rc->frames_to_key - gop_coding_frames) > 0) { // Reduce the active best quality in the first half of key frame interval. rc->arf_active_best_quality_adjustment_factor = LAST_ALR_ACTIVE_BEST_QUALITY_ADJUSTMENT_FACTOR + (1.0 - LAST_ALR_ACTIVE_BEST_QUALITY_ADJUSTMENT_FACTOR) * - (rc->frames_since_key + i) / - (VPXMAX(1, (rc->frames_to_key + rc->frames_since_key) / 2 + i)); + (rc->frames_since_key + gop_coding_frames) / + (VPXMAX(1, (rc->frames_to_key + rc->frames_since_key) / 2 + + gop_coding_frames)); rc->arf_increase_active_best_quality = -1; } } #ifdef AGGRESSIVE_VBR // Limit maximum boost based on interval length. - rc->gfu_boost = VPXMIN((int)rc->gfu_boost, i * 140); + rc->gfu_boost = VPXMIN((int)rc->gfu_boost, gop_coding_frames * 140); #else - rc->gfu_boost = VPXMIN((int)rc->gfu_boost, i * 200); + rc->gfu_boost = VPXMIN((int)rc->gfu_boost, gop_coding_frames * 200); #endif // Cap the ARF boost when perceptual quality AQ mode is enabled. This is @@ -2746,7 +2771,7 @@ static void define_gf_group(VP9_COMP *cpi, int gf_start_show_idx) { if (oxcf->aq_mode == PERCEPTUAL_AQ) rc->gfu_boost = VPXMIN(rc->gfu_boost, MIN_ARF_GF_BOOST); - rc->baseline_gf_interval = i - rc->source_alt_ref_pending; + rc->baseline_gf_interval = gop_coding_frames - rc->source_alt_ref_pending; if (rc->source_alt_ref_pending) is_alt_ref_flash = detect_flash(twopass, rc->baseline_gf_interval); @@ -2757,8 +2782,8 @@ static void define_gf_group(VP9_COMP *cpi, int gf_start_show_idx) { // If the first frame is a key frame or the overlay from a previous arf then // the error score / cost of this frame has already been accounted for. int start_idx = arf_active_or_kf ? 1 : 0; - int num_coding_frames = i; - for (j = start_idx; j < num_coding_frames; ++j) { + int j; + for (j = start_idx; j < gop_coding_frames; ++j) { int show_idx = gf_start_show_idx + j; const FIRSTPASS_STATS *frame_stats = fps_get_frame_stats(first_pass_info, show_idx); @@ -3030,13 +3055,15 @@ static int test_candidate_kf(TWO_PASS *twopass, #define MAX_KF_TOT_BOOST 5400 #endif -static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { +static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame, + int kf_show_idx) { int i, j; RATE_CONTROL *const rc = &cpi->rc; TWO_PASS *const twopass = &cpi->twopass; GF_GROUP *const gf_group = &twopass->gf_group; const VP9EncoderConfig *const oxcf = &cpi->oxcf; - const FIRSTPASS_STATS first_frame = *this_frame; + const FIRST_PASS_INFO *first_pass_info = &twopass->first_pass_info; + const FRAME_INFO *frame_info = &cpi->frame_info; const FIRSTPASS_STATS *const start_position = twopass->stats_in; FIRSTPASS_STATS next_frame; FIRSTPASS_STATS last_frame; @@ -3058,6 +3085,7 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { double sr_accumulator = 0.0; double abs_mv_in_out_accumulator = 0.0; const double av_err = get_distribution_av_err(cpi, twopass); + const double mean_mod_score = twopass->mean_mod_score; vp9_zero(next_frame); cpi->common.frame_type = KEY_FRAME; @@ -3092,10 +3120,6 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { i = 0; while (twopass->stats_in < twopass->stats_in_end && rc->frames_to_key < cpi->oxcf.key_freq) { - // Accumulate kf group error. - kf_group_err += - calculate_norm_frame_score(cpi, twopass, oxcf, this_frame, av_err); - // Load the next frame's stats. last_frame = *this_frame; input_stats(twopass, this_frame); @@ -3128,14 +3152,8 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { break; // Step on to the next frame. - ++rc->frames_to_key; - - // If we don't have a real key frame within the next two - // key_freq intervals then break out of the loop. - if (rc->frames_to_key >= 2 * cpi->oxcf.key_freq) break; - } else { - ++rc->frames_to_key; } + ++rc->frames_to_key; ++i; } @@ -3143,35 +3161,19 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { // We already breakout of the loop above at 2x max. // This code centers the extra kf if the actual natural interval // is between 1x and 2x. - if (cpi->oxcf.auto_key && rc->frames_to_key > cpi->oxcf.key_freq) { - FIRSTPASS_STATS tmp_frame = first_frame; - - rc->frames_to_key /= 2; - - // Reset to the start of the group. - reset_fpf_position(twopass, start_position); - - kf_group_err = 0.0; - - // Rescan to get the correct error data for the forced kf group. - for (i = 0; i < rc->frames_to_key; ++i) { - kf_group_err += - calculate_norm_frame_score(cpi, twopass, oxcf, &tmp_frame, av_err); - input_stats(twopass, &tmp_frame); - } - rc->next_key_frame_forced = 1; - } else if (twopass->stats_in == twopass->stats_in_end || - rc->frames_to_key >= cpi->oxcf.key_freq) { + if (twopass->stats_in == twopass->stats_in_end || + rc->frames_to_key >= cpi->oxcf.key_freq) { rc->next_key_frame_forced = 1; } else { rc->next_key_frame_forced = 0; } - // Special case for the last key frame of the file. - if (twopass->stats_in >= twopass->stats_in_end) { + for (i = 0; i < rc->frames_to_key; ++i) { + const FIRSTPASS_STATS *frame_stats = + fps_get_frame_stats(first_pass_info, kf_show_idx + i); // Accumulate kf group error. - kf_group_err += - calculate_norm_frame_score(cpi, twopass, oxcf, this_frame, av_err); + kf_group_err += calc_norm_frame_score(oxcf, frame_info, frame_stats, + mean_mod_score, av_err); } // Calculate the number of bits that should be assigned to the kf group. @@ -3349,6 +3351,7 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { TWO_PASS *const twopass = &cpi->twopass; GF_GROUP *const gf_group = &twopass->gf_group; FIRSTPASS_STATS this_frame; + const int show_idx = cm->current_video_frame; if (!twopass->stats_in) return; @@ -3434,7 +3437,7 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { FIRSTPASS_STATS this_frame_copy; this_frame_copy = this_frame; // Define next KF group and assign bits to it. - find_next_key_frame(cpi, &this_frame); + find_next_key_frame(cpi, &this_frame, show_idx); this_frame = this_frame_copy; } else { cm->frame_type = INTER_FRAME; @@ -3442,8 +3445,7 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { // Define a new GF/ARF group. (Should always enter here for key frames). if (rc->frames_till_gf_update_due == 0) { - const int gf_start_show_idx = cm->current_video_frame; - define_gf_group(cpi, gf_start_show_idx); + define_gf_group(cpi, show_idx); rc->frames_till_gf_update_due = rc->baseline_gf_interval; |