diff --git a/av1/common/mv.h b/av1/common/mv.h index 9640c7332..22a47f763 100644 --- a/av1/common/mv.h +++ b/av1/common/mv.h @@ -14,9 +14,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" { @@ -37,6 +34,41 @@ typedef struct mv32 { 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| @@ -62,16 +94,16 @@ typedef struct mv32 { // // 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) @@ -103,11 +135,10 @@ static INLINE TransformationType gm_to_trans_type(GLOBAL_MOTION_TYPE gmtype) { } 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 c742c3650..2ff1fcee5 100644 --- a/av1/common/warped_motion.c +++ b/av1/common/warped_motion.c @@ -26,7 +26,7 @@ static ProjectPointsType get_project_points_type(TransformationType type) { } } -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 @@ void projectPointsTranslation(int *mat, int *points, int *proj, const int n, 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 @@ void projectPointsRotZoom(int *mat, int *points, int *proj, const int n, 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 @@ void projectPointsAffine(int *mat, int *points, int *proj, const int n, 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 @@ void projectPointsHomography(int *mat, int *points, int *proj, const int n, 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 @@ static double highbd_warp_erroradv(WarpedMotionParams *wm, uint8_t *ref8, 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 @@ static void highbd_warp_plane(WarpedMotionParams *wm, uint8_t *ref8, int width, 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 @@ static double warp_erroradv(WarpedMotionParams *wm, uint8_t *ref, int width, 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 @@ static void warp_plane(WarpedMotionParams *wm, uint8_t *ref, int width, 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 @@ void av1_integerize_model(const double *model, TransformationType wmtype, 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 965b296d5..d9574017b 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 diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c index 13bb257ca..2daf4bf5e 100644 --- a/av1/decoder/decodeframe.c +++ b/av1/decoder/decodeframe.c @@ -3411,28 +3411,28 @@ static void read_global_motion_params(Global_Motion_Params *params, 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; @@ -3446,6 +3446,14 @@ static void read_global_motion(AV1_COMMON *cm, aom_reader *r) { 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 diff --git a/av1/decoder/decodemv.c b/av1/decoder/decodemv.c index 09adf086f..316d31744 100644 --- a/av1/decoder/decodemv.c +++ b/av1/decoder/decodemv.c @@ -939,6 +939,7 @@ static INLINE int is_mv_valid(const MV *mv) { 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 @@ -953,6 +954,7 @@ static INLINE int assign_mv(AV1_COMMON *cm, MACROBLOCKD *xd, 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 @@ -1007,8 +1009,16 @@ static INLINE int assign_mv(AV1_COMMON *cm, MACROBLOCKD *xd, 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; @@ -1429,7 +1439,7 @@ static void read_inter_block_mode_info(AV1Decoder *const pbi, (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 @@ -1481,7 +1491,7 @@ static void read_inter_block_mode_info(AV1Decoder *const pbi, } xd->corrupted |= - !assign_mv(cm, xd, mbmi->mode, + !assign_mv(cm, xd, mbmi->mode, mbmi->ref_frame, #if CONFIG_REF_MV 0, #endif diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c index a5b539632..3bd5adc42 100644 --- a/av1/encoder/bitstream.c +++ b/av1/encoder/bitstream.c @@ -3196,29 +3196,29 @@ static void write_global_motion_params(Global_Motion_Params *params, 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); @@ -3234,6 +3234,14 @@ static void write_global_motion(AV1_COMP *cpi, aom_writer *w) { } 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 diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c index b5d471235..f172fbb7f 100644 --- a/av1/encoder/encodeframe.c +++ b/av1/encoder/encodeframe.c @@ -41,6 +41,7 @@ #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" @@ -4402,37 +4403,30 @@ static int input_fpmb_stats(FIRSTPASS_MB_STATS *firstpass_mb_stats, #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; } } } @@ -4440,7 +4434,8 @@ static void convert_to_params(double *H, TransformationType type, 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); } diff --git a/av1/encoder/ransac.c b/av1/encoder/ransac.c index 0beaab8b1..a3072bc02 100644 --- a/av1/encoder/ransac.c +++ b/av1/encoder/ransac.c @@ -469,7 +469,8 @@ int ransac_(double *matched_points, int npoints, int *number_of_inliers, } 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 = @@ -610,12 +611,12 @@ static void denormalizeAffine(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[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) { @@ -629,10 +630,10 @@ 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) { @@ -646,8 +647,8 @@ 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) { diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c index 63cc75e4e..0178721a7 100644 --- a/av1/encoder/rdopt.c +++ b/av1/encoder/rdopt.c @@ -4069,6 +4069,31 @@ static int cost_mv_ref(const AV1_COMP *cpi, PREDICTION_MODE mode, #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], @@ -4077,6 +4102,9 @@ static int set_and_cost_bmi_mvs( 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; @@ -4128,8 +4156,21 @@ static int set_and_cost_bmi_mvs( 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: @@ -4838,7 +4879,12 @@ static int64_t rd_pick_best_sub8x8_mode( 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], @@ -4974,12 +5020,19 @@ static int64_t rd_pick_best_sub8x8_mode( #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, @@ -7639,6 +7692,12 @@ static int64_t handle_inter_mode( *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); @@ -8275,7 +8334,12 @@ void av1_rd_pick_inter_mode_sb(AV1_COMP *cpi, TileDataEnc *tile_data, 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; @@ -8352,6 +8416,7 @@ void av1_rd_pick_inter_mode_sb(AV1_COMP *cpi, TileDataEnc *tile_data, // 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) | @@ -8362,18 +8427,24 @@ void av1_rd_pick_inter_mode_sb(AV1_COMP *cpi, TileDataEnc *tile_data, // 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 } @@ -8581,7 +8652,14 @@ void av1_rd_pick_inter_mode_sb(AV1_COMP *cpi, TileDataEnc *tile_data, 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 @@ -9426,8 +9504,18 @@ PALETTE_EXIT: 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) @@ -9444,7 +9532,7 @@ PALETTE_EXIT: 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]; @@ -9500,7 +9588,8 @@ PALETTE_EXIT: 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 } @@ -9519,8 +9608,9 @@ PALETTE_EXIT: 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 @@ -9692,7 +9782,13 @@ void av1_rd_pick_inter_mode_sb_seg_skip(AV1_COMP *cpi, TileDataEnc *tile_data, 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;