Find warped reference MV

While finding the reference MV for a block, if one neighbouring block's
motion mode is warped motion mode, instead of directly adding that
block's MV to the candidate MV list, we use that neighbouring block's
warped motion parameters to compute a MV for the center point of the
current block, and then add that MV to the candidate MV list.

Borg test result:
             avg_psnr ovr_psnr ssim
cam_lowres:  -0.507   -0.514  -0.685
lowres:      -0.114   -0.122  -0.180

The change is added under ext_warped_motion config flag.

Change-Id: I3ce6290a1fd512b613eab5d7620c8bcb08f189a6
diff --git a/av1/common/mv.h b/av1/common/mv.h
index 65f0f7e..f470817 100644
--- a/av1/common/mv.h
+++ b/av1/common/mv.h
@@ -37,10 +37,6 @@
   int32_t col;
 } MV32;
 
-#if CONFIG_WARPED_MOTION
-#define WARPED_MOTION_SORT_SAMPLES 1
-#endif  // CONFIG_WARPED_MOTION
-
 #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
 // Bits of precision used for the model
 #define WARPEDMODEL_PREC_BITS 16
diff --git a/av1/common/mvref_common.c b/av1/common/mvref_common.c
index 7f9ca1d..d412206 100644
--- a/av1/common/mvref_common.c
+++ b/av1/common/mvref_common.c
@@ -57,12 +57,12 @@
 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
     int_mv *gm_mv_candidates, const WarpedMotionParams *gm_params,
 #endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
-    int col, int weight
+    int col, int weight,
 #if CONFIG_AMVR
-    ,
-    int is_integer
+    int is_integer,
 #endif
