ref: 3758650c98f75a0b719d79fb97b80262732fb1c3
parent: feb4be8552dd4bfeb4d2f0ef55c2dc2db13b46db
parent: 65753eeb8a77f239121857c8286f35bc1603385b
author: Paul Wilkins <[email protected]>
date: Fri Oct 24 01:50:39 EDT 2014
Merge "Move frame re-sizing into the recode loop"
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -2409,30 +2409,37 @@
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 (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
- cm->use_highbitdepth,
-#endif // CONFIG_VP9_HIGHBITDEPTH
- VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL);
-#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 @@
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 @@
}
#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_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 @@
}
}
-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 @@
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 @@
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 @@
// 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 @@
}
}
- // 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 @@
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 @@
}
#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 @@
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 @@
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 @@
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 @@
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 @@
}
}
+ // Start with a 0 size frame.
+ *size = 0;
+
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);
+ 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);
}
- // 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);
-
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 @@
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);
}
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -44,6 +44,7 @@
#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 @@
// 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 @@
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;
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -138,7 +138,7 @@
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 @@
#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 @@
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 @@
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 @@
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 @@
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 @@
#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 @@
// 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 @@
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 @@
// 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 @@
// 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 @@
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,7 +1784,7 @@
// 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;
@@ -1782,7 +1791,7 @@
// 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 @@
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 @@
// 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 @@
// 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,7 +2303,25 @@
}
}
+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;
RATE_CONTROL *const rc = &cpi->rc;
@@ -2329,11 +2355,6 @@
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 @@
}
}
+ // 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 @@
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 @@
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);
@@ -2438,12 +2472,6 @@
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);
// Update the total stats remaining structure.
subtract_stats(&twopass->total_left_stats, &this_frame);