Add global motion experiment to rdopt
This patch completes the global motion experiment
implementation. It modifies the format of the motion
parameters to use the mv union to facilitate faster
copying and checks for parameters equal to 0 that occur
frequently in rdopt. The rd decisions for the global motion experiment
have also been added to rdopt.
Change-Id: Idfb9f0c6d23e538221763881099c5a2a3891f5a9
diff --git a/av1/common/mv.h b/av1/common/mv.h
index 4908d74..fe08e9d 100644
--- a/av1/common/mv.h
+++ b/av1/common/mv.h
@@ -13,9 +13,6 @@
#include "av1/common/common.h"
#include "aom_dsp/aom_filter.h"
-#if CONFIG_GLOBAL_MOTION
-#include "av1/common/warped_motion.h"
-#endif // CONFIG_GLOBAL_MOTION
#ifdef __cplusplus
extern "C" {
@@ -36,6 +33,41 @@
int32_t col;
} MV32;
+#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
+// Bits of precision used for the model
+#define WARPEDMODEL_PREC_BITS 8
+#define WARPEDMODEL_ROW3HOMO_PREC_BITS 12
+
+// Bits of subpel precision for warped interpolation
+#define WARPEDPIXEL_PREC_BITS 6
+#define WARPEDPIXEL_PREC_SHIFTS (1 << WARPEDPIXEL_PREC_BITS)
+
+// Taps for ntap filter
+#define WARPEDPIXEL_FILTER_TAPS 6
+
+// Precision of filter taps
+#define WARPEDPIXEL_FILTER_BITS 7
+
+#define WARPEDDIFF_PREC_BITS (WARPEDMODEL_PREC_BITS - WARPEDPIXEL_PREC_BITS)
+
+typedef enum {
+ UNKNOWN_TRANSFORM = -1,
+ HOMOGRAPHY, // homography, 8-parameter
+ AFFINE, // affine, 6-parameter
+ ROTZOOM, // simplified affine with rotation and zoom only, 4-parameter
+ TRANSLATION, // translational motion 2-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 };
+
+typedef struct {
+ TransformationType wmtype;
+ int_mv wmmat[4]; // For homography wmmat[9] is assumed to be 1
+} WarpedMotionParams;
+#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
+
#if CONFIG_GLOBAL_MOTION
// ALPHA here refers to parameters a and b in rotzoom model:
// | a b|
@@ -61,16 +93,16 @@
//
// XX_MIN, XX_MAX are also computed to avoid repeated computation
-#define GM_TRANS_PREC_BITS 5
+#define GM_TRANS_PREC_BITS 8
#define GM_TRANS_PREC_DIFF (WARPEDMODEL_PREC_BITS - GM_TRANS_PREC_BITS)
#define GM_TRANS_DECODE_FACTOR (1 << GM_TRANS_PREC_DIFF)
-#define GM_ALPHA_PREC_BITS 5
+#define GM_ALPHA_PREC_BITS 8
#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 8
-#define GM_ABS_TRANS_BITS 8
+#define GM_ABS_ALPHA_BITS 18
+#define GM_ABS_TRANS_BITS 18
#define GM_TRANS_MAX (1 << GM_ABS_TRANS_BITS)
#define GM_ALPHA_MAX (1 << GM_ABS_ALPHA_BITS)
@@ -102,11 +134,10 @@
}
static INLINE GLOBAL_MOTION_TYPE get_gmtype(const Global_Motion_Params *gm) {
- if (gm->motion_params.wmmat[4] == 0 && gm->motion_params.wmmat[5] == 0) {
- if (gm->motion_params.wmmat[2] == 0 && gm->motion_params.wmmat[3] == 0) {
- return ((gm->motion_params.wmmat[0] | gm->motion_params.wmmat[1])
- ? GLOBAL_TRANSLATION
- : GLOBAL_ZERO);
+ if (!gm->motion_params.wmmat[2].as_int) {
+ if (!gm->motion_params.wmmat[1].as_int) {
+ return (gm->motion_params.wmmat[0].as_int ? GLOBAL_TRANSLATION
+ : GLOBAL_ZERO);
} else {
return GLOBAL_ROTZOOM;
}
diff --git a/av1/common/warped_motion.c b/av1/common/warped_motion.c
index c742c36..2ff1fce 100644
--- a/av1/common/warped_motion.c
+++ b/av1/common/warped_motion.c
@@ -26,7 +26,7 @@
}
}
-void projectPointsTranslation(int *mat, int *points, int *proj, const int n,
+void projectPointsTranslation(int16_t *mat, int *points, int *proj, const int n,
const int stride_points, const int stride_proj,
const int subsampling_x,
const int subsampling_y) {
@@ -35,24 +35,24 @@
const int x = *(points++), y = *(points++);
if (subsampling_x)
*(proj++) = ROUND_POWER_OF_TWO_SIGNED(
- ((x << (WARPEDMODEL_PREC_BITS + 1)) + mat[0]),
+ ((x << (WARPEDMODEL_PREC_BITS + 1)) + mat[1]),
WARPEDDIFF_PREC_BITS + 1);
else
*(proj++) = ROUND_POWER_OF_TWO_SIGNED(
- ((x << WARPEDMODEL_PREC_BITS)) + mat[0], WARPEDDIFF_PREC_BITS);
+ ((x << WARPEDMODEL_PREC_BITS) + mat[1]), WARPEDDIFF_PREC_BITS);
if (subsampling_y)
*(proj++) = ROUND_POWER_OF_TWO_SIGNED(
- ((y << (WARPEDMODEL_PREC_BITS + 1)) + mat[1]),
+ ((y << (WARPEDMODEL_PREC_BITS + 1)) + mat[0]),
WARPEDDIFF_PREC_BITS + 1);
else
*(proj++) = ROUND_POWER_OF_TWO_SIGNED(
- ((y << WARPEDMODEL_PREC_BITS)) + mat[1], WARPEDDIFF_PREC_BITS);
+ ((y << WARPEDMODEL_PREC_BITS)) + mat[0], WARPEDDIFF_PREC_BITS);
points += stride_points - 2;
proj += stride_proj - 2;
}
}
-void projectPointsRotZoom(int *mat, int *points, int *proj, const int n,
+void projectPointsRotZoom(int16_t *mat, int *points, int *proj, const int n,
const int stride_points, const int stride_proj,
const int subsampling_x, const int subsampling_y) {
int i;
@@ -60,26 +60,26 @@
const int x = *(points++), y = *(points++);
if (subsampling_x)
*(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);
if (subsampling_y)
*(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);
points += stride_points - 2;
proj += stride_proj - 2;
}
}
-void projectPointsAffine(int *mat, int *points, int *proj, const int n,
+void projectPointsAffine(int16_t *mat, int *points, int *proj, const int n,
const int stride_points, const int stride_proj,
const int subsampling_x, const int subsampling_y) {
int i;
@@ -87,26 +87,26 @@
const int x = *(points++), y = *(points++);
if (subsampling_x)
*(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);
if (subsampling_y)
*(proj++) = ROUND_POWER_OF_TWO_SIGNED(
- mat[4] * 2 * x + mat[5] * 2 * y + mat[1] +
- (mat[4] + mat[5] - (1 << WARPEDMODEL_PREC_BITS)) / 2,
+ mat[5] * 2 * x + mat[4] * 2 * y + mat[0] +
+ (mat[5] + mat[4] - (1 << WARPEDMODEL_PREC_BITS)) / 2,
WARPEDDIFF_PREC_BITS + 1);
else
- *(proj++) = ROUND_POWER_OF_TWO_SIGNED(mat[4] * x + mat[5] * y + mat[1],
+ *(proj++) = ROUND_POWER_OF_TWO_SIGNED(mat[5] * x + mat[4] * y + mat[0],
WARPEDDIFF_PREC_BITS);
points += stride_points - 2;
proj += stride_proj - 2;
}
}
-void projectPointsHomography(int *mat, int *points, int *proj, const int n,
+void projectPointsHomography(int16_t *mat, int *points, int *proj, const int n,
const int stride_points, const int stride_proj,
const int subsampling_x, const int subsampling_y) {
int i;
@@ -117,11 +117,11 @@
x = (subsampling_x ? 4 * x + 1 : 2 * x);
y = (subsampling_y ? 4 * y + 1 : 2 * y);
- Z = (mat[6] * x + mat[7] * y + (1 << (WARPEDMODEL_ROW3HOMO_PREC_BITS + 1)));
- xp = (mat[0] * x + mat[1] * y + 2 * mat[2])
+ Z = (mat[7] * x + mat[6] * y + (1 << (WARPEDMODEL_ROW3HOMO_PREC_BITS + 1)));
+ xp = (mat[1] * x + mat[0] * y + 2 * mat[3])
<< (WARPEDPIXEL_PREC_BITS + WARPEDMODEL_ROW3HOMO_PREC_BITS -
WARPEDMODEL_PREC_BITS);
- yp = (mat[3] * x + mat[4] * y + 2 * mat[5])
+ yp = (mat[2] * x + mat[5] * y + 2 * mat[4])
<< (WARPEDPIXEL_PREC_BITS + WARPEDMODEL_ROW3HOMO_PREC_BITS -
WARPEDMODEL_PREC_BITS);
@@ -483,7 +483,8 @@
int in[2], out[2];
in[0] = j;
in[1] = i;
- projectpoints(wm->wmmat, in, out, 1, 2, 2, subsampling_x, subsampling_y);
+ projectpoints((int16_t *)wm->wmmat, in, out, 1, 2, 2, subsampling_x,
+ subsampling_y);
out[0] = ROUND_POWER_OF_TWO_SIGNED(out[0] * x_scale, 4);
out[1] = ROUND_POWER_OF_TWO_SIGNED(out[1] * y_scale, 4);
gm_err = dst[(j - p_col) + (i - p_row) * p_stride] -
@@ -514,7 +515,8 @@
int in[2], out[2];
in[0] = j;
in[1] = i;
- projectpoints(wm->wmmat, in, out, 1, 2, 2, subsampling_x, subsampling_y);
+ projectpoints((int16_t *)wm->wmmat, in, out, 1, 2, 2, subsampling_x,
+ subsampling_y);
out[0] = ROUND_POWER_OF_TWO_SIGNED(out[0] * x_scale, 4);
out[1] = ROUND_POWER_OF_TWO_SIGNED(out[1] * y_scale, 4);
pred[(j - p_col) + (i - p_row) * p_stride] = highbd_warp_interpolate(
@@ -538,7 +540,8 @@
int in[2], out[2];
in[0] = j;
in[1] = i;
- projectpoints(wm->wmmat, in, out, 1, 2, 2, subsampling_x, subsampling_y);
+ projectpoints((int16_t *)wm->wmmat, in, out, 1, 2, 2, subsampling_x,
+ subsampling_y);
out[0] = ROUND_POWER_OF_TWO_SIGNED(out[0] * x_scale, 4);
out[1] = ROUND_POWER_OF_TWO_SIGNED(out[1] * y_scale, 4);
gm_err = dst[(j - p_col) + (i - p_row) * p_stride] -
@@ -565,7 +568,8 @@
int in[2], out[2];
in[0] = j;
in[1] = i;
- projectpoints(wm->wmmat, in, out, 1, 2, 2, subsampling_x, subsampling_y);
+ projectpoints((int16_t *)wm->wmmat, in, out, 1, 2, 2, subsampling_x,
+ subsampling_y);
out[0] = ROUND_POWER_OF_TWO_SIGNED(out[0] * x_scale, 4);
out[1] = ROUND_POWER_OF_TWO_SIGNED(out[1] * y_scale, 4);
pred[(j - p_col) + (i - p_row) * p_stride] =
@@ -620,22 +624,28 @@
switch (wmtype) {
case HOMOGRAPHY:
assert(fabs(model[8] - 1.0) < 1e-12);
- wm->wmmat[7] =
- (int)lrint(model[7] * (1 << WARPEDMODEL_ROW3HOMO_PREC_BITS));
- wm->wmmat[6] =
- (int)lrint(model[6] * (1 << WARPEDMODEL_ROW3HOMO_PREC_BITS));
+ wm->wmmat[3].as_mv.row =
+ (int16_t)lrint(model[6] * (1 << WARPEDMODEL_ROW3HOMO_PREC_BITS));
+ wm->wmmat[3].as_mv.col =
+ (int16_t)lrint(model[7] * (1 << WARPEDMODEL_ROW3HOMO_PREC_BITS));
/* fallthrough intended */
case AFFINE:
- wm->wmmat[5] = (int)lrint(model[5] * (1 << WARPEDMODEL_PREC_BITS));
- wm->wmmat[4] = (int)lrint(model[4] * (1 << WARPEDMODEL_PREC_BITS));
+ wm->wmmat[2].as_mv.row =
+ (int16_t)lrint(model[4] * (1 << WARPEDMODEL_PREC_BITS));
+ wm->wmmat[2].as_mv.col =
+ (int16_t)lrint(model[5] * (1 << WARPEDMODEL_PREC_BITS));
/* fallthrough intended */
case ROTZOOM:
- wm->wmmat[3] = (int)lrint(model[3] * (1 << WARPEDMODEL_PREC_BITS));
- wm->wmmat[2] = (int)lrint(model[2] * (1 << WARPEDMODEL_PREC_BITS));
+ wm->wmmat[1].as_mv.row =
+ (int16_t)lrint(model[2] * (1 << WARPEDMODEL_PREC_BITS));
+ wm->wmmat[1].as_mv.col =
+ (int16_t)lrint(model[3] * (1 << WARPEDMODEL_PREC_BITS));
/* fallthrough intended */
case TRANSLATION:
- wm->wmmat[1] = (int)lrint(model[1] * (1 << WARPEDMODEL_PREC_BITS));
- wm->wmmat[0] = (int)lrint(model[0] * (1 << WARPEDMODEL_PREC_BITS));
+ wm->wmmat[0].as_mv.row =
+ (int16_t)lrint(model[0] * (1 << WARPEDMODEL_PREC_BITS));
+ wm->wmmat[0].as_mv.col =
+ (int16_t)lrint(model[1] * (1 << WARPEDMODEL_PREC_BITS));
break;
default: assert(0 && "Invalid TransformationType");
}
diff --git a/av1/common/warped_motion.h b/av1/common/warped_motion.h
index 965b296..d957401 100644
--- a/av1/common/warped_motion.h
+++ b/av1/common/warped_motion.h
@@ -20,6 +20,7 @@
#include "./aom_config.h"
#include "aom_ports/mem.h"
#include "aom_dsp/aom_dsp_common.h"
+#include "av1/common/mv.h"
// Bits of precision used for the model
#define WARPEDMODEL_PREC_BITS 8
@@ -37,49 +38,36 @@
#define WARPEDDIFF_PREC_BITS (WARPEDMODEL_PREC_BITS - WARPEDPIXEL_PREC_BITS)
-typedef void (*ProjectPointsType)(int *mat, int *points, int *proj, const int n,
- const int stride_points,
+typedef void (*ProjectPointsType)(int16_t *mat, int *points, int *proj,
+ const int n, const int stride_points,
const int stride_proj,
const int subsampling_x,
const int subsampling_y);
-void projectPointsHomography(int *mat, int *points, int *proj, const int n,
+
+void projectPointsHomography(int16_t *mat, int *points, int *proj, const int n,
const int stride_points, const int stride_proj,
const int subsampling_x, const int subsampling_y);
-void projectPointsAffine(int *mat, int *points, int *proj, const int n,
+
+void projectPointsAffine(int16_t *mat, int *points, int *proj, const int n,
const int stride_points, const int stride_proj,
const int subsampling_x, const int subsampling_y);
-void projectPointsRotZoom(int *mat, int *points, int *proj, const int n,
+
+void projectPointsRotZoom(int16_t *mat, int *points, int *proj, const int n,
const int stride_points, const int stride_proj,
const int subsampling_x, const int subsampling_y);
-void projectPointsTranslation(int *mat, int *points, int *proj, const int n,
+
+void projectPointsTranslation(int16_t *mat, int *points, int *proj, const int n,
const int stride_points, const int stride_proj,
const int subsampling_x, const int subsampling_y);
-typedef enum {
- UNKNOWN_TRANSFORM = -1,
- HOMOGRAPHY, // homography, 8-parameter
- AFFINE, // affine, 6-parameter
- ROTZOOM, // simplified affine with rotation and zoom only, 4-parameter
- TRANSLATION, // translational motion 2-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 };
-
-typedef struct {
- TransformationType wmtype;
- int wmmat[8]; // For homography wmmat[9] is assumed to be 1
-} WarpedMotionParams;
-
double av1_warp_erroradv(WarpedMotionParams *wm,
-#if CONFIG_AOM_HIGHBITDEPTH
- int use_hbd, int bd,
-#endif // CONFIG_AOM_HIGHBITDEPTH
- uint8_t *ref, int width, int height, int stride,
- uint8_t *dst, int p_col, int p_row, int p_width,
- int p_height, int p_stride, int subsampling_x,
- int subsampling_y, int x_scale, int y_scale);
+#if CONFIG_VP9_HIGHBITDEPTH
+ int use_hbd, int bd,
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ uint8_t *ref, int width, int height, int stride,
+ uint8_t *dst, int p_col, int p_row, int p_width,
+ int p_height, int p_stride, int subsampling_x,
+ int subsampling_y, int x_scale, int y_scale);
void av1_warp_plane(WarpedMotionParams *wm,
#if CONFIG_AOM_HIGHBITDEPTH