From: angiebird Date: Mon, 21 Oct 2019 18:44:36 +0000 (-0700) Subject: Add get_gop_coding_frame_num() X-Git-Tag: v1.8.2~81^2~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=31193de1ccccbcc4e3580613a28340a30ad7e6d4;p=platform%2Fupstream%2Flibvpx.git Add get_gop_coding_frame_num() This function will decide number of coding frames and whether to use altref Change-Id: I736190512ea92ce5387600712bd0e250ad7cb44c --- diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index 7e8129b..a765f6c 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,7 +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; - 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; @@ -2563,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; @@ -2571,121 +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; - double zero_motion_accumulator = 1.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; - } - } - allow_alt_ref &= zero_motion_accumulator < 0.995; + 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 (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 = @@ -2693,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 @@ -2717,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 @@ -2745,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); @@ -2756,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);