Start from block motion search result
Change-Id: Ifbaa658528911462a28d903533e7c2e0bc108628
diff --git a/av1/common/spherical_pred.c b/av1/common/spherical_pred.c
index 3b9a125..9fba493 100644
--- a/av1/common/spherical_pred.c
+++ b/av1/common/spherical_pred.c
@@ -176,7 +176,7 @@
cur_x = x - fo + k;
cur_x = cur_x % frame_width;
- cur_x = cur_x > 0 ? cur_x : frame_width + cur_x;
+ cur_x = cur_x >= 0 ? cur_x : frame_width + cur_x;
sum += ref_frame[cur_x + cur_y * ref_frame_stride] * coeff;
}
@@ -452,8 +452,10 @@
// Small Diamond Search Pattern on shpere
SphereMV sdsp_mv[5];
- double search_step_phi = 0.5 * block_height * PI / frame_height;
- double search_step_theta = 0.5 * block_width * 2 * PI / frame_width;
+ double search_step_phi =
+ AOMMIN(0.2 * block_height, 0.5 * search_range) * PI / frame_height;
+ double search_step_theta =
+ AOMMIN(0.2 * block_width, 0.5 * search_range) * 2 * PI / frame_width;
const uint8_t *cur_block = &cur_frame[block_x + block_y * frame_stride];
uint8_t pred_block[128 * 128];
@@ -464,8 +466,10 @@
av1_plane_to_sphere_erp(block_x, block_y, frame_width, frame_height,
&start_phi, &start_theta);
- double max_range_phi = start_phi + search_range * PI / frame_height;
- double min_range_phi = start_phi - search_range * PI / frame_height;
+ double max_range_phi =
+ start_phi + start_mv->phi + search_range * PI / frame_height;
+ double min_range_phi =
+ start_phi + start_mv->theta - search_range * PI / frame_height;
double max_range_theta = start_theta + search_range * 2 * PI / frame_height;
double min_range_theta = start_theta - search_range * 2 * PI / frame_height;
@@ -480,10 +484,14 @@
frame_height, pred_block_stride, pred_block);
best_sad = get_sad_of_blocks(cur_block, pred_block, block_width, block_height,
frame_stride, pred_block_stride);
+ update_sphere_mv_ldsp(ldsp_mv, search_step_phi, search_step_theta);
- do {
- update_sphere_mv_ldsp(ldsp_mv, search_step_phi, search_step_theta);
+ const double min_scale = 0.125;
+ while (start_phi + ldsp_mv[5].phi <= max_range_phi &&
+ start_phi + ldsp_mv[1].phi >= min_range_phi &&
+ start_theta + ldsp_mv[3].theta <= max_range_theta &&
+ start_theta + ldsp_mv[7].theta >= min_range_theta) {
for (int i = 0; i < 9; i++) {
av1_get_pred_erp(block_x, block_y, block_width, block_height,
ldsp_mv[i].phi, ldsp_mv[i].theta, ref_frame,
@@ -501,11 +509,10 @@
} // for
if (best_mv_idx == 0) {
- if (search_step_phi > PI / frame_height &&
- search_step_theta > 2 * PI / frame_height) {
+ if (search_step_phi > min_scale * PI / frame_height &&
+ search_step_theta > min_scale * 2 * PI / frame_height) {
search_step_phi *= 0.5;
search_step_theta *= 0.5;
- continue;
} else {
break;
}
@@ -514,31 +521,35 @@
ldsp_mv[0].theta = ldsp_mv[best_mv_idx].theta;
best_mv_idx = 0;
}
- } while (start_phi + ldsp_mv[5].phi <= max_range_phi &&
- start_phi + ldsp_mv[1].phi >= min_range_phi &&
- start_theta + ldsp_mv[3].theta <= max_range_theta &&
- start_theta + ldsp_mv[7].theta >= min_range_theta);
+ update_sphere_mv_ldsp(ldsp_mv, search_step_phi, search_step_theta);
+ }
- sdsp_mv[0].phi = ldsp_mv[best_mv_idx].phi;
- sdsp_mv[0].theta = ldsp_mv[best_mv_idx].theta;
+ sdsp_mv[0].phi = ldsp_mv[0].phi;
+ sdsp_mv[0].theta = ldsp_mv[0].theta;
best_mv_idx = 0;
- search_step_phi = PI / frame_height;
- search_step_theta = 2 * PI / frame_width;
-
+ search_step_phi = min_scale * PI / frame_height;
+ search_step_theta = min_scale * 2 * PI / frame_width;
update_sphere_mv_sdsp(sdsp_mv, search_step_phi, search_step_theta);
- for (int i = 0; i < 5; i++) {
- av1_get_pred_erp(block_x, block_y, block_width, block_height,
- sdsp_mv[i].phi, sdsp_mv[i].theta, ref_frame, frame_stride,
- frame_width, frame_height, pred_block_stride, pred_block);
+ if (start_phi + sdsp_mv[3].phi <= max_range_phi &&
+ start_phi + sdsp_mv[1].phi >= min_range_phi &&
+ start_theta + sdsp_mv[2].theta <= max_range_theta &&
+ start_theta + sdsp_mv[4].theta >= min_range_theta) {
+ for (int i = 0; i < 5; i++) {
+ av1_get_pred_erp(block_x, block_y, block_width, block_height,
+ sdsp_mv[i].phi, sdsp_mv[i].theta, ref_frame,
+ frame_stride, frame_width, frame_height,
+ pred_block_stride, pred_block);
- temp_sad = get_sad_of_blocks(cur_block, pred_block, block_width,
- block_height, frame_stride, pred_block_stride);
+ temp_sad =
+ get_sad_of_blocks(cur_block, pred_block, block_width, block_height,
+ frame_stride, pred_block_stride);
- if (temp_sad < best_sad) {
- best_sad = temp_sad;
- best_mv_idx = i;
- }
- } // for
+ if (temp_sad < best_sad) {
+ best_sad = temp_sad;
+ best_mv_idx = i;
+ }
+ } // for
+ }
best_mv->phi = sdsp_mv[best_mv_idx].phi;
best_mv->theta = sdsp_mv[best_mv_idx].theta;
diff --git a/av1/encoder/motion_search_facade.c b/av1/encoder/motion_search_facade.c
index a34f62c..8730a44 100644
--- a/av1/encoder/motion_search_facade.c
+++ b/av1/encoder/motion_search_facade.c
@@ -147,14 +147,15 @@
SphereMV best_sp_mv, start_sp_mv;
// TODO(bohanli,yaoyaogoogle): start with mbmi->mv[0] may also make sense?
const MV ref_mv = av1_get_ref_mv(x, ref_idx).as_mv;
+ const MV start_mv = mbmi->mv[0].as_mv;
// assume ref_mv is converted from sphere MV for the top left pixel of the
// block
double blk_phi, blk_theta, this_phi, this_theta;
double this_x, this_y;
av1_plane_to_sphere_erp(block_x, block_y, frame_width, frame_height, &blk_phi,
&blk_theta);
- av1_plane_to_sphere_erp(block_x + (double)ref_mv.col / 8.0,
- block_y + (double)ref_mv.row / 8.0, frame_width,
+ av1_plane_to_sphere_erp(block_x + (double)start_mv.col / 8.0,
+ block_y + (double)start_mv.row / 8.0, frame_width,
frame_height, &this_phi, &this_theta);
start_sp_mv.phi = this_phi - blk_phi;
start_sp_mv.theta = this_theta - blk_theta;
@@ -184,6 +185,20 @@
best_mv->as_mv.col = (int16_t)round((mv_x)*8.0);
best_mv->as_mv.row = (int16_t)round((mv_y)*8.0);
+ SubpelMvLimits mv_limits;
+ av1_set_subpel_mv_search_range(&mv_limits, &x->mv_limits, &ref_mv);
+ clamp_mv(&best_mv->as_mv, &mv_limits);
+
+ if (cpi->common.features.allow_high_precision_mv == 0) {
+ best_mv->as_mv.col = 2 * ((best_mv->as_mv.col + 1) / 2);
+ best_mv->as_mv.row = 2 * ((best_mv->as_mv.row + 1) / 2);
+ }
+
+ if (cpi->common.features.cur_frame_force_integer_mv) {
+ best_mv->as_mv.col = 8 * ((best_mv->as_mv.col + 4) / 8);
+ best_mv->as_mv.row = 8 * ((best_mv->as_mv.row + 4) / 8);
+ }
+
*rate_mv = av1_mv_bit_cost(&best_mv->as_mv, &ref_mv, mv_costs->nmv_joint_cost,
mv_costs->mv_cost_stack, MV_COST_WEIGHT);
}
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index a14fbed..2d92cb5 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -1376,6 +1376,8 @@
assert(!is_comp_pred);
#if CONFIG_SPHERICAL_PRED
if (have_newmv_in_inter_mode(this_mode)) {
+ av1_single_motion_search(cpi, x, bsize, 0, &tmp_rate_mv, INT_MAX, NULL,
+ &mbmi->mv[0], NULL);
av1_erp_motion_search(cpi, x, bsize, 0, &tmp_rate_mv, 30, &mbmi->mv[0]);
tmp_rate2 = rate2_nocoeff - rate_mv0 + tmp_rate_mv;
}