summaryrefslogtreecommitdiff
path: root/vp9
diff options
context:
space:
mode:
authorAdrian Grange <agrange@google.com>2014-11-10 09:51:38 -0800
committerAdrian Grange <agrange@google.com>2014-11-13 11:41:20 -0800
commit0d085ebc0ace8edbc691e51d91e579dcb55cf881 (patch)
treea96e36c0fb941b1e90cbae8e3ac3d01f7eb86ef6 /vp9
parent8e112d9586a9a79227859fc0a39150ac955ff134 (diff)
downloadlibvpx-0d085ebc0ace8edbc691e51d91e579dcb55cf881.tar
libvpx-0d085ebc0ace8edbc691e51d91e579dcb55cf881.tar.gz
libvpx-0d085ebc0ace8edbc691e51d91e579dcb55cf881.tar.bz2
libvpx-0d085ebc0ace8edbc691e51d91e579dcb55cf881.zip
Prepare for dynamic frame resizing in the recode loop
Prepare for the introduction of frame-size change logic into the recode loop. Separated the speed dependent features into separate static and dynamic parts, the latter being those features that are dependent on the frame size. Change-Id: Ia693e28c5cf069a1a7bf12e49ecf83e440e1d313
Diffstat (limited to 'vp9')
-rw-r--r--vp9/encoder/vp9_encoder.c121
-rw-r--r--vp9/encoder/vp9_encoder.h13
-rw-r--r--vp9/encoder/vp9_firstpass.c53
-rw-r--r--vp9/encoder/vp9_ratectrl.c40
-rw-r--r--vp9/encoder/vp9_ratectrl.h2
-rw-r--r--vp9/encoder/vp9_rd.c13
-rw-r--r--vp9/encoder/vp9_speed_features.c191
-rw-r--r--vp9/encoder/vp9_speed_features.h3
-rw-r--r--vp9/vp9_cx_iface.c20
9 files changed, 270 insertions, 186 deletions
diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c
index 72e11d668..2dc7a71ca 100644
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -1625,7 +1625,8 @@ VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf) {
}
}
- vp9_set_speed_features(cpi);
+ vp9_set_speed_features_framesize_independent(cpi);
+ vp9_set_speed_features_framesize_dependent(cpi);
// Allocate memory to store variances for a frame.
CHECK_MEM_ERROR(cm, cpi->source_diff_var,
@@ -2309,7 +2310,6 @@ static void scale_and_extend_frame(const YV12_BUFFER_CONFIG *src,
static int recode_loop_test(const VP9_COMP *cpi,
int high_limit, int low_limit,
int q, int maxq, int minq) {
- const VP9_COMMON *const cm = &cpi->common;
const RATE_CONTROL *const rc = &cpi->rc;
const VP9EncoderConfig *const oxcf = &cpi->oxcf;
int force_recode = 0;
@@ -2323,8 +2323,7 @@ static int recode_loop_test(const VP9_COMP *cpi,
// and the frame is a key frame, golden frame or alt_ref_frame
} else if ((cpi->sf.recode_loop == ALLOW_RECODE) ||
((cpi->sf.recode_loop == ALLOW_RECODE_KFARFGF) &&
- (cm->frame_type == KEY_FRAME ||
- cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame))) {
+ frame_is_kf_gf_arf(cpi))) {
// General over and under shoot tests
if ((rc->projected_frame_size > high_limit && q < maxq) ||
(rc->projected_frame_size < low_limit && q > minq)) {
@@ -2505,8 +2504,10 @@ static void release_scaled_references(VP9_COMP *cpi) {
const int idx = cpi->scaled_ref_idx[i];
RefCntBuffer *const buf =
idx != INVALID_REF_BUFFER_IDX ? &cm->frame_bufs[idx] : NULL;
- if (buf != NULL)
+ if (buf != NULL) {
--buf->ref_count;
+ cpi->scaled_ref_idx[i] = INVALID_REF_BUFFER_IDX;
+ }
}
}
@@ -2617,13 +2618,27 @@ static void set_mv_search_params(VP9_COMP *cpi) {
}
}
+static void set_size_independent_vars(VP9_COMP *cpi) {
+ vp9_set_speed_features_framesize_independent(cpi);
+ vp9_set_rd_speed_thresholds(cpi);
+ vp9_set_rd_speed_thresholds_sub8x8(cpi);
+ cpi->common.interp_filter = cpi->sf.default_interp_filter;
+}
+
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);
+ vp9_set_speed_features_framesize_dependent(cpi);
+
+ // Decide q and q bounds.
+ *q = vp9_rc_pick_q_and_bounds(cpi, bottom_index, top_index);
+
+ if (!frame_is_intra_only(cm)) {
+ vp9_set_high_precision_mv(cpi, (*q) < HIGH_PRECISION_MV_QTHRESH);
+ }
// Configure experimental use of segmentation for enhanced coding of
// static regions if indicated.
@@ -2656,19 +2671,6 @@ static void set_size_dependent_vars(VP9_COMP *cpi, int *q,
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) {
@@ -2681,36 +2683,28 @@ static void init_motion_estimation(VP9_COMP *cpi) {
}
}
-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->resize_mode == RESIZE_FIXED &&
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_set_target_rate(cpi);
+ }
+
// Reset the frame pointers to the current frame size.
vp9_realloc_frame_buffer(get_frame_new_buffer(cm),
cm->width, cm->height,
@@ -2748,9 +2742,8 @@ void set_frame_size(VP9_COMP *cpi) {
}
static void encode_without_recode_loop(VP9_COMP *cpi) {
- int q;
- int bottom_index, top_index; // Dummy.
VP9_COMMON *const cm = &cpi->common;
+ int q, bottom_index, top_index; // Dummy variables.
vp9_clear_system_state();
@@ -2763,8 +2756,11 @@ static void encode_without_recode_loop(VP9_COMP *cpi) {
cpi->Last_Source = vp9_scale_if_required(cm, cpi->unscaled_last_source,
&cpi->scaled_last_source);
- vp9_scale_references(cpi);
+ if (frame_is_intra_only(cm) == 0) {
+ vp9_scale_references(cpi);
+ }
+ set_size_independent_vars(cpi);
set_size_dependent_vars(cpi, &q, &bottom_index, &top_index);
vp9_set_quantizer(cm, q);
@@ -2792,8 +2788,6 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
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;
@@ -2801,31 +2795,42 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
int undershoot_seen = 0;
int frame_over_shoot_limit;
int frame_under_shoot_limit;
+ int q = 0, q_low = 0, q_high = 0;
+ int frame_size_changed = 0;
+
+ set_size_independent_vars(cpi);
do {
vp9_clear_system_state();
- if (loop_count == 0) {
- set_frame_size(cpi);
+ 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);
+ if (loop_count == 0 || frame_size_changed != 0) {
+ set_size_dependent_vars(cpi, &q, &bottom_index, &top_index);
+ q_low = bottom_index;
+ q_high = top_index;
- cpi->Source = vp9_scale_if_required(cm, cpi->un_scaled_source,
- &cpi->scaled_source);
+ // TODO(agrange) Scale cpi->max_mv_magnitude if frame-size has changed.
+ set_mv_search_params(cpi);
+ }
- if (cpi->unscaled_last_source != NULL)
- cpi->Last_Source = vp9_scale_if_required(cm, cpi->unscaled_last_source,
- &cpi->scaled_last_source);
+ // Decide frame size bounds
+ vp9_rc_compute_frame_size_bounds(cpi, rc->this_frame_target,
+ &frame_under_shoot_limit,
+ &frame_over_shoot_limit);
- vp9_scale_references(cpi);
+ cpi->Source = vp9_scale_if_required(cm, cpi->un_scaled_source,
+ &cpi->scaled_source);
- set_size_dependent_vars(cpi, &q, &bottom_index, &top_index);
+ if (cpi->unscaled_last_source != NULL)
+ cpi->Last_Source = vp9_scale_if_required(cm, cpi->unscaled_last_source,
+ &cpi->scaled_last_source);
- q_low = bottom_index;
- q_high = top_index;
+ if (frame_is_intra_only(cm) == 0) {
+ if (loop_count > 0) {
+ release_scaled_references(cpi);
+ }
+ vp9_scale_references(cpi);
}
vp9_set_quantizer(cm, q);
@@ -3272,7 +3277,9 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
if (cm->seg.update_map)
update_reference_segmentation_map(cpi);
- release_scaled_references(cpi);
+ if (frame_is_intra_only(cm) == 0) {
+ release_scaled_references(cpi);
+ }
vp9_update_reference_frames(cpi);
for (t = TX_4X4; t <= TX_32X32; t++)
@@ -3744,7 +3751,7 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
cm->frame_contexts[cm->frame_context_idx] = *cm->fc;
// No frame encoded, or frame was dropped, release scaled references.
- if (*size == 0) {
+ if ((*size == 0) && (frame_is_intra_only(cm) == 0)) {
release_scaled_references(cpi);
}
diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h
index f0c05430a..206d1df6e 100644
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -110,6 +110,11 @@ typedef enum {
AQ_MODE_COUNT // This should always be the last member of the enum
} AQ_MODE;
+typedef enum {
+ RESIZE_NONE = 0, // No frame resizing allowed (except for SVC).
+ RESIZE_FIXED = 1, // All frames are coded at the specified dimension.
+ RESIZE_DYNAMIC = 2 // Coded size of each frame is determined by the codec.
+} RESIZE_TYPE;
typedef struct VP9EncoderConfig {
BITSTREAM_PROFILE profile;
@@ -165,7 +170,7 @@ typedef struct VP9EncoderConfig {
AQ_MODE aq_mode; // Adaptive Quantization mode
// Internal frame size scaling.
- int allow_spatial_resampling;
+ RESIZE_TYPE resize_mode;
int scaled_frame_width;
int scaled_frame_height;
@@ -472,6 +477,12 @@ void vp9_set_svc(VP9_COMP *cpi, int use_svc);
int vp9_get_quantizer(struct VP9_COMP *cpi);
+static INLINE int frame_is_kf_gf_arf(const VP9_COMP *cpi) {
+ return frame_is_intra_only(&cpi->common) ||
+ cpi->refresh_alt_ref_frame ||
+ (cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref);
+}
+
static INLINE int get_ref_frame_idx(const VP9_COMP *cpi,
MV_REFERENCE_FRAME ref_frame) {
if (ref_frame == LAST_FRAME) {
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index 327082fcd..3f462c052 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -338,9 +338,9 @@ static unsigned int highbd_get_prediction_error(BLOCK_SIZE bsize,
// Refine the motion search range according to the frame dimension
// for first pass test.
-static int get_search_range(const VP9_COMMON *cm) {
+static int get_search_range(const VP9_COMP *cpi) {
int sr = 0;
- const int dim = MIN(cm->width, cm->height);
+ const int dim = MIN(cpi->initial_width, cpi->initial_height);
while ((dim << sr) < MAX_FULL_PEL_VAL)
++sr;
@@ -360,7 +360,7 @@ static void first_pass_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
int step_param = 3;
int further_steps = (MAX_MVSEARCH_STEPS - 1) - step_param;
- const int sr = get_search_range(&cpi->common);
+ const int sr = get_search_range(cpi);
step_param += sr;
further_steps -= sr;
@@ -947,7 +947,8 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) {
// Initial estimate here uses sqrt(mbs) to define the min_err, where the
// number of mbs is proportional to the image area.
const int num_mbs =
- cpi->oxcf.allow_spatial_resampling ? cpi->initial_mbs : cpi->common.MBs;
+ cpi->oxcf.resize_mode == RESIZE_FIXED ?
+ cpi->initial_mbs : cpi->common.MBs;
const double min_err = 200 * sqrt(num_mbs);
intra_factor = intra_factor / (double)num_mbs;
@@ -1088,7 +1089,8 @@ static int get_twopass_worst_quality(const VP9_COMP *cpi,
return rc->worst_quality; // Highest value allowed
} else {
const int num_mbs =
- cpi->oxcf.allow_spatial_resampling ? cpi->initial_mbs : cpi->common.MBs;
+ cpi->oxcf.resize_mode == RESIZE_FIXED ?
+ 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;
@@ -1206,7 +1208,8 @@ void vp9_init_second_pass(VP9_COMP *cpi) {
static double get_sr_decay_rate(const VP9_COMP *cpi,
const FIRSTPASS_STATS *frame) {
const int num_mbs =
- cpi->oxcf.allow_spatial_resampling ? cpi->initial_mbs : cpi->common.MBs;
+ cpi->oxcf.resize_mode == RESIZE_FIXED ?
+ cpi->initial_mbs : cpi->common.MBs;
double sr_diff =
(frame->sr_coded_error - frame->coded_error) / num_mbs;
double sr_decay = 1.0;
@@ -1333,7 +1336,8 @@ static double calc_frame_boost(VP9_COMP *cpi,
cpi->common.bit_depth);
const double boost_q_correction = MIN((0.5 + (lq * 0.015)), 1.5);
const int num_mbs =
- cpi->oxcf.allow_spatial_resampling ? cpi->initial_mbs : cpi->common.MBs;
+ cpi->oxcf.resize_mode == RESIZE_FIXED ?
+ cpi->initial_mbs : cpi->common.MBs;
// Underlying boost factor is based on inter error ratio.
frame_boost = (BASELINE_ERR_PER_MB * num_mbs) /
@@ -1744,7 +1748,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
// Motion breakout threshold for loop below depends on image size.
mv_ratio_accumulator_thresh =
- (cpi->common.height + cpi->common.width) / 4.0;
+ (cpi->initial_height + cpi->initial_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.
@@ -1802,8 +1806,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
// Monitor for static sections.
zero_motion_accumulator =
- MIN(zero_motion_accumulator,
- get_zero_motion_factor(cpi, &next_frame));
+ MIN(zero_motion_accumulator, 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.
@@ -2237,36 +2240,6 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
twopass->modified_error_left -= kf_group_err;
}
-#define VBR_PCT_ADJUSTMENT_LIMIT 50
-// For VBR...adjustment to the frame target based on error from previous frames
-void vbr_rate_correction(VP9_COMP *cpi,
- int * this_frame_target,
- const int64_t vbr_bits_off_target) {
- int max_delta;
- double position_factor = 1.0;
-
- // How far through the clip are we.
- // This number is used to damp the per frame rate correction.
- // Range 0 - 1.0
- if (cpi->twopass.total_stats.count) {
- position_factor = sqrt((double)cpi->common.current_video_frame /
- cpi->twopass.total_stats.count);
- }
- max_delta = (int)(position_factor *
- ((*this_frame_target * VBR_PCT_ADJUSTMENT_LIMIT) / 100));
-
- // vbr_bits_off_target > 0 means we have extra bits to spend
- if (vbr_bits_off_target > 0) {
- *this_frame_target +=
- (vbr_bits_off_target > max_delta) ? max_delta
- : (int)vbr_bits_off_target;
- } else {
- *this_frame_target -=
- (vbr_bits_off_target < -max_delta) ? max_delta
- : (int)-vbr_bits_off_target;
- }
-}
-
// Define the reference buffers that will be updated post encode.
void configure_buffer_updates(VP9_COMP *cpi) {
TWO_PASS *const twopass = &cpi->twopass;
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index 6f165797e..bd5b0df82 100644
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -1575,3 +1575,43 @@ void vp9_rc_update_framerate(VP9_COMP *cpi) {
vp9_rc_set_gf_max_interval(cpi, rc);
}
+
+#define VBR_PCT_ADJUSTMENT_LIMIT 50
+// For VBR...adjustment to the frame target based on error from previous frames
+static void vbr_rate_correction(VP9_COMP *cpi,
+ int *this_frame_target,
+ int64_t vbr_bits_off_target) {
+ int max_delta;
+ double position_factor = 1.0;
+
+ // How far through the clip are we.
+ // This number is used to damp the per frame rate correction.
+ // Range 0 - 1.0
+ if (cpi->twopass.total_stats.count) {
+ position_factor = sqrt((double)cpi->common.current_video_frame /
+ cpi->twopass.total_stats.count);
+ }
+ max_delta = (int)(position_factor *
+ ((*this_frame_target * VBR_PCT_ADJUSTMENT_LIMIT) / 100));
+
+ // vbr_bits_off_target > 0 means we have extra bits to spend
+ if (vbr_bits_off_target > 0) {
+ *this_frame_target +=
+ (vbr_bits_off_target > max_delta) ? max_delta
+ : (int)vbr_bits_off_target;
+ } else {
+ *this_frame_target -=
+ (vbr_bits_off_target < -max_delta) ? max_delta
+ : (int)-vbr_bits_off_target;
+ }
+}
+
+void vp9_set_target_rate(VP9_COMP *cpi) {
+ RATE_CONTROL *const rc = &cpi->rc;
+ int target_rate = rc->base_frame_target;
+
+ // 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);
+}
diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h
index bc74129e5..2bc5b59f2 100644
--- a/vp9/encoder/vp9_ratectrl.h
+++ b/vp9/encoder/vp9_ratectrl.h
@@ -198,6 +198,8 @@ void vp9_rc_update_framerate(struct VP9_COMP *cpi);
void vp9_rc_set_gf_max_interval(const struct VP9_COMP *const cpi,
RATE_CONTROL *const rc);
+void vp9_set_target_rate(struct VP9_COMP *cpi);
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/vp9/encoder/vp9_rd.c b/vp9/encoder/vp9_rd.c
index 2f19d2942..4ed324a0e 100644
--- a/vp9/encoder/vp9_rd.c
+++ b/vp9/encoder/vp9_rd.c
@@ -591,18 +591,13 @@ void vp9_set_rd_speed_thresholds(VP9_COMP *cpi) {
}
void vp9_set_rd_speed_thresholds_sub8x8(VP9_COMP *cpi) {
- const SPEED_FEATURES *const sf = &cpi->sf;
- RD_OPT *const rd = &cpi->rd;
- int i;
static const int thresh_mult[2][MAX_REFS] =
{{2500, 2500, 2500, 4500, 4500, 2500},
{2000, 2000, 2000, 4000, 4000, 2000}};
-
- for (i = 0; i < MAX_REFS; ++i) {
- rd->thresh_mult_sub8x8[i] =
- (sf->disable_split_mask & (1 << i)) ?
- INT_MAX : thresh_mult[cpi->oxcf.mode == BEST][i];
- }
+ RD_OPT *const rd = &cpi->rd;
+ const int idx = cpi->oxcf.mode == BEST;
+ vpx_memcpy(rd->thresh_mult_sub8x8, thresh_mult[idx],
+ sizeof(thresh_mult[idx]));
}
void vp9_update_rd_thresh_fact(int (*factor_buf)[MAX_MODES], int rd_thresh,
diff --git a/vp9/encoder/vp9_speed_features.c b/vp9/encoder/vp9_speed_features.c
index 7a1b0cc1f..9225ae2c6 100644
--- a/vp9/encoder/vp9_speed_features.c
+++ b/vp9/encoder/vp9_speed_features.c
@@ -16,12 +16,61 @@
// Intra only frames, golden frames (except alt ref overlays) and
// alt ref frames tend to be coded at a higher than ambient quality
static int frame_is_boosted(const VP9_COMP *cpi) {
- return frame_is_intra_only(&cpi->common) ||
- cpi->refresh_alt_ref_frame ||
- (cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref) ||
- vp9_is_upper_layer_key_frame(cpi);
+ return frame_is_kf_gf_arf(cpi) || vp9_is_upper_layer_key_frame(cpi);
}
+static void set_good_speed_feature_framesize_dependent(VP9_COMMON *cm,
+ SPEED_FEATURES *sf,
+ int speed) {
+ if (speed >= 1) {
+ if (MIN(cm->width, cm->height) >= 720) {
+ sf->disable_split_mask = cm->show_frame ? DISABLE_ALL_SPLIT
+ : DISABLE_ALL_INTER_SPLIT;
+ sf->partition_search_breakout_dist_thr = (1 << 23);
+ } else {
+ sf->disable_split_mask = DISABLE_COMPOUND_SPLIT;
+ sf->partition_search_breakout_dist_thr = (1 << 21);
+ }
+ }
+
+ if (speed >= 2) {
+ if (MIN(cm->width, cm->height) >= 720) {
+ sf->disable_split_mask = cm->show_frame ? DISABLE_ALL_SPLIT
+ : DISABLE_ALL_INTER_SPLIT;
+ sf->adaptive_pred_interp_filter = 0;
+ sf->partition_search_breakout_dist_thr = (1 << 24);
+ sf->partition_search_breakout_rate_thr = 120;
+ } else {
+ sf->disable_split_mask = LAST_AND_INTRA_SPLIT_ONLY;
+ sf->partition_search_breakout_dist_thr = (1 << 22);
+ sf->partition_search_breakout_rate_thr = 100;
+ }
+ }
+
+ if (speed >= 3) {
+ if (MIN(cm->width, cm->height) >= 720) {
+ sf->disable_split_mask = DISABLE_ALL_SPLIT;
+ sf->schedule_mode_search = cm->base_qindex < 220 ? 1 : 0;
+ sf->partition_search_breakout_dist_thr = (1 << 25);
+ sf->partition_search_breakout_rate_thr = 200;
+ } else {
+ sf->max_intra_bsize = BLOCK_32X32;
+ sf->disable_split_mask = DISABLE_ALL_INTER_SPLIT;
+ sf->schedule_mode_search = cm->base_qindex < 175 ? 1 : 0;
+ sf->partition_search_breakout_dist_thr = (1 << 23);
+ sf->partition_search_breakout_rate_thr = 120;
+ }
+ }
+
+ if (speed >= 4) {
+ if (MIN(cm->width, cm->height) >= 720) {
+ sf->partition_search_breakout_dist_thr = (1 << 26);
+ } else {
+ sf->partition_search_breakout_dist_thr = (1 << 24);
+ }
+ sf->disable_split_mask = DISABLE_ALL_SPLIT;
+ }
+}
static void set_good_speed_feature(VP9_COMP *cpi, VP9_COMMON *cm,
SPEED_FEATURES *sf, int speed) {
@@ -34,11 +83,6 @@ static void set_good_speed_feature(VP9_COMP *cpi, VP9_COMMON *cm,
sf->use_square_partition_only = !frame_is_intra_only(cm);
sf->less_rectangular_check = 1;
- if (MIN(cm->width, cm->height) >= 720)
- sf->disable_split_mask = cm->show_frame ? DISABLE_ALL_SPLIT
- : DISABLE_ALL_INTER_SPLIT;
- else
- sf->disable_split_mask = DISABLE_COMPOUND_SPLIT;
sf->use_rd_breakout = 1;
sf->adaptive_motion_search = 1;
sf->mv.auto_mv_step_size = 1;
@@ -54,11 +98,6 @@ static void set_good_speed_feature(VP9_COMP *cpi, VP9_COMMON *cm,
sf->intra_uv_mode_mask[TX_16X16] = INTRA_DC_H_V;
sf->tx_size_search_breakout = 1;
-
- if (MIN(cm->width, cm->height) >= 720)
- sf->partition_search_breakout_dist_thr = (1 << 23);
- else
- sf->partition_search_breakout_dist_thr = (1 << 21);
sf->partition_search_breakout_rate_thr = 80;
}
@@ -66,18 +105,6 @@ static void set_good_speed_feature(VP9_COMP *cpi, VP9_COMMON *cm,
sf->tx_size_search_method = frame_is_boosted(cpi) ? USE_FULL_RD
: USE_LARGESTALL;
- if (MIN(cm->width, cm->height) >= 720) {
- sf->disable_split_mask = cm->show_frame ? DISABLE_ALL_SPLIT
- : DISABLE_ALL_INTER_SPLIT;
- sf->adaptive_pred_interp_filter = 0;
- sf->partition_search_breakout_dist_thr = (1 << 24);
- sf->partition_search_breakout_rate_thr = 120;
- } else {
- sf->disable_split_mask = LAST_AND_INTRA_SPLIT_ONLY;
- sf->partition_search_breakout_dist_thr = (1 << 22);
- sf->partition_search_breakout_rate_thr = 100;
- }
-
sf->reference_masking = 1;
sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH |
FLAG_SKIP_INTRA_BESTINTER |
@@ -93,18 +120,6 @@ static void set_good_speed_feature(VP9_COMP *cpi, VP9_COMMON *cm,
if (speed >= 3) {
sf->tx_size_search_method = frame_is_intra_only(cm) ? USE_FULL_RD
: USE_LARGESTALL;
- if (MIN(cm->width, cm->height) >= 720) {
- sf->disable_split_mask = DISABLE_ALL_SPLIT;
- sf->schedule_mode_search = cm->base_qindex < 220 ? 1 : 0;
- sf->partition_search_breakout_dist_thr = (1 << 25);
- sf->partition_search_breakout_rate_thr = 200;
- } else {
- sf->max_intra_bsize = BLOCK_32X32;
- sf->disable_split_mask = DISABLE_ALL_INTER_SPLIT;
- sf->schedule_mode_search = cm->base_qindex < 175 ? 1 : 0;
- sf->partition_search_breakout_dist_thr = (1 << 23);
- sf->partition_search_breakout_rate_thr = 120;
- }
sf->mv.subpel_search_method = SUBPEL_TREE_PRUNED;
sf->adaptive_pred_interp_filter = 0;
sf->adaptive_mode_search = 1;
@@ -122,7 +137,6 @@ static void set_good_speed_feature(VP9_COMP *cpi, VP9_COMMON *cm,
if (speed >= 4) {
sf->use_square_partition_only = 1;
sf->tx_size_search_method = USE_LARGESTALL;
- sf->disable_split_mask = DISABLE_ALL_SPLIT;
sf->mv.search_method = BIGDIA;
sf->mv.subpel_search_method = SUBPEL_TREE_PRUNED_MORE;
sf->adaptive_rd_thresh = 4;
@@ -132,11 +146,6 @@ static void set_good_speed_feature(VP9_COMP *cpi, VP9_COMMON *cm,
sf->use_fast_coef_updates = ONE_LOOP_REDUCED;
sf->use_fast_coef_costing = 1;
sf->motion_field_mode_search = !boosted;
-
- if (MIN(cm->width, cm->height) >= 720)
- sf->partition_search_breakout_dist_thr = (1 << 26);
- else
- sf->partition_search_breakout_dist_thr = (1 << 24);
sf->partition_search_breakout_rate_thr = 300;
}
@@ -154,6 +163,42 @@ static void set_good_speed_feature(VP9_COMP *cpi, VP9_COMMON *cm,
}
}
+static void set_rt_speed_feature_framesize_dependent(VP9_COMP *cpi,
+ SPEED_FEATURES *sf, int speed) {
+ VP9_COMMON *const cm = &cpi->common;
+
+ if (speed >= 1) {
+ if (MIN(cm->width, cm->height) >= 720) {
+ sf->disable_split_mask = cm->show_frame ? DISABLE_ALL_SPLIT
+ : DISABLE_ALL_INTER_SPLIT;
+ } else {
+ sf->disable_split_mask = DISABLE_COMPOUND_SPLIT;
+ }
+ }
+
+ if (speed >= 2) {
+ if (MIN(cm->width, cm->height) >= 720) {
+ sf->disable_split_mask = cm->show_frame ? DISABLE_ALL_SPLIT
+ : DISABLE_ALL_INTER_SPLIT;
+ } else {
+ sf->disable_split_mask = LAST_AND_INTRA_SPLIT_ONLY;
+ }
+ }
+
+ if (speed >= 5) {
+ if (MIN(cm->width, cm->height) >= 720) {
+ sf->partition_search_breakout_dist_thr = (1 << 25);
+ } else {
+ sf->partition_search_breakout_dist_thr = (1 << 23);
+ }
+ }
+
+ if (speed >= 7) {
+ sf->encode_breakout_thresh = (MIN(cm->width, cm->height) >= 720) ?
+ 800 : 300;
+ }
+}
+
static void set_rt_speed_feature(VP9_COMP *cpi, SPEED_FEATURES *sf,
int speed, vp9e_tune_content content) {
VP9_COMMON *const cm = &cpi->common;
@@ -169,12 +214,6 @@ static void set_rt_speed_feature(VP9_COMP *cpi, SPEED_FEATURES *sf,
sf->tx_size_search_method = frame_is_intra_only(cm) ? USE_FULL_RD
: USE_LARGESTALL;
- if (MIN(cm->width, cm->height) >= 720)
- sf->disable_split_mask = cm->show_frame ? DISABLE_ALL_SPLIT
- : DISABLE_ALL_INTER_SPLIT;
- else
- sf->disable_split_mask = DISABLE_COMPOUND_SPLIT;
-
sf->use_rd_breakout = 1;
sf->adaptive_motion_search = 1;
@@ -187,12 +226,6 @@ static void set_rt_speed_feature(VP9_COMP *cpi, SPEED_FEATURES *sf,
}
if (speed >= 2) {
- if (MIN(cm->width, cm->height) >= 720)
- sf->disable_split_mask = cm->show_frame ? DISABLE_ALL_SPLIT
- : DISABLE_ALL_INTER_SPLIT;
- else
- sf->disable_split_mask = LAST_AND_INTRA_SPLIT_ONLY;
-
sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH |
FLAG_SKIP_INTRA_BESTINTER |
FLAG_SKIP_COMP_BESTINTRA |
@@ -270,11 +303,6 @@ static void set_rt_speed_feature(VP9_COMP *cpi, SPEED_FEATURES *sf,
sf->adaptive_rd_thresh = 2;
// This feature is only enabled when partition search is disabled.
sf->reuse_inter_pred_sby = 1;
-
- if (MIN(cm->width, cm->height) >= 720)
- sf->partition_search_breakout_dist_thr = (1 << 25);
- else
- sf->partition_search_breakout_dist_thr = (1 << 23);
sf->partition_search_breakout_rate_thr = 200;
}
@@ -299,8 +327,6 @@ static void set_rt_speed_feature(VP9_COMP *cpi, SPEED_FEATURES *sf,
sf->mv.search_method = FAST_DIAMOND;
sf->mv.fullpel_search_step_param = 10;
sf->lpf_pick = LPF_PICK_MINIMAL_LPF;
- sf->encode_breakout_thresh = (MIN(cm->width, cm->height) >= 720) ?
- 800 : 300;
}
if (speed >= 12) {
@@ -316,7 +342,37 @@ static void set_rt_speed_feature(VP9_COMP *cpi, SPEED_FEATURES *sf,
}
}
-void vp9_set_speed_features(VP9_COMP *cpi) {
+void vp9_set_speed_features_framesize_dependent(VP9_COMP *cpi) {
+ SPEED_FEATURES *const sf = &cpi->sf;
+ VP9_COMMON *const cm = &cpi->common;
+ const VP9EncoderConfig *const oxcf = &cpi->oxcf;
+ RD_OPT *const rd = &cpi->rd;
+ int i;
+
+ if (oxcf->mode == REALTIME) {
+ set_rt_speed_feature_framesize_dependent(cpi, sf, oxcf->speed);
+ } else if (oxcf->mode == GOOD) {
+ set_good_speed_feature_framesize_dependent(cm, sf, oxcf->speed);
+ }
+
+ if (sf->disable_split_mask == DISABLE_ALL_SPLIT) {
+ sf->adaptive_pred_interp_filter = 0;
+ }
+
+ if (cpi->encode_breakout && oxcf->mode == REALTIME &&
+ sf->encode_breakout_thresh > cpi->encode_breakout) {
+ cpi->encode_breakout = sf->encode_breakout_thresh;
+ }
+
+ // Check for masked out split cases.
+ for (i = 0; i < MAX_REFS; ++i) {
+ if (sf->disable_split_mask & (1 << i)) {
+ rd->thresh_mult_sub8x8[i] = INT_MAX;
+ }
+ }
+}
+
+void vp9_set_speed_features_framesize_independent(VP9_COMP *cpi) {
SPEED_FEATURES *const sf = &cpi->sf;
VP9_COMMON *const cm = &cpi->common;
const VP9EncoderConfig *const oxcf = &cpi->oxcf;
@@ -427,14 +483,7 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
cpi->mb.optimize = sf->optimize_coefficients == 1 && oxcf->pass != 1;
- if (sf->disable_split_mask == DISABLE_ALL_SPLIT)
- sf->adaptive_pred_interp_filter = 0;
-
if (!cpi->oxcf.frame_periodic_boost) {
sf->max_delta_qindex = 0;
}
-
- if (cpi->encode_breakout && oxcf->mode == REALTIME &&
- sf->encode_breakout_thresh > cpi->encode_breakout)
- cpi->encode_breakout = sf->encode_breakout_thresh;
}
diff --git a/vp9/encoder/vp9_speed_features.h b/vp9/encoder/vp9_speed_features.h
index a314f6040..53b504113 100644
--- a/vp9/encoder/vp9_speed_features.h
+++ b/vp9/encoder/vp9_speed_features.h
@@ -416,7 +416,8 @@ typedef struct SPEED_FEATURES {
struct VP9_COMP;
-void vp9_set_speed_features(struct VP9_COMP *cpi);
+void vp9_set_speed_features_framesize_independent(struct VP9_COMP *cpi);
+void vp9_set_speed_features_framesize_dependent(struct VP9_COMP *cpi);
#ifdef __cplusplus
} // extern "C"
diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c
index 59486995a..e86df2242 100644
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -163,8 +163,8 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
RANGE_CHECK(cfg, g_pass, VPX_RC_ONE_PASS, VPX_RC_LAST_PASS);
if (cfg->rc_resize_allowed == 1) {
- RANGE_CHECK(cfg, rc_scaled_width, 1, cfg->g_w);
- RANGE_CHECK(cfg, rc_scaled_height, 1, cfg->g_h);
+ RANGE_CHECK(cfg, rc_scaled_width, 0, cfg->g_w);
+ RANGE_CHECK(cfg, rc_scaled_height, 0, cfg->g_h);
}
RANGE_CHECK(cfg, ss_number_layers, 1, VPX_SS_MAX_LAYERS);
@@ -398,9 +398,15 @@ static vpx_codec_err_t set_encoder_config(
oxcf->under_shoot_pct = cfg->rc_undershoot_pct;
oxcf->over_shoot_pct = cfg->rc_overshoot_pct;
- oxcf->allow_spatial_resampling = cfg->rc_resize_allowed;
- oxcf->scaled_frame_width = cfg->rc_scaled_width;
- oxcf->scaled_frame_height = cfg->rc_scaled_height;
+ oxcf->scaled_frame_width = cfg->rc_scaled_width;
+ oxcf->scaled_frame_height = cfg->rc_scaled_height;
+ if (cfg->rc_resize_allowed == 1) {
+ oxcf->resize_mode =
+ (oxcf->scaled_frame_width == 0 || oxcf->scaled_frame_height == 0) ?
+ RESIZE_DYNAMIC : RESIZE_FIXED;
+ } else {
+ oxcf->resize_mode = RESIZE_NONE;
+ }
oxcf->maximum_buffer_size_ms = is_vbr ? 240000 : cfg->rc_buf_sz;
oxcf->starting_buffer_level_ms = is_vbr ? 60000 : cfg->rc_buf_initial_sz;
@@ -1383,8 +1389,8 @@ static vpx_codec_enc_cfg_map_t encoder_usage_cfg_map[] = {
0, // rc_dropframe_thresh
0, // rc_resize_allowed
- 1, // rc_scaled_width
- 1, // rc_scaled_height
+ 0, // rc_scaled_width
+ 0, // rc_scaled_height
60, // rc_resize_down_thresold
30, // rc_resize_up_thresold