Move frame level twopass members to twopass_frame structure Moved elements stats_in, mb_av_energy and fr_content_type out of TWOPASS into TWOPASS_FRAME. Each frame context(cpi) will have a copy of TWOPASS_FRAME, initialized appropriately for the frame it will be processing. Change-Id: I864860db45a152b370b3e6f342f8372277febc7d
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c index 490f3aa..45da020 100644 --- a/av1/av1_cx_iface.c +++ b/av1/av1_cx_iface.c
@@ -2385,8 +2385,6 @@ priv->ppi->twopass.frame_stats_arr[i] = &priv->frame_stats_buffer[i]; priv->ppi->twopass.stats_buf_ctx = &priv->stats_buf_context; - priv->ppi->twopass.stats_in = - priv->ppi->twopass.stats_buf_ctx->stats_in_start; #endif #if CONFIG_FRAME_PARALLEL_ENCODE @@ -2408,12 +2406,16 @@ priv->ppi->parallel_cpi[i], priv->ppi->parallel_cpi[i]->oxcf.max_threads)); } + priv->ppi->parallel_cpi[i]->twopass_frame.stats_in = + priv->ppi->twopass.stats_buf_ctx->stats_in_start; } priv->ppi->cpi = priv->ppi->parallel_cpi[0]; #else res = create_context_and_bufferpool(priv->ppi, &priv->ppi->cpi, &priv->buffer_pool, &priv->oxcf, ENCODE_STAGE, -1); + priv->ppi->cpi->twopass_frame.stats_in = + priv->ppi->twopass.stats_buf_ctx->stats_in_start; #endif // CONFIG_FRAME_PARALLEL_ENCODE // Create another compressor if look ahead is enabled
diff --git a/av1/encoder/aq_complexity.c b/av1/encoder/aq_complexity.c index 1c3d710..3573b2a 100644 --- a/av1/encoder/aq_complexity.c +++ b/av1/encoder/aq_complexity.c
@@ -155,10 +155,10 @@ const int aq_strength = get_aq_c_strength(cm->quant_params.base_qindex, cm->seq_params->bit_depth); - low_var_thresh = - (is_stat_consumption_stage_twopass(cpi)) - ? AOMMAX(exp(cpi->ppi->twopass.mb_av_energy), MIN_DEFAULT_LV_THRESH) - : DEFAULT_LV_THRESH; + low_var_thresh = (is_stat_consumption_stage_twopass(cpi)) + ? AOMMAX(exp(cpi->twopass_frame.mb_av_energy), + MIN_DEFAULT_LV_THRESH) + : DEFAULT_LV_THRESH; av1_setup_src_planes(mb, cpi->source, mi_row, mi_col, num_planes, bs); logvar = av1_log_block_var(cpi, mb, bs);
diff --git a/av1/encoder/aq_variance.c b/av1/encoder/aq_variance.c index 02daa8f..c2d0a07 100644 --- a/av1/encoder/aq_variance.c +++ b/av1/encoder/aq_variance.c
@@ -51,7 +51,7 @@ int resolution_change = cm->prev_frame && (cm->width != cm->prev_frame->width || cm->height != cm->prev_frame->height); - int avg_energy = (int)(cpi->ppi->twopass.mb_av_energy - 2); + int avg_energy = (int)(cpi->twopass_frame.mb_av_energy - 2); double avg_ratio; if (avg_energy > 7) avg_energy = 7; if (avg_energy < 0) avg_energy = 0; @@ -166,7 +166,7 @@ BLOCK_SIZE bs) { double energy, energy_midpoint; energy_midpoint = (is_stat_consumption_stage_twopass(cpi)) - ? cpi->ppi->twopass.frame_avg_haar_energy + ? cpi->twopass_frame.frame_avg_haar_energy : DEFAULT_E_MIDPOINT; energy = av1_log_block_wavelet_energy(x, bs) - energy_midpoint; return clamp((int)round(energy), ENERGY_MIN, ENERGY_MAX);
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c index e78c85a..ec956a8 100644 --- a/av1/encoder/encoder.c +++ b/av1/encoder/encoder.c
@@ -1332,7 +1332,7 @@ * two pass*/ cpi->ppi->twopass.stats_buf_ctx->stats_in_start = oxcf->twopass_stats_in.buf; - cpi->ppi->twopass.stats_in = + cpi->twopass_frame.stats_in = cpi->ppi->twopass.stats_buf_ctx->stats_in_start; cpi->ppi->twopass.stats_buf_ctx->stats_in_end = &cpi->ppi->twopass.stats_buf_ctx->stats_in_start[packets - 1]; @@ -3113,7 +3113,7 @@ int64_t frame_avg_wavelet_energy = av1_haar_ac_sad_mxn_uint8_input( src, stride, hbd, num_8x8_rows, num_8x8_cols); - twopass->frame_avg_haar_energy = + cpi->twopass_frame.frame_avg_haar_energy = log(((double)frame_avg_wavelet_energy / num_mbs) + 1.0); } #endif
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h index 7736ae0..8876f5f 100644 --- a/av1/encoder/encoder.h +++ b/av1/encoder/encoder.h
@@ -3105,6 +3105,11 @@ */ VBR_RATECTRL_INFO vbr_rc_info; #endif + + /*! + * Frame level twopass status and control data + */ + TWO_PASS_FRAME twopass_frame; } AV1_COMP; /*!
diff --git a/av1/encoder/firstpass.h b/av1/encoder/firstpass.h index 7adb91e..d89a763 100644 --- a/av1/encoder/firstpass.h +++ b/av1/encoder/firstpass.h
@@ -252,18 +252,12 @@ // here. FIRSTPASS_STATS *frame_stats_arr[MAX_LAP_BUFFERS + 1]; int frame_stats_next_idx; // Index to next unused element in frame_stats_arr. - const FIRSTPASS_STATS *stats_in; STATS_BUFFER_CTX *stats_buf_ctx; int first_pass_done; int64_t bits_left; double modified_error_min; double modified_error_max; double modified_error_left; - double mb_av_energy; - double frame_avg_haar_energy; - - // 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; @@ -288,6 +282,19 @@ /*!\endcond */ } TWO_PASS; +/*! + * \brief Frame level Two pass status and control data. + */ +typedef struct { + /*!\cond */ + const FIRSTPASS_STATS *stats_in; + double mb_av_energy; + // An indication of the content type of the current frame + FRAME_CONTENT_TYPE fr_content_type; + double frame_avg_haar_energy; + /*!\endcond */ +} TWO_PASS_FRAME; + /*!\cond */ // This structure contains several key parameters to be accumulated for this @@ -356,6 +363,7 @@ static INLINE int is_fp_wavelet_energy_invalid( const FIRSTPASS_STATS *fp_stats) { + assert(fp_stats != NULL); return (fp_stats->frame_avg_wavelet_energy < 0); }
diff --git a/av1/encoder/gop_structure.c b/av1/encoder/gop_structure.c index feb5053..f474093 100644 --- a/av1/encoder/gop_structure.c +++ b/av1/encoder/gop_structure.c
@@ -409,9 +409,10 @@ // Set parameters for frames between 'start' and 'end' (excluding both). static void set_multi_layer_params( - const TWO_PASS *twopass, GF_GROUP *const gf_group, - const PRIMARY_RATE_CONTROL *p_rc, RATE_CONTROL *rc, FRAME_INFO *frame_info, - int start, int end, int *cur_frame_idx, int *frame_ind, + const TWO_PASS *twopass, const TWO_PASS_FRAME *twopass_frame, + GF_GROUP *const gf_group, const PRIMARY_RATE_CONTROL *p_rc, + RATE_CONTROL *rc, FRAME_INFO *frame_info, int start, int end, + int *cur_frame_idx, int *frame_ind, #if CONFIG_FRAME_PARALLEL_ENCODE int *parallel_frame_count, int max_parallel_frames, int do_frame_parallel_encode, int *first_frame_index, @@ -429,8 +430,9 @@ gf_group->arf_src_offset[*frame_ind] = 0; gf_group->cur_frame_idx[*frame_ind] = *cur_frame_idx; gf_group->layer_depth[*frame_ind] = MAX_ARF_LAYERS; - gf_group->arf_boost[*frame_ind] = av1_calc_arf_boost( - twopass, p_rc, frame_info, start, end - start, 0, NULL, NULL, 0); + gf_group->arf_boost[*frame_ind] = + av1_calc_arf_boost(twopass, twopass_frame, p_rc, frame_info, start, + end - start, 0, NULL, NULL, 0); gf_group->frame_type[*frame_ind] = INTER_FRAME; gf_group->refbuf_state[*frame_ind] = REFBUF_UPDATE; gf_group->max_layer_depth = @@ -474,13 +476,14 @@ #endif // CONFIG_FRAME_PARALLEL_ENCODE // Get the boost factor for intermediate ARF frames. - gf_group->arf_boost[*frame_ind] = av1_calc_arf_boost( - twopass, p_rc, frame_info, m, end - m, m - start, NULL, NULL, 0); + gf_group->arf_boost[*frame_ind] = + av1_calc_arf_boost(twopass, twopass_frame, p_rc, frame_info, m, end - m, + m - start, NULL, NULL, 0); ++(*frame_ind); // Frames displayed before this internal ARF. - set_multi_layer_params(twopass, gf_group, p_rc, rc, frame_info, start, m, - cur_frame_idx, frame_ind, + set_multi_layer_params(twopass, twopass_frame, gf_group, p_rc, rc, + frame_info, start, m, cur_frame_idx, frame_ind, #if CONFIG_FRAME_PARALLEL_ENCODE parallel_frame_count, max_parallel_frames, do_frame_parallel_encode, first_frame_index, @@ -503,8 +506,8 @@ ++(*cur_frame_idx); // Frames displayed after this internal ARF. - set_multi_layer_params(twopass, gf_group, p_rc, rc, frame_info, m + 1, end, - cur_frame_idx, frame_ind, + set_multi_layer_params(twopass, twopass_frame, gf_group, p_rc, rc, + frame_info, m + 1, end, cur_frame_idx, frame_ind, #if CONFIG_FRAME_PARALLEL_ENCODE parallel_frame_count, max_parallel_frames, do_frame_parallel_encode, first_frame_index, @@ -716,9 +719,9 @@ // Rest of the frames. if (!is_multi_layer_configured) - set_multi_layer_params(twopass, gf_group, p_rc, rc, frame_info, - cur_frame_index, gf_interval, &cur_frame_index, - &frame_index, + set_multi_layer_params(twopass, &cpi->twopass_frame, gf_group, p_rc, rc, + frame_info, cur_frame_index, gf_interval, + &cur_frame_index, &frame_index, #if CONFIG_FRAME_PARALLEL_ENCODE ¶llel_frame_count, cpi->ppi->num_fp_contexts, do_frame_parallel_encode, &first_frame_index,
diff --git a/av1/encoder/gop_structure.h b/av1/encoder/gop_structure.h index 0a6f4ab..3d37e2b 100644 --- a/av1/encoder/gop_structure.h +++ b/av1/encoder/gop_structure.h
@@ -67,6 +67,7 @@ /*!\cond */ int av1_calc_arf_boost(const TWO_PASS *twopass, + const TWO_PASS_FRAME *twopass_frame, const PRIMARY_RATE_CONTROL *p_rc, FRAME_INFO *frame_info, int offset, int f_frames, int b_frames, int *num_fpstats_used, int *num_fpstats_required,
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c index a96b292..151fe00 100644 --- a/av1/encoder/pass2_strategy.c +++ b/av1/encoder/pass2_strategy.c
@@ -88,38 +88,45 @@ // Resets the first pass file to the given position using a relative seek from // the current position. -static void reset_fpf_position(TWO_PASS *p, const FIRSTPASS_STATS *position) { - p->stats_in = position; +static void reset_fpf_position(TWO_PASS_FRAME *p_frame, + const FIRSTPASS_STATS *position) { + p_frame->stats_in = position; } -static int input_stats(TWO_PASS *p, FIRSTPASS_STATS *fps) { - if (p->stats_in >= p->stats_buf_ctx->stats_in_end) return EOF; +static int input_stats(TWO_PASS *p, TWO_PASS_FRAME *p_frame, + FIRSTPASS_STATS *fps) { + if (p_frame->stats_in >= p->stats_buf_ctx->stats_in_end) return EOF; - *fps = *p->stats_in; - ++p->stats_in; + *fps = *p_frame->stats_in; + ++p_frame->stats_in; return 1; } -static int input_stats_lap(TWO_PASS *p, FIRSTPASS_STATS *fps) { - if (p->stats_in >= p->stats_buf_ctx->stats_in_end) return EOF; +static int input_stats_lap(TWO_PASS *p, TWO_PASS_FRAME *p_frame, + FIRSTPASS_STATS *fps) { + if (p_frame->stats_in >= p->stats_buf_ctx->stats_in_end) return EOF; - *fps = *p->stats_in; + *fps = *p_frame->stats_in; /* Move old stats[0] out to accommodate for next frame stats */ memmove(p->frame_stats_arr[0], p->frame_stats_arr[1], - (p->stats_buf_ctx->stats_in_end - p->stats_in - 1) * + (p->stats_buf_ctx->stats_in_end - p_frame->stats_in - 1) * sizeof(FIRSTPASS_STATS)); p->stats_buf_ctx->stats_in_end--; return 1; } // Read frame stats at an offset from the current position. -static const FIRSTPASS_STATS *read_frame_stats(const TWO_PASS *p, int offset) { - if ((offset >= 0 && p->stats_in + offset >= p->stats_buf_ctx->stats_in_end) || - (offset < 0 && p->stats_in + offset < p->stats_buf_ctx->stats_in_start)) { +static const FIRSTPASS_STATS *read_frame_stats(const TWO_PASS *p, + const TWO_PASS_FRAME *p_frame, + int offset) { + if ((offset >= 0 && + p_frame->stats_in + offset >= p->stats_buf_ctx->stats_in_end) || + (offset < 0 && + p_frame->stats_in + offset < p->stats_buf_ctx->stats_in_start)) { return NULL; } - return &p->stats_in[offset]; + return &p_frame->stats_in[offset]; } static void subtract_stats(FIRSTPASS_STATS *section, @@ -416,6 +423,7 @@ // by a static section. For example in slide shows where there is a fade // between slides. This is to help with more optimal kf and gf positioning. static int detect_transition_to_still(TWO_PASS *const twopass, + TWO_PASS_FRAME *const twopass_frame, const int min_gf_interval, const int frame_interval, const int still_interval, @@ -429,7 +437,7 @@ int j; // Look ahead a few frames to see if static condition persists... for (j = 0; j < still_interval; ++j) { - const FIRSTPASS_STATS *stats = &twopass->stats_in[j]; + const FIRSTPASS_STATS *stats = &twopass_frame->stats_in[j]; if (stats >= twopass->stats_buf_ctx->stats_in_end) break; if (stats->pcnt_inter - stats->pcnt_motion < 0.999) break; @@ -443,8 +451,10 @@ // This function detects a flash through the high relative pcnt_second_ref // score in the frame following a flash frame. The offset passed in should // reflect this. -static int detect_flash(const TWO_PASS *twopass, const int offset) { - const FIRSTPASS_STATS *const next_frame = read_frame_stats(twopass, offset); +static int detect_flash(const TWO_PASS *twopass, + const TWO_PASS_FRAME *twopass_frame, const int offset) { + const FIRSTPASS_STATS *const next_frame = + read_frame_stats(twopass, twopass_frame, offset); // What we are looking for here is a situation where there is a // brief break in prediction (such as a flash) but subsequent frames @@ -639,6 +649,7 @@ #define GF_MIN_BOOST 50 #define MIN_DECAY_FACTOR 0.01 int av1_calc_arf_boost(const TWO_PASS *twopass, + const TWO_PASS_FRAME *twopass_frame, const PRIMARY_RATE_CONTROL *p_rc, FRAME_INFO *frame_info, int offset, int f_frames, int b_frames, int *num_fpstats_used, int *num_fpstats_required, @@ -653,7 +664,8 @@ // Search forward from the proposed arf/next gf position. for (i = 0; i < f_frames; ++i) { - const FIRSTPASS_STATS *this_frame = read_frame_stats(twopass, i + offset); + const FIRSTPASS_STATS *this_frame = + read_frame_stats(twopass, twopass_frame, i + offset); if (this_frame == NULL) break; // Update the motion related elements to the boost calculation. @@ -663,8 +675,8 @@ // We want to discount the flash frame itself and the recovery // frame that follows as both will have poor scores. - flash_detected = detect_flash(twopass, i + offset) || - detect_flash(twopass, i + offset + 1); + flash_detected = detect_flash(twopass, twopass_frame, i + offset) || + detect_flash(twopass, twopass_frame, i + offset + 1); // Accumulate the effect of prediction quality decay. if (!flash_detected) { @@ -688,7 +700,8 @@ init_gf_stats(&gf_stats); // Search backward towards last gf position. for (i = -1; i >= -b_frames; --i) { - const FIRSTPASS_STATS *this_frame = read_frame_stats(twopass, i + offset); + const FIRSTPASS_STATS *this_frame = + read_frame_stats(twopass, twopass_frame, i + offset); if (this_frame == NULL) break; // Update the motion related elements to the boost calculation. @@ -698,8 +711,8 @@ // We want to discount the the flash frame itself and the recovery // frame that follows as both will have poor scores. - flash_detected = detect_flash(twopass, i + offset) || - detect_flash(twopass, i + offset + 1); + flash_detected = detect_flash(twopass, twopass_frame, i + offset) || + detect_flash(twopass, twopass_frame, i + offset + 1); // Cumulative effect of prediction quality decay. if (!flash_detected) { @@ -980,9 +993,10 @@ if (!flash_detected) { // Break clause to detect very still sections after motion. For example, // a static image after a fade or other transition. - if (detect_transition_to_still( - twopass, rc->min_gf_interval, frame_index - cur_start, 5, - gf_stats->loop_decay_rate, gf_stats->last_loop_decay_rate)) { + if (detect_transition_to_still(twopass, &cpi->twopass_frame, + rc->min_gf_interval, frame_index - cur_start, + 5, gf_stats->loop_decay_rate, + gf_stats->last_loop_decay_rate)) { return 1; } } @@ -1869,7 +1883,7 @@ PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc; TWO_PASS *const twopass = &cpi->ppi->twopass; FIRSTPASS_STATS next_frame; - const FIRSTPASS_STATS *const start_pos = twopass->stats_in; + const FIRSTPASS_STATS *const start_pos = cpi->twopass_frame.stats_in; const FIRSTPASS_STATS *const stats = start_pos - (rc->frames_since_key == 0); const int f_w = cpi->common.width; @@ -1912,13 +1926,13 @@ // reached maximum len, but nothing special yet (almost static) // let's look at the next interval cut_here = 1; - } else if (EOF == input_stats(twopass, &next_frame)) { + } else if (EOF == input_stats(twopass, &cpi->twopass_frame, &next_frame)) { // reaches last frame, break cut_here = 2; } else { // Test for the case where there is a brief flash but the prediction // quality back to an earlier frame is then restored. - flash_detected = detect_flash(twopass, 0); + flash_detected = detect_flash(twopass, &cpi->twopass_frame, 0); // TODO(bohanli): remove redundant accumulations here, or unify // this and the ones in define_gf_group accumulate_next_frame_stats(&next_frame, flash_detected, @@ -2081,7 +2095,7 @@ count_cuts++; // reset pointers to the shrinked location - twopass->stats_in = start_pos + cur_last; + cpi->twopass_frame.stats_in = start_pos + cur_last; cur_start = cur_last; int cur_region_idx = find_regions_index(regions, num_regions, cur_start + 1 + offset); @@ -2104,7 +2118,7 @@ p_rc->gf_intervals[n - 1] = cut_pos[n] - cut_pos[n - 1]; } p_rc->cur_gf_index = 0; - twopass->stats_in = start_pos; + cpi->twopass_frame.stats_in = start_pos; } static void correct_frames_to_key(AV1_COMP *cpi) { @@ -2205,7 +2219,7 @@ // If forward keyframes are enabled, ensure the final gf group obeys the // MIN_FWD_KF_INTERVAL. const int is_last_kf = - (twopass->stats_in - arf_position + rc->frames_to_key) >= + (cpi->twopass_frame.stats_in - arf_position + rc->frames_to_key) >= twopass->stats_buf_ctx->stats_in_end; if (cpi->oxcf.kf_cfg.fwd_kf_enabled && use_alt_ref && !is_last_kf && @@ -2282,7 +2296,7 @@ const AV1EncoderConfig *const oxcf = &cpi->oxcf; TWO_PASS *const twopass = &cpi->ppi->twopass; FIRSTPASS_STATS next_frame; - const FIRSTPASS_STATS *const start_pos = twopass->stats_in; + const FIRSTPASS_STATS *const start_pos = cpi->twopass_frame.stats_in; GF_GROUP *gf_group = &cpi->ppi->gf_group; FRAME_INFO *frame_info = &cpi->frame_info; const GFConfig *const gf_cfg = &oxcf->gf_cfg; @@ -2332,7 +2346,7 @@ // get the determined gf group length from p_rc->gf_intervals while (i < p_rc->gf_intervals[p_rc->cur_gf_index]) { // read in the next frame - if (EOF == input_stats(twopass, &next_frame)) break; + if (EOF == input_stats(twopass, &cpi->twopass_frame, &next_frame)) break; // Accumulate error score of frames in this gf group. double mod_frame_err = calculate_modified_err(frame_info, twopass, oxcf, &next_frame); @@ -2341,17 +2355,17 @@ ++i; } - reset_fpf_position(twopass, start_pos); + reset_fpf_position(&cpi->twopass_frame, start_pos); i = is_intra_only; - input_stats(twopass, &next_frame); + input_stats(twopass, &cpi->twopass_frame, &next_frame); while (i < p_rc->gf_intervals[p_rc->cur_gf_index]) { // read in the next frame - if (EOF == input_stats(twopass, &next_frame)) break; + if (EOF == input_stats(twopass, &cpi->twopass_frame, &next_frame)) break; // Test for the case where there is a brief flash but the prediction // quality back to an earlier frame is then restored. - flash_detected = detect_flash(twopass, 0); + flash_detected = detect_flash(twopass, &cpi->twopass_frame, 0); // accumulate stats for next frame accumulate_next_frame_stats(&next_frame, flash_detected, @@ -2448,21 +2462,21 @@ // Calculate the boost for alt ref. p_rc->gfu_boost = av1_calc_arf_boost( - twopass, p_rc, frame_info, alt_offset, forward_frames, ext_len, - &p_rc->num_stats_used_for_gfu_boost, + twopass, &cpi->twopass_frame, p_rc, frame_info, alt_offset, + forward_frames, ext_len, &p_rc->num_stats_used_for_gfu_boost, &p_rc->num_stats_required_for_gfu_boost, cpi->ppi->lap_enabled); } else { - reset_fpf_position(twopass, start_pos); + reset_fpf_position(&cpi->twopass_frame, start_pos); gf_group->max_layer_depth_allowed = 0; set_baseline_gf_interval(cpi, i, active_max_gf_interval, use_alt_ref, is_final_pass); p_rc->gfu_boost = AOMMIN( MAX_GF_BOOST, - av1_calc_arf_boost(twopass, p_rc, frame_info, alt_offset, ext_len, 0, - &p_rc->num_stats_used_for_gfu_boost, - &p_rc->num_stats_required_for_gfu_boost, - cpi->ppi->lap_enabled)); + av1_calc_arf_boost( + twopass, &cpi->twopass_frame, p_rc, frame_info, alt_offset, ext_len, + 0, &p_rc->num_stats_used_for_gfu_boost, + &p_rc->num_stats_required_for_gfu_boost, cpi->ppi->lap_enabled)); } #define LAST_ALR_BOOST_FACTOR 0.2f @@ -2478,7 +2492,7 @@ rc->frames_till_gf_update_due = p_rc->baseline_gf_interval; // Reset the file position. - reset_fpf_position(twopass, start_pos); + reset_fpf_position(&cpi->twopass_frame, start_pos); if (cpi->ppi->lap_enabled) { // Since we don't have enough stats to know the actual error of the @@ -2523,7 +2537,7 @@ av1_gop_setup_structure(cpi); // Reset the file position. - reset_fpf_position(twopass, start_pos); + reset_fpf_position(&cpi->twopass_frame, start_pos); // Calculate a section intra ratio used in setting max loop filter. if (rc->frames_since_key != 0) { @@ -2639,7 +2653,7 @@ second_ref_usage_thresh_max_delta; } -static int test_candidate_kf(TWO_PASS *twopass, +static int test_candidate_kf(TWO_PASS *twopass, TWO_PASS_FRAME *twopass_frame, const FIRSTPASS_STATS *last_frame, const FIRSTPASS_STATS *this_frame, const FIRSTPASS_STATS *next_frame, @@ -2658,11 +2672,11 @@ if (scenecut_mode == ENABLE_SCENECUT_MODE_1) { curr_frame = *this_frame; - const FIRSTPASS_STATS *const start_position = twopass->stats_in; + const FIRSTPASS_STATS *const start_position = twopass_frame->stats_in; for (num_future_frames = 0; num_future_frames < SCENE_CUT_KEY_TEST_INTERVAL; num_future_frames++) - if (EOF == input_stats(twopass, &curr_frame)) break; - reset_fpf_position(twopass, start_position); + if (EOF == input_stats(twopass, twopass_frame, &curr_frame)) break; + reset_fpf_position(twopass_frame, start_position); if (num_future_frames < 3) { return 0; } else { @@ -2694,7 +2708,7 @@ DOUBLE_DIVIDE_CHECK(next_frame->coded_error)) > II_IMPROVEMENT_THRESHOLD))))) { int i; - const FIRSTPASS_STATS *start_pos = twopass->stats_in; + const FIRSTPASS_STATS *start_pos = twopass_frame->stats_in; double boost_score = 0.0; double old_boost_score = 0.0; double decay_accumulator = 1.0; @@ -2703,7 +2717,7 @@ for (i = 0; i < total_frames_to_test; ++i) { // Get the next frame details FIRSTPASS_STATS local_next_frame; - if (EOF == input_stats(twopass, &local_next_frame)) break; + if (EOF == input_stats(twopass, twopass_frame, &local_next_frame)) break; double next_iiratio = (BOOST_FACTOR * local_next_frame.intra_error / DOUBLE_DIVIDE_CHECK(local_next_frame.coded_error)); @@ -2741,7 +2755,7 @@ } // Reset the file position - reset_fpf_position(twopass, start_pos); + reset_fpf_position(twopass_frame, start_pos); } return is_viable_kf; } @@ -2831,7 +2845,7 @@ const int num_mbs = (oxcf->resize_cfg.resize_mode != RESIZE_NONE) ? cpi->initial_mbs : cpi->common.mi_params.MBs; - while (twopass->stats_in < twopass->stats_buf_ctx->stats_in_end && + while (cpi->twopass_frame.stats_in < twopass->stats_buf_ctx->stats_in_end && frames_to_key < num_frames_to_detect_scenecut) { // Accumulate total number of stats available till next key frame num_stats_used_for_kf_boost++; @@ -2843,25 +2857,25 @@ // Load the next frame's stats. last_frame = *this_frame; - input_stats(twopass, this_frame); + input_stats(twopass, &cpi->twopass_frame, this_frame); // Provided that we are not at the end of the file... if ((cpi->ppi->p_rc.enable_scenecut_detection > 0) && kf_cfg->auto_key && - twopass->stats_in < twopass->stats_buf_ctx->stats_in_end) { + cpi->twopass_frame.stats_in < twopass->stats_buf_ctx->stats_in_end) { double loop_decay_rate; // Check for a scene cut. if (frames_since_key >= kf_cfg->key_freq_min && - test_candidate_kf(twopass, &last_frame, this_frame, twopass->stats_in, - frames_since_key, oxcf->rc_cfg.mode, - cpi->ppi->p_rc.enable_scenecut_detection, - num_mbs)) { + test_candidate_kf( + twopass, &cpi->twopass_frame, &last_frame, this_frame, + cpi->twopass_frame.stats_in, frames_since_key, oxcf->rc_cfg.mode, + cpi->ppi->p_rc.enable_scenecut_detection, num_mbs)) { scenecut_detected = 1; break; } // How fast is the prediction quality decaying? - loop_decay_rate = get_prediction_decay_rate(twopass->stats_in); + loop_decay_rate = get_prediction_decay_rate(cpi->twopass_frame.stats_in); // We want to know something about the recent past... rather than // as used elsewhere where we are concerned with decay in prediction @@ -2874,9 +2888,9 @@ // Special check for transition or high motion followed by a // static scene. if (frames_since_key >= kf_cfg->key_freq_min && - detect_transition_to_still(twopass, rc->min_gf_interval, i, - kf_cfg->key_freq_max - i, loop_decay_rate, - decay_accumulator)) { + detect_transition_to_still( + twopass, &cpi->twopass_frame, rc->min_gf_interval, i, + kf_cfg->key_freq_max - i, loop_decay_rate, decay_accumulator)) { scenecut_detected = 1; // In the case of transition followed by a static scene, the key frame // could be a good predictor for the following frames, therefore we @@ -2906,13 +2920,14 @@ frames_to_key = num_frames_to_next_key; if (!kf_cfg->fwd_kf_enabled || scenecut_detected || - twopass->stats_in >= twopass->stats_buf_ctx->stats_in_end) + cpi->twopass_frame.stats_in >= twopass->stats_buf_ctx->stats_in_end) p_rc->next_is_fwd_key = 0; return frames_to_key; } static double get_kf_group_avg_error(TWO_PASS *twopass, + TWO_PASS_FRAME *twopass_frame, const FIRSTPASS_STATS *first_frame, const FIRSTPASS_STATS *start_position, int frames_to_key) { @@ -2920,11 +2935,11 @@ int num_frames, i; double kf_group_avg_error = 0.0; - reset_fpf_position(twopass, start_position); + reset_fpf_position(twopass_frame, start_position); for (i = 0; i < frames_to_key; ++i) { kf_group_avg_error += cur_frame.coded_error; - if (EOF == input_stats(twopass, &cur_frame)) break; + if (EOF == input_stats(twopass, twopass_frame, &cur_frame)) break; } num_frames = i + 1; num_frames = AOMMIN(num_frames, frames_to_key); @@ -2963,7 +2978,7 @@ int num_frames = 0; // Accumulate total stat using available number of stats. for (num_frames = 0; num_frames < (rc->frames_to_key - 1); ++num_frames) { - if (EOF == input_stats(twopass, &cur_frame)) break; + if (EOF == input_stats(twopass, &cpi->twopass_frame, &cur_frame)) break; av1_accumulate_stats(avg_frame_stat, &cur_frame); } @@ -3022,7 +3037,9 @@ if (use_avg_stat) num_stat_used = calc_avg_stats(cpi, &frame_stat); for (i = num_stat_used; i < (rc->frames_to_key - 1); ++i) { - if (!use_avg_stat && EOF == input_stats(twopass, &frame_stat)) break; + if (!use_avg_stat && + EOF == input_stats(twopass, &cpi->twopass_frame, &frame_stat)) + break; // Monitor for static sections. // For the first frame in kf group, the second ref indicator is invalid. @@ -3107,7 +3124,7 @@ return; } int i; - const FIRSTPASS_STATS *const start_position = twopass->stats_in; + const FIRSTPASS_STATS *const start_position = cpi->twopass_frame.stats_in; int kf_bits = 0; double zero_motion_accumulator = 1.0; double boost_score = 0.0; @@ -3150,7 +3167,7 @@ rc->frames_to_key /= 2; // Reset to the start of the group. - reset_fpf_position(twopass, start_position); + reset_fpf_position(&cpi->twopass_frame, start_position); kf_group_err = 0.0; @@ -3158,10 +3175,11 @@ for (i = 0; i < rc->frames_to_key; ++i) { kf_group_err += calculate_modified_err(frame_info, twopass, oxcf, &tmp_frame); - if (EOF == input_stats(twopass, &tmp_frame)) break; + if (EOF == input_stats(twopass, &cpi->twopass_frame, &tmp_frame)) break; } p_rc->next_key_frame_forced = 1; - } else if ((twopass->stats_in == twopass->stats_buf_ctx->stats_in_end && + } else if ((cpi->twopass_frame.stats_in == + twopass->stats_buf_ctx->stats_in_end && is_stat_consumption_stage_twopass(cpi)) || rc->frames_to_key >= kf_cfg->key_freq_max) { p_rc->next_key_frame_forced = 1; @@ -3173,7 +3191,7 @@ p_rc->next_is_fwd_key |= p_rc->next_key_frame_forced; // Special case for the last key frame of the file. - if (twopass->stats_in >= twopass->stats_buf_ctx->stats_in_end) { + if (cpi->twopass_frame.stats_in >= twopass->stats_buf_ctx->stats_in_end) { // Accumulate kf group error. kf_group_err += calculate_modified_err(frame_info, twopass, oxcf, this_frame); @@ -3190,8 +3208,9 @@ int64_t max_grp_bits; if (oxcf->rc_cfg.vbr_corpus_complexity_lap) { - kf_group_avg_error = get_kf_group_avg_error( - twopass, &first_frame, start_position, rc->frames_to_key); + kf_group_avg_error = + get_kf_group_avg_error(twopass, &cpi->twopass_frame, &first_frame, + start_position, rc->frames_to_key); } // Default allocation based on bits left and relative @@ -3224,13 +3243,13 @@ } // Reset the first pass file position. - reset_fpf_position(twopass, start_position); + reset_fpf_position(&cpi->twopass_frame, start_position); // Scan through the kf group collating various stats used to determine // how many bits to spend on it. boost_score = get_kf_boost_score(cpi, kf_raw_err, &zero_motion_accumulator, &sr_accumulator, 0); - reset_fpf_position(twopass, start_position); + reset_fpf_position(&cpi->twopass_frame, start_position); // Store the zero motion percentage twopass->kf_zeromotion_pct = (int)(zero_motion_accumulator * 100.0); @@ -3247,7 +3266,7 @@ // TODO(any): Explore using average frame stats for AOM_Q as well. boost_score = get_kf_boost_score( cpi, kf_raw_err, &zero_motion_accumulator, &sr_accumulator, 1); - reset_fpf_position(twopass, start_position); + reset_fpf_position(&cpi->twopass_frame, start_position); p_rc->kf_boost += (int)boost_score; } } @@ -3309,15 +3328,18 @@ const TWO_PASS *const twopass = &cpi->ppi->twopass; return (!frame_is_intra_only(&cpi->common) && - twopass->stats_in - 2 > twopass->stats_buf_ctx->stats_in_start && - twopass->stats_in < twopass->stats_buf_ctx->stats_in_end && - (twopass->stats_in - 1)->pcnt_inter - - (twopass->stats_in - 1)->pcnt_motion == + cpi->twopass_frame.stats_in - 2 > + twopass->stats_buf_ctx->stats_in_start && + cpi->twopass_frame.stats_in < twopass->stats_buf_ctx->stats_in_end && + (cpi->twopass_frame.stats_in - 1)->pcnt_inter - + (cpi->twopass_frame.stats_in - 1)->pcnt_motion == 1 && - (twopass->stats_in - 2)->pcnt_inter - - (twopass->stats_in - 2)->pcnt_motion == + (cpi->twopass_frame.stats_in - 2)->pcnt_inter - + (cpi->twopass_frame.stats_in - 2)->pcnt_motion == 1 && - twopass->stats_in->pcnt_inter - twopass->stats_in->pcnt_motion == 1); + cpi->twopass_frame.stats_in->pcnt_inter - + cpi->twopass_frame.stats_in->pcnt_motion == + 1); } #define ARF_STATS_OUTPUT 0 @@ -3341,26 +3363,26 @@ } static INLINE void set_twopass_params_based_on_fp_stats( - const AV1_COMP *cpi, const FIRSTPASS_STATS *this_frame_ptr) { + AV1_COMP *cpi, const FIRSTPASS_STATS *this_frame_ptr) { if (this_frame_ptr == NULL) return; - TWO_PASS *const twopass = &cpi->ppi->twopass; + TWO_PASS_FRAME *twopass_frame = &cpi->twopass_frame; // The multiplication by 256 reverses a scaling factor of (>> 8) // applied when combining MB error values for the frame. - twopass->mb_av_energy = log((this_frame_ptr->intra_error) + 1.0); + twopass_frame->mb_av_energy = log((this_frame_ptr->intra_error) + 1.0); const FIRSTPASS_STATS *const total_stats = - twopass->stats_buf_ctx->total_stats; + cpi->ppi->twopass.stats_buf_ctx->total_stats; if (is_fp_wavelet_energy_invalid(total_stats) == 0) { - twopass->frame_avg_haar_energy = + twopass_frame->frame_avg_haar_energy = log((this_frame_ptr->frame_avg_wavelet_energy) + 1.0); } // Set the frame content type flag. if (this_frame_ptr->intra_skip_pct >= FC_ANIMATION_THRESH) - twopass->fr_content_type = FC_GRAPHICS_ANIMATION; + twopass_frame->fr_content_type = FC_GRAPHICS_ANIMATION; else - twopass->fr_content_type = FC_NORMAL; + twopass_frame->fr_content_type = FC_NORMAL; } static void process_first_pass_stats(AV1_COMP *cpi, @@ -3408,9 +3430,9 @@ } if (cpi->ppi->lap_enabled) { - input_stats_lap(twopass, this_frame); + input_stats_lap(twopass, &cpi->twopass_frame, this_frame); } else { - input_stats(twopass, this_frame); + input_stats(twopass, &cpi->twopass_frame, this_frame); } set_twopass_params_based_on_fp_stats(cpi, this_frame); } @@ -3573,11 +3595,11 @@ GF_GROUP *const gf_group = &cpi->ppi->gf_group; const AV1EncoderConfig *const oxcf = &cpi->oxcf; - const FIRSTPASS_STATS *const start_pos = twopass->stats_in; + const FIRSTPASS_STATS *const start_pos = cpi->twopass_frame.stats_in; - if (is_stat_consumption_stage(cpi) && !twopass->stats_in) return; + if (is_stat_consumption_stage(cpi) && !cpi->twopass_frame.stats_in) return; - assert(twopass->stats_in != NULL); + assert(cpi->twopass_frame.stats_in != NULL); const int update_type = gf_group->update_type[cpi->gf_frame_index]; frame_params->frame_type = gf_group->frame_type[cpi->gf_frame_index]; @@ -3595,8 +3617,9 @@ oxcf->pass >= AOM_RC_SECOND_PASS) { cpi->partition_search_skippable_frame = is_skippable_frame(cpi); } - const FIRSTPASS_STATS *const this_frame_ptr = read_frame_stats( - twopass, gf_group->arf_src_offset[cpi->gf_frame_index]); + const FIRSTPASS_STATS *const this_frame_ptr = + read_frame_stats(twopass, &cpi->twopass_frame, + gf_group->arf_src_offset[cpi->gf_frame_index]); set_twopass_params_based_on_fp_stats(cpi, this_frame_ptr); return; } @@ -3626,7 +3649,7 @@ // Define next KF group and assign bits to it. int kf_offset = rc->frames_to_key; if (rc->frames_to_key < 0) { - this_frame = *(twopass->stats_in - 1); + this_frame = *(cpi->twopass_frame.stats_in - 1); } else { frame_params->frame_type = KEY_FRAME; } @@ -3674,7 +3697,7 @@ // Define a new GF/ARF group. (Should always enter here for key frames). if (cpi->gf_frame_index == gf_group->size) { - const FIRSTPASS_STATS *const start_position = twopass->stats_in; + const FIRSTPASS_STATS *const start_position = cpi->twopass_frame.stats_in; if (cpi->ppi->lap_enabled && cpi->ppi->p_rc.enable_scenecut_detection) { int num_frames_to_detect_scenecut, frames_to_key; @@ -3685,7 +3708,7 @@ rc->frames_to_key = AOMMIN(rc->frames_to_key, frames_to_key); } - reset_fpf_position(twopass, start_position); + reset_fpf_position(&cpi->twopass_frame, start_position); int max_gop_length = (oxcf->gf_cfg.lag_in_frames >= 32 && @@ -3704,9 +3727,10 @@ // how many frames we can analyze from this frame int rest_frames = AOMMIN(rc->frames_to_key + p_rc->next_is_fwd_key, MAX_FIRSTPASS_ANALYSIS_FRAMES); - rest_frames = AOMMIN( - rest_frames, (int)(twopass->stats_buf_ctx->stats_in_end - - twopass->stats_in + (rc->frames_since_key == 0))); + rest_frames = + AOMMIN(rest_frames, (int)(twopass->stats_buf_ctx->stats_in_end - + cpi->twopass_frame.stats_in + + (rc->frames_since_key == 0))); p_rc->frames_till_regions_update = rest_frames; if (cpi->ppi->lap_enabled) { @@ -3716,12 +3740,13 @@ twopass->stats_buf_ctx->stats_in_end); estimate_coeff(twopass->stats_buf_ctx->stats_in_start, twopass->stats_buf_ctx->stats_in_end); - identify_regions(twopass->stats_in, rest_frames, + identify_regions(cpi->twopass_frame.stats_in, rest_frames, (rc->frames_since_key == 0), p_rc->regions, &p_rc->num_regions); } else { - identify_regions(twopass->stats_in - (rc->frames_since_key == 0), - rest_frames, 0, p_rc->regions, &p_rc->num_regions); + identify_regions( + cpi->twopass_frame.stats_in - (rc->frames_since_key == 0), + rest_frames, 0, p_rc->regions, &p_rc->num_regions); } } @@ -3803,10 +3828,11 @@ if (gf_group->update_type[cpi->gf_frame_index] == ARF_UPDATE || gf_group->update_type[cpi->gf_frame_index] == INTNL_ARF_UPDATE) { - reset_fpf_position(twopass, start_pos); + reset_fpf_position(&cpi->twopass_frame, start_pos); - const FIRSTPASS_STATS *const this_frame_ptr = read_frame_stats( - twopass, gf_group->arf_src_offset[cpi->gf_frame_index]); + const FIRSTPASS_STATS *const this_frame_ptr = + read_frame_stats(twopass, &cpi->twopass_frame, + gf_group->arf_src_offset[cpi->gf_frame_index]); set_twopass_params_based_on_fp_stats(cpi, this_frame_ptr); } else { // Update the total stats remaining structure. @@ -3871,7 +3897,7 @@ { const double avg_error = stats->coded_error / DOUBLE_DIVIDE_CHECK(stats->count); - const FIRSTPASS_STATS *s = twopass->stats_in; + const FIRSTPASS_STATS *s = cpi->twopass_frame.stats_in; double modified_error_total = 0.0; twopass->modified_error_min = (avg_error * oxcf->rc_cfg.vbrmin_section) / 100;
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c index f4e05d3..cb5e3af 100644 --- a/av1/encoder/speed_features.c +++ b/av1/encoder/speed_features.c
@@ -323,7 +323,7 @@ sf->rt_sf.use_nonrd_pick_mode = 0; sf->rt_sf.use_real_time_ref_set = 0; - if (cpi->ppi->twopass.fr_content_type == FC_GRAPHICS_ANIMATION || + if (cpi->twopass_frame.fr_content_type == FC_GRAPHICS_ANIMATION || cpi->use_screen_content_tools) { sf->mv_sf.exhaustive_searches_thresh = (1 << 20); } else { @@ -814,7 +814,7 @@ sf->rt_sf.use_nonrd_pick_mode = 0; sf->rt_sf.use_real_time_ref_set = 0; - if (cpi->ppi->twopass.fr_content_type == FC_GRAPHICS_ANIMATION || + if (cpi->twopass_frame.fr_content_type == FC_GRAPHICS_ANIMATION || cpi->use_screen_content_tools) { sf->mv_sf.exhaustive_searches_thresh = (1 << 20); } else {
diff --git a/av1/encoder/temporal_filter.c b/av1/encoder/temporal_filter.c index c77d454..a131259 100644 --- a/av1/encoder/temporal_filter.c +++ b/av1/encoder/temporal_filter.c
@@ -978,7 +978,7 @@ const int q = av1_get_q(cpi); // Get correlation estimates from first-pass; const FIRSTPASS_STATS *stats = - cpi->ppi->twopass.stats_in - (cpi->rc.frames_since_key == 0); + cpi->twopass_frame.stats_in - (cpi->rc.frames_since_key == 0); double accu_coeff0 = 1.0, accu_coeff1 = 1.0; for (int i = 1; i <= max_after; i++) { if (stats + filter_frame_lookahead_idx + i >=