-    ) {
+    BLOCK_SIZE bsize, int mi_row, int mi_col, int subsampling_x,
+    int subsampling_y) {
   int index = 0, ref;
   int newmv_count = 0;
 #if CONFIG_CB4X4
@@ -71,23 +71,69 @@
   const int unify_bsize = 0;
 #endif
   assert(weight % 2 == 0);
+#if !CONFIG_EXT_WARPED_MOTION
+  (void)bsize;
+  (void)mi_row;
+  (void)mi_col;
+  (void)subsampling_x;
+  (void)subsampling_y;
+#endif  // CONFIG_EXT_WARPED_MOTION
 
   if (rf[1] == NONE_FRAME) {
     // single reference frame
     for (ref = 0; ref < 2; ++ref) {
       if (candidate->ref_frame[ref] == rf[0]) {
         int_mv this_refmv;
+#if CONFIG_EXT_WARPED_MOTION
+        if (candidate->motion_mode == WARPED_CAUSAL) {
+          WarpedMotionParams wm = candidate->wm_params[0];
+          const int bw = block_size_wide[bsize];
+          const int bh = block_size_high[bsize];
+          int global_offset_c = mi_col * MI_SIZE;
+          int global_offset_r = mi_row * MI_SIZE;
+          int cc_offset = bw / 2 - 1;
+          int cr_offset = bh / 2 - 1;
+          int xc0 = cc_offset + global_offset_c;
+          int yc0 = cr_offset + global_offset_r;
+          int xc1 = xc0 + 1;
+          int yc1 = yc0 + 1;
+          int in[4] = { xc0, yc0, xc1, yc1 };
+          int out[4] = { 0, 0, 0, 0 };
+
+          assert(ref == 0);
+          // For WARPED_CAUSAL, wmtype is always AFFINE.
+          assert(wm.wmtype == AFFINE);
+          project_points_affine(wm.wmmat, in, out, 2, 2, 2, subsampling_x,
+                                subsampling_y);
+
+          // assert(x_scale == 1024 && y_scale == 1024);
+          // out[]'s precision is 1/64, adjust xc, yc accordingly.
+          out[0] -= (xc0 << (3 + SCALING_FCT));
+          out[1] -= (yc0 << (3 + SCALING_FCT));
+          out[2] -= (xc1 << (3 + SCALING_FCT));
+          out[3] -= (yc1 << (3 + SCALING_FCT));
+
+          this_refmv.as_mv.col =
+              ROUND_POWER_OF_TWO_SIGNED(out[0] + out[2], SCALING_FCT + 1);
+          this_refmv.as_mv.row =
+              ROUND_POWER_OF_TWO_SIGNED(out[1] + out[3], SCALING_FCT + 1);
+          lower_mv_precision(&this_refmv.as_mv, use_hp);
+        } else {
+#endif  // CONFIG_EXT_WARPED_MOTION
 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
-        if (is_global_mv_block(candidate_mi, block, gm_params[rf[0]].wmtype))
-          this_refmv = gm_mv_candidates[0];
-        else
+          if (is_global_mv_block(candidate_mi, block, gm_params[rf[0]].wmtype))
+            this_refmv = gm_mv_candidates[0];
+          else
 #endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
-          this_refmv = get_sub_block_mv(candidate_mi, ref, col, block);
+            this_refmv = get_sub_block_mv(candidate_mi, ref, col, block);
 #if CONFIG_AMVR
-        lower_mv_precision(&this_refmv.as_mv, use_hp, is_integer);
+          lower_mv_precision(&this_refmv.as_mv, use_hp, is_integer);
 #else
         lower_mv_precision(&this_refmv.as_mv, use_hp);
 #endif  // CONFIG_AMVR
+#if CONFIG_EXT_WARPED_MOTION
+        }
+#endif  // CONFIG_EXT_WARPED_MOTION
 
         for (index = 0; index < *refmv_count; ++index)
           if (ref_mv_stack[index].this_mv.as_int == this_refmv.as_int) break;
@@ -215,7 +261,7 @@
 }
 
 static uint8_t scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
-                             const int mi_col, int block,
+                             int mi_row, int mi_col, int block,
                              const MV_REFERENCE_FRAME rf[2], int row_offset,
                              CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count,
 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
@@ -270,15 +316,18 @@
 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
         gm_mv_candidates, cm->global_motion,
 #endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
-        col_offset + i, weight, cm->cur_frame_mv_precision_level);
+        col_offset + i, weight, cm->cur_frame_mv_precision_level,
+        xd->mi[0]->mbmi.sb_type, mi_row, mi_col, xd->plane[0].subsampling_x,
+        xd->plane[0].subsampling_y);
 #else
-    newmv_count += add_ref_mv_candidate(candidate_mi, candidate, rf,
-                                        refmv_count, ref_mv_stack,
-                                        cm->allow_high_precision_mv, len, block,
+    newmv_count += add_ref_mv_candidate(
+        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
+        cm->allow_high_precision_mv, len, block,
 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
-                                        gm_mv_candidates, cm->global_motion,
+        gm_mv_candidates, cm->global_motion,
 #endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
-                                        col_offset + i, weight);
+        col_offset + i, weight, xd->mi[0]->mbmi.sb_type, mi_row, mi_col,
+        xd->plane[0].subsampling_x, xd->plane[0].subsampling_y);
 #endif
 
     i += len;
@@ -288,7 +337,7 @@
 }
 
 static uint8_t scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
-                             const int mi_row, int block,
+                             int mi_row, int mi_col, int block,
                              const MV_REFERENCE_FRAME rf[2], int col_offset,
                              CANDIDATE_MV *ref_mv_stack, uint8_t *refmv_count,
 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
@@ -342,15 +391,18 @@
 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
         gm_mv_candidates, cm->global_motion,
 #endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
-        col_offset, weight, cm->cur_frame_mv_precision_level);
+        col_offset, weight, cm->cur_frame_mv_precision_level,
+        xd->mi[0]->mbmi.sb_type, mi_row, mi_col, xd->plane[0].subsampling_x,
+        xd->plane[0].subsampling_y);
 #else
