#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" {
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|
//
// 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)
}
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;
}
}
}
-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) {
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;
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;
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;
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);
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] -
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(
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] -
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] =
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");
}
#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
#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
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] =
+ params->motion_params.wmmat[2].as_mv.row =
aom_read_primitive_symmetric(r, GM_ABS_ALPHA_BITS) *
GM_ALPHA_DECODE_FACTOR +
(1 << WARPEDMODEL_PREC_BITS);
+ params->motion_params.wmmat[2].as_mv.col =
+ (aom_read_primitive_symmetric(r, GM_ABS_ALPHA_BITS) *
+ GM_ALPHA_DECODE_FACTOR);
// fallthrough intended
case GLOBAL_ROTZOOM:
- params->motion_params.wmmat[2] =
+ params->motion_params.wmmat[1].as_mv.row =
+ aom_read_primitive_symmetric(r, GM_ABS_ALPHA_BITS) *
+ GM_ALPHA_DECODE_FACTOR;
+ params->motion_params.wmmat[1].as_mv.col =
(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;
// fallthrough intended
case GLOBAL_TRANSLATION:
- params->motion_params.wmmat[0] =
+ params->motion_params.wmmat[0].as_mv.row =
aom_read_primitive_symmetric(r, GM_ABS_TRANS_BITS) *
GM_TRANS_DECODE_FACTOR;
- params->motion_params.wmmat[1] =
+ params->motion_params.wmmat[0].as_mv.col =
aom_read_primitive_symmetric(r, GM_ABS_TRANS_BITS) *
GM_TRANS_DECODE_FACTOR;
break;
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);
+ */
}
}
#endif // CONFIG_GLOBAL_MOTION
static INLINE int assign_mv(AV1_COMMON *cm, MACROBLOCKD *xd,
PREDICTION_MODE mode,
+ MV_REFERENCE_FRAME ref_frame[2],
#if CONFIG_REF_MV
int block,
#endif
int_mv *pred_mv =
(bsize >= BLOCK_8X8) ? mbmi->pred_mv : xd->mi[0]->bmi[block].pred_mv_s8;
#endif
+ (void)ref_frame;
switch (mode) {
#if CONFIG_EXT_INTER
break;
}
case ZEROMV: {
+#if CONFIG_GLOBAL_MOTION
+ mv[0].as_int =
+ cm->global_motion[ref_frame[0]].motion_params.wmmat[0].as_int;
+ if (is_compound)
+ mv[1].as_int =
+ cm->global_motion[ref_frame[1]].motion_params.wmmat[0].as_int;
+#else
mv[0].as_int = 0;
if (is_compound) mv[1].as_int = 0;
+#endif // CONFIG_GLOBAL_MOTION
#if CONFIG_REF_MV
pred_mv[0].as_int = 0;
(void)ref_mv_s8;
#endif
- if (!assign_mv(cm, xd, b_mode,
+ if (!assign_mv(cm, xd, b_mode, mbmi->ref_frame,
#if CONFIG_REF_MV
j,
#endif
}
xd->corrupted |=
- !assign_mv(cm, xd, mbmi->mode,
+ !assign_mv(cm, xd, mbmi->mode, mbmi->ref_frame,
#if CONFIG_REF_MV
0,
#endif
switch (gmtype) {
case GLOBAL_ZERO: break;
case GLOBAL_AFFINE:
- av1_write_primitive_symmetric(
- w, params->motion_params.wmmat[4] >> GM_ALPHA_PREC_DIFF,
- GM_ABS_ALPHA_BITS);
- av1_write_primitive_symmetric(
- w, (params->motion_params.wmmat[5] >> GM_ALPHA_PREC_DIFF) -
+ aom_write_primitive_symmetric(
+ w, (params->motion_params.wmmat[2].as_mv.row >> GM_ALPHA_PREC_DIFF) -
(1 << GM_ALPHA_PREC_BITS),
GM_ABS_ALPHA_BITS);
+ aom_write_primitive_symmetric(
+ w, (params->motion_params.wmmat[2].as_mv.col >> GM_ALPHA_PREC_DIFF),
+ GM_ABS_ALPHA_BITS);
// fallthrough intended
case GLOBAL_ROTZOOM:
aom_write_primitive_symmetric(
- w, (params->motion_params.wmmat[2] >> GM_ALPHA_PREC_DIFF) -
- (1 << GM_ALPHA_PREC_BITS),
+ w, (params->motion_params.wmmat[1].as_mv.row >> GM_ALPHA_PREC_DIFF),
GM_ABS_ALPHA_BITS);
aom_write_primitive_symmetric(
- w, params->motion_params.wmmat[3] >> GM_ALPHA_PREC_DIFF,
+ w, (params->motion_params.wmmat[1].as_mv.col >> GM_ALPHA_PREC_DIFF) -
+ (1 << GM_ALPHA_PREC_BITS),
GM_ABS_ALPHA_BITS);
// fallthrough intended
case GLOBAL_TRANSLATION:
aom_write_primitive_symmetric(
- w, params->motion_params.wmmat[0] >> GM_TRANS_PREC_DIFF,
+ w, (params->motion_params.wmmat[0].as_mv.row >> GM_TRANS_PREC_DIFF),
GM_ABS_TRANS_BITS);
aom_write_primitive_symmetric(
- w, params->motion_params.wmmat[1] >> GM_TRANS_PREC_DIFF,
+ w, (params->motion_params.wmmat[0].as_mv.col >> GM_TRANS_PREC_DIFF),
GM_ABS_TRANS_BITS);
break;
default: assert(0);
}
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);
+ */
}
}
#endif
#include "av1/encoder/cost.h"
#endif
#if CONFIG_GLOBAL_MOTION
+#include "av1/common/warped_motion.h"
#include "av1/encoder/global_motion.h"
#endif
#include "av1/encoder/encodeframe.h"
#if CONFIG_GLOBAL_MOTION
#define MIN_TRANS_THRESH 8
#define GLOBAL_MOTION_ADVANTAGE_THRESH 0.60
-#define GLOBAL_MOTION_MODEL ROTZOOM
+#define GLOBAL_MOTION_MODEL TRANSLATION
static void convert_to_params(double *H, TransformationType type,
- Global_Motion_Params *model) {
+ int16_t *model) {
int i;
int alpha_present = 0;
int n_params = n_trans_model_params[type];
- model->motion_params.wmmat[0] =
- (int)floor(H[0] * (1 << GM_TRANS_PREC_BITS) + 0.5);
- model->motion_params.wmmat[1] =
- (int)floor(H[1] * (1 << GM_TRANS_PREC_BITS) + 0.5);
- model->motion_params.wmmat[0] =
- clamp(model->motion_params.wmmat[0], GM_TRANS_MIN, GM_TRANS_MAX) *
- GM_TRANS_DECODE_FACTOR;
- model->motion_params.wmmat[1] =
- clamp(model->motion_params.wmmat[1], GM_TRANS_MIN, GM_TRANS_MAX) *
- GM_TRANS_DECODE_FACTOR;
+ model[0] = (int16_t)floor(H[0] * (1 << GM_TRANS_PREC_BITS) + 0.5);
+ model[1] = (int16_t)floor(H[1] * (1 << GM_TRANS_PREC_BITS) + 0.5);
+ model[0] = (int16_t)clamp(model[0], GM_TRANS_MIN, GM_TRANS_MAX) *
+ GM_TRANS_DECODE_FACTOR;
+ model[1] = (int16_t)clamp(model[1], GM_TRANS_MIN, GM_TRANS_MAX) *
+ GM_TRANS_DECODE_FACTOR;
for (i = 2; i < n_params; ++i) {
- model->motion_params.wmmat[i] =
- (int)floor(H[i] * (1 << GM_ALPHA_PREC_BITS) + 0.5);
- model->motion_params.wmmat[i] =
- clamp(model->motion_params.wmmat[i], GM_ALPHA_MIN, GM_ALPHA_MAX) *
- GM_ALPHA_DECODE_FACTOR;
- alpha_present |= (model->motion_params.wmmat[i] != 0);
+ model[i] = (int16_t)floor(H[i] * (1 << GM_ALPHA_PREC_BITS) + 0.5);
+ model[i] = (int16_t)clamp(model[i], GM_ALPHA_MIN, GM_ALPHA_MAX) *
+ GM_ALPHA_DECODE_FACTOR;
+ alpha_present |= (model[i] != 0);
}
if (!alpha_present) {
- if (abs(model->motion_params.wmmat[0]) < MIN_TRANS_THRESH &&
- abs(model->motion_params.wmmat[1]) < MIN_TRANS_THRESH) {
- model->motion_params.wmmat[0] = 0;
- model->motion_params.wmmat[1] = 0;
+ if (abs(model[0]) < MIN_TRANS_THRESH && abs(model[1]) < MIN_TRANS_THRESH) {
+ model[0] = 0;
+ model[1] = 0;
}
}
}
static void convert_model_to_params(double *H, TransformationType type,
Global_Motion_Params *model) {
// TODO(sarahparker) implement for homography
- if (type > HOMOGRAPHY) convert_to_params(H, type, model);
+ if (type > HOMOGRAPHY)
+ convert_to_params(H, type, (int16_t *)model->motion_params.wmmat);
model->gmtype = get_gmtype(model);
model->motion_params.wmtype = gm_to_trans_type(model->gmtype);
}
}
av1_integerize_model(H, type, &wm);
- projectpoints(wm.wmmat, corners1_int, image1_coord, npoints, 2, 2, 0, 0);
+ projectpoints((int16_t *)wm.wmmat, corners1_int, image1_coord, npoints, 2,
+ 2, 0, 0);
for (i = 0; i < npoints; ++i) {
double dx =
Ha[6] = Ha[7] = 0;
Ha[8] = 1;
denormalizeHomography(Ha, T1, T2);
- H[0] = Ha[2];
- H[1] = Ha[5];
- H[2] = Ha[0];
- H[3] = Ha[1];
- H[4] = Ha[3];
- H[5] = Ha[4];
+ H[0] = Ha[5];
+ H[1] = Ha[2];
+ H[2] = Ha[1];
+ H[3] = Ha[0];
+ H[4] = Ha[4];
+ H[5] = Ha[3];
}
static void denormalizeRotZoom(double *H, double *T1, double *T2) {
Ha[6] = Ha[7] = 0;
Ha[8] = 1;
denormalizeHomography(Ha, T1, T2);
- H[0] = Ha[2];
- H[1] = Ha[5];
- H[2] = Ha[0];
- H[3] = Ha[1];
+ H[0] = Ha[5];
+ H[1] = Ha[2];
+ H[2] = Ha[1];
+ H[3] = Ha[0];
}
static void denormalizeTranslation(double *H, double *T1, double *T2) {
Ha[6] = Ha[7] = 0;
Ha[8] = 1;
denormalizeHomography(Ha, T1, T2);
- H[0] = Ha[2];
- H[1] = Ha[5];
+ H[0] = Ha[5];
+ H[1] = Ha[2];
}
static int is_collinear3(double *p1, double *p2, double *p3) {
#endif
}
+#if CONFIG_GLOBAL_MOTION
+static int get_gmbitcost(const Global_Motion_Params *gm,
+ const aom_prob *probs) {
+ int gmtype_cost[GLOBAL_MOTION_TYPES];
+ int bits;
+ av1_cost_tokens(gmtype_cost, probs, av1_global_motion_types_tree);
+ if (gm->motion_params.wmmat[2].as_int) {
+ bits = (GM_ABS_TRANS_BITS + 1) * 2 + 4 * GM_ABS_ALPHA_BITS + 4;
+ } else if (gm->motion_params.wmmat[1].as_int) {
+ bits = (GM_ABS_TRANS_BITS + 1) * 2 + 2 * GM_ABS_ALPHA_BITS + 2;
+ } else {
+ bits =
+ (gm->motion_params.wmmat[0].as_int ? ((GM_ABS_TRANS_BITS + 1) * 2) : 0);
+ }
+ return (bits << AV1_PROB_COST_SHIFT) + gmtype_cost[gm->gmtype];
+}
+
+#define GLOBAL_MOTION_RATE(ref) \
+ (cpi->global_motion_used[ref] >= 2 \
+ ? 0 \
+ : get_gmbitcost(&cm->global_motion[(ref)], \
+ cm->fc->global_motion_types_prob) / \
+ 2);
+#endif // CONFIG_GLOBAL_MOTION
+
static int set_and_cost_bmi_mvs(
AV1_COMP *cpi, MACROBLOCK *x, MACROBLOCKD *xd, int i, PREDICTION_MODE mode,
int_mv this_mv[2], int_mv frame_mv[MB_MODE_COUNT][TOTAL_REFS_PER_FRAME],
int_mv compound_seg_newmvs[2],
#endif // CONFIG_EXT_INTER
int_mv *best_ref_mv[2], const int *mvjcost, int *mvcost[2]) {
+#if CONFIG_GLOBAL_MOTION
+ const AV1_COMMON *cm = &cpi->common;
+#endif // CONFIG_GLOBAL_MOTION
MODE_INFO *const mic = xd->mi[0];
const MB_MODE_INFO *const mbmi = &mic->mbmi;
const MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
this_mv[1].as_int = frame_mv[mode][mbmi->ref_frame[1]].as_int;
break;
case ZEROMV:
+#if CONFIG_GLOBAL_MOTION
+ this_mv[0].as_int = cpi->common.global_motion[mbmi->ref_frame[0]]
+ .motion_params.wmmat[0]
+ .as_int;
+ thismvcost += GLOBAL_MOTION_RATE(mbmi->ref_frame[0]);
+ if (is_compound) {
+ this_mv[1].as_int = cpi->common.global_motion[mbmi->ref_frame[1]]
+ .motion_params.wmmat[0]
+ .as_int;
+ thismvcost += GLOBAL_MOTION_RATE(mbmi->ref_frame[1]);
+ }
+#else // CONFIG_GLOBAL_MOTION
this_mv[0].as_int = 0;
if (is_compound) this_mv[1].as_int = 0;
+#endif // CONFIG_GLOBAL_MOTION
break;
#if CONFIG_EXT_INTER
case NEW_NEWMV:
av1_update_mv_context(xd, mi, frame, mv_ref_list, i, mi_row, mi_col,
NULL);
#endif // CONFIG_EXT_INTER
+#if CONFIG_GLOBAL_MOTION
+ frame_mv[ZEROMV][frame].as_int =
+ cm->global_motion[frame].motion_params.wmmat[0].as_int;
+#else // CONFIG_GLOBAL_MOTION
frame_mv[ZEROMV][frame].as_int = 0;
+#endif // CONFIG_GLOBAL_MOTION
av1_append_sub8x8_mvs_for_idx(cm, xd, i, ref, mi_row, mi_col,
#if CONFIG_REF_MV
ref_mv_stack[ref], &ref_mv_count[ref],
#endif // CONFIG_EXT_INTER
#endif // CONFIG_REF_MV
- if (!check_best_zero_mv(cpi, mbmi_ext->mode_context,
+#if CONFIG_GLOBAL_MOTION
+ if (get_gmtype(&cm->global_motion[mbmi->ref_frame[0]]) == GLOBAL_ZERO &&
+ (!has_second_rf ||
+ get_gmtype(&cm->global_motion[mbmi->ref_frame[1]]) == GLOBAL_ZERO))
+#endif // CONFIG_GLOBAL_MOTION
+
+ if (!check_best_zero_mv(cpi, mbmi_ext->mode_context,
#if CONFIG_REF_MV && CONFIG_EXT_INTER
- mbmi_ext->compound_mode_context,
+ mbmi_ext->compound_mode_context,
#endif // CONFIG_REF_MV && CONFIG_EXT_INTER
- frame_mv, this_mode, mbmi->ref_frame, bsize, i))
- continue;
+ frame_mv, this_mode, mbmi->ref_frame, bsize,
+ i))
+ continue;
memcpy(orig_pre, pd->pre, sizeof(orig_pre));
memcpy(bsi->rdstat[i][mode_idx].ta, t_above,
*rate_uv = 0;
*skippable = 1;
}
+#if CONFIG_GLOBAL_MOTION
+ if (this_mode == ZEROMV) {
+ *rate2 += GLOBAL_MOTION_RATE(mbmi->ref_frame[0]);
+ if (is_comp_pred) *rate2 += GLOBAL_MOTION_RATE(mbmi->ref_frame[1]);
+ }
+#endif // CONFIG_GLOBAL_MOTION
#if CONFIG_OBMC || CONFIG_WARPED_MOTION
tmp_rd = RDCOST(x->rdmult, x->rddiv, *rate2, *distortion);
frame_mv[NEARESTMV], frame_mv[NEARMV], yv12_mb);
}
frame_mv[NEWMV][ref_frame].as_int = INVALID_MV;
+#if CONFIG_GLOBAL_MOTION
+ frame_mv[ZEROMV][ref_frame].as_int =
+ cm->global_motion[ref_frame].motion_params.wmmat[0].as_int;
+#else // CONFIG_GLOBAL_MOTION
frame_mv[ZEROMV][ref_frame].as_int = 0;
+#endif // CONFIG_GLOBAL_MOTION
#if CONFIG_EXT_INTER
frame_mv[NEWFROMNEARMV][ref_frame].as_int = INVALID_MV;
frame_mv[NEW_NEWMV][ref_frame].as_int = INVALID_MV;
// an unfiltered alternative. We allow near/nearest as well
// because they may result in zero-zero MVs but be cheaper.
if (cpi->rc.is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames == 0)) {
+ int_mv zeromv;
ref_frame_skip_mask[0] = (1 << LAST_FRAME) |
#if CONFIG_EXT_REFS
(1 << LAST2_FRAME) | (1 << LAST3_FRAME) |
// TODO(zoeliu): To further explore whether following needs to be done for
// BWDREF_FRAME as well.
mode_skip_mask[ALTREF_FRAME] = ~INTER_NEAREST_NEAR_ZERO;
- if (frame_mv[NEARMV][ALTREF_FRAME].as_int != 0)
+#if CONFIG_GLOBAL_MOTION
+ zeromv.as_int =
+ cm->global_motion[ALTREF_FRAME].motion_params.wmmat[0].as_int;
+#else
+ zeromv.as_int = 0;
+#endif // CONFIG_GLOBAL_MOTION
+ if (frame_mv[NEARMV][ALTREF_FRAME].as_int != zeromv.as_int)
mode_skip_mask[ALTREF_FRAME] |= (1 << NEARMV);
- if (frame_mv[NEARESTMV][ALTREF_FRAME].as_int != 0)
+ if (frame_mv[NEARESTMV][ALTREF_FRAME].as_int != zeromv.as_int)
mode_skip_mask[ALTREF_FRAME] |= (1 << NEARESTMV);
#if CONFIG_EXT_INTER
- if (frame_mv[NEAREST_NEARESTMV][ALTREF_FRAME].as_int != 0)
+ if (frame_mv[NEAREST_NEARESTMV][ALTREF_FRAME].as_int != zeromv.as_int)
mode_skip_mask[ALTREF_FRAME] |= (1 << NEAREST_NEARESTMV);
- if (frame_mv[NEAREST_NEARMV][ALTREF_FRAME].as_int != 0)
+ if (frame_mv[NEAREST_NEARMV][ALTREF_FRAME].as_int != zeromv.as_int)
mode_skip_mask[ALTREF_FRAME] |= (1 << NEAREST_NEARMV);
- if (frame_mv[NEAR_NEARESTMV][ALTREF_FRAME].as_int != 0)
+ if (frame_mv[NEAR_NEARESTMV][ALTREF_FRAME].as_int != zeromv.as_int)
mode_skip_mask[ALTREF_FRAME] |= (1 << NEAR_NEARESTMV);
- if (frame_mv[NEAR_NEARMV][ALTREF_FRAME].as_int != 0)
+ if (frame_mv[NEAR_NEARMV][ALTREF_FRAME].as_int != zeromv.as_int)
mode_skip_mask[ALTREF_FRAME] |= (1 << NEAR_NEARMV);
#endif // CONFIG_EXT_INTER
}
if (conditional_skipintra(this_mode, best_intra_mode)) continue;
}
}
+#if CONFIG_GLOBAL_MOTION
+ } else if (get_gmtype(&cm->global_motion[ref_frame]) == GLOBAL_ZERO &&
+ (!comp_pred ||
+ get_gmtype(&cm->global_motion[second_ref_frame]) ==
+ GLOBAL_ZERO)) {
+#else // CONFIG_GLOBAL_MOTION
} else {
+#endif // CONFIG_GLOBAL_MOTION
const MV_REFERENCE_FRAME ref_frames[2] = { ref_frame, second_ref_frame };
if (!check_best_zero_mv(cpi, mbmi_ext->mode_context,
#if CONFIG_REF_MV && CONFIG_EXT_INTER
const MV_REFERENCE_FRAME refs[2] = { best_mbmode.ref_frame[0],
best_mbmode.ref_frame[1] };
int comp_pred_mode = refs[1] > INTRA_FRAME;
+ int_mv zeromv[2];
#if CONFIG_REF_MV
const uint8_t rf_type = av1_ref_frame_type(best_mbmode.ref_frame);
+#endif // CONFIG_REF_MV
+#if CONFIG_GLOBAL_MOTION
+ zeromv[0].as_int = cm->global_motion[refs[0]].motion_params.wmmat[0].as_int;
+ zeromv[1].as_int = cm->global_motion[refs[1]].motion_params.wmmat[0].as_int;
+#else
+ zeromv[0].as_int = 0;
+ zeromv[1].as_int = 0;
+#endif // CONFIG_GLOBAL_MOTION
+#if CONFIG_REF_MV
if (!comp_pred_mode) {
int i;
int ref_set = (mbmi_ext->ref_mv_count[rf_type] >= 2)
if (frame_mv[NEARESTMV][refs[0]].as_int == best_mbmode.mv[0].as_int)
best_mbmode.mode = NEARESTMV;
- else if (best_mbmode.mv[0].as_int == 0)
+ else if (best_mbmode.mv[0].as_int == zeromv[0].as_int)
best_mbmode.mode = ZEROMV;
} else {
int_mv nearestmv[2];
best_mbmode.mode = ZERO_ZEROMV;
#else
best_mbmode.mode = NEARESTMV;
- else if (best_mbmode.mv[0].as_int == 0 && best_mbmode.mv[1].as_int == 0)
+ else if (best_mbmode.mv[0].as_int == zeromv[0].as_int &&
+ best_mbmode.mv[1].as_int == zeromv[1].as_int)
best_mbmode.mode = ZEROMV;
#endif // CONFIG_EXT_INTER
}
best_mbmode.mv[1].as_int) ||
!comp_pred_mode))
best_mbmode.mode = NEARMV;
- else if (best_mbmode.mv[0].as_int == 0 &&
- ((comp_pred_mode && best_mbmode.mv[1].as_int == 0) ||
+ else if (best_mbmode.mv[0].as_int == zeromv[0].as_int &&
+ ((comp_pred_mode &&
+ best_mbmode.mv[1].as_int == zeromv[1].as_int) ||
!comp_pred_mode))
best_mbmode.mode = ZEROMV;
#if CONFIG_EXT_INTER
mbmi->uv_mode = DC_PRED;
mbmi->ref_frame[0] = LAST_FRAME;
mbmi->ref_frame[1] = NONE;
+#if CONFIG_GLOBAL_MOTION
+ mbmi->mv[0].as_int =
+ cm->global_motion[mbmi->ref_frame[0]].motion_params.wmmat[0].as_int;
+#else // CONFIG_GLOBAL_MOTION
mbmi->mv[0].as_int = 0;
+#endif // CONFIG_GLOBAL_MOTION
+
#if CONFIG_REF_MV
mbmi->ref_mv_idx = 0;
mbmi->pred_mv[0].as_int = 0;