From 65753eeb8a77f239121857c8286f35bc1603385b Mon Sep 17 00:00:00 2001 From: Adrian Grange Date: Fri, 17 Oct 2014 15:12:43 -0700 Subject: [PATCH] Move frame re-sizing into the recode loop The point at which frames are scaled to their coded dimensions is moved into the re-code loop. This is in preparation for a further patch that will add logic into the re-code loop to reduce the coded frame size if the encoder is struggling to hit the target data rate at the native frame size. Change-Id: Ie4131f5ec6fb93148879f6ce96123296442bf2d1 --- vp9/encoder/vp9_encoder.c | 473 +++++++++++++++++++----------------- vp9/encoder/vp9_encoder.h | 7 +- vp9/encoder/vp9_firstpass.c | 106 +++++--- 3 files changed, 327 insertions(+), 259 deletions(-) diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index 0ea129b90..ded590b96 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -2409,30 +2409,37 @@ void vp9_scale_references(VP9_COMP *cpi) { const VP9_REFFRAME ref_mask[3] = {VP9_LAST_FLAG, VP9_GOLD_FLAG, VP9_ALT_FLAG}; for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) { - const int idx = cm->ref_frame_map[get_ref_frame_idx(cpi, ref_frame)]; - const YV12_BUFFER_CONFIG *const ref = &cm->frame_bufs[idx].buf; - // Need to convert from VP9_REFFRAME to index into ref_mask (subtract 1). - if ((cpi->ref_frame_flags & ref_mask[ref_frame - 1]) && - (ref->y_crop_width != cm->width || ref->y_crop_height != cm->height)) { - const int new_fb = get_free_fb(cm); - vp9_realloc_frame_buffer(&cm->frame_bufs[new_fb].buf, - cm->width, cm->height, - cm->subsampling_x, cm->subsampling_y, -#if CONFIG_VP9_HIGHBITDEPTH - cm->use_highbitdepth, -#endif // CONFIG_VP9_HIGHBITDEPTH - VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL); + if (cpi->ref_frame_flags & ref_mask[ref_frame - 1]) { + const int idx = cm->ref_frame_map[get_ref_frame_idx(cpi, ref_frame)]; + const YV12_BUFFER_CONFIG *const ref = &cm->frame_bufs[idx].buf; + #if CONFIG_VP9_HIGHBITDEPTH - scale_and_extend_frame(ref, &cm->frame_bufs[new_fb].buf, - (int)cm->bit_depth); + if (ref->y_crop_width != cm->width || ref->y_crop_height != cm->height) { + const int new_fb = get_free_fb(cm); + vp9_realloc_frame_buffer(&cm->frame_bufs[new_fb].buf, + cm->width, cm->height, + cm->subsampling_x, cm->subsampling_y, + cm->use_highbitdepth, + VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL); + scale_and_extend_frame(ref, &cm->frame_bufs[new_fb].buf, + (int)cm->bit_depth); #else - scale_and_extend_frame(ref, &cm->frame_bufs[new_fb].buf); + if (ref->y_crop_width != cm->width || ref->y_crop_height != cm->height) { + const int new_fb = get_free_fb(cm); + vp9_realloc_frame_buffer(&cm->frame_bufs[new_fb].buf, + cm->width, cm->height, + cm->subsampling_x, cm->subsampling_y, + VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL); + scale_and_extend_frame(ref, &cm->frame_bufs[new_fb].buf); #endif // CONFIG_VP9_HIGHBITDEPTH - cpi->scaled_ref_idx[ref_frame - 1] = new_fb; + cpi->scaled_ref_idx[ref_frame - 1] = new_fb; + } else { + cpi->scaled_ref_idx[ref_frame - 1] = idx; + ++cm->frame_bufs[idx].ref_count; + } } else { - cpi->scaled_ref_idx[ref_frame - 1] = idx; - cm->frame_bufs[idx].ref_count++; + cpi->scaled_ref_idx[ref_frame - 1] = INVALID_REF_BUFFER_IDX; } } } @@ -2440,9 +2447,13 @@ void vp9_scale_references(VP9_COMP *cpi) { static void release_scaled_references(VP9_COMP *cpi) { VP9_COMMON *cm = &cpi->common; int i; - - for (i = 0; i < 3; i++) - cm->frame_bufs[cpi->scaled_ref_idx[i]].ref_count--; + for (i = 0; i < MAX_REF_FRAMES; ++i) { + const int idx = cpi->scaled_ref_idx[i]; + RefCntBuffer *const buf = + idx != INVALID_REF_BUFFER_IDX ? &cm->frame_bufs[idx] : NULL; + if (buf != NULL) + --buf->ref_count; + } } static void full_to_model_count(unsigned int *model_count, @@ -2527,10 +2538,181 @@ static void output_frame_level_debug_stats(VP9_COMP *cpi) { } #endif -static void encode_without_recode_loop(VP9_COMP *cpi, - int q) { +static void set_mv_search_params(VP9_COMP *cpi) { + const VP9_COMMON *const cm = &cpi->common; + const unsigned int max_mv_def = MIN(cm->width, cm->height); + + // Default based on max resolution. + cpi->mv_step_param = vp9_init_search_range(max_mv_def); + + if (cpi->sf.mv.auto_mv_step_size) { + if (frame_is_intra_only(cm)) { + // Initialize max_mv_magnitude for use in the first INTER frame + // after a key/intra-only frame. + cpi->max_mv_magnitude = max_mv_def; + } else { + if (cm->show_frame) { + // Allow mv_steps to correspond to twice the max mv magnitude found + // in the previous frame, capped by the default max_mv_magnitude based + // on resolution. + cpi->mv_step_param = + vp9_init_search_range(MIN(max_mv_def, 2 * cpi->max_mv_magnitude)); + } + cpi->max_mv_magnitude = 0; + } + } +} + +static void set_size_dependent_vars(VP9_COMP *cpi, int *q, + int *bottom_index, int *top_index) { + VP9_COMMON *const cm = &cpi->common; + const VP9EncoderConfig *const oxcf = &cpi->oxcf; + + // Setup variables that depend on the dimensions of the frame. + set_mv_search_params(cpi); + + // Configure experimental use of segmentation for enhanced coding of + // static regions if indicated. + // Only allowed in the second pass of a two pass encode, as it requires + // lagged coding, and if the relevant speed feature flag is set. + if (oxcf->pass == 2 && cpi->sf.static_segmentation) + configure_static_seg_features(cpi); + +#if CONFIG_VP9_POSTPROC + if (oxcf->noise_sensitivity > 0) { + int l = 0; + switch (oxcf->noise_sensitivity) { + case 1: + l = 20; + break; + case 2: + l = 40; + break; + case 3: + l = 60; + break; + case 4: + case 5: + l = 100; + break; + case 6: + l = 150; + break; + } + vp9_denoise(cpi->Source, cpi->Source, l); + } +#endif // CONFIG_VP9_POSTPROC + + vp9_set_speed_features(cpi); + + vp9_set_rd_speed_thresholds(cpi); + vp9_set_rd_speed_thresholds_sub8x8(cpi); + + // Decide q and q bounds. + *q = vp9_rc_pick_q_and_bounds(cpi, bottom_index, top_index); + + if (!frame_is_intra_only(cm)) { + cm->interp_filter = cpi->sf.default_interp_filter; + vp9_set_high_precision_mv(cpi, (*q) < HIGH_PRECISION_MV_QTHRESH); + } +} + +static void init_motion_estimation(VP9_COMP *cpi) { + int y_stride = cpi->scaled_source.y_stride; + + if (cpi->sf.mv.search_method == NSTEP) { + vp9_init3smotion_compensation(&cpi->ss_cfg, y_stride); + } else if (cpi->sf.mv.search_method == DIAMOND) { + vp9_init_dsmotion_compensation(&cpi->ss_cfg, y_stride); + } +} + +extern void vbr_rate_correction(VP9_COMP *cpi, + int * this_frame_target, + const int64_t vbr_bits_off_target); + +void set_frame_size(VP9_COMP *cpi) { + int ref_frame; + VP9_COMMON *const cm = &cpi->common; + const RATE_CONTROL *const rc = &cpi->rc; + const VP9EncoderConfig *const oxcf = &cpi->oxcf; + MACROBLOCKD *const xd = &cpi->mb.e_mbd; + + if ((oxcf->pass == 2) && + (!cpi->use_svc || + (is_two_pass_svc(cpi) && + cpi->svc.encode_empty_frame_state != ENCODING))) { + int target_rate = rc->base_frame_target; + if (oxcf->rc_mode == VPX_VBR) + vbr_rate_correction(cpi, &target_rate, rc->vbr_bits_off_target); + vp9_rc_set_frame_target(cpi, target_rate); + } + + if (oxcf->pass == 2 && + cm->current_video_frame == 0 && + oxcf->allow_spatial_resampling && + oxcf->rc_mode == VPX_VBR) { + // Internal scaling is triggered on the first frame. + vp9_set_size_literal(cpi, oxcf->scaled_frame_width, + oxcf->scaled_frame_height); + } + + // Reset the frame pointers to the current frame size. + vp9_realloc_frame_buffer(get_frame_new_buffer(cm), + cm->width, cm->height, + cm->subsampling_x, cm->subsampling_y, +#if CONFIG_VP9_HIGHBITDEPTH + cm->use_highbitdepth, +#endif + VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL); + + alloc_util_frame_buffers(cpi); + init_motion_estimation(cpi); + + for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) { + const int idx = cm->ref_frame_map[get_ref_frame_idx(cpi, ref_frame)]; + YV12_BUFFER_CONFIG *const buf = &cm->frame_bufs[idx].buf; + RefBuffer *const ref_buf = &cm->frame_refs[ref_frame - 1]; + ref_buf->buf = buf; + ref_buf->idx = idx; +#if CONFIG_VP9_HIGHBITDEPTH + vp9_setup_scale_factors_for_frame(&ref_buf->sf, + buf->y_crop_width, buf->y_crop_height, + cm->width, cm->height, + (buf->flags & YV12_FLAG_HIGHBITDEPTH) ? + 1 : 0); +#else + vp9_setup_scale_factors_for_frame(&ref_buf->sf, + buf->y_crop_width, buf->y_crop_height, + cm->width, cm->height); +#endif // CONFIG_VP9_HIGHBITDEPTH + if (vp9_is_scaled(&ref_buf->sf)) + vp9_extend_frame_borders(buf); + } + + set_ref_ptrs(cm, xd, LAST_FRAME, LAST_FRAME); +} + +static void encode_without_recode_loop(VP9_COMP *cpi) { + int q; + int bottom_index, top_index; // Dummy. VP9_COMMON *const cm = &cpi->common; + vp9_clear_system_state(); + + set_frame_size(cpi); + + cpi->Source = vp9_scale_if_required(cm, cpi->un_scaled_source, + &cpi->scaled_source); + + if (cpi->unscaled_last_source != NULL) + cpi->Last_Source = vp9_scale_if_required(cm, cpi->unscaled_last_source, + &cpi->scaled_last_source); + + vp9_scale_references(cpi); + + set_size_dependent_vars(cpi, &q, &bottom_index, &top_index); + vp9_set_quantizer(cm, q); setup_frame(cpi); // Variance adaptive and in frame q adjustment experiments are mutually @@ -2553,28 +2735,45 @@ static void encode_without_recode_loop(VP9_COMP *cpi, static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, - uint8_t *dest, - int q, - int bottom_index, - int top_index) { + uint8_t *dest) { VP9_COMMON *const cm = &cpi->common; RATE_CONTROL *const rc = &cpi->rc; + int q; + int q_low, q_high; + int bottom_index, top_index; int loop_count = 0; int loop = 0; int overshoot_seen = 0; int undershoot_seen = 0; - int q_low = bottom_index, q_high = top_index; int frame_over_shoot_limit; int frame_under_shoot_limit; - // Decide frame size bounds - vp9_rc_compute_frame_size_bounds(cpi, rc->this_frame_target, - &frame_under_shoot_limit, - &frame_over_shoot_limit); - do { vp9_clear_system_state(); + if (loop_count == 0) { + set_frame_size(cpi); + + // Decide frame size bounds + 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); + + if (cpi->unscaled_last_source != NULL) + cpi->Last_Source = vp9_scale_if_required(cm, cpi->unscaled_last_source, + &cpi->scaled_last_source); + + vp9_scale_references(cpi); + + set_size_dependent_vars(cpi, &q, &bottom_index, &top_index); + + q_low = bottom_index; + q_high = top_index; + } + vp9_set_quantizer(cm, q); if (loop_count == 0) @@ -2816,25 +3015,6 @@ YV12_BUFFER_CONFIG *vp9_scale_if_required(VP9_COMMON *cm, } } -static int is_skippable_frame(const VP9_COMP *cpi) { - // If the current frame does not have non-zero motion vector detected in the - // first pass, and so do its previous and forward frames, then this frame - // can be skipped for partition check, and the partition size is assigned - // according to the variance - const SVC *const svc = &cpi->svc; - const TWO_PASS *const twopass = is_two_pass_svc(cpi) ? - &svc->layer_context[svc->spatial_layer_id].twopass : &cpi->twopass; - - return (!frame_is_intra_only(&cpi->common) && - twopass->stats_in - 2 > twopass->stats_in_start && - twopass->stats_in < twopass->stats_in_end && - (twopass->stats_in - 1)->pcnt_inter - (twopass->stats_in - 1)->pcnt_motion - == 1 && - (twopass->stats_in - 2)->pcnt_inter - (twopass->stats_in - 2)->pcnt_motion - == 1 && - twopass->stats_in->pcnt_inter - twopass->stats_in->pcnt_motion == 1); -} - static void set_arf_sign_bias(VP9_COMP *cpi) { VP9_COMMON *const cm = &cpi->common; int arf_sign_bias; @@ -2851,31 +3031,6 @@ static void set_arf_sign_bias(VP9_COMP *cpi) { cm->ref_frame_sign_bias[ALTREF_FRAME] = arf_sign_bias; } -static void set_mv_search_params(VP9_COMP *cpi) { - const VP9_COMMON *const cm = &cpi->common; - const unsigned int max_mv_def = MIN(cm->width, cm->height); - - // Default based on max resolution. - cpi->mv_step_param = vp9_init_search_range(max_mv_def); - - if (cpi->sf.mv.auto_mv_step_size) { - if (frame_is_intra_only(cm)) { - // Initialize max_mv_magnitude for use in the first INTER frame - // after a key/intra-only frame. - cpi->max_mv_magnitude = max_mv_def; - } else { - if (cm->show_frame) - // Allow mv_steps to correspond to twice the max mv magnitude found - // in the previous frame, capped by the default max_mv_magnitude based - // on resolution. - cpi->mv_step_param = - vp9_init_search_range(MIN(max_mv_def, 2 * cpi->max_mv_magnitude)); - cpi->max_mv_magnitude = 0; - } - } -} - - int setup_interp_filter_search_mask(VP9_COMP *cpi) { INTERP_FILTER ifilter; int ref_total[MAX_REF_FRAMES] = {0}; @@ -2910,21 +3065,9 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, const VP9EncoderConfig *const oxcf = &cpi->oxcf; struct segmentation *const seg = &cm->seg; TX_SIZE t; - int q; - int top_index; - int bottom_index; set_ext_overrides(cpi); - cpi->Source = vp9_scale_if_required(cm, cpi->un_scaled_source, - &cpi->scaled_source); - - if (cpi->unscaled_last_source != NULL) - cpi->Last_Source = vp9_scale_if_required(cm, cpi->unscaled_last_source, - &cpi->scaled_last_source); - - vp9_scale_references(cpi); - vp9_clear_system_state(); // Enable or disable mode based tweaking of the zbin. @@ -2939,14 +3082,11 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, // Set default state for segment based loop filter update flags. cm->lf.mode_ref_delta_update = 0; - set_mv_search_params(cpi); - if (cpi->oxcf.pass == 2 && cpi->sf.adaptive_interp_filter_search) cpi->sf.interp_filter_search_mask = setup_interp_filter_search_mask(cpi); - // Set various flags etc to special state if it is a key frame. if (frame_is_intra_only(cm)) { // Reset the loop filter deltas and segmentation map. @@ -3006,20 +3146,6 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, } } - // Configure experimental use of segmentation for enhanced coding of - // static regions if indicated. - // Only allowed in second pass of two pass (as requires lagged coding) - // and if the relevant speed feature flag is set. - if (oxcf->pass == 2 && cpi->sf.static_segmentation) - configure_static_seg_features(cpi); - - // Check if the current frame is skippable for the partition search in the - // second pass according to the first pass stats - if (cpi->sf.allow_partition_search_skip && oxcf->pass == 2 && - (!cpi->use_svc || is_two_pass_svc(cpi))) { - cpi->partition_search_skippable_frame = is_skippable_frame(cpi); - } - // For 1 pass CBR, check if we are dropping this frame. // Never drop on key frame. if (oxcf->pass == 0 && @@ -3034,31 +3160,6 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, vp9_clear_system_state(); -#if CONFIG_VP9_POSTPROC - if (oxcf->noise_sensitivity > 0) { - int l = 0; - switch (oxcf->noise_sensitivity) { - case 1: - l = 20; - break; - case 2: - l = 40; - break; - case 3: - l = 60; - break; - case 4: - case 5: - l = 100; - break; - case 6: - l = 150; - break; - } - vp9_denoise(cpi->Source, cpi->Source, l); - } -#endif - #if CONFIG_INTERNAL_STATS { int i; @@ -3067,24 +3168,10 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, } #endif - vp9_set_speed_features(cpi); - - vp9_set_rd_speed_thresholds(cpi); - vp9_set_rd_speed_thresholds_sub8x8(cpi); - - // Decide q and q bounds. - q = vp9_rc_pick_q_and_bounds(cpi, &bottom_index, &top_index); - - if (!frame_is_intra_only(cm)) { - cm->interp_filter = cpi->sf.default_interp_filter; - /* TODO: Decide this more intelligently */ - vp9_set_high_precision_mv(cpi, q < HIGH_PRECISION_MV_QTHRESH); - } - if (cpi->sf.recode_loop == DISALLOW_RECODE) { - encode_without_recode_loop(cpi, q); + encode_without_recode_loop(cpi); } else { - encode_with_recode_loop(cpi, size, dest, q, bottom_index, top_index); + encode_with_recode_loop(cpi, size, dest); } #if CONFIG_VP9_TEMPORAL_DENOISING @@ -3227,16 +3314,6 @@ static void Pass2Encode(VP9_COMP *cpi, size_t *size, vp9_twopass_postencode_update(cpi); } -static void init_motion_estimation(VP9_COMP *cpi) { - int y_stride = cpi->scaled_source.y_stride; - - if (cpi->sf.mv.search_method == NSTEP) { - vp9_init3smotion_compensation(&cpi->ss_cfg, y_stride); - } else if (cpi->sf.mv.search_method == DIAMOND) { - vp9_init_dsmotion_compensation(&cpi->ss_cfg, y_stride); - } -} - static void check_initial_width(VP9_COMP *cpi, #if CONFIG_VP9_HIGHBITDEPTH int use_highbitdepth, @@ -3255,10 +3332,11 @@ static void check_initial_width(VP9_COMP *cpi, alloc_ref_frame_buffers(cpi); alloc_util_frame_buffers(cpi); - init_motion_estimation(cpi); + init_motion_estimation(cpi); // TODO(agrange) This can be removed. cpi->initial_width = cm->width; cpi->initial_height = cm->height; + cpi->initial_mbs = cm->MBs; } } @@ -3400,14 +3478,13 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags, int64_t *time_stamp, int64_t *time_end, int flush) { const VP9EncoderConfig *const oxcf = &cpi->oxcf; VP9_COMMON *const cm = &cpi->common; - MACROBLOCKD *const xd = &cpi->mb.e_mbd; RATE_CONTROL *const rc = &cpi->rc; struct vpx_usec_timer cmptimer; YV12_BUFFER_CONFIG *force_src_buffer = NULL; struct lookahead_entry *last_source = NULL; struct lookahead_entry *source = NULL; - MV_REFERENCE_FRAME ref_frame; int arf_src_index; + int i; if (is_two_pass_svc(cpi)) { #if CONFIG_SPATIAL_SVC @@ -3546,24 +3623,11 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags, vp9_restore_layer_context(cpi); } - // start with a 0 size frame - *size = 0; - - /* find a free buffer for the new frame, releasing the reference previously - * held. - */ + // Find a free buffer for the new frame, releasing the reference previously + // held. cm->frame_bufs[cm->new_fb_idx].ref_count--; cm->new_fb_idx = get_free_fb(cm); - // For two pass encodes analyse the first pass stats and determine - // the bit allocation and other parameters for this frame / group of frames. - if ((oxcf->pass == 2) && - (!cpi->use_svc || - (is_two_pass_svc(cpi) && - cpi->svc.encode_empty_frame_state != ENCODING))) { - vp9_rc_get_second_pass_params(cpi); - } - if (!cpi->use_svc && cpi->multi_arf_allowed) { if (cm->frame_type == KEY_FRAME) { init_buffer_indices(cpi); @@ -3573,56 +3637,27 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags, } } - cpi->frame_flags = *frame_flags; - - if (oxcf->pass == 2 && - cm->current_video_frame == 0 && - oxcf->allow_spatial_resampling && - oxcf->rc_mode == VPX_VBR) { - // Internal scaling is triggered on the first frame. - vp9_set_size_literal(cpi, oxcf->scaled_frame_width, - oxcf->scaled_frame_height); - } - - // Reset the frame pointers to the current frame size - vp9_realloc_frame_buffer(get_frame_new_buffer(cm), - cm->width, cm->height, - cm->subsampling_x, cm->subsampling_y, -#if CONFIG_VP9_HIGHBITDEPTH - cm->use_highbitdepth, -#endif - VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL); + // Start with a 0 size frame. + *size = 0; - alloc_util_frame_buffers(cpi); - init_motion_estimation(cpi); + cpi->frame_flags = *frame_flags; - for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) { - const int idx = cm->ref_frame_map[get_ref_frame_idx(cpi, ref_frame)]; - YV12_BUFFER_CONFIG *const buf = &cm->frame_bufs[idx].buf; - RefBuffer *const ref_buf = &cm->frame_refs[ref_frame - 1]; - ref_buf->buf = buf; - ref_buf->idx = idx; -#if CONFIG_VP9_HIGHBITDEPTH - vp9_setup_scale_factors_for_frame(&ref_buf->sf, - buf->y_crop_width, buf->y_crop_height, - cm->width, cm->height, - (buf->flags & YV12_FLAG_HIGHBITDEPTH) ? - 1 : 0); -#else - vp9_setup_scale_factors_for_frame(&ref_buf->sf, - buf->y_crop_width, buf->y_crop_height, - cm->width, cm->height); -#endif // CONFIG_VP9_HIGHBITDEPTH - if (vp9_is_scaled(&ref_buf->sf)) - vp9_extend_frame_borders(buf); + if ((oxcf->pass == 2) && + (!cpi->use_svc || + (is_two_pass_svc(cpi) && + cpi->svc.encode_empty_frame_state != ENCODING))) { + vp9_rc_get_second_pass_params(cpi); + } else { + set_frame_size(cpi); } - set_ref_ptrs(cm, xd, LAST_FRAME, LAST_FRAME); - if (oxcf->aq_mode == VARIANCE_AQ) { vp9_vaq_init(); } + for (i = 0; i < MAX_REF_FRAMES; ++i) + cpi->scaled_ref_idx[i] = INVALID_REF_BUFFER_IDX; + if (oxcf->pass == 1 && (!cpi->use_svc || is_two_pass_svc(cpi))) { const int lossless = is_lossless_requested(oxcf); @@ -3651,7 +3686,7 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags, if (cm->refresh_frame_context) cm->frame_contexts[cm->frame_context_idx] = *cm->fc; - // Frame was dropped, release scaled references. + // No frame encoded, or frame was dropped, release scaled references. if (*size == 0) { release_scaled_references(cpi); } diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h index 1e6047464..52b00e6be 100644 --- a/vp9/encoder/vp9_encoder.h +++ b/vp9/encoder/vp9_encoder.h @@ -44,6 +44,7 @@ extern "C" { #endif #define DEFAULT_GF_INTERVAL 10 +#define INVALID_REF_BUFFER_IDX -1 // Marks an invalid reference buffer id. typedef struct { int nmvjointcost[MV_JOINTS]; @@ -241,7 +242,7 @@ typedef struct VP9_COMP { // For a still frame, this flag is set to 1 to skip partition search. int partition_search_skippable_frame; - int scaled_ref_idx[3]; + int scaled_ref_idx[MAX_REF_FRAMES]; int lst_fb_idx; int gld_fb_idx; int alt_fb_idx; @@ -374,6 +375,10 @@ typedef struct VP9_COMP { int initial_width; int initial_height; + int initial_mbs; // Number of MBs in the full-size frame; to be used to + // normalize the firstpass stats. This will differ from the + // number of MBs in the current frame when the frame is + // scaled. int use_svc; diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index f1baf8323..5a67ef414 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -138,7 +138,7 @@ static void output_fpmb_stats(uint8_t *this_frame_mb_stats, VP9_COMMON *cm, struct vpx_codec_cx_pkt pkt; pkt.kind = VPX_CODEC_FPMB_STATS_PKT; pkt.data.firstpass_mb_stats.buf = this_frame_mb_stats; - pkt.data.firstpass_mb_stats.sz = cm->MBs * sizeof(uint8_t); + pkt.data.firstpass_mb_stats.sz = cm->initial_mbs * sizeof(uint8_t); vpx_codec_pkt_list_add(pktlist, &pkt); } #endif @@ -483,7 +483,7 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) { #if CONFIG_FP_MB_STATS if (cpi->use_fp_mb_stats) { - vp9_zero_array(cpi->twopass.frame_mb_stats_buf, cm->MBs); + vp9_zero_array(cpi->twopass.frame_mb_stats_buf, cm->initial_mbs); } #endif @@ -934,12 +934,14 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) { vp9_clear_system_state(); { FIRSTPASS_STATS fps; - // The minimum error here insures some bit alocation to frames even + // The minimum error here insures some bit allocation to frames even // in static regions. The allocation per MB declines for larger formats // where the typical "real" energy per MB also falls. // Initial estimate here uses sqrt(mbs) to define the min_err, where the - // number of mbs is propotional to image area. - const double min_err = 200 * sqrt(cm->MBs); + // number of mbs is proportional to the image area. + const int num_mbs = + cpi->oxcf.allow_spatial_resampling ? cpi->initial_mbs : cpi->common.MBs; + const double min_err = 200 * sqrt(num_mbs); fps.frame = cm->current_video_frame; fps.spatial_layer_id = cpi->svc.spatial_layer_id; @@ -947,9 +949,9 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) { fps.sr_coded_error = (double)(sr_coded_error >> 8) + min_err; fps.intra_error = (double)(intra_error >> 8) + min_err; fps.count = 1.0; - fps.pcnt_inter = (double)intercount / cm->MBs; - fps.pcnt_second_ref = (double)second_ref_count / cm->MBs; - fps.pcnt_neutral = (double)neutral_count / cm->MBs; + fps.pcnt_inter = (double)intercount / num_mbs; + fps.pcnt_second_ref = (double)second_ref_count / num_mbs; + fps.pcnt_neutral = (double)neutral_count / num_mbs; if (mvcount > 0) { fps.MVr = (double)sum_mvr / mvcount; @@ -960,7 +962,7 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) { fps.MVcv = ((double)sum_mvcs - (fps.MVc * fps.MVc / mvcount)) / mvcount; fps.mv_in_out_count = (double)sum_in_vectors / (mvcount * 2); fps.new_mv_count = new_mv_count; - fps.pcnt_motion = (double)mvcount / cm->MBs; + fps.pcnt_motion = (double)mvcount / num_mbs; } else { fps.MVr = 0.0; fps.mvr_abs = 0.0; @@ -1074,7 +1076,8 @@ static int get_twopass_worst_quality(const VP9_COMP *cpi, if (section_target_bandwidth <= 0) { return rc->worst_quality; // Highest value allowed } else { - const int num_mbs = cpi->common.MBs; + const int num_mbs = + cpi->oxcf.allow_spatial_resampling ? cpi->initial_mbs : cpi->common.MBs; const double section_err = stats->coded_error / stats->count; const double err_per_mb = section_err / num_mbs; const double speed_term = 1.0 + 0.04 * oxcf->speed; @@ -1188,9 +1191,12 @@ void vp9_init_second_pass(VP9_COMP *cpi) { #define LOW_SR_DIFF_TRHESH 0.1 #define SR_DIFF_MAX 128.0 -static double get_sr_decay_rate(const VP9_COMMON *cm, +static double get_sr_decay_rate(const VP9_COMP *cpi, const FIRSTPASS_STATS *frame) { - double sr_diff = (frame->sr_coded_error - frame->coded_error) / cm->MBs; + const int num_mbs = + cpi->oxcf.allow_spatial_resampling ? cpi->initial_mbs : cpi->common.MBs; + double sr_diff = + (frame->sr_coded_error - frame->coded_error) / num_mbs; double sr_decay = 1.0; const double motion_amplitude_factor = frame->pcnt_motion * ((frame->mvc_abs + frame->mvr_abs) / 2); @@ -1207,19 +1213,19 @@ static double get_sr_decay_rate(const VP9_COMMON *cm, // This function gives an estimate of how badly we believe the prediction // quality is decaying from frame to frame. -static double get_zero_motion_factor(const VP9_COMMON *cm, +static double get_zero_motion_factor(const VP9_COMP *cpi, const FIRSTPASS_STATS *frame) { const double zero_motion_pct = frame->pcnt_inter - frame->pcnt_motion; - double sr_decay = get_sr_decay_rate(cm, frame); + double sr_decay = get_sr_decay_rate(cpi, frame); return MIN(sr_decay, zero_motion_pct); } #define ZM_POWER_FACTOR 0.75 -static double get_prediction_decay_rate(const VP9_COMMON *cm, +static double get_prediction_decay_rate(const VP9_COMP *cpi, const FIRSTPASS_STATS *next_frame) { - const double sr_decay_rate = get_sr_decay_rate(cm, next_frame); + const double sr_decay_rate = get_sr_decay_rate(cpi, next_frame); const double zero_motion_factor = (0.95 * pow((next_frame->pcnt_inter - next_frame->pcnt_motion), ZM_POWER_FACTOR)); @@ -1314,9 +1320,11 @@ static double calc_frame_boost(VP9_COMP *cpi, vp9_convert_qindex_to_q(cpi->rc.avg_frame_qindex[INTER_FRAME], cpi->common.bit_depth); const double boost_correction = MIN((0.5 + (lq * 0.015)), 1.5); + const int num_mbs = + cpi->oxcf.allow_spatial_resampling ? cpi->initial_mbs : cpi->common.MBs; // Underlying boost factor is based on inter error ratio. - frame_boost = (BASELINE_ERR_PER_MB * cpi->common.MBs) / + frame_boost = (BASELINE_ERR_PER_MB * num_mbs) / DOUBLE_DIVIDE_CHECK(this_frame->coded_error); frame_boost = frame_boost * BOOST_FACTOR * boost_correction; @@ -1365,7 +1373,7 @@ static int calc_arf_boost(VP9_COMP *cpi, int offset, // Accumulate the effect of prediction quality decay. if (!flash_detected) { - decay_accumulator *= get_prediction_decay_rate(&cpi->common, this_frame); + decay_accumulator *= get_prediction_decay_rate(cpi, this_frame); decay_accumulator = decay_accumulator < MIN_DECAY_FACTOR ? MIN_DECAY_FACTOR : decay_accumulator; } @@ -1404,7 +1412,7 @@ static int calc_arf_boost(VP9_COMP *cpi, int offset, // Cumulative effect of prediction quality decay. if (!flash_detected) { - decay_accumulator *= get_prediction_decay_rate(&cpi->common, this_frame); + decay_accumulator *= get_prediction_decay_rate(cpi, this_frame); decay_accumulator = decay_accumulator < MIN_DECAY_FACTOR ? MIN_DECAY_FACTOR : decay_accumulator; } @@ -1723,7 +1731,8 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { gf_group_err -= gf_first_frame_err; // Motion breakout threshold for loop below depends on image size. - mv_ratio_accumulator_thresh = (cpi->common.width + cpi->common.height) / 4.0; + mv_ratio_accumulator_thresh = + (cpi->common.height + cpi->common.width) / 4.0; // Set a maximum and minimum interval for the GF group. // If the image appears almost completely static we can extend beyond this. @@ -1775,14 +1784,14 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { // Accumulate the effect of prediction quality decay. if (!flash_detected) { last_loop_decay_rate = loop_decay_rate; - loop_decay_rate = get_prediction_decay_rate(&cpi->common, &next_frame); + loop_decay_rate = get_prediction_decay_rate(cpi, &next_frame); decay_accumulator = decay_accumulator * loop_decay_rate; // Monitor for static sections. zero_motion_accumulator = MIN(zero_motion_accumulator, - get_zero_motion_factor(&cpi->common, &next_frame)); + get_zero_motion_factor(cpi, &next_frame)); // Break clause to detect very still sections after motion. For example, // a static image after a fade or other transition. @@ -2048,8 +2057,7 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { break; // How fast is the prediction quality decaying? - loop_decay_rate = get_prediction_decay_rate(&cpi->common, - twopass->stats_in); + loop_decay_rate = get_prediction_decay_rate(cpi, twopass->stats_in); // We want to know something about the recent past... rather than // as used elsewhere where we are concerned with decay in prediction @@ -2160,7 +2168,7 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { // Monitor for static sections. zero_motion_accumulator = MIN(zero_motion_accumulator, - get_zero_motion_factor(&cpi->common, &next_frame)); + get_zero_motion_factor(cpi, &next_frame)); // Not all frames in the group are necessarily used in calculating boost. if ((i <= rc->max_gf_interval) || @@ -2171,7 +2179,7 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { // How fast is prediction quality decaying. if (!detect_flash(twopass, 0)) { const double loop_decay_rate = - get_prediction_decay_rate(&cpi->common, &next_frame); + get_prediction_decay_rate(cpi, &next_frame); decay_accumulator *= loop_decay_rate; decay_accumulator = MAX(decay_accumulator, MIN_DECAY_FACTOR); av_decay_accumulator += decay_accumulator; @@ -2295,6 +2303,24 @@ void configure_buffer_updates(VP9_COMP *cpi) { } } +int is_skippable_frame(const VP9_COMP *cpi) { + // If the current frame does not have non-zero motion vector detected in the + // first pass, and so do its previous and forward frames, then this frame + // can be skipped for partition check, and the partition size is assigned + // according to the variance + const SVC *const svc = &cpi->svc; + const TWO_PASS *const twopass = is_two_pass_svc(cpi) ? + &svc->layer_context[svc->spatial_layer_id].twopass : &cpi->twopass; + + return (!frame_is_intra_only(&cpi->common) && + twopass->stats_in - 2 > twopass->stats_in_start && + twopass->stats_in < twopass->stats_in_end && + (twopass->stats_in - 1)->pcnt_inter - (twopass->stats_in - 1)->pcnt_motion + == 1 && + (twopass->stats_in - 2)->pcnt_inter - (twopass->stats_in - 2)->pcnt_motion + == 1 && + twopass->stats_in->pcnt_inter - twopass->stats_in->pcnt_motion == 1); +} void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { VP9_COMMON *const cm = &cpi->common; @@ -2329,11 +2355,6 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { target_rate = vp9_rc_clamp_pframe_target_size(cpi, target_rate); rc->base_frame_target = target_rate; - // Correction to rate target based on prior over or under shoot. - if (cpi->oxcf.rc_mode == VPX_VBR) - vbr_rate_correction(cpi, &target_rate, rc->vbr_bits_off_target); - - vp9_rc_set_frame_target(cpi, target_rate); cm->frame_type = INTER_FRAME; if (lc != NULL) { @@ -2347,6 +2368,13 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { } } + // Do the firstpass stats indicate that this frame is skippable for the + // partition search? + if (cpi->sf.allow_partition_search_skip && + cpi->oxcf.pass == 2 && (!cpi->use_svc || is_two_pass_svc(cpi))) { + cpi->partition_search_skippable_frame = is_skippable_frame(cpi); + } + return; } @@ -2377,8 +2405,7 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { this_frame_copy = this_frame; // Keyframe and section processing. - if (rc->frames_to_key == 0 || - (cpi->frame_flags & FRAMEFLAGS_KEY)) { + if (rc->frames_to_key == 0 || (cpi->frame_flags & FRAMEFLAGS_KEY)) { // Define next KF group and assign bits to it. find_next_key_frame(cpi, &this_frame_copy); } else { @@ -2431,6 +2458,13 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { configure_buffer_updates(cpi); + // Do the firstpass stats indicate that this frame is skippable for the + // partition search? + if (cpi->sf.allow_partition_search_skip && cpi->oxcf.pass == 2 && + (!cpi->use_svc || is_two_pass_svc(cpi))) { + cpi->partition_search_skippable_frame = is_skippable_frame(cpi); + } + target_rate = gf_group->bit_allocation[gf_group->index]; if (cpi->common.frame_type == KEY_FRAME) target_rate = vp9_rc_clamp_iframe_target_size(cpi, target_rate); @@ -2439,12 +2473,6 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { rc->base_frame_target = target_rate; - // Correction to rate target based on prior over or under shoot. - if (cpi->oxcf.rc_mode == VPX_VBR) - vbr_rate_correction(cpi, &target_rate, rc->vbr_bits_off_target); - - vp9_rc_set_frame_target(cpi, target_rate); - // Update the total stats remaining structure. subtract_stats(&twopass->total_left_stats, &this_frame); } -- 2.40.0