-    newmv_count += add_ref_mv_candidate(candidate_mi, candidate, rf,
-                                        refmv_count, ref_mv_stack,
-                                        cm->allow_high_precision_mv, len, block,
+    newmv_count += add_ref_mv_candidate(
+        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
+        cm->allow_high_precision_mv, len, block,
 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
-                                        gm_mv_candidates, cm->global_motion,
+        gm_mv_candidates, cm->global_motion,
 #endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
-                                        col_offset, weight);
+        col_offset, weight, xd->mi[0]->mbmi.sb_type, mi_row, mi_col,
+        xd->plane[0].subsampling_x, xd->plane[0].subsampling_y);
 #endif
     i += len;
   }
@@ -387,15 +439,18 @@
 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
         gm_mv_candidates, cm->global_motion,
 #endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
-        mi_pos.col, 2, cm->cur_frame_mv_precision_level);
+        mi_pos.col, 2, cm->cur_frame_mv_precision_level,
+        xd->mi[0]->mbmi.sb_type, mi_row, mi_col, xd->plane[0].subsampling_x,
+        xd->plane[0].subsampling_y);
 #else
-    newmv_count += add_ref_mv_candidate(candidate_mi, candidate, rf,
-                                        refmv_count, ref_mv_stack,
-                                        cm->allow_high_precision_mv, len, block,
+    newmv_count += add_ref_mv_candidate(
+        candidate_mi, candidate, rf, refmv_count, ref_mv_stack,
+        cm->allow_high_precision_mv, len, block,
 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
-                                        gm_mv_candidates, cm->global_motion,
+        gm_mv_candidates, cm->global_motion,
 #endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
-                                        mi_pos.col, 2);
+        mi_pos.col, 2, xd->mi[0]->mbmi.sb_type, mi_row, mi_col,
+        xd->plane[0].subsampling_x, xd->plane[0].subsampling_y);
 #endif
   }  // Analyze a single 8x8 block motion information.
 
@@ -730,20 +785,20 @@
 
   // Scan the first above row mode info. row_offset = -1;
   if (abs(max_row_offset) >= 1)
-    newmv_count +=
-        scan_row_mbmi(cm, xd, mi_col, block, rf, -1, ref_mv_stack, refmv_count,
+    newmv_count += scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
+                                 ref_mv_stack, refmv_count,
 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
-                      gm_mv_candidates,
+                                 gm_mv_candidates,
 #endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
-                      max_row_offset, &processed_rows);
+                                 max_row_offset, &processed_rows);
   // Scan the first left column mode info. col_offset = -1;
   if (abs(max_col_offset) >= 1)
-    newmv_count +=
-        scan_col_mbmi(cm, xd, mi_row, block, rf, -1, ref_mv_stack, refmv_count,
+    newmv_count += scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
+                                 ref_mv_stack, refmv_count,
 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
-                      gm_mv_candidates,
+                                 gm_mv_candidates,
 #endif  // CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
-                      max_col_offset, &processed_cols);
+                                 max_col_offset, &processed_cols);
   // Check top-right boundary
   if (has_tr)
     newmv_count += scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1,
@@ -884,7 +939,7 @@
 
     if (abs(row_offset) <= abs(max_row_offset) &&
         abs(row_offset) > processed_rows)
