]> granicus.if.org Git - libvpx/commitdiff
Add global motion experiment to rdopt
authorSarah Parker <sarahparker@google.com>
Tue, 16 Aug 2016 21:57:37 +0000 (14:57 -0700)
committerSarah Parker <sarahparker@google.com>
Fri, 2 Sep 2016 02:51:11 +0000 (19:51 -0700)
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

av1/common/mv.h
av1/common/warped_motion.c
av1/common/warped_motion.h
av1/decoder/decodeframe.c
av1/decoder/decodemv.c
av1/encoder/bitstream.c
av1/encoder/encodeframe.c
av1/encoder/ransac.c
av1/encoder/rdopt.c

index 4908d744fe4302e6c422672fadcfd3b99c2b7482..fe08e9d0114952ef183426cbf785c6ea70ecd84e 100644 (file)
@@ -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 @@ 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|
@@ -61,16 +93,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)
@@ -102,11 +134,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;
     }
index c742c3650c6548ea23b17bc8a64334767b3d0682..2ff1fcee59d99942cff61b8989432fcd7e8182b0 100644 (file)
@@ -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");
   }
index 965b296d5181e23e549885973d54c658f941d8d1..d9574017b9725bc4b68056aeca980a8b9a147354 100644 (file)
@@ -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
 
 #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
index 638fa01f5c1ee4bb0d587ca716836b0920ebcf91..50ecef3f820db37fdbf3cdc76c9d6333207737de 100644 (file)
@@ -3423,28 +3423,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;
@@ -3458,6 +3458,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
index 47cfea6b7dfb4d7c641a306f4f2d9768fd565e33..59554a444a9744709536dec68861b06af0227042 100644 (file)
@@ -938,6 +938,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
@@ -952,6 +953,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
@@ -1006,8 +1008,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;
@@ -1428,7 +1438,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
@@ -1480,7 +1490,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
index 305a672fbe0d458221d55d08ce1280bf0dca5d09..f5a4858f5099b508825b4eb83816417a26170cac 100644 (file)
@@ -3195,29 +3195,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);
@@ -3233,6 +3233,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
index a7183f9e25460e1fa038edd966d1899288c4d9f3..d510b1988ebec5dd78c98b1cfd5a67b22a8931b7 100644 (file)
@@ -40,6 +40,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"
@@ -4401,37 +4402,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;
     }
   }
 }
@@ -4439,7 +4433,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);
 }
index 0beaab8b12d44aa26388815307ec6a2b92e36a89..a3072bc0237cbaab1bd5862d7a7ce3a89974d9ec 100644 (file)
@@ -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) {
index bd937469473560361bc90c2617eb062c75db2032..e3941cb346a7da5eef1796df138477589f4c590d 100644 (file)
@@ -4068,6 +4068,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],
@@ -4076,6 +4101,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;
@@ -4127,8 +4155,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:
@@ -4837,7 +4878,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],
@@ -4973,12 +5019,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,
@@ -7638,6 +7691,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);
@@ -8274,7 +8333,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;
@@ -8351,6 +8415,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) |
@@ -8361,18 +8426,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
     }
@@ -8580,7 +8651,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;