Set mv_step_param based on previous frame in speed >= 2
For lowres and midres in speed >= 2, mv_step_param is initialized based
on previous frame's max_mv_magnitude.
Instruction Count BD-Rate Loss(%)
cpu-used Reduction(%) avg.psnr ovr.psnr ssim
2 0.512 -0.0076 -0.0052 0.0092
3 0.683 0.0329 0.0337 0.0360
4 0.954 0.0188 0.0281 0.0181
5 1.036 0.0248 0.0114 0.0096
6 1.132 0.0415 0.0179 0.0210
STATS_CHANGED
Change-Id: Ic1c772d3063cb7a881e3905527cb3aa0bc577c18
diff --git a/av1/encoder/encode_strategy.c b/av1/encoder/encode_strategy.c
index fe4a02a..6af6b87 100644
--- a/av1/encoder/encode_strategy.c
+++ b/av1/encoder/encode_strategy.c
@@ -1057,9 +1057,14 @@
if (cpi->oxcf.pass == 2) end_timing(cpi, apply_filtering_time);
#endif
+ int set_mv_params = frame_params->frame_type == KEY_FRAME ||
+ update_type == ARF_UPDATE || update_type == GF_UPDATE;
+ cm->show_frame = frame_params->show_frame;
+ cm->current_frame.frame_type = frame_params->frame_type;
// TODO(bohanli): Why is this? what part of it is necessary?
av1_set_frame_size(cpi, cm->superres_upscaled_width,
cm->superres_upscaled_height);
+ if (set_mv_params) av1_set_mv_search_params(cpi);
#if CONFIG_RD_COMMAND
if (frame_params->frame_type == KEY_FRAME) {
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 231c684..a907860 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -1747,7 +1747,7 @@
}
#endif // OUTPUT_YUV_REC
-static void set_mv_search_params(AV1_COMP *cpi) {
+void av1_set_mv_search_params(AV1_COMP *cpi) {
const AV1_COMMON *const cm = &cpi->common;
MotionVectorSearchParams *const mv_search_params = &cpi->mv_search_params;
const int max_mv_def = AOMMAX(cm->width, cm->height);
@@ -1761,15 +1761,27 @@
// after a key/intra-only frame.
mv_search_params->max_mv_magnitude = max_mv_def;
} else {
- // Use cpi->max_mv_magnitude == -1 to exclude first pass case.
- if (cm->show_frame && mv_search_params->max_mv_magnitude != -1) {
+ // Use adaptive mv steps based on previous frame stats for show frames and
+ // internal arfs.
+ FRAME_UPDATE_TYPE cur_update_type =
+ cpi->ppi->gf_group.update_type[cpi->gf_frame_index];
+ int use_auto_mv_step =
+ (cm->show_frame || cur_update_type == INTNL_ARF_UPDATE) &&
+ mv_search_params->max_mv_magnitude != -1 &&
+ cpi->sf.mv_sf.auto_mv_step_size >= 2;
+ if (use_auto_mv_step) {
// 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.
mv_search_params->mv_step_param = av1_init_search_range(
AOMMIN(max_mv_def, 2 * mv_search_params->max_mv_magnitude));
}
+#if CONFIG_FRAME_PARALLEL_ENCODE
+ // Reset max_mv_magnitude based on update flag.
+ if (cpi->do_frame_data_update) mv_search_params->max_mv_magnitude = -1;
+#else
mv_search_params->max_mv_magnitude = -1;
+#endif
}
}
}
@@ -2054,7 +2066,6 @@
}
#endif
}
- set_mv_search_params(cpi);
if (is_stat_consumption_stage(cpi)) {
av1_set_target_rate(cpi, cm->width, cm->height);
@@ -2284,6 +2295,7 @@
set_size_independent_vars(cpi);
av1_setup_frame_size(cpi);
av1_set_size_dependent_vars(cpi, &q, &bottom_index, &top_index);
+ av1_set_mv_search_params(cpi);
if (!cpi->ppi->use_svc) {
phase_scaler = 8;
@@ -2521,6 +2533,8 @@
q_low = bottom_index;
q_high = top_index;
+ av1_set_mv_search_params(cpi);
+
allocate_gradient_info_for_hog(&cpi->td.pixel_gradient_info, cpi);
if (cpi->sf.part_sf.partition_search_type == VAR_BASED_PARTITION)
@@ -3410,6 +3424,7 @@
current_frame->frame_type != KEY_FRAME) {
if (cpi->oxcf.rc_cfg.target_bandwidth == 0 || av1_rc_drop_frame(cpi)) {
av1_setup_frame_size(cpi);
+ av1_set_mv_search_params(cpi);
av1_rc_postencode_update_drop_frame(cpi);
release_scaled_references(cpi);
cpi->is_dropped_frame = true;
@@ -4688,7 +4703,8 @@
cur_cpi->rc.min_frame_bandwidth = first_cpi->rc.min_frame_bandwidth;
cur_cpi->rc.intervals_till_gf_calculate_due =
first_cpi->rc.intervals_till_gf_calculate_due;
- cur_cpi->mv_search_params.max_mv_magnitude = -1;
+ cur_cpi->mv_search_params.max_mv_magnitude =
+ first_cpi->mv_search_params.max_mv_magnitude;
if (gf_group->update_type[cur_cpi->gf_frame_index] == INTNL_ARF_UPDATE) {
cur_cpi->common.lf.mode_ref_delta_enabled = 1;
}
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 7208c36..06f5871 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -3502,6 +3502,8 @@
void av1_set_frame_size(AV1_COMP *cpi, int width, int height);
+void av1_set_mv_search_params(AV1_COMP *cpi);
+
int av1_set_active_map(AV1_COMP *cpi, unsigned char *map, int rows, int cols);
int av1_get_active_map(AV1_COMP *cpi, unsigned char *map, int rows, int cols);
diff --git a/av1/encoder/firstpass.c b/av1/encoder/firstpass.c
index af1e8c1..24ed329 100644
--- a/av1/encoder/firstpass.c
+++ b/av1/encoder/firstpass.c
@@ -1264,6 +1264,7 @@
assert(frame_is_intra_only(cm) || (last_frame != NULL));
av1_setup_frame_size(cpi);
+ av1_set_mv_search_params(cpi);
set_mi_offsets(mi_params, xd, 0, 0);
xd->mi[0]->bsize = fp_block_size;
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index 8c24706..eb93a6c 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -661,8 +661,10 @@
if (!is_720p_or_larger) {
sf->mv_sf.disable_second_mv = 1;
+ sf->mv_sf.auto_mv_step_size = 2;
} else {
sf->mv_sf.disable_second_mv = boosted ? 0 : 2;
+ sf->mv_sf.auto_mv_step_size = 1;
}
if (!is_720p_or_larger) {
@@ -936,7 +938,6 @@
sf->part_sf.reuse_best_prediction_for_part_ab =
!frame_is_intra_only(&cpi->common);
- sf->mv_sf.auto_mv_step_size = 1;
sf->mv_sf.simple_motion_subpel_force_stop = QUARTER_PEL;
sf->mv_sf.subpel_iters_per_step = 1;