Commit 8db4c776 authored by Debargha Mukherjee's avatar Debargha Mukherjee

Harmonize the global parameter mappings

lowres: -0.401% BDRATE (tempete -5.4%)

Also includes some fixes and cleanups.

Change-Id: I82922a453fad59fad2f12829d2ef1e56b2d20949
parent 76159124
......@@ -37,7 +37,7 @@ typedef struct mv32 {
#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
// Bits of precision used for the model
#define WARPEDMODEL_PREC_BITS 12
#define WARPEDMODEL_ROW3HOMO_PREC_BITS 12
#define WARPEDMODEL_ROW3HOMO_PREC_BITS 14
// Bits of subpel precision for warped interpolation
#define WARPEDPIXEL_PREC_BITS 6
......@@ -57,12 +57,18 @@ typedef enum {
AFFINE, // affine, 6-parameter
ROTZOOM, // simplified affine with rotation and zoom only, 4-parameter
TRANSLATION, // translational motion 2-parameter
IDENTITY, // identity transformation, 0-parameter
TRANS_TYPES
} TransformationType;
// number of parameters used by each transformation in TransformationTypes
static const int n_trans_model_params[TRANS_TYPES] = { 9, 6, 4, 2 };
static const int n_trans_model_params[TRANS_TYPES] = { 8, 6, 4, 2, 0 };
// The order of values in the wmmat matrix below is best described
// by the homography:
// [x' (m2 m3 m0 [x
// y' = m4 m5 m1 = y
// 1] m6 m7 1) 1]
typedef struct {
TransformationType wmtype;
int32_t wmmat[8]; // For homography wmmat[9] is assumed to be 1
......@@ -102,19 +108,29 @@ typedef struct {
#define GM_ALPHA_PREC_DIFF (WARPEDMODEL_PREC_BITS - GM_ALPHA_PREC_BITS)
#define GM_ALPHA_DECODE_FACTOR (1 << GM_ALPHA_PREC_DIFF)
#define GM_ABS_ALPHA_BITS 9
#define GM_ROW3HOMO_PREC_BITS 14
#define GM_ROW3HOMO_PREC_DIFF \
(WARPEDMODEL_ROW3HOMO_PREC_BITS - GM_ROW3HOMO_PREC_BITS)
#define GM_ROW3HOMO_DECODE_FACTOR (1 << GM_ROW3HOMO_PREC_DIFF)
#define GM_ABS_TRANS_BITS 9
#define GM_ABS_ALPHA_BITS 9
#define GM_ABS_ROW3HOMO_BITS 9
#define GM_TRANS_MAX (1 << GM_ABS_TRANS_BITS)
#define GM_ALPHA_MAX (1 << GM_ABS_ALPHA_BITS)
#define GM_ROW3HOMO_MAX (1 << GM_ABS_ROW3HOMO_BITS)
#define GM_TRANS_MIN -GM_TRANS_MAX
#define GM_ALPHA_MIN -GM_ALPHA_MAX
#define GM_ROW3HOMO_MIN -GM_ROW3HOMO_MAX
typedef enum {
GLOBAL_ZERO = 0,
GLOBAL_TRANSLATION = 1,
GLOBAL_ROTZOOM = 2,
GLOBAL_AFFINE = 3,
// GLOBAL_HOMOGRAPHY = 4,
GLOBAL_MOTION_TYPES
} GLOBAL_MOTION_TYPE;
......@@ -127,36 +143,53 @@ typedef struct {
// regular motion vector) into a motion vector
static INLINE int_mv gm_get_motion_vector(const Global_Motion_Params *gm) {
int_mv res;
res.as_mv.row = (int16_t)ROUND_POWER_OF_TWO_SIGNED(gm->motion_params.wmmat[0],
res.as_mv.row = (int16_t)ROUND_POWER_OF_TWO_SIGNED(gm->motion_params.wmmat[1],
WARPEDMODEL_PREC_BITS - 3);
res.as_mv.col = (int16_t)ROUND_POWER_OF_TWO_SIGNED(gm->motion_params.wmmat[1],
res.as_mv.col = (int16_t)ROUND_POWER_OF_TWO_SIGNED(gm->motion_params.wmmat[0],
WARPEDMODEL_PREC_BITS - 3);
return res;
}
static INLINE TransformationType gm_to_trans_type(GLOBAL_MOTION_TYPE gmtype) {
switch (gmtype) {
case GLOBAL_ZERO: return UNKNOWN_TRANSFORM; break;
case GLOBAL_ZERO: return IDENTITY; break;
case GLOBAL_TRANSLATION: return TRANSLATION; break;
case GLOBAL_ROTZOOM: return ROTZOOM; break;
case GLOBAL_AFFINE: return AFFINE; break;
case GLOBAL_AFFINE:
return AFFINE;
break;
// case GLOBAL_HOMOGRAPHY: return HOMOGRAPHY; break;
default: assert(0);
}
return UNKNOWN_TRANSFORM;
}
static INLINE GLOBAL_MOTION_TYPE get_gmtype(const Global_Motion_Params *gm) {
if (!gm->motion_params.wmmat[5] && !gm->motion_params.wmmat[4]) {
if (!gm->motion_params.wmmat[3] && !gm->motion_params.wmmat[2]) {
return ((!gm->motion_params.wmmat[1] && !gm->motion_params.wmmat[0])
? GLOBAL_ZERO
: GLOBAL_TRANSLATION);
} else {
return GLOBAL_ROTZOOM;
}
} else {
return GLOBAL_AFFINE;
// if (gm->motion_params.wmmat[6] != 0 || gm->motion_params.wmmat[7] != 0)
// return GLOBAL_HOMOGRAPHY;
if (gm->motion_params.wmmat[5] == (1 << WARPEDMODEL_PREC_BITS) &&
!gm->motion_params.wmmat[4] &&
gm->motion_params.wmmat[2] == (1 << WARPEDMODEL_PREC_BITS) &&
!gm->motion_params.wmmat[3]) {
return ((!gm->motion_params.wmmat[1] && !gm->motion_params.wmmat[0])
? GLOBAL_ZERO
: GLOBAL_TRANSLATION);
}
if (gm->motion_params.wmmat[2] == gm->motion_params.wmmat[5] &&
gm->motion_params.wmmat[3] == -gm->motion_params.wmmat[4])
return GLOBAL_ROTZOOM;
else
return GLOBAL_AFFINE;
}
static INLINE void set_default_gmparams(Global_Motion_Params *gm) {
static const int32_t default_gm_params[8] = {
0, 0, (1 << WARPEDMODEL_PREC_BITS), 0, 0, (1 << WARPEDMODEL_PREC_BITS), 0, 0
};
memcpy(gm->motion_params.wmmat, default_gm_params,
sizeof(gm->motion_params.wmmat));
gm->gmtype = GLOBAL_ZERO;
gm->motion_params.wmtype = IDENTITY;
}
#endif // CONFIG_GLOBAL_MOTION
......
......@@ -558,7 +558,7 @@ void build_inter_predictors(MACROBLOCKD *xd, int plane,
for (ref = 0; ref < 1 + is_compound; ++ref) {
gm[ref] = &xd->global_motion[mi->mbmi.ref_frame[ref]];
is_global[ref] =
(get_y_mode(mi, block) == ZEROMV && get_gmtype(gm[ref]) > GLOBAL_ZERO);
(get_y_mode(mi, block) == ZEROMV && gm[ref]->gmtype > GLOBAL_ZERO);
}
// TODO(sarahparker) remove these once gm works with all experiments
(void)gm;
......
......@@ -35,18 +35,18 @@ void project_points_translation(int32_t *mat, int *points, int *proj,
const int x = *(points++), y = *(points++);
if (subsampling_x)
*(proj++) = ROUND_POWER_OF_TWO_SIGNED(
((x * (1 << (WARPEDMODEL_PREC_BITS + 1))) + mat[1]),
((x * (1 << (WARPEDMODEL_PREC_BITS + 1))) + mat[0]),
WARPEDDIFF_PREC_BITS + 1);
else
*(proj++) = ROUND_POWER_OF_TWO_SIGNED(
((x * (1 << WARPEDMODEL_PREC_BITS)) + mat[1]), WARPEDDIFF_PREC_BITS);
((x * (1 << WARPEDMODEL_PREC_BITS)) + mat[0]), WARPEDDIFF_PREC_BITS);
if (subsampling_y)
*(proj++) = ROUND_POWER_OF_TWO_SIGNED(
((y * (1 << (WARPEDMODEL_PREC_BITS + 1))) + mat[0]),
((y * (1 << (WARPEDMODEL_PREC_BITS + 1))) + mat[1]),
WARPEDDIFF_PREC_BITS + 1);
else
*(proj++) = ROUND_POWER_OF_TWO_SIGNED(
((y * (1 << WARPEDMODEL_PREC_BITS))) + mat[0], WARPEDDIFF_PREC_BITS);
((y * (1 << WARPEDMODEL_PREC_BITS))) + mat[1], WARPEDDIFF_PREC_BITS);
points += stride_points - 2;
proj += stride_proj - 2;
}
......@@ -60,19 +60,19 @@ void project_points_rotzoom(int32_t *mat, int *points, int *proj, const int n,
const int x = *(points++), y = *(points++);
if (subsampling_x)
*(proj++) = ROUND_POWER_OF_TWO_SIGNED(
mat[3] * 2 * x + mat[2] * 2 * y + mat[1] +
(mat[3] + mat[2] - (1 << WARPEDMODEL_PREC_BITS)) / 2,
mat[2] * 2 * x + mat[3] * 2 * y + mat[0] +
(mat[2] + mat[3] - (1 << WARPEDMODEL_PREC_BITS)) / 2,
WARPEDDIFF_PREC_BITS + 1);
else
*(proj++) = ROUND_POWER_OF_TWO_SIGNED(mat[3] * x + mat[2] * y + mat[1],
*(proj++) = ROUND_POWER_OF_TWO_SIGNED(mat[2] * x + mat[3] * y + mat[0],
WARPEDDIFF_PREC_BITS);
if (subsampling_y)
*(proj++) = ROUND_POWER_OF_TWO_SIGNED(
-mat[2] * 2 * x + mat[3] * 2 * y + mat[0] +
(-mat[2] + mat[3] - (1 << WARPEDMODEL_PREC_BITS)) / 2,
-mat[3] * 2 * x + mat[2] * 2 * y + mat[1] +
(-mat[3] + mat[2] - (1 << WARPEDMODEL_PREC_BITS)) / 2,
WARPEDDIFF_PREC_BITS + 1);
else
*(proj++) = ROUND_POWER_OF_TWO_SIGNED(-mat[2] * x + mat[3] * y + mat[0],
*(proj++) = ROUND_POWER_OF_TWO_SIGNED(-mat[3] * x + mat[2] * y + mat[1],
WARPEDDIFF_PREC_BITS);
points += stride_points - 2;
proj += stride_proj - 2;
......@@ -87,19 +87,19 @@ void project_points_affine(int32_t *mat, int *points, int *proj, const int n,
const int x = *(points++), y = *(points++);
if (subsampling_x)
*(proj++) = ROUND_POWER_OF_TWO_SIGNED(
mat[3] * 2 * x + mat[2] * 2 * y + mat[1] +
(mat[3] + mat[2] - (1 << WARPEDMODEL_PREC_BITS)) / 2,
mat[2] * 2 * x + mat[3] * 2 * y + mat[0] +
(mat[2] + mat[3] - (1 << WARPEDMODEL_PREC_BITS)) / 2,
WARPEDDIFF_PREC_BITS + 1);
else
*(proj++) = ROUND_POWER_OF_TWO_SIGNED(mat[3] * x + mat[2] * y + mat[1],
*(proj++) = ROUND_POWER_OF_TWO_SIGNED(mat[2] * x + mat[3] * y + mat[0],
WARPEDDIFF_PREC_BITS);
if (subsampling_y)
*(proj++) = ROUND_POWER_OF_TWO_SIGNED(
mat[4] * 2 * x + mat[5] * 2 * y + mat[0] +
mat[4] * 2 * x + mat[5] * 2 * y + mat[1] +
(mat[4] + mat[5] - (1 << WARPEDMODEL_PREC_BITS)) / 2,
WARPEDDIFF_PREC_BITS + 1);
else
*(proj++) = ROUND_POWER_OF_TWO_SIGNED(mat[4] * x + mat[5] * y + mat[0],
*(proj++) = ROUND_POWER_OF_TWO_SIGNED(mat[4] * x + mat[5] * y + mat[1],
WARPEDDIFF_PREC_BITS);
points += stride_points - 2;
proj += stride_proj - 2;
......@@ -118,11 +118,11 @@ void project_points_homography(int32_t *mat, int *points, int *proj,
x = (subsampling_x ? 4 * x + 1 : 2 * x);
y = (subsampling_y ? 4 * y + 1 : 2 * y);
Z = (mat[7] * x + mat[6] * y + (1 << (WARPEDMODEL_ROW3HOMO_PREC_BITS + 1)));
xp = (mat[1] * x + mat[0] * y + 2 * mat[3]) *
Z = (mat[6] * x + mat[7] * y + (1 << (WARPEDMODEL_ROW3HOMO_PREC_BITS + 1)));
xp = (mat[2] * x + mat[3] * y + 2 * mat[0]) *
(1 << (WARPEDPIXEL_PREC_BITS + WARPEDMODEL_ROW3HOMO_PREC_BITS -
WARPEDMODEL_PREC_BITS));
yp = (mat[2] * x + mat[5] * y + 2 * mat[4]) *
yp = (mat[4] * x + mat[5] * y + 2 * mat[1]) *
(1 << (WARPEDPIXEL_PREC_BITS + WARPEDMODEL_ROW3HOMO_PREC_BITS -
WARPEDMODEL_PREC_BITS));
......@@ -779,6 +779,7 @@ static int svdcmp(double **u, int m, int n, double w[], double **v) {
break;
}
if (its == max_its - 1) {
aom_free(rv1);
return 1;
}
assert(k > 0);
......@@ -886,10 +887,16 @@ int pseudo_inverse(double *inv, double *matx, const int M, const int N) {
return 1;
}
if (SVD(U, W, V, matx, M, N)) {
aom_free(U);
aom_free(W);
aom_free(V);
return 1;
}
for (i = 0; i < N; i++) {
if (fabs(W[i]) < TINY_NEAR_ZERO) {
aom_free(U);
aom_free(W);
aom_free(V);
return 1;
}
}
......@@ -978,12 +985,13 @@ static void denormalize_affine(double *params, double *T1, double *T2) {
params_denorm[6] = params_denorm[7] = 0;
params_denorm[8] = 1;
denormalize_homography(params_denorm, T1, T2);
params[0] = params_denorm[5];
params[1] = params_denorm[2];
params[2] = params_denorm[1];
params[3] = params_denorm[0];
params[0] = params_denorm[2];
params[1] = params_denorm[5];
params[2] = params_denorm[0];
params[3] = params_denorm[1];
params[4] = params_denorm[3];
params[5] = params_denorm[4];
params[6] = params[7] = 0;
}
static void denormalize_rotzoom(double *params, double *T1, double *T2) {
......@@ -997,10 +1005,13 @@ static void denormalize_rotzoom(double *params, double *T1, double *T2) {
params_denorm[6] = params_denorm[7] = 0;
params_denorm[8] = 1;
denormalize_homography(params_denorm, T1, T2);
params[0] = params_denorm[5];
params[1] = params_denorm[2];
params[2] = params_denorm[1];
params[3] = params_denorm[0];
params[0] = params_denorm[2];
params[1] = params_denorm[5];
params[2] = params_denorm[0];
params[3] = params_denorm[1];
params[4] = -params[3];
params[5] = params[2];
params[6] = params[7] = 0;
}
static void denormalize_translation(double *params, double *T1, double *T2) {
......@@ -1014,8 +1025,11 @@ static void denormalize_translation(double *params, double *T1, double *T2) {
params_denorm[6] = params_denorm[7] = 0;
params_denorm[8] = 1;
denormalize_homography(params_denorm, T1, T2);
params[0] = params_denorm[5];
params[1] = params_denorm[2];
params[0] = params_denorm[2];
params[1] = params_denorm[5];
params[2] = params[5] = 1;
params[3] = params[4] = 0;
params[6] = params[7] = 0;
}
int find_translation(const int np, double *pts1, double *pts2, double *mat) {
......
......@@ -4010,27 +4010,32 @@ static void read_global_motion_params(Global_Motion_Params *params,
aom_prob *probs, aom_reader *r) {
GLOBAL_MOTION_TYPE gmtype =
aom_read_tree(r, av1_global_motion_types_tree, probs, ACCT_STR);
set_default_gmparams(params);
params->gmtype = gmtype;
params->motion_params.wmtype = gm_to_trans_type(gmtype);
switch (gmtype) {
case GLOBAL_ZERO: break;
case GLOBAL_AFFINE:
params->motion_params.wmmat[4] =
(aom_read_primitive_symmetric(r, GM_ABS_ALPHA_BITS) *
GM_ALPHA_DECODE_FACTOR);
params->motion_params.wmmat[5] =
aom_read_primitive_symmetric(r, GM_ABS_ALPHA_BITS) *
GM_ALPHA_DECODE_FACTOR +
(1 << WARPEDMODEL_PREC_BITS);
// fallthrough intended
case GLOBAL_ROTZOOM:
params->motion_params.wmmat[2] =
aom_read_primitive_symmetric(r, GM_ABS_ALPHA_BITS) *
GM_ALPHA_DECODE_FACTOR;
params->motion_params.wmmat[3] =
(aom_read_primitive_symmetric(r, GM_ABS_ALPHA_BITS) *
GM_ALPHA_DECODE_FACTOR) +
(1 << WARPEDMODEL_PREC_BITS);
params->motion_params.wmmat[3] =
aom_read_primitive_symmetric(r, GM_ABS_ALPHA_BITS) *
GM_ALPHA_DECODE_FACTOR;
if (gmtype == GLOBAL_AFFINE) {
params->motion_params.wmmat[4] =
(aom_read_primitive_symmetric(r, GM_ABS_ALPHA_BITS) *
GM_ALPHA_DECODE_FACTOR);
params->motion_params.wmmat[5] =
aom_read_primitive_symmetric(r, GM_ABS_ALPHA_BITS) *
GM_ALPHA_DECODE_FACTOR +
(1 << WARPEDMODEL_PREC_BITS);
} else {
params->motion_params.wmmat[4] = -params->motion_params.wmmat[3];
params->motion_params.wmmat[5] = params->motion_params.wmmat[2];
}
// fallthrough intended
case GLOBAL_TRANSLATION:
params->motion_params.wmmat[0] =
......@@ -4046,18 +4051,17 @@ static void read_global_motion_params(Global_Motion_Params *params,
static void read_global_motion(AV1_COMMON *cm, aom_reader *r) {
int frame;
memset(cm->global_motion, 0, sizeof(cm->global_motion));
for (frame = LAST_FRAME; frame <= ALTREF_FRAME; ++frame) {
read_global_motion_params(&cm->global_motion[frame],
cm->fc->global_motion_types_prob, r);
/*
printf("Dec Ref %d [%d]: %d %d %d %d\n",
frame, cm->current_video_frame,
cm->global_motion[frame].motion_params.wmmat[0].as_mv.row,
cm->global_motion[frame].motion_params.wmmat[0].as_mv.col,
cm->global_motion[frame].motion_params.wmmat[1].as_mv.row,
cm->global_motion[frame].motion_params.wmmat[1].as_mv.col);
*/
printf("Dec Ref %d [%d/%d]: %d %d %d %d\n",
frame, cm->current_video_frame, cm->show_frame,
cm->global_motion[frame].motion_params.wmmat[0],
cm->global_motion[frame].motion_params.wmmat[1],
cm->global_motion[frame].motion_params.wmmat[2],
cm->global_motion[frame].motion_params.wmmat[3]);
*/
}
}
#endif // CONFIG_GLOBAL_MOTION
......
......@@ -3952,28 +3952,29 @@ static void write_uncompressed_header(AV1_COMP *cpi,
#if CONFIG_GLOBAL_MOTION
static void write_global_motion_params(Global_Motion_Params *params,
aom_prob *probs, aom_writer *w) {
GLOBAL_MOTION_TYPE gmtype = get_gmtype(params);
GLOBAL_MOTION_TYPE gmtype = params->gmtype;
av1_write_token(w, av1_global_motion_types_tree, probs,
&global_motion_types_encodings[gmtype]);
switch (gmtype) {
case GLOBAL_ZERO: break;
case GLOBAL_AFFINE:
aom_write_primitive_symmetric(
w, (params->motion_params.wmmat[4] >> GM_ALPHA_PREC_DIFF),
GM_ABS_ALPHA_BITS);
aom_write_primitive_symmetric(
w, (params->motion_params.wmmat[5] >> GM_ALPHA_PREC_DIFF) -
(1 << GM_ALPHA_PREC_BITS),
GM_ABS_ALPHA_BITS);
// fallthrough intended
case GLOBAL_ROTZOOM:
aom_write_primitive_symmetric(
w, (params->motion_params.wmmat[2] >> GM_ALPHA_PREC_DIFF),
w, (params->motion_params.wmmat[2] >> GM_ALPHA_PREC_DIFF) -
(1 << GM_ALPHA_PREC_BITS),
GM_ABS_ALPHA_BITS);
aom_write_primitive_symmetric(
w, (params->motion_params.wmmat[3] >> GM_ALPHA_PREC_DIFF) -
(1 << GM_ALPHA_PREC_BITS),
w, (params->motion_params.wmmat[3] >> GM_ALPHA_PREC_DIFF),
GM_ABS_ALPHA_BITS);
if (gmtype == GLOBAL_AFFINE) {
aom_write_primitive_symmetric(
w, (params->motion_params.wmmat[4] >> GM_ALPHA_PREC_DIFF),
GM_ABS_ALPHA_BITS);
aom_write_primitive_symmetric(
w, (params->motion_params.wmmat[5] >> GM_ALPHA_PREC_DIFF) -
(1 << GM_ALPHA_PREC_BITS),
GM_ABS_ALPHA_BITS);
}
// fallthrough intended
case GLOBAL_TRANSLATION:
aom_write_primitive_symmetric(
......@@ -3992,18 +3993,19 @@ static void write_global_motion(AV1_COMP *cpi, aom_writer *w) {
int frame;
for (frame = LAST_FRAME; frame <= ALTREF_FRAME; ++frame) {
if (!cpi->global_motion_used[frame]) {
memset(&cm->global_motion[frame], 0, sizeof(*cm->global_motion));
set_default_gmparams(&cm->global_motion[frame]);
}
write_global_motion_params(&cm->global_motion[frame],
cm->fc->global_motion_types_prob, w);
/*
printf("Enc Ref %d [%d] (used %d): %d %d %d %d\n",
frame, cm->current_video_frame, cpi->global_motion_used[frame],
cm->global_motion[frame].motion_params.wmmat[0].as_mv.row,
cm->global_motion[frame].motion_params.wmmat[0].as_mv.col,
cm->global_motion[frame].motion_params.wmmat[1].as_mv.row,
cm->global_motion[frame].motion_params.wmmat[1].as_mv.col);
*/
printf("Enc Ref %d [%d/%d] (used %d): %d %d %d %d\n",
frame, cm->current_video_frame, cm->show_frame,
cpi->global_motion_used[frame],
cm->global_motion[frame].motion_params.wmmat[0],
cm->global_motion[frame].motion_params.wmmat[1],
cm->global_motion[frame].motion_params.wmmat[2],
cm->global_motion[frame].motion_params.wmmat[3]);
*/
}
}
#endif
......
......@@ -4612,7 +4612,7 @@ static int input_fpmb_stats(FIRSTPASS_MB_STATS *firstpass_mb_stats,
#endif
#if CONFIG_GLOBAL_MOTION
#define MIN_TRANS_THRESH 8
#define MIN_TRANS_THRESH (1 * GM_TRANS_DECODE_FACTOR)
#define GLOBAL_MOTION_ADVANTAGE_THRESH 0.60
#define GLOBAL_MOTION_MODEL ROTZOOM
......@@ -4621,24 +4621,26 @@ static int input_fpmb_stats(FIRSTPASS_MB_STATS *firstpass_mb_stats,
// zero-centering.
static int32_t add_param_offset(int param_index, int32_t param_value,
int32_t offset) {
const int scale_vals[2] = { GM_ALPHA_PREC_DIFF, GM_TRANS_PREC_DIFF };
const int clamp_vals[2] = { GM_ALPHA_MAX, GM_TRANS_MAX };
const int is_trans_param = param_index < 2;
const int is_one_centered = (!is_trans_param) && (param_index & 1);
const int scale_vals[3] = { GM_TRANS_PREC_DIFF, GM_ALPHA_PREC_DIFF,
GM_ROW3HOMO_PREC_DIFF };
const int clamp_vals[3] = { GM_TRANS_MAX, GM_ALPHA_MAX, GM_ROW3HOMO_MAX };
// type of param: 0 - translation, 1 - affine, 2 - homography
const int param_type = (param_index < 2 ? 0 : (param_index < 6 ? 1 : 2));
const int is_one_centered = (param_index == 2 || param_index == 5);
// Make parameter zero-centered and offset the shift that was done to make
// it compatible with the warped model
param_value = (param_value - (is_one_centered << WARPEDMODEL_PREC_BITS)) >>
scale_vals[is_trans_param];
scale_vals[param_type];
// Add desired offset to the rescaled/zero-centered parameter
param_value += offset;
// Clamp the parameter so it does not overflow the number of bits allotted
// to it in the bitstream
param_value = (int32_t)clamp(param_value, -clamp_vals[is_trans_param],
clamp_vals[is_trans_param]);
param_value = (int32_t)clamp(param_value, -clamp_vals[param_type],
clamp_vals[param_type]);
// Rescale the parameter to WARPEDMODEL_PRECISION_BITS so it is compatible
// with the warped motion library
param_value *= (1 << scale_vals[is_trans_param]);
param_value *= (1 << scale_vals[param_type]);
// Undo the zero-centering step if necessary
return param_value + (is_one_centered << WARPEDMODEL_PREC_BITS);
......@@ -4712,16 +4714,18 @@ static void refine_integerized_param(WarpedMotionParams *wm,
// step is too wide
step >>= 1;
}
*param = best_param;
}
// For rotzoom model enforce the constraints on mat[4] and mat[5]
if (wm->wmtype == ROTZOOM) {
param_mat[5] = param_mat[2];
param_mat[4] = -param_mat[3];
}
}
static void convert_to_params(const double *params, TransformationType type,
int32_t *model) {
int i, diag_value;
static void convert_to_params(const double *params, int32_t *model) {
int i;
int alpha_present = 0;
int n_params = n_trans_model_params[type];
model[0] = (int32_t)floor(params[0] * (1 << GM_TRANS_PREC_BITS) + 0.5);
model[1] = (int32_t)floor(params[1] * (1 << GM_TRANS_PREC_BITS) + 0.5);
model[0] = (int32_t)clamp(model[0], GM_TRANS_MIN, GM_TRANS_MAX) *
......@@ -4729,13 +4733,18 @@ static void convert_to_params(const double *params, TransformationType type,
model[1] = (int32_t)clamp(model[1], GM_TRANS_MIN, GM_TRANS_MAX) *
GM_TRANS_DECODE_FACTOR;
for (i = 2; i < n_params; ++i) {
diag_value = ((i & 1) ? (1 << GM_ALPHA_PREC_BITS) : 0);
for (i = 2; i < 6; ++i) {
const int diag_value = ((i == 2 || i == 5) ? (1 << GM_ALPHA_PREC_BITS) : 0);
model[i] = (int32_t)floor(params[i] * (1 << GM_ALPHA_PREC_BITS) + 0.5);
model[i] =
(int32_t)(clamp(model[i] - diag_value, GM_ALPHA_MIN, GM_ALPHA_MAX) +
diag_value) *
GM_ALPHA_DECODE_FACTOR;
(int32_t)clamp(model[i] - diag_value, GM_ALPHA_MIN, GM_ALPHA_MAX);
alpha_present |= (model[i] != 0);
model[i] = (model[i] + diag_value) * GM_ALPHA_DECODE_FACTOR;
}
for (; i < 8; ++i) {
model[i] = (int32_t)floor(params[i] * (1 << GM_ROW3HOMO_PREC_BITS) + 0.5);
model[i] = (int32_t)clamp(model[i], GM_ROW3HOMO_MIN, GM_ROW3HOMO_MAX) *
GM_ROW3HOMO_DECODE_FACTOR;
alpha_present |= (model[i] != 0);
}
......@@ -4748,11 +4757,8 @@ static void convert_to_params(const double *params, TransformationType type,
}
static void convert_model_to_params(const double *params,
TransformationType type,
Global_Motion_Params *model) {
// TODO(sarahparker) implement for homography
if (type > HOMOGRAPHY)
convert_to_params(params, type, model->motion_params.wmmat);
convert_to_params(params, model->motion_params.wmmat);
model->gmtype = get_gmtype(model);
model->motion_params.wmtype = gm_to_trans_type(model->gmtype);
}
......@@ -4782,19 +4788,21 @@ static void encode_frame_internal(AV1_COMP *cpi) {
#if CONFIG_GLOBAL_MOTION
aom_clear_system_state();
av1_zero(cpi->global_motion_used);
for (i = LAST_FRAME; i <= ALTREF_FRAME; ++i) {
set_default_gmparams(&cm->global_motion[i]);
}
if (cpi->common.frame_type == INTER_FRAME && cpi->Source) {
YV12_BUFFER_CONFIG *ref_buf;
int frame;
double erroradvantage = 0;
double params[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
double params[8] = { 0, 0, 1, 0, 0, 1, 0, 0 };
for (frame = LAST_FRAME; frame <= ALTREF_FRAME; ++frame) {
ref_buf = get_ref_frame_buffer(cpi, frame);
if (ref_buf) {
if (compute_global_motion_feature_based(GLOBAL_MOTION_MODEL,
cpi->Source, ref_buf, params)) {
convert_model_to_params(params, GLOBAL_MOTION_MODEL,
&cm->global_motion[frame]);
if (get_gmtype(&cm->global_motion[frame]) > GLOBAL_ZERO) {
convert_model_to_params(params, &cm->global_motion[frame]);
if (cm->global_motion[frame].gmtype > GLOBAL_ZERO) {
refine_integerized_param(
&cm->global_motion[frame].motion_params,
#if CONFIG_AOM_HIGHBITDEPTH
......@@ -4814,9 +4822,8 @@ static void encode_frame_internal(AV1_COMP *cpi) {
cpi->Source->y_width, cpi->Source->y_height,
cpi->Source->y_stride, 0, 0, 16, 16);
if (erroradvantage > GLOBAL_MOTION_ADVANTAGE_THRESH)
// Not enough advantage in using a global model. Make 0.
memset(&cm->global_motion[frame], 0,
sizeof(cm->global_motion[frame]));
// Not enough advantage in using a global model. Make identity.
set_default_gmparams(&cm->global_motion[frame]);
}
}
}
......
......@@ -41,8 +41,8 @@ static void project_points_double_translation(double *mat, double *points,
int i;
for (i = 0; i < n; ++i) {
const double x = *(points++), y = *(points++);
*(proj++) = x + mat[1];
*(proj++) = y + mat[0];
*(proj++) = x + mat[0];
*(proj++) = y + mat[1];
points += stride_points - 2;
proj += stride_proj - 2;
}
......@@ -55,8 +55,8 @@ static void project_points_double_rotzoom(double *mat, double *points,
int i;
for (i = 0; i < n; ++i) {
const double x = *(points++), y = *(points++);
*(proj++) = mat[3] * x + mat[2] * y + mat[1];
*(proj++) = -mat[2] * x + mat[3] * y + mat[0];
*(proj++) = mat[2] * x + mat[3] * y + mat[0];
*(proj++) = -mat[3] * x + mat[2] * y + mat[1];
points += stride_points - 2;
proj += stride_proj - 2;
}
......@@ -69,8 +69,8 @@ static void project_points_double_affine(double *mat, double *points,
int i;
for (i = 0; i < n; ++i) {
const double x = *(points++), y = *(points++);
*(proj++) = mat[3] * x + mat[2] * y + mat[1];
*(proj++) = mat[4] * x + mat[5] * y + mat[0];
*(proj++) = mat[2] * x + mat[3] * y + mat[0];
*(proj++) = mat[4] * x + mat[5] * y + mat[1];
points += stride_points - 2;
proj += stride_proj - 2;
}
......@@ -84,11 +84,11 @@ static void project_points_double_homography(double *mat, double *points,
double x, y, Z, Z_inv;
for (i = 0; i < n; ++i) {
x = *(points++), y = *(points++);
Z_inv = mat[7] * x + mat[6] * y + 1;
assert(fabs(Z_inv) > 0.00001);
Z_inv = mat[6] * x + mat[7] * y + 1;
assert(fabs(Z_inv) > 0.000001);
Z = 1. / Z_inv;
*(proj++) = (mat[1] * x + mat[0] * y + mat[3]) * Z;
*(proj++) = (mat[2] * x + mat[4] * y + mat[4]) * Z;
*(proj++) = (mat[0] * x + mat[1] * y + mat[2]) * Z;
*(proj++) = (mat[3] * x + mat[4] * y + mat[5]) * Z;
points += stride_points - 2;
proj += stride_proj - 2;
}
......@@ -273,7 +273,7 @@ static int ransac(double *matched_points, int npoints, int *number_of_inliers,
pNoOutliers = 1 - pow(fracinliers, minpts);
pNoOutliers = fmax(EPS, pNoOutliers);
pNoOutliers = fmin(1 - EPS, pNoOutliers);
assert(fabs(1.0 - pNoOutliers) > 0.00001);
// assert(fabs(1.0 - pNoOutliers) > 0.00001);
temp = (int)(log(1.0 - PROBABILITY_REQUIRED) / log(pNoOutliers));
if (temp > 0 && temp < N) {
N = AOMMAX(temp, MIN_TRIALS);
......@@ -360,10 +360,18 @@ int ransac_homography(double *matched_points, int npoints,
if (!result) {
// normalize so that H33 = 1
int i;