diff --git a/vp9/common/vp9_motion_model.c b/vp9/common/vp9_motion_model.c index c4f18030f..7547bce68 100644 --- a/vp9/common/vp9_motion_model.c +++ b/vp9/common/vp9_motion_model.c @@ -216,31 +216,39 @@ static void WarpImage(TransformationType type, double *H, } } -// computes warp error -double compute_warp_and_error(TransformationType type, - unsigned char *ref, - unsigned char *frm, - int width, int height, int stride, - double *H) { +double compute_warp_and_error(Global_Motion_Params *gm, + projectPointsType projectPoints, + unsigned char *ref, + int width, int height, int stride, + unsigned char *src, + int p_col, int p_row, + int p_width, int p_height, int p_stride, + int subsampling_col, int subsampling_row, + int x_scale, int y_scale) { + double H[9]; + vp9_convert_params_to_rotzoom(gm, H); int i, j; - double warped; - double mse = 0; - double err = 0; - projectPointsType projectPoints = get_projectPointsType(type); - if (projectPoints == NULL) return -1.0; - for (i = 0; i < height; ++i) - for (j = 0; j < width; ++j) { + int64_t sumerr = 0; + if (projectPoints == NULL) + return -1; + for (i = p_row; i < p_row + p_height; ++i) { + for (j = p_col; j < p_col + p_width; ++j) { double in[2], out[2]; - in[0] = j; - in[1] = i; + uint8_t pred; + int err; + in[0] = subsampling_col ? 2 * j + 0.5 : j; + in[1] = subsampling_row ? 2 * i + 0.5 : i; projectPoints(H, in, out, 1, 2, 2); - warped = interpolate(ref, out[0], out[1], width, height, stride); - err = warped - frm[j + i * stride]; - mse += err * err; + out[0] = subsampling_col ? (out[0] - 0.5) / 2.0 : out[0]; + out[1] = subsampling_row ? (out[1] - 0.5) / 2.0 : out[1]; + out[0] *= x_scale / 16.0; + out[1] *= y_scale / 16.0; + pred = interpolate(ref, out[0], out[1], width, height, stride); + err = pred - src[(j - p_col) + (i - p_row) * p_stride]; + sumerr += err * err; } - - mse /= (width * height); - return mse; + } + return sumerr/(width * height); } // Computes the ratio of the warp error to the zero motion error diff --git a/vp9/common/vp9_motion_model.h b/vp9/common/vp9_motion_model.h index 71f5872d4..8069c2129 100644 --- a/vp9/common/vp9_motion_model.h +++ b/vp9/common/vp9_motion_model.h @@ -92,13 +92,15 @@ double vp9_warp_erroradv_unq(TransformationType type, double *H, int subsampling_col, int subsampling_row, int x_scale, int y_scale); -double compute_warp_and_error(TransformationType type, +double compute_warp_and_error(Global_Motion_Params *gm, + projectPointsType projectPoints, unsigned char *ref, - unsigned char *frm, int width, int height, int stride, - double *H); - - + unsigned char *src, + int p_col, int p_row, + int p_width, int p_height, int p_stride, + int subsampling_col, int subsampling_row, + int x_scale, int y_scale); unsigned char interpolate(unsigned char *ref, double x, double y, int width, int height, int stride); diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index 814eced6f..3f5280290 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -4228,7 +4228,7 @@ static int input_fpmb_stats(FIRSTPASS_MB_STATS *firstpass_mb_stats, #define GLOBAL_MOTION_ADVANTAGE_THRESH_RZ 0.60 #define GLOBAL_MOTION_ADVANTAGE_THRESH_TR 0.75 // #define USE_BLOCK_BASED_GLOBAL_MOTION_COMPUTATION -// #define USE_FEATURE_BASED_GLOBAL_MOTION_COMPUTATION +#define USE_FEATURE_BASED_GLOBAL_MOTION_COMPUTATION static void convert_translation_to_params( double *H, Global_Motion_Params *model) { @@ -4350,6 +4350,16 @@ static void encode_frame_internal(VP9_COMP *cpi) { global_motion + i * get_numparams(GLOBAL_MOTION_MODEL), GLOBAL_MOTION_MODEL, &cm->global_motion[frame][i]); + refine_quant_param(&cm->global_motion[frame][i], + GLOBAL_MOTION_MODEL, ref_buf->y_buffer, + ref_buf->y_crop_width, + ref_buf->y_crop_height, + ref_buf->y_stride, + cpi->Source->y_buffer, + cpi->Source->y_crop_width, + cpi->Source->y_crop_height, + cpi->Source->y_stride, 3); + if (get_gmtype(&cm->global_motion[frame][i]) != GLOBAL_ZERO) { double erroradvantage_trans; double erroradvantage = diff --git a/vp9/encoder/vp9_global_motion.c b/vp9/encoder/vp9_global_motion.c index 654439a56..16926e792 100644 --- a/vp9/encoder/vp9_global_motion.c +++ b/vp9/encoder/vp9_global_motion.c @@ -95,51 +95,177 @@ static double compute_error_score(TransformationType type, return sqrt(sqerr / n); } -void refine_param(TransformationType type, unsigned char *frm, - unsigned char *ref, double *H, - int param_index, int width, int height, - int stride, int n_refinements) { - int i; - double step_mse; - double best_mse; - double curr_mse; - double curr_param = H[param_index]; - double step = 0.5; - double best_param = curr_param; - - curr_mse = compute_warp_and_error(type, ref, frm, width, height, stride, H); - best_mse = curr_mse; - for (i = 0; i < n_refinements; i++) { - // look to the left - H[param_index] = curr_param - step; - step_mse = compute_warp_and_error(type, ref, frm, width, height, stride, H); - if (step_mse < best_mse) { - step /= 2; - best_mse = step_mse; - best_param = H[param_index]; - curr_param = best_param; - curr_mse = step_mse; - continue; - } - - // look to the right - H[param_index] = curr_param + step; - step_mse = compute_warp_and_error(type, ref, frm, width, height, stride, H); - if (step_mse < best_mse) { - step /= 2; - best_mse = step_mse; - best_param = H[param_index]; - curr_param = best_param; - curr_mse = step_mse; - continue; - } - - // no improvement found-> means we're either already at a minimum or - // step is too wide - step /= 4; +static int16_t* get_gm_param_trans(Global_Motion_Params *gm, int index) { + switch (index) { + case 0 : + return &gm->mv.as_mv.row; + break; + case 1 : + return &gm->mv.as_mv.col; + break; } + assert(0); + return NULL; +} - H[param_index] = best_param; +static int* get_gm_param_rotzoom(Global_Motion_Params *gm, int index) { + switch (index) { + case 0 : + return &gm->rotation; + break; + case 1 : + return &gm->zoom; + break; + } + assert(0); + return NULL; +} + +static void refine_quant_param_trans(Global_Motion_Params *gm, + TransformationType type, + unsigned char *ref, int ref_width, + int ref_height, int ref_stride, + unsigned char *frm, int frm_width, + int frm_height, int frm_stride, + int n_refinements) { + int i = 0, p; + double step_mse; + int step; + int16_t *param; + int16_t curr_param; + int16_t best_param; + projectPointsType projectPoints = get_projectPointsType(type); + double best_mse = compute_warp_and_error(gm, projectPoints, ref, ref_width, + ref_height, ref_stride, frm, 0, 0, + frm_width, frm_height, frm_stride, + 0, 0, 16, 16); + for (p = 0; p < 2; ++p) { + param = get_gm_param_trans(gm, p); + step = 1 << (n_refinements + 1); + curr_param = *param; + best_param = curr_param; + for (i = 0; i < n_refinements; i++) { + // look to the left + *param = curr_param - step; + step_mse = compute_warp_and_error(gm, projectPoints, ref, ref_width, + ref_height, ref_stride, frm, 0, 0, + frm_width, frm_height, frm_stride, + 0, 0, 16, 16); + if (step_mse < best_mse) { + step >>= 1; + best_mse = step_mse; + best_param = *param; + curr_param = best_param; + continue; + } + + // look to the right + *param = curr_param + step; + step_mse = compute_warp_and_error(gm, projectPoints, ref, ref_width, + ref_height, ref_stride, frm, 0, 0, + frm_width, frm_height, frm_stride, + 0, 0, 16, 16); + if (step_mse < best_mse) { + step >>= 1; + best_mse = step_mse; + best_param = *param; + curr_param = best_param; + continue; + } + + // no improvement found-> means we're either already at a minimum or + // step is too wide + step >>= 1; + } + + *param = best_param; + } +} + +static void refine_quant_param_rotzoom(Global_Motion_Params *gm, + TransformationType type, + unsigned char *ref, int ref_width, + int ref_height, int ref_stride, + unsigned char *frm, int frm_width, + int frm_height, int frm_stride, + int n_refinements) { + int i = 0, p; + double step_mse; + int step; + int *param; + int curr_param; + int best_param; + projectPointsType projectPoints = get_projectPointsType(type); + double best_mse = compute_warp_and_error(gm, projectPoints, ref, ref_width, + ref_height, ref_stride, frm, 0, 0, + frm_width, frm_height, frm_stride, + 0, 0, 16, 16); + for (p = 0; p < 2; ++p) { + param = get_gm_param_rotzoom(gm, p); + step = 1 << (n_refinements + 1); + curr_param = *param; + best_param = curr_param; + for (i = 0; i < n_refinements; i++) { + // look to the left + *param = curr_param - step; + step_mse = compute_warp_and_error(gm, projectPoints, ref, ref_width, + ref_height, ref_stride, frm, 0, 0, + frm_width, frm_height, frm_stride, + 0, 0, 16, 16); + if (step_mse < best_mse) { + step >>= 1; + best_mse = step_mse; + best_param = *param; + curr_param = best_param; + continue; + } + + // look to the right + *param = curr_param + step; + step_mse = compute_warp_and_error(gm, projectPoints, ref, ref_width, + ref_height, ref_stride, frm, 0, 0, + frm_width, frm_height, frm_stride, + 0, 0, 16, 16); + if (step_mse < best_mse) { + step >>= 1; + best_mse = step_mse; + best_param = *param; + curr_param = best_param; + continue; + } + + // no improvement found-> means we're either already at a minimum or + // step is too wide + step >>= 1; + } + + *param = best_param; + } +} + +void refine_quant_param(Global_Motion_Params *gm, + TransformationType type, + unsigned char *ref, int ref_width, + int ref_height, int ref_stride, + unsigned char *frm, int frm_width, int frm_height, + int frm_stride, int n_refinements) { + switch (gm->gmtype) { + case GLOBAL_TRANSLATION : + refine_quant_param_trans(gm, type, ref, ref_width, ref_height, + ref_stride, frm, frm_width, frm_height, + frm_stride, n_refinements); + break; + case GLOBAL_ROTZOOM : + refine_quant_param_rotzoom(gm, type, ref, ref_width, ref_height, + ref_stride, frm, frm_width, frm_height, + frm_stride, n_refinements); + refine_quant_param_trans(gm, type, ref, ref_width, ref_height, + ref_stride, frm, frm_width, frm_height, + frm_stride, n_refinements); + break; + default : + break; + } } static int compute_global_motion_single(TransformationType type, @@ -366,16 +492,6 @@ int vp9_compute_global_motion_multiple_optical_flow(struct VP9_COMP *cpi, num_correspondences, H, max_models, inlier_prob, &num_models, inlier_map); -#ifdef PARAM_SEARCH - for (j = 0; j < num_models; ++j) { - for (i = 0; i < get_numparams(type); ++i) - - refine_param(type, frm->y_buffer, ref->y_buffer, H, - i + j * get_numparams(type), frm->y_width, frm->y_height, - frm->y_stride, 2); - } -#endif - #ifdef VERBOSE printf("Models = %d, Inliers = %d\n", num_models, num_inliers); if (num_models) @@ -458,16 +574,6 @@ int vp9_compute_global_motion_multiple_feature_based( num_correspondences, H, max_models, inlier_prob, &num_models, inlier_map); -#ifdef PARAM_SEARCH - for (j = 0; j < num_models; ++j) { - for (i = 0; i < get_numparams(type); ++i) - - refine_param(type, frm->y_buffer, ref->y_buffer, H, - i + j * get_numparams(type), frm->y_width, frm->y_height, - frm->y_stride, 3); - } -#endif - #ifdef VERBOSE printf("Models = %d, Inliers = %d\n", num_models, num_inliers); if (num_models) diff --git a/vp9/encoder/vp9_global_motion.h b/vp9/encoder/vp9_global_motion.h index 5828ae703..b597d16cb 100644 --- a/vp9/encoder/vp9_global_motion.h +++ b/vp9/encoder/vp9_global_motion.h @@ -31,10 +31,11 @@ INLINE ransacType get_ransacType(TransformationType type); // Searches around each parameter and seeks to minimize MSE between // the warped frame produced from the set of parameters and the frame being // approximated. -void refine_param(TransformationType type, unsigned char *frm, - unsigned char *ref, double *H, - int param_index, int width, int height, - int stride, int n_refinements); +void refine_quant_param(Global_Motion_Params *gm, TransformationType type, + unsigned char *ref, int ref_width, + int ref_height, int ref_stride, + unsigned char *frm, int frm_width, int frm_height, + int frm_stride, int n_refinements); // Returns number of models actually returned: 1 - if success, 0 - if failure int vp9_compute_global_motion_single_feature_based(struct VP9_COMP *cpi,