-      scan_row_mbmi(cm, xd, mi_col, block, rf, row_offset, ref_mv_stack,
+      scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf, row_offset, ref_mv_stack,
                     refmv_count,
 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                     gm_mv_candidates,
@@ -893,7 +948,7 @@
 
     if (abs(col_offset) <= abs(max_col_offset) &&
         abs(col_offset) > processed_cols)
-      scan_col_mbmi(cm, xd, mi_row, block, rf, col_offset, ref_mv_stack,
+      scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, col_offset, ref_mv_stack,
                     refmv_count,
 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                     gm_mv_candidates,
@@ -908,7 +963,7 @@
 #endif
   if (abs(col_offset) <= abs(max_col_offset) &&
       abs(col_offset) > processed_cols)
-    scan_col_mbmi(cm, xd, mi_row, block, rf, col_offset, ref_mv_stack,
+    scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, col_offset, ref_mv_stack,
                   refmv_count,
 #if CONFIG_GLOBAL_MOTION && USE_CUR_GM_REFMV
                   gm_mv_candidates,
@@ -1993,7 +2048,7 @@
 #endif  // CONFIG_MFMV
 
 #if CONFIG_WARPED_MOTION
-#if WARPED_MOTION_SORT_SAMPLES
+#if CONFIG_EXT_WARPED_MOTION
 static INLINE void record_samples(MB_MODE_INFO *mbmi, int *pts, int *pts_inref,
                                   int *pts_mv, int global_offset_r,
                                   int global_offset_c, int row_offset,
@@ -2315,5 +2370,5 @@
 
   return np;
 }
-#endif  // WARPED_MOTION_SORT_SAMPLES
+#endif  // CONFIG_EXT_WARPED_MOTION
 #endif  // CONFIG_WARPED_MOTION
diff --git a/av1/common/mvref_common.h b/av1/common/mvref_common.h
index 67ea981..6b964dc 100644
--- a/av1/common/mvref_common.h
+++ b/av1/common/mvref_common.h
@@ -433,14 +433,14 @@
                            int mi_col, int16_t *mode_context);
 
 #if CONFIG_WARPED_MOTION
-#if WARPED_MOTION_SORT_SAMPLES
+#if CONFIG_EXT_WARPED_MOTION
 int sortSamples(int *pts_mv, MV *mv, int *pts, int *pts_inref, int len);
 int findSamples(const AV1_COMMON *cm, MACROBLOCKD *xd, int mi_row, int mi_col,
                 int *pts, int *pts_inref, int *pts_mv);
 #else
 int findSamples(const AV1_COMMON *cm, MACROBLOCKD *xd, int mi_row, int mi_col,
                 int *pts, int *pts_inref);
-#endif  // WARPED_MOTION_SORT_SAMPLES
+#endif  // CONFIG_EXT_WARPED_MOTION
 #endif  // CONFIG_WARPED_MOTION
 
 #if CONFIG_INTRABC
diff --git a/av1/common/warped_motion.h b/av1/common/warped_motion.h
index e05f6a8..32e5dda 100644
--- a/av1/common/warped_motion.h
+++ b/av1/common/warped_motion.h
@@ -29,13 +29,14 @@
 #define LEAST_SQUARES_SAMPLES_MAX_BITS 3
 #define LEAST_SQUARES_SAMPLES_MAX (1 << LEAST_SQUARES_SAMPLES_MAX_BITS)
 
-#if WARPED_MOTION_SORT_SAMPLES
+#if CONFIG_EXT_WARPED_MOTION
 // Search 1 row on the top and 1 column on the left, 1 upper-left block,
 // 1 upper-right block.
 #define SAMPLES_ARRAY_SIZE ((MAX_MIB_SIZE * 2 + 2) * 2)
+#define SCALING_FCT 3
 #else
 #define SAMPLES_ARRAY_SIZE (LEAST_SQUARES_SAMPLES_MAX * 2)
-#endif  // WARPED_MOTION_SORT_SAMPLES
+#endif  // CONFIG_EXT_WARPED_MOTION
 
 #define DEFAULT_WMTYPE AFFINE
 #endif  // CONFIG_WARPED_MOTION
diff --git a/av1/decoder/decodemv.c b/av1/decoder/decodemv.c
index dd048a8..cdd8d16 100644
--- a/av1/decoder/decodemv.c
+++ b/av1/decoder/decodemv.c
@@ -2339,9 +2339,9 @@
   int16_t mode_ctx = 0;
 #if CONFIG_WARPED_MOTION
   int pts[SAMPLES_ARRAY_SIZE], pts_inref[SAMPLES_ARRAY_SIZE];
-#if WARPED_MOTION_SORT_SAMPLES
+#if CONFIG_EXT_WARPED_MOTION
   int pts_mv[SAMPLES_ARRAY_SIZE];
-#endif  // WARPED_MOTION_SORT_SAMPLES
+#endif  // CONFIG_EXT_WARPED_MOTION
 #endif  // CONFIG_WARPED_MOTION
   FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
 
@@ -2804,12 +2804,12 @@
   mbmi->motion_mode = SIMPLE_TRANSLATION;
 #if CONFIG_WARPED_MOTION
   if (mbmi->sb_type >= BLOCK_8X8 && !has_second_ref(mbmi))
-#if WARPED_MOTION_SORT_SAMPLES
+#if CONFIG_EXT_WARPED_MOTION
     mbmi->num_proj_ref[0] =
         findSamples(cm, xd, mi_row, mi_col, pts, pts_inref, pts_mv);
 #else
     mbmi->num_proj_ref[0] = findSamples(cm, xd, mi_row, mi_col, pts, pts_inref);
-#endif  // WARPED_MOTION_SORT_SAMPLES
+#endif  // CONFIG_EXT_WARPED_MOTION
 #endif  // CONFIG_WARPED_MOTION
 #if CONFIG_MOTION_VAR
   av1_count_overlappable_neighbors(cm, xd, mi_row, mi_col);
@@ -2832,11 +2832,11 @@
     if (mbmi->motion_mode == WARPED_CAUSAL) {
       mbmi->wm_params[0].wmtype = DEFAULT_WMTYPE;
 
-#if WARPED_MOTION_SORT_SAMPLES
+#if CONFIG_EXT_WARPED_MOTION
       if (mbmi->num_proj_ref[0] > 1)
         mbmi->num_proj_ref[0] = sortSamples(pts_mv, &mbmi->mv[0].as_mv, pts,
                                             pts_inref, mbmi->num_proj_ref[0]);
-#endif  // WARPED_MOTION_SORT_SAMPLES
+#endif  // CONFIG_EXT_WARPED_MOTION
 
       if (find_projection(mbmi->num_proj_ref[0], pts, pts_inref, bsize,
                           mbmi->mv[0].as_mv.row, mbmi->mv[0].as_mv.col,
diff --git a/av1/encoder/mcomp.c b/av1/encoder/mcomp.c
index 6c8503d..f861c31 100644
--- a/av1/encoder/mcomp.c
+++ b/av1/encoder/mcomp.c
@@ -886,7 +886,7 @@
 }
 
 // Refine MV in a small range
-#if WARPED_MOTION_SORT_SAMPLES
+#if CONFIG_EXT_WARPED_MOTION
 unsigned int av1_refine_warped_mv(const AV1_COMP *cpi, MACROBLOCK *const x,
                                   BLOCK_SIZE bsize, int mi_row, int mi_col,
                                   int *pts0, int *pts_inref0, int *pts_mv0,
@@ -895,7 +895,7 @@
 unsigned int av1_refine_warped_mv(const AV1_COMP *cpi, MACROBLOCK *const x,
                                   BLOCK_SIZE bsize, int mi_row, int mi_col,
                                   int *pts, int *pts_inref) {
-#endif  // WARPED_MOTION_SORT_SAMPLES
+#endif  // CONFIG_EXT_WARPED_MOTION
   const AV1_COMMON *const cm = &cpi->common;
   MACROBLOCKD *xd = &x->e_mbd;
   MODE_INFO *mi = xd->mi[0];
@@ -908,9 +908,9 @@
   int16_t *tr = &mbmi->mv[0].as_mv.row;
   int16_t *tc = &mbmi->mv[0].as_mv.col;
   WarpedMotionParams best_wm_params = mbmi->wm_params[0];
-#if WARPED_MOTION_SORT_SAMPLES
+#if CONFIG_EXT_WARPED_MOTION
   int best_num_proj_ref = mbmi->num_proj_ref[0];
-#endif  // WARPED_MOTION_SORT_SAMPLES
+#endif  // CONFIG_EXT_WARPED_MOTION
   unsigned int bestmse;
   int minc, maxc, minr, maxr;
   const int start = cm->allow_high_precision_mv ? 0 : 4;
@@ -937,7 +937,7 @@
 
       if (*tc >= minc && *tc <= maxc && *tr >= minr && *tr <= maxr) {
         MV this_mv = { *tr, *tc };
-#if WARPED_MOTION_SORT_SAMPLES
+#if CONFIG_EXT_WARPED_MOTION
         int pts[SAMPLES_ARRAY_SIZE], pts_inref[SAMPLES_ARRAY_SIZE];
 
         memcpy(pts, pts0, total_samples * 2 * sizeof(*pts0));
@@ -945,7 +945,7 @@
         if (total_samples > 1)
           mbmi->num_proj_ref[0] =
               sortSamples(pts_mv0, &this_mv, pts, pts_inref, total_samples);
-#endif  // WARPED_MOTION_SORT_SAMPLES
+#endif  // CONFIG_EXT_WARPED_MOTION
 
         if (!find_projection(mbmi->num_proj_ref[0], pts, pts_inref, bsize, *tr,
                              *tc, &mbmi->wm_params[0], mi_row, mi_col)) {
@@ -955,9 +955,9 @@
           if (thismse < bestmse) {
             best_idx = idx;
             best_wm_params = mbmi->wm_params[0];
-#if WARPED_MOTION_SORT_SAMPLES
+#if CONFIG_EXT_WARPED_MOTION
             best_num_proj_ref = mbmi->num_proj_ref[0];
-#endif  // WARPED_MOTION_SORT_SAMPLES
+#endif  // CONFIG_EXT_WARPED_MOTION
             bestmse = thismse;
           }
         }
@@ -975,9 +975,9 @@
   *tr = br;
   *tc = bc;
   mbmi->wm_params[0] = best_wm_params;
-#if WARPED_MOTION_SORT_SAMPLES
+#if CONFIG_EXT_WARPED_MOTION
   mbmi->num_proj_ref[0] = best_num_proj_ref;
-#endif  // WARPED_MOTION_SORT_SAMPLES
+#endif  // CONFIG_EXT_WARPED_MOTION
   return bestmse;
 }
 #endif  // CONFIG_WARPED_MOTION
diff --git a/av1/encoder/mcomp.h b/av1/encoder/mcomp.h
index 2c53075..37cd2d2 100644
--- a/av1/encoder/mcomp.h
+++ b/av1/encoder/mcomp.h
@@ -157,7 +157,7 @@
 unsigned int av1_compute_motion_cost(const struct AV1_COMP *cpi,
                                      MACROBLOCK *const x, BLOCK_SIZE bsize,
                                      int mi_row, int mi_col, const MV *this_mv);
-#if WARPED_MOTION_SORT_SAMPLES
+#if CONFIG_EXT_WARPED_MOTION
 unsigned int av1_refine_warped_mv(const struct AV1_COMP *cpi,
                                   MACROBLOCK *const x, BLOCK_SIZE bsize,
                                   int mi_row, int mi_col, int *pts0,
@@ -168,7 +168,7 @@
                                   MACROBLOCK *const x, BLOCK_SIZE bsize,
                                   int mi_row, int mi_col, int *pts,
                                   int *pts_inref);
-#endif  // WARPED_MOTION_SORT_SAMPLES
+#endif  // CONFIG_EXT_WARPED_MOTION
 #endif  // CONFIG_WARPED_MOTION
 
 #endif  // AV1_ENCODER_MCOMP_H_
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index 9f15370..7b7afb2 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -8771,13 +8771,13 @@
 #endif  // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
 
 #if CONFIG_WARPED_MOTION
-#if WARPED_MOTION_SORT_SAMPLES
+#if CONFIG_EXT_WARPED_MOTION
   int pts0[SAMPLES_ARRAY_SIZE], pts_inref0[SAMPLES_ARRAY_SIZE];
   int pts_mv0[SAMPLES_ARRAY_SIZE];
   int total_samples;
 #else
   int pts[SAMPLES_ARRAY_SIZE], pts_inref[SAMPLES_ARRAY_SIZE];
-#endif  // WARPED_MOTION_SORT_SAMPLES
+#endif  // CONFIG_EXT_WARPED_MOTION
 #endif  // CONFIG_WARPED_MOTION
 
 #if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
@@ -8787,13 +8787,13 @@
   if (cm->interp_filter == SWITCHABLE) rd_stats->rate += rs;
 #if CONFIG_WARPED_MOTION
   aom_clear_system_state();
-#if WARPED_MOTION_SORT_SAMPLES
+#if CONFIG_EXT_WARPED_MOTION
   mbmi->num_proj_ref[0] =
       findSamples(cm, xd, mi_row, mi_col, pts0, pts_inref0, pts_mv0);
   total_samples = mbmi->num_proj_ref[0];
 #else
   mbmi->num_proj_ref[0] = findSamples(cm, xd, mi_row, mi_col, pts, pts_inref);
-#endif  // WARPED_MOTION_SORT_SAMPLES
+#endif  // CONFIG_EXT_WARPED_MOTION
   best_bmc_mbmi->num_proj_ref[0] = mbmi->num_proj_ref[0];
 #endif  // CONFIG_WARPED_MOTION
 #if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
@@ -8865,16 +8865,16 @@
 
 #if CONFIG_WARPED_MOTION
     if (mbmi->motion_mode == WARPED_CAUSAL) {
-#if WARPED_MOTION_SORT_SAMPLES
+#if CONFIG_EXT_WARPED_MOTION
       int pts[SAMPLES_ARRAY_SIZE], pts_inref[SAMPLES_ARRAY_SIZE];
-#endif  // WARPED_MOTION_SORT_SAMPLES
+#endif  // CONFIG_EXT_WARPED_MOTION
       *mbmi = *best_bmc_mbmi;
       mbmi->motion_mode = WARPED_CAUSAL;
       mbmi->wm_params[0].wmtype = DEFAULT_WMTYPE;
       mbmi->interp_filters = av1_broadcast_interp_filter(
           av1_unswitchable_filter(cm->interp_filter));
 
-#if WARPED_MOTION_SORT_SAMPLES
+#if CONFIG_EXT_WARPED_MOTION
       memcpy(pts, pts0, total_samples * 2 * sizeof(*pts0));
       memcpy(pts_inref, pts_inref0, total_samples * 2 * sizeof(*pts_inref0));
       // Rank the samples by motion vector difference
@@ -8883,7 +8883,7 @@
                                             pts_inref, mbmi->num_proj_ref[0]);
         best_bmc_mbmi->num_proj_ref[0] = mbmi->num_proj_ref[0];
       }
-#endif  // WARPED_MOTION_SORT_SAMPLES
+#endif  // CONFIG_EXT_WARPED_MOTION
 
       if (!find_projection(mbmi->num_proj_ref[0], pts, pts_inref, bsize,
                            mbmi->mv[0].as_mv.row, mbmi->mv[0].as_mv.col,
@@ -8893,7 +8893,7 @@
           int tmp_rate_mv = 0;
           const int_mv mv0 = mbmi->mv[0];
           WarpedMotionParams wm_params0 = mbmi->wm_params[0];
-#if WARPED_MOTION_SORT_SAMPLES
+#if CONFIG_EXT_WARPED_MOTION
           int num_proj_ref0 = mbmi->num_proj_ref[0];
 
           // Refine MV in a small range.
@@ -8902,7 +8902,7 @@
 #else
           // Refine MV in a small range.
           av1_refine_warped_mv(cpi, x, bsize, mi_row, mi_col, pts, pts_inref);
-#endif  // WARPED_MOTION_SORT_SAMPLES
+#endif  // CONFIG_EXT_WARPED_MOTION
 
           // Keep the refined MV and WM parameters.
           if (mv0.as_int != mbmi->mv[0].as_int) {
@@ -8922,9 +8922,9 @@
                                     refs[0])) {
               tmp_rate_mv = AOMMAX((tmp_rate_mv / NEW_MV_DISCOUNT_FACTOR), 1);
             }
-#if WARPED_MOTION_SORT_SAMPLES
+#if CONFIG_EXT_WARPED_MOTION
             best_bmc_mbmi->num_proj_ref[0] = mbmi->num_proj_ref[0];
-#endif  // WARPED_MOTION_SORT_SAMPLES
+#endif  // CONFIG_EXT_WARPED_MOTION
             tmp_rate2 = rate2_bmc_nocoeff - rate_mv_bmc + tmp_rate_mv;
 #if CONFIG_DUAL_FILTER
             mbmi->interp_filters =
@@ -8934,9 +8934,9 @@
             // Restore the old MV and WM parameters.
             mbmi->mv[0] = mv0;
             mbmi->wm_params[0] = wm_params0;
-#if WARPED_MOTION_SORT_SAMPLES
+#if CONFIG_EXT_WARPED_MOTION
             mbmi->num_proj_ref[0] = num_proj_ref0;
-#endif  // WARPED_MOTION_SORT_SAMPLES
+#endif  // CONFIG_EXT_WARPED_MOTION
           }
         }
 
@@ -12234,7 +12234,7 @@
 #if CONFIG_WARPED_MOTION
   if (is_motion_variation_allowed_bsize(bsize) && !has_second_ref(mbmi)) {
     int pts[SAMPLES_ARRAY_SIZE], pts_inref[SAMPLES_ARRAY_SIZE];
-#if WARPED_MOTION_SORT_SAMPLES
+#if CONFIG_EXT_WARPED_MOTION
     int pts_mv[SAMPLES_ARRAY_SIZE];
     mbmi->num_proj_ref[0] =
         findSamples(cm, xd, mi_row, mi_col, pts, pts_inref, pts_mv);
@@ -12244,7 +12244,7 @@
                                           pts_inref, mbmi->num_proj_ref[0]);
 #else
     mbmi->num_proj_ref[0] = findSamples(cm, xd, mi_row, mi_col, pts, pts_inref);
-#endif  // WARPED_MOTION_SORT_SAMPLES
+#endif  // CONFIG_EXT_WARPED_MOTION
   }
 #endif
 
diff --git a/build/cmake/aom_config_defaults.cmake b/build/cmake/aom_config_defaults.cmake
index a2f08d4..f0feedb 100644
--- a/build/cmake/aom_config_defaults.cmake
+++ b/build/cmake/aom_config_defaults.cmake
@@ -145,6 +145,7 @@
 set(CONFIG_EXT_SKIP 0 CACHE NUMBER "AV1 experiment flag.")
 set(CONFIG_EXT_TILE 0 CACHE NUMBER "AV1 experiment flag.")
 set(CONFIG_EXT_TX 1 CACHE NUMBER "AV1 experiment flag.")
+set(CONFIG_EXT_WARPED_MOTION 0 CACHE NUMBER "AV1 experiment flag.")
 set(CONFIG_FILTER_INTRA 0 CACHE NUMBER "AV1 experiment flag.")
 set(CONFIG_FP_MB_STATS 0 CACHE NUMBER "AV1 experiment flag.")
 set(CONFIG_FRAME_MARKER 0 CACHE NUMBER "AV1 experiment flag.")
diff --git a/configure b/configure
index c73ab0c..dccc16b 100755
--- a/configure
+++ b/configure
@@ -352,6 +352,7 @@
     lpf_sb
     opt_ref_mv
     tmv
+    ext_warped_motion
     restrict_compressed_hdr
     horzonly_frame_superres
 "
@@ -591,6 +592,7 @@
     enabled ext_skip && enable_feature frame_marker
     enabled ext_skip && enable_feature ext_refs
     enabled horzonly_frame_superres && enable_feature frame_superres
+    enabled ext_warped_motion && enable_feature warped_motion
 
     if enabled rawbits && enabled ans; then
       log_echo "rawbits requires not ans, so disabling rawbits"