Add WARPED_MOTION experiment
Performance gain (REF_MV on by default)
WARPED_MOTION: 1.061%
WARPED_MOTION+MOTION_VAR: 2.917%
MOTION_VAR: 2.337%
Change-Id: I43f742a02cdd43d13ef333a0a15087062ad020ab
diff --git a/av1/common/blockd.h b/av1/common/blockd.h
index 6798b69..2a88725 100644
--- a/av1/common/blockd.h
+++ b/av1/common/blockd.h
@@ -309,6 +309,10 @@
int mi_row;
int mi_col;
#endif
+#if CONFIG_WARPED_MOTION
+ int num_proj_ref[2];
+ WarpedMotionParams wm_params[2];
+#endif // CONFIG_WARPED_MOTION
} MB_MODE_INFO;
typedef struct MODE_INFO {
@@ -894,13 +898,27 @@
return (bsize >= BLOCK_8X8);
}
-static INLINE int is_motion_variation_allowed(const MB_MODE_INFO *mbmi) {
+static INLINE MOTION_MODE motion_mode_allowed(const MB_MODE_INFO *mbmi) {
#if CONFIG_EXT_INTER
- return is_motion_variation_allowed_bsize(mbmi->sb_type) &&
- mbmi->ref_frame[1] != INTRA_FRAME;
+ if (is_motion_variation_allowed_bsize(mbmi->sb_type) &&
+ is_inter_mode(mbmi->mode) && mbmi->ref_frame[1] != INTRA_FRAME) {
#else
- return is_motion_variation_allowed_bsize(mbmi->sb_type);
+ if (is_motion_variation_allowed_bsize(mbmi->sb_type) &&
+ is_inter_mode(mbmi->mode)) {
#endif // CONFIG_EXT_INTER
+#if CONFIG_WARPED_MOTION
+ if (!has_second_ref(mbmi) && mbmi->num_proj_ref[0] >= 3)
+ return WARPED_CAUSAL;
+ else
+#endif // CONFIG_WARPED_MOTION
+#if CONFIG_MOTION_VAR
+ return OBMC_CAUSAL;
+#else
+ return SIMPLE_TRANSLATION;
+#endif // CONFIG_MOTION_VAR
+ } else {
+ return SIMPLE_TRANSLATION;
+ }
}
#if CONFIG_MOTION_VAR
diff --git a/av1/common/entropymode.c b/av1/common/entropymode.c
index 83d0822..faa9abf 100644
--- a/av1/common/entropymode.c
+++ b/av1/common/entropymode.c
@@ -530,6 +530,7 @@
const aom_tree_index av1_motion_mode_tree[TREE_SIZE(MOTION_MODES)] = {
-SIMPLE_TRANSLATION, -WARPED_CAUSAL
};
+
static const aom_prob default_motion_mode_prob[BLOCK_SIZES]
[MOTION_MODES - 1] = {
{ 255 }, { 255 }, { 255 },
@@ -556,7 +557,15 @@
{ 252, 200 }, { 252, 200 }, { 252, 200 },
#endif // CONFIG_EXT_PARTITION
};
-#endif // CONFIG_MOTION_VAR || !CONFIG_WARPED_MOTION
+
+// Probability for the case that only 1 additional motion mode is allowed
+static const aom_prob default_obmc_prob[BLOCK_SIZES] = {
+ 255, 255, 255, 151, 153, 144, 178, 165, 160, 207, 195, 168, 244,
+#if CONFIG_EXT_PARTITION
+ 252, 252, 252,
+#endif // CONFIG_EXT_PARTITION
+};
+#endif
#if CONFIG_DELTA_Q
static const aom_prob default_delta_q_probs[DELTA_Q_CONTEXTS] = { 220, 220,
@@ -1688,6 +1697,9 @@
av1_copy(fc->inter_mode_probs, default_inter_mode_probs);
#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
av1_copy(fc->motion_mode_prob, default_motion_mode_prob);
+#if CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
+ av1_copy(fc->obmc_prob, default_obmc_prob);
+#endif // CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
#if CONFIG_EXT_INTER
av1_copy(fc->inter_compound_mode_probs, default_inter_compound_mode_probs);
@@ -1860,6 +1872,11 @@
for (i = BLOCK_8X8; i < BLOCK_SIZES; ++i)
aom_tree_merge_probs(av1_motion_mode_tree, pre_fc->motion_mode_prob[i],
counts->motion_mode[i], fc->motion_mode_prob[i]);
+#if CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
+ for (i = BLOCK_8X8; i < BLOCK_SIZES; ++i)
+ fc->obmc_prob[i] =
+ av1_mode_mv_merge_probs(pre_fc->obmc_prob[i], counts->obmc[i]);
+#endif // CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
#if CONFIG_SUPERTX
diff --git a/av1/common/entropymode.h b/av1/common/entropymode.h
index 3db5f67..4059cad 100644
--- a/av1/common/entropymode.h
+++ b/av1/common/entropymode.h
@@ -115,6 +115,9 @@
#endif // CONFIG_EXT_INTER
#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
aom_prob motion_mode_prob[BLOCK_SIZES][MOTION_MODES - 1];
+#if CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
+ aom_prob obmc_prob[BLOCK_SIZES];
+#endif // CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
aom_prob intra_inter_prob[INTRA_INTER_CONTEXTS];
aom_prob comp_inter_prob[COMP_INTER_CONTEXTS];
@@ -221,6 +224,9 @@
#endif // CONFIG_EXT_INTER
#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
unsigned int motion_mode[BLOCK_SIZES][MOTION_MODES];
+#if CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
+ unsigned int obmc[BLOCK_SIZES][2];
+#endif // CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
unsigned int intra_inter[INTRA_INTER_CONTEXTS][2];
unsigned int comp_inter[COMP_INTER_CONTEXTS][2];
diff --git a/av1/common/mvref_common.c b/av1/common/mvref_common.c
index 31568de..d47ce10 100644
--- a/av1/common/mvref_common.c
+++ b/av1/common/mvref_common.c
@@ -10,6 +10,9 @@
*/
#include "av1/common/mvref_common.h"
+#if CONFIG_WARPED_MOTION
+#include "av1/common/warped_motion.h"
+#endif // CONFIG_WARPED_MOTION
#if CONFIG_REF_MV
@@ -884,3 +887,214 @@
default: assert(0 && "Invalid block index.");
}
}
+
+#if CONFIG_WARPED_MOTION
+int findSamples(const AV1_COMMON *cm, MACROBLOCKD *xd, int mi_row, int mi_col,
+ double *pts, double *pts_inref) {
+ MB_MODE_INFO *const mbmi0 = &(xd->mi[0]->mbmi);
+ int ref_frame = mbmi0->ref_frame[0];
+ int up_available = xd->up_available;
+ int left_available = xd->left_available;
+ int i, mi_step, np = 0;
+ int mvasint[100];
+ int mvnumber = 0;
+ int global_offset_c = mi_col * 8;
+ int global_offset_r = mi_row * 8;
+ int samples_per_neighbor = 4;
+
+ // scan the above row
+ if (up_available) {
+ for (i = 0; i < AOMMIN(xd->n8_w, cm->mi_cols - mi_col); i += mi_step) {
+ int mi_row_offset = -1;
+ int mi_col_offset = i;
+
+ MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
+ MB_MODE_INFO *mbmi = &mi->mbmi;
+
+ mi_step = AOMMIN(xd->n8_w, num_8x8_blocks_wide_lookup[mbmi->sb_type]);
+
+ if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE) {
+ int bw = num_4x4_blocks_wide_lookup[mbmi->sb_type] * 4;
+ int bh = num_4x4_blocks_high_lookup[mbmi->sb_type] * 4;
+ int mv_row = mbmi->mv[0].as_mv.row;
+ int mv_col = mbmi->mv[0].as_mv.col;
+ int cr_offset = -AOMMAX(bh, 8) / 2 - 1;
+ int cc_offset = i * 8 + AOMMAX(bw, 8) / 2 - 1;
+ int j;
+ int pixelperblock = samples_per_neighbor;
+
+ mvasint[mvnumber] = mbmi->mv[0].as_int;
+ mvnumber++;
+
+ for (j = 0; j < pixelperblock; j++) {
+ int r_offset = j / 2;
+ int c_offset = j % 2;
+
+ pts[0] = (double)(cc_offset + c_offset + global_offset_c);
+ pts[1] = (double)(cr_offset + r_offset + global_offset_r);
+
+ if (mbmi->motion_mode == WARPED_CAUSAL) {
+ int ipts[2], ipts_inref[2];
+ ipts[0] = cc_offset + c_offset + global_offset_c;
+ ipts[1] = cr_offset + r_offset + global_offset_r;
+
+ project_points(&mbmi->wm_params[0], ipts, ipts_inref, 1, 2, 2, 0,
+ 0);
+ pts_inref[0] =
+ (double)ipts_inref[0] / (double)WARPEDPIXEL_PREC_SHIFTS;
+ pts_inref[1] =
+ (double)ipts_inref[1] / (double)WARPEDPIXEL_PREC_SHIFTS;
+ } else {
+ pts_inref[0] = pts[0] + (double)(mv_col)*0.125;
+ pts_inref[1] = pts[1] + (double)(mv_row)*0.125;
+ }
+
+ pts += 2;
+ pts_inref += 2;
+ }
+ np += pixelperblock;
+ }
+ }
+ }
+
+ // scan the left column
+ if (left_available) {
+ for (i = 0; i < AOMMIN(xd->n8_h, cm->mi_rows - mi_row); i += mi_step) {
+ int mi_row_offset = i;
+ int mi_col_offset = -1;
+
+ MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
+ MB_MODE_INFO *mbmi = &mi->mbmi;
+
+ mi_step = AOMMIN(xd->n8_h, num_8x8_blocks_high_lookup[mbmi->sb_type]);
+
+ if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE) {
+ int bw = num_4x4_blocks_wide_lookup[mbmi->sb_type] * 4;
+ int bh = num_4x4_blocks_high_lookup[mbmi->sb_type] * 4;
+ int mv_row = mbmi->mv[0].as_mv.row;
+ int mv_col = mbmi->mv[0].as_mv.col;
+ int cr_offset = i * 8 + AOMMAX(bh, 8) / 2 - 1;
+ int cc_offset = -AOMMAX(bw, 8) / 2 - 1;
+ int j;
+ int pixelperblock = samples_per_neighbor;
+
+ mvasint[mvnumber] = mbmi->mv[0].as_int;
+ mvnumber++;
+
+ for (j = 0; j < pixelperblock; j++) {
+ int r_offset = j / 2;
+ int c_offset = j % 2;
+
+ pts[0] = (double)(cc_offset + c_offset + global_offset_c);
+ pts[1] = (double)(cr_offset + r_offset + global_offset_r);
+
+ if (mbmi->motion_mode == WARPED_CAUSAL) {
+ int ipts[2], ipts_inref[2];
+ ipts[0] = cc_offset + c_offset + global_offset_c;
+ ipts[1] = cr_offset + r_offset + global_offset_r;
+
+ project_points(&mbmi->wm_params[0], ipts, ipts_inref, 1, 2, 2, 0,
+ 0);
+ pts_inref[0] =
+ (double)ipts_inref[0] / (double)WARPEDPIXEL_PREC_SHIFTS;
+ pts_inref[1] =
+ (double)ipts_inref[1] / (double)WARPEDPIXEL_PREC_SHIFTS;
+ } else {
+ pts_inref[0] = pts[0] + (double)(mv_col)*0.125;
+ pts_inref[1] = pts[1] + (double)(mv_row)*0.125;
+ }
+
+ pts += 2;
+ pts_inref += 2;
+ }
+ np += pixelperblock;
+ }
+ }
+ }
+
+ if (left_available && up_available) {
+ int mi_row_offset = -1;
+ int mi_col_offset = -1;
+
+ MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
+ MB_MODE_INFO *mbmi = &mi->mbmi;
+
+ if (mbmi->ref_frame[0] == ref_frame && mbmi->ref_frame[1] == NONE) {
+ int bw = num_4x4_blocks_wide_lookup[mbmi->sb_type] * 4;
+ int bh = num_4x4_blocks_high_lookup[mbmi->sb_type] * 4;
+ int mv_row = mbmi->mv[0].as_mv.row;
+ int mv_col = mbmi->mv[0].as_mv.col;
+ int cr_offset = -AOMMAX(bh, 8) / 2 - 1;
+ int cc_offset = -AOMMAX(bw, 8) / 2 - 1;
+ int j;
+ int pixelperblock = samples_per_neighbor;
+
+ mvasint[mvnumber] = mbmi->mv[0].as_int;
+ mvnumber++;
+
+ for (j = 0; j < pixelperblock; j++) {
+ int r_offset = j / 2;
+ int c_offset = j % 2;
+
+ pts[0] = (double)(cc_offset + c_offset + global_offset_c);
+ pts[1] = (double)(cr_offset + r_offset + global_offset_r);
+
+ if (mbmi->motion_mode == WARPED_CAUSAL) {
+ int ipts[2], ipts_inref[2];
+ ipts[0] = cc_offset + c_offset + global_offset_c;
+ ipts[1] = cr_offset + r_offset + global_offset_r;
+
+ project_points(&mbmi->wm_params[0], ipts, ipts_inref, 1, 2, 2, 0, 0);
+ pts_inref[0] =
+ (double)ipts_inref[0] / (double)WARPEDPIXEL_PREC_SHIFTS;
+ pts_inref[1] =
+ (double)ipts_inref[1] / (double)WARPEDPIXEL_PREC_SHIFTS;
+ } else {
+ pts_inref[0] = pts[0] + (double)(mv_col)*0.125;
+ pts_inref[1] = pts[1] + (double)(mv_row)*0.125;
+ }
+
+ pts += 2;
+ pts_inref += 2;
+ }
+ np += pixelperblock;
+ }
+ }
+
+ for (i = 0; i < (mvnumber - 1); ++i) {
+ if (mvasint[i] != mvasint[i + 1]) break;
+ }
+
+ if (np == 0 || i == (mvnumber - 1)) {
+ return 0;
+ } else {
+ MODE_INFO *mi = xd->mi[0];
+ MB_MODE_INFO *mbmi = &mi->mbmi;
+ int bw = num_4x4_blocks_wide_lookup[mbmi->sb_type] * 4;
+ int bh = num_4x4_blocks_high_lookup[mbmi->sb_type] * 4;
+ int mv_row = mbmi->mv[0].as_mv.row;
+ int mv_col = mbmi->mv[0].as_mv.col;
+ int cr_offset = AOMMAX(bh, 8) / 2 - 1;
+ int cc_offset = AOMMAX(bw, 8) / 2 - 1;
+ int j;
+ int pixelperblock = samples_per_neighbor;
+
+ for (j = 0; j < pixelperblock; j++) {
+ int r_offset = j / 2;
+ int c_offset = j % 2;
+
+ pts[0] = (double)(cc_offset + c_offset + global_offset_c);
+ pts[1] = (double)(cr_offset + r_offset + global_offset_r);
+
+ pts_inref[0] = pts[0] + (double)(mv_col)*0.125;
+ pts_inref[1] = pts[1] + (double)(mv_row)*0.125;
+
+ pts += 2;
+ pts_inref += 2;
+ }
+ np += pixelperblock;
+ }
+
+ return np;
+}
+#endif // CONFIG_WARPED_MOTION
diff --git a/av1/common/mvref_common.h b/av1/common/mvref_common.h
index 95fd6ca..e520336 100644
--- a/av1/common/mvref_common.h
+++ b/av1/common/mvref_common.h
@@ -488,6 +488,11 @@
int16_t *mode_context);
#endif // CONFIG_EXT_INTER
+#if CONFIG_WARPED_MOTION
+int findSamples(const AV1_COMMON *cm, MACROBLOCKD *xd, int mi_row, int mi_col,
+ double *pts, double *pts_inref);
+#endif // CONFIG_WARPED_MOTION
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/av1/common/reconinter.c b/av1/common/reconinter.c
index 3642f90..21921a8 100644
--- a/av1/common/reconinter.c
+++ b/av1/common/reconinter.c
@@ -24,9 +24,9 @@
#if CONFIG_MOTION_VAR
#include "av1/common/onyxc_int.h"
#endif // CONFIG_MOTION_VAR
-#if CONFIG_GLOBAL_MOTION
+#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
#include "av1/common/warped_motion.h"
-#endif // CONFIG_GLOBAL_MOTION
+#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
#if CONFIG_EXT_INTER
@@ -1377,12 +1377,30 @@
mi_x, mi_y);
}
} else {
- build_inter_predictors(xd, j, mi_col_offset, mi_row_offset, 0, bw, bh,
- 0, 0, bw, bh,
+#if CONFIG_WARPED_MOTION
+ if (above_mbmi->motion_mode == WARPED_CAUSAL) {
+ av1_warp_plane(&above_mbmi->wm_params[0],
+#if CONFIG_AOM_HIGHBITDEPTH
+ xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH, xd->bd,
+#endif // CONFIG_AOM_HIGHBITDEPTH
+ pd->pre[0].buf0, pd->pre[0].width, pd->pre[0].height,
+ pd->pre[0].stride, pd->dst.buf,
+ (((mi_col + i) * MI_SIZE) >> pd->subsampling_x),
+ ((mi_row * MI_SIZE) >> pd->subsampling_y), bw, bh,
+ pd->dst.stride, pd->subsampling_x, pd->subsampling_y,
+ 16, 16, 0);
+
+ } else {
+#endif // CONFIG_WARPED_MOTION
+ build_inter_predictors(xd, j, mi_col_offset, mi_row_offset, 0, bw, bh,
+ 0, 0, bw, bh,
#if CONFIG_SUPERTX && CONFIG_EXT_INTER
- 0, 0,
+ 0, 0,
#endif // CONFIG_SUPERTX && CONFIG_EXT_INTER
- mi_x, mi_y);
+ mi_x, mi_y);
+#if CONFIG_WARPED_MOTION
+ }
+#endif // CONFIG_WARPED_MOTION
}
}
#if CONFIG_EXT_INTER
@@ -1480,12 +1498,30 @@
mi_x, mi_y);
}
} else {
- build_inter_predictors(xd, j, mi_col_offset, mi_row_offset, 0, bw, bh,
- 0, 0, bw, bh,
+#if CONFIG_WARPED_MOTION
+ if (left_mbmi->motion_mode == WARPED_CAUSAL) {
+ av1_warp_plane(&left_mbmi->wm_params[0],
+#if CONFIG_AOM_HIGHBITDEPTH
+ xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH, xd->bd,
+#endif // CONFIG_AOM_HIGHBITDEPTH
+ pd->pre[0].buf0, pd->pre[0].width, pd->pre[0].height,
+ pd->pre[0].stride, pd->dst.buf,
+ ((mi_col * MI_SIZE) >> pd->subsampling_x),
+ (((mi_row + i) * MI_SIZE) >> pd->subsampling_y), bw,
+ bh, pd->dst.stride, pd->subsampling_x,
+ pd->subsampling_y, 16, 16, 0);
+
+ } else {
+#endif // CONFIG_WARPED_MOTION
+ build_inter_predictors(xd, j, mi_col_offset, mi_row_offset, 0, bw, bh,
+ 0, 0, bw, bh,
#if CONFIG_SUPERTX && CONFIG_EXT_INTER
- 0, 0,
+ 0, 0,
#endif // CONFIG_SUPERTX && CONFIG_EXT_INTER
- mi_x, mi_y);
+ mi_x, mi_y);
+#if CONFIG_WARPED_MOTION
+ }
+#endif // CONFIG_WARPED_MOTION
}
}
#if CONFIG_EXT_INTER
diff --git a/av1/common/warped_motion.c b/av1/common/warped_motion.c
index 1d3a869..d7d81db 100644
--- a/av1/common/warped_motion.c
+++ b/av1/common/warped_motion.c
@@ -210,6 +210,29 @@
}
}
+// 'points' are at original scale, output 'proj's are scaled up by
+// 1 << WARPEDPIXEL_PREC_BITS
+void project_points(WarpedMotionParams *wm_params, int *points, int *proj,
+ const int n, const int stride_points, const int stride_proj,
+ const int subsampling_x, const int subsampling_y) {
+ switch (wm_params->wmtype) {
+ case AFFINE:
+ project_points_affine(wm_params->wmmat, points, proj, n, stride_points,
+ stride_proj, subsampling_x, subsampling_y);
+ break;
+ case ROTZOOM:
+ project_points_rotzoom(wm_params->wmmat, points, proj, n, stride_points,
+ stride_proj, subsampling_x, subsampling_y);
+ break;
+ case HOMOGRAPHY:
+ project_points_homography(wm_params->wmmat, points, proj, n,
+ stride_points, stride_proj, subsampling_x,
+ subsampling_y);
+ break;
+ default: assert(0 && "Invalid warped motion type!"); return;
+ }
+}
+
static const int16_t
filter_ntap[WARPEDPIXEL_PREC_SHIFTS][WARPEDPIXEL_FILTER_TAPS] = {
{ 0, 0, 128, 0, 0, 0 }, { 0, -1, 128, 2, -1, 0 },
@@ -342,11 +365,11 @@
if (ix < 0 && iy < 0)
return ref[0];
- else if (ix < 0 && iy > height - 1)
+ else if (ix < 0 && iy >= height - 1)
return ref[(height - 1) * stride];
- else if (ix > width - 1 && iy < 0)
+ else if (ix >= width - 1 && iy < 0)
return ref[width - 1];
- else if (ix > width - 1 && iy > height - 1)
+ else if (ix >= width - 1 && iy >= height - 1)
return ref[(height - 1) * stride + (width - 1)];
else if (ix < 0) {
v = ROUND_POWER_OF_TWO_SIGNED(
@@ -359,13 +382,13 @@
ref[ix] * (WARPEDPIXEL_PREC_SHIFTS - sx) + ref[ix + 1] * sx,
WARPEDPIXEL_PREC_BITS);
return clip_pixel(v);
- } else if (ix > width - 1) {
+ } else if (ix >= width - 1) {
v = ROUND_POWER_OF_TWO_SIGNED(
ref[iy * stride + width - 1] * (WARPEDPIXEL_PREC_SHIFTS - sy) +
ref[(iy + 1) * stride + width - 1] * sy,
WARPEDPIXEL_PREC_BITS);
return clip_pixel(v);
- } else if (iy > height - 1) {
+ } else if (iy >= height - 1) {
v = ROUND_POWER_OF_TWO_SIGNED(
ref[(height - 1) * stride + ix] * (WARPEDPIXEL_PREC_SHIFTS - sx) +
ref[(height - 1) * stride + ix + 1] * sx,
@@ -1318,3 +1341,19 @@
}
return 0;
}
+
+int find_projection(const int np, double *pts1, double *pts2,
+ WarpedMotionParams *wm_params) {
+ double H[9];
+ int result = 1;
+
+ switch (wm_params->wmtype) {
+ case AFFINE: result = find_affine(np, pts1, pts2, H); break;
+ case ROTZOOM: result = find_rotzoom(np, pts1, pts2, H); break;
+ case HOMOGRAPHY: result = find_homography(np, pts1, pts2, H); break;
+ default: assert(0 && "Invalid warped motion type!"); return 1;
+ }
+ if (result == 0) av1_integerize_model(H, wm_params->wmtype, wm_params);
+
+ return result;
+}
diff --git a/av1/common/warped_motion.h b/av1/common/warped_motion.h
index e3894d8..76ab53f 100644
--- a/av1/common/warped_motion.h
+++ b/av1/common/warped_motion.h
@@ -24,6 +24,9 @@
#include "av1/common/mv.h"
#define MAX_PARAMDIM 9
+#if CONFIG_WARPED_MOTION
+#define DEFAULT_WMTYPE AFFINE
+#endif // CONFIG_WARPED_MOTION
typedef void (*ProjectPointsFunc)(int32_t *mat, int *points, int *proj,
const int n, const int stride_points,
@@ -49,6 +52,10 @@
const int stride_proj, const int subsampling_x,
const int subsampling_y);
+void project_points(WarpedMotionParams *wm_params, int *points, int *proj,
+ const int n, const int stride_points, const int stride_proj,
+ const int subsampling_x, const int subsampling_y);
+
double av1_warp_erroradv(WarpedMotionParams *wm,
#if CONFIG_AOM_HIGHBITDEPTH
int use_hbd, int bd,
@@ -75,4 +82,6 @@
int find_rotzoom(const int np, double *pts1, double *pts2, double *mat);
int find_affine(const int np, double *pts1, double *pts2, double *mat);
int find_homography(const int np, double *pts1, double *pts2, double *mat);
+int find_projection(const int np, double *pts1, double *pts2,
+ WarpedMotionParams *wm_params);
#endif // AV1_COMMON_WARPED_MOTION_H_
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index c155963..2b00c51 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -54,6 +54,10 @@
#include "av1/decoder/detokenize.h"
#include "av1/decoder/dsubexp.h"
+#if CONFIG_WARPED_MOTION
+#include "av1/common/warped_motion.h"
+#endif // CONFIG_WARPED_MOTION
+
#define MAX_AV1_HEADER_SIZE 80
#define ACCT_STR __func__
@@ -1588,8 +1592,36 @@
tx_size);
}
} else {
- // Prediction
- av1_build_inter_predictors_sb(xd, mi_row, mi_col, AOMMAX(bsize, BLOCK_8X8));
+// Prediction
+#if CONFIG_WARPED_MOTION
+ if (mbmi->motion_mode == WARPED_CAUSAL) {
+ int i;
+#if CONFIG_AOM_HIGHBITDEPTH
+ int use_hbd = xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH;
+#endif // CONFIG_AOM_HIGHBITDEPTH
+
+ for (i = 0; i < 3; ++i) {
+ const struct macroblockd_plane *pd = &xd->plane[i];
+
+ av1_warp_plane(&mbmi->wm_params[0],
+#if CONFIG_AOM_HIGHBITDEPTH
+ xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH, xd->bd,
+#endif // CONFIG_AOM_HIGHBITDEPTH
+ pd->pre[0].buf0, pd->pre[0].width, pd->pre[0].height,
+ pd->pre[0].stride, pd->dst.buf,
+ ((mi_col * MI_SIZE) >> pd->subsampling_x),
+ ((mi_row * MI_SIZE) >> pd->subsampling_y),
+ xd->n8_w * (8 >> pd->subsampling_x),
+ xd->n8_h * (8 >> pd->subsampling_y), pd->dst.stride,
+ pd->subsampling_x, pd->subsampling_y, 16, 16, 0);
+ }
+ } else {
+#endif // CONFIG_WARPED_MOTION
+ av1_build_inter_predictors_sb(xd, mi_row, mi_col,
+ AOMMAX(bsize, BLOCK_8X8));
+#if CONFIG_WARPED_MOTION
+ }
+#endif // CONFIG_WARPED_MOTION
#if CONFIG_MOTION_VAR
if (mbmi->motion_mode == OBMC_CAUSAL) {
av1_build_obmc_inter_predictors_sb(cm, xd, mi_row, mi_col);
diff --git a/av1/decoder/decodemv.c b/av1/decoder/decodemv.c
index f9830d9..101ed3e 100644
--- a/av1/decoder/decodemv.c
+++ b/av1/decoder/decodemv.c
@@ -19,6 +19,9 @@
#include "av1/common/pred_common.h"
#include "av1/common/reconinter.h"
#include "av1/common/seg_common.h"
+#if CONFIG_WARPED_MOTION
+#include "av1/common/warped_motion.h"
+#endif // CONFIG_WARPED_MOTION
#include "av1/decoder/decodeframe.h"
#include "av1/decoder/decodemv.h"
@@ -252,18 +255,26 @@
#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
static MOTION_MODE read_motion_mode(AV1_COMMON *cm, MACROBLOCKD *xd,
MB_MODE_INFO *mbmi, aom_reader *r) {
- if (is_motion_variation_allowed(mbmi)) {
- int motion_mode;
- FRAME_COUNTS *counts = xd->counts;
+ MOTION_MODE last_motion_mode_allowed = motion_mode_allowed(mbmi);
+ int motion_mode;
+ FRAME_COUNTS *counts = xd->counts;
+ if (last_motion_mode_allowed == SIMPLE_TRANSLATION) return SIMPLE_TRANSLATION;
+#if CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
+ if (last_motion_mode_allowed == OBMC_CAUSAL) {
+ motion_mode = aom_read(r, cm->fc->obmc_prob[mbmi->sb_type], ACCT_STR);
+ if (counts) ++counts->obmc[mbmi->sb_type][motion_mode];
+ return (MOTION_MODE)(SIMPLE_TRANSLATION + motion_mode);
+ } else {
+#endif // CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
motion_mode =
aom_read_tree(r, av1_motion_mode_tree,
cm->fc->motion_mode_prob[mbmi->sb_type], ACCT_STR);
if (counts) ++counts->motion_mode[mbmi->sb_type][motion_mode];
return (MOTION_MODE)(SIMPLE_TRANSLATION + motion_mode);
- } else {
- return SIMPLE_TRANSLATION;
+#if CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
}
+#endif // CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
}
#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
@@ -1423,6 +1434,9 @@
int16_t compound_inter_mode_ctx[MODE_CTX_REF_FRAMES];
#endif // CONFIG_REF_MV && CONFIG_EXT_INTER
int16_t mode_ctx = 0;
+#if CONFIG_WARPED_MOTION
+ double pts[144], pts_inref[144];
+#endif // CONFIG_WARPED_MOTION
#if CONFIG_PALETTE
mbmi->palette_mode_info.palette_size[0] = 0;
@@ -1591,9 +1605,9 @@
}
#endif
-#if !CONFIG_EXT_INTERP && !CONFIG_DUAL_FILTER
+#if !CONFIG_EXT_INTERP && !CONFIG_DUAL_FILTER && !CONFIG_WARPED_MOTION
read_mb_interp_filter(cm, xd, mbmi, r);
-#endif // !CONFIG_EXT_INTERP && !CONFIG_DUAL_FILTER
+#endif // !CONFIG_EXT_INTERP && !CONFIG_DUAL_FILTER && !CONFIG_WARPED_MOTION
if (bsize < BLOCK_8X8) {
const int num_4x4_w = 1 << xd->bmode_blocks_wl;
@@ -1777,13 +1791,28 @@
#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
mbmi->motion_mode = SIMPLE_TRANSLATION;
+#if CONFIG_WARPED_MOTION
+ if (mbmi->sb_type >= BLOCK_8X8 && !has_second_ref(mbmi))
+ mbmi->num_proj_ref[0] = findSamples(cm, xd, mi_row, mi_col, pts, pts_inref);
+#endif // CONFIG_WARPED_MOTION
+
#if CONFIG_SUPERTX
- if (!supertx_enabled)
+ if (!supertx_enabled) {
#endif // CONFIG_SUPERTX
#if CONFIG_EXT_INTER
if (mbmi->ref_frame[1] != INTRA_FRAME)
#endif // CONFIG_EXT_INTER
mbmi->motion_mode = read_motion_mode(cm, xd, mbmi, r);
+#if CONFIG_WARPED_MOTION
+ if (mbmi->motion_mode == WARPED_CAUSAL) {
+ mbmi->wm_params[0].wmtype = DEFAULT_WMTYPE;
+ find_projection(mbmi->num_proj_ref[0], pts, pts_inref,
+ &mbmi->wm_params[0]);
+ }
+#endif // CONFIG_WARPED_MOTION
+#if CONFIG_SUPERTX
+ }
+#endif // CONFIG_SUPERTX
#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
#if CONFIG_EXT_INTER
@@ -1791,8 +1820,7 @@
if (cm->reference_mode != SINGLE_REFERENCE &&
is_inter_compound_mode(mbmi->mode) &&
#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
- !(is_motion_variation_allowed(mbmi) &&
- mbmi->motion_mode != SIMPLE_TRANSLATION) &&
+ mbmi->motion_mode == SIMPLE_TRANSLATION &&
#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
is_interinter_wedge_used(bsize)) {
mbmi->interinter_compound = aom_read_tree(
@@ -1807,9 +1835,25 @@
}
#endif // CONFIG_EXT_INTER
-#if CONFIG_DUAL_FILTER || CONFIG_EXT_INTERP
- read_mb_interp_filter(cm, xd, mbmi, r);
-#endif // CONFIG_DUAL_FILTER || CONFIG_EXT_INTERP
+#if CONFIG_WARPED_MOTION
+ if (mbmi->motion_mode != WARPED_CAUSAL) {
+#endif // CONFIG_WARPED_MOTION
+#if CONFIG_DUAL_FILTER || CONFIG_EXT_INTERP || CONFIG_WARPED_MOTION
+ read_mb_interp_filter(cm, xd, mbmi, r);
+#endif // CONFIG_DUAL_FILTER || CONFIG_EXT_INTERP || CONFIG_WARPED_MOTION
+#if CONFIG_WARPED_MOTION
+ } else {
+#if CONFIG_DUAL_FILTER
+ mbmi->interp_filter[0] =
+ cm->interp_filter == SWITCHABLE ? EIGHTTAP_REGULAR : cm->interp_filter;
+ mbmi->interp_filter[1] =
+ cm->interp_filter == SWITCHABLE ? EIGHTTAP_REGULAR : cm->interp_filter;
+#else
+ mbmi->interp_filter =
+ cm->interp_filter == SWITCHABLE ? EIGHTTAP_REGULAR : cm->interp_filter;
+#endif // CONFIG_DUAL_FILTER
+ }
+#endif // CONFIG_WARPED_MOTION
}
static void read_inter_frame_mode_info(AV1Decoder *const pbi,
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 11d11e0..e4d8db0 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -506,6 +506,27 @@
}
}
+#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
+static void write_motion_mode(const AV1_COMMON *cm, const MB_MODE_INFO *mbmi,
+ aom_writer *w) {
+ MOTION_MODE last_motion_mode_allowed = motion_mode_allowed(mbmi);
+
+ if (last_motion_mode_allowed == SIMPLE_TRANSLATION) return;
+#if CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
+ if (last_motion_mode_allowed == OBMC_CAUSAL) {
+ aom_write(w, mbmi->motion_mode == OBMC_CAUSAL,
+ cm->fc->obmc_prob[mbmi->sb_type]);
+ } else {
+#endif // CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
+ av1_write_token(w, av1_motion_mode_tree,
+ cm->fc->motion_mode_prob[mbmi->sb_type],
+ &motion_mode_encodings[mbmi->motion_mode]);
+#if CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
+ }
+#endif // CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
+}
+#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
+
#if CONFIG_DELTA_Q
static void write_delta_qindex(const AV1_COMMON *cm, int delta_qindex,
aom_writer *w) {
@@ -1383,9 +1404,9 @@
}
}
-#if !CONFIG_EXT_INTERP && !CONFIG_DUAL_FILTER
+#if !CONFIG_EXT_INTERP && !CONFIG_DUAL_FILTER && !CONFIG_WARPED_MOTION
write_mb_interp_filter(cpi, xd, w);
-#endif // !CONFIG_EXT_INTERP
+#endif // !CONFIG_EXT_INTERP && !CONFIG_DUAL_FILTER && !CONFIG_WARPED_MOTION
if (bsize < BLOCK_8X8) {
const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
@@ -1573,23 +1594,14 @@
#if CONFIG_EXT_INTER
if (mbmi->ref_frame[1] != INTRA_FRAME)
#endif // CONFIG_EXT_INTER
- if (is_motion_variation_allowed(mbmi)) {
- // TODO(debargha): Might want to only emit this if SEG_LVL_SKIP
- // is not active, and assume SIMPLE_TRANSLATION in the decoder if
- // it is active.
- assert(mbmi->motion_mode < MOTION_MODES);
- av1_write_token(w, av1_motion_mode_tree,
- cm->fc->motion_mode_prob[bsize],
- &motion_mode_encodings[mbmi->motion_mode]);
- }
+ write_motion_mode(cm, mbmi, w);
#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
#if CONFIG_EXT_INTER
if (cpi->common.reference_mode != SINGLE_REFERENCE &&
is_inter_compound_mode(mbmi->mode) &&
#if CONFIG_MOTION_VAR
- !(is_motion_variation_allowed(mbmi) &&
- mbmi->motion_mode != SIMPLE_TRANSLATION) &&
+ mbmi->motion_mode == SIMPLE_TRANSLATION &&
#endif // CONFIG_MOTION_VAR
is_interinter_wedge_used(bsize)) {
av1_write_token(w, av1_compound_type_tree,
@@ -1603,9 +1615,12 @@
}
#endif // CONFIG_EXT_INTER
-#if CONFIG_EXT_INTERP || CONFIG_DUAL_FILTER
- write_mb_interp_filter(cpi, xd, w);
-#endif // CONFIG_EXT_INTERP
+#if CONFIG_WARPED_MOTION
+ if (mbmi->motion_mode != WARPED_CAUSAL)
+#endif // CONFIG_WARPED_MOTION
+#if CONFIG_EXT_INTERP || CONFIG_DUAL_FILTER || CONFIG_WARPED_MOTION
+ write_mb_interp_filter(cpi, xd, w);
+#endif // CONFIG_EXT_INTERP || CONFIG_DUAL_FILTE || CONFIG_WARPED_MOTION
}
write_tx_type(cm, mbmi,
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index d828275..8540cc4 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -40,10 +40,12 @@
#if CONFIG_SUPERTX
#include "av1/encoder/cost.h"
#endif
-#if CONFIG_GLOBAL_MOTION
+#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
#include "av1/common/warped_motion.h"
+#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
+#if CONFIG_GLOBAL_MOTION
#include "av1/encoder/global_motion.h"
-#endif
+#endif // CONFIG_GLOBAL_MOTION
#include "av1/encoder/encodeframe.h"
#include "av1/encoder/encodemb.h"
#include "av1/encoder/encodemv.h"
@@ -1182,7 +1184,10 @@
#if CONFIG_EXT_INTERP
&& av1_is_interp_needed(xd)
#endif
- ) {
+#if CONFIG_WARPED_MOTION
+ && mbmi->motion_mode != WARPED_CAUSAL
+#endif // CONFIG_WARPED_MOTION
+ ) {
#if CONFIG_DUAL_FILTER
update_filter_type_count(td->counts, xd, mbmi);
#else
@@ -1972,16 +1977,24 @@
#if CONFIG_EXT_INTER
if (mbmi->ref_frame[1] != INTRA_FRAME)
#endif // CONFIG_EXT_INTER
- if (is_motion_variation_allowed(mbmi))
+#if CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
+ {
+ if (motion_mode_allowed(mbmi) == WARPED_CAUSAL)
counts->motion_mode[mbmi->sb_type][mbmi->motion_mode]++;
+ else if (motion_mode_allowed(mbmi) == OBMC_CAUSAL)
+ counts->obmc[mbmi->sb_type][mbmi->motion_mode == OBMC_CAUSAL]++;
+ }
+#else
+ if (motion_mode_allowed(mbmi) > SIMPLE_TRANSLATION)
+ counts->motion_mode[mbmi->sb_type][mbmi->motion_mode]++;
+#endif // CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
#if CONFIG_EXT_INTER
if (cm->reference_mode != SINGLE_REFERENCE &&
is_inter_compound_mode(mbmi->mode) &&
#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
- !(is_motion_variation_allowed(mbmi) &&
- mbmi->motion_mode != SIMPLE_TRANSLATION) &&
+ mbmi->motion_mode == SIMPLE_TRANSLATION &&
#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
is_interinter_wedge_used(bsize)) {
counts->compound_interinter[bsize][mbmi->interinter_compound]++;
@@ -5488,12 +5501,39 @@
av1_setup_pre_planes(xd, ref, cfg, mi_row, mi_col,
&xd->block_refs[ref]->sf);
}
- if (!(cpi->sf.reuse_inter_pred_sby && ctx->pred_pixel_ready) || seg_skip)
- av1_build_inter_predictors_sby(xd, mi_row, mi_col,
- AOMMAX(bsize, BLOCK_8X8));
+#if CONFIG_WARPED_MOTION
+ if (mbmi->motion_mode == WARPED_CAUSAL) {
+ int i;
+#if CONFIG_AOM_HIGHBITDEPTH
+ int use_hbd = xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH;
+#endif // CONFIG_AOM_HIGHBITDEPTH
- av1_build_inter_predictors_sbuv(xd, mi_row, mi_col,
- AOMMAX(bsize, BLOCK_8X8));
+ for (i = 0; i < 3; ++i) {
+ const struct macroblockd_plane *pd = &xd->plane[i];
+
+ av1_warp_plane(&mbmi->wm_params[0],
+#if CONFIG_AOM_HIGHBITDEPTH
+ xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH, xd->bd,
+#endif // CONFIG_AOM_HIGHBITDEPTH
+ pd->pre[0].buf0, pd->pre[0].width, pd->pre[0].height,
+ pd->pre[0].stride, pd->dst.buf,
+ ((mi_col * MI_SIZE) >> pd->subsampling_x),
+ ((mi_row * MI_SIZE) >> pd->subsampling_y),
+ xd->n8_w * (8 >> pd->subsampling_x),
+ xd->n8_h * (8 >> pd->subsampling_y), pd->dst.stride,
+ pd->subsampling_x, pd->subsampling_y, 16, 16, 0);
+ }
+ } else {
+#endif // CONFIG_WARPED_MOTION
+ if (!(cpi->sf.reuse_inter_pred_sby && ctx->pred_pixel_ready) || seg_skip)
+ av1_build_inter_predictors_sby(xd, mi_row, mi_col,
+ AOMMAX(bsize, BLOCK_8X8));
+
+ av1_build_inter_predictors_sbuv(xd, mi_row, mi_col,
+ AOMMAX(bsize, BLOCK_8X8));
+#if CONFIG_WARPED_MOTION
+ }
+#endif // CONFIG_WARPED_MOTION
#if CONFIG_MOTION_VAR
if (mbmi->motion_mode == OBMC_CAUSAL) {
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 28a44c3..be64d79 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -535,6 +535,9 @@
#endif // CONFIG_EXT_INTER
#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
int motion_mode_cost[BLOCK_SIZES][MOTION_MODES];
+#if CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
+ int motion_mode_cost1[BLOCK_SIZES][2];
+#endif // CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
int intra_uv_mode_cost[INTRA_MODES][INTRA_MODES];
int y_mode_costs[INTRA_MODES][INTRA_MODES][INTRA_MODES];
diff --git a/av1/encoder/ransac.c b/av1/encoder/ransac.c
index c47e1ae..9c19903 100644
--- a/av1/encoder/ransac.c
+++ b/av1/encoder/ransac.c
@@ -18,7 +18,6 @@
#include "av1/encoder/ransac.h"
#define MAX_MINPTS 4
-
#define MAX_DEGENERATE_ITER 10
#define MINPTS_MULTIPLIER 5
diff --git a/av1/encoder/rd.c b/av1/encoder/rd.c
index e1e1595..9b327b2 100644
--- a/av1/encoder/rd.c
+++ b/av1/encoder/rd.c
@@ -443,6 +443,12 @@
av1_cost_tokens((int *)cpi->motion_mode_cost[i],
cm->fc->motion_mode_prob[i], av1_motion_mode_tree);
}
+#if CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
+ for (i = BLOCK_8X8; i < BLOCK_SIZES; i++) {
+ cpi->motion_mode_cost1[i][0] = av1_cost_bit(cm->fc->obmc_prob[i], 0);
+ cpi->motion_mode_cost1[i][1] = av1_cost_bit(cm->fc->obmc_prob[i], 1);
+ }
+#endif // CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
}
}
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index 23e1729..27db8f6 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -33,6 +33,9 @@
#include "av1/common/reconintra.h"
#include "av1/common/scan.h"
#include "av1/common/seg_common.h"
+#if CONFIG_WARPED_MOTION
+#include "av1/common/warped_motion.h"
+#endif // CONFIG_WARPED_MOTION
#include "av1/encoder/aq_variance.h"
#include "av1/encoder/cost.h"
@@ -6907,12 +6910,7 @@
uint8_t *tmp_buf;
#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
- MOTION_MODE motion_mode;
- int allow_motvar =
-#if CONFIG_EXT_INTER
- !is_comp_interintra_pred &&
-#endif // CONFIG_EXT_INTER
- is_motion_variation_allowed(mbmi);
+ MOTION_MODE motion_mode, last_motion_mode_allowed;
int rate2_nocoeff = 0, best_xskip, best_disable_skip = 0;
RD_STATS best_rd_stats, best_rd_stats_y, best_rd_stats_uv;
#if CONFIG_VAR_TX
@@ -6922,10 +6920,15 @@
MB_MODE_INFO base_mbmi, best_mbmi;
#if CONFIG_EXT_INTER
int rate2_bmc_nocoeff;
- int rate_mv_bmc;
MB_MODE_INFO best_bmc_mbmi;
+#if CONFIG_MOTION_VAR
+ int rate_mv_bmc;
+#endif // CONFIG_MOTION_VAR
#endif // CONFIG_EXT_INTER
#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
+#if CONFIG_WARPED_MOTION
+ double pts[144], pts_inref[144];
+#endif // CONFIG_WARPED_MOTION
int64_t rd = INT64_MAX;
uint8_t *orig_dst[MAX_MB_PLANE];
int orig_dst_stride[MAX_MB_PLANE];
@@ -6975,6 +6978,11 @@
// to tmp_buf at the end of the last iteration
assert(xd->plane[0].dst.buf != tmp_buf);
+#if CONFIG_WARPED_MOTION
+ mbmi->num_proj_ref[0] = 0;
+ mbmi->num_proj_ref[1] = 0;
+#endif // CONFIG_WARPED_MOTION
+
if (is_comp_pred) {
if (frame_mv[refs[0]].as_int == INVALID_MV ||
frame_mv[refs[1]].as_int == INVALID_MV)
@@ -7340,12 +7348,14 @@
}
#if CONFIG_EXT_INTER
-#if CONFIG_MOTION_VAR
+#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
best_bmc_mbmi = *mbmi;
- rate_mv_bmc = rate_mv;
rate2_bmc_nocoeff = rd_stats->rate;
if (cm->interp_filter == SWITCHABLE) rate2_bmc_nocoeff += rs;
+#if CONFIG_MOTION_VAR
+ rate_mv_bmc = rate_mv;
#endif // CONFIG_MOTION_VAR
+#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
if (is_comp_pred && is_interinter_wedge_used(bsize)) {
int rate_sum, rs2;
@@ -7684,17 +7694,23 @@
}
if (cm->interp_filter == SWITCHABLE) rd_stats->rate += rs;
-#if CONFIG_MOTION_VAR
+#if CONFIG_WARPED_MOTION
+ aom_clear_system_state();
+ mbmi->num_proj_ref[0] = findSamples(cm, xd, mi_row, mi_col, pts, pts_inref);
+#endif // CONFIG_WARPED_MOTION
+#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
rate2_nocoeff = rd_stats->rate;
+ last_motion_mode_allowed = motion_mode_allowed(mbmi);
base_mbmi = *mbmi;
-#endif // CONFIG_MOTION_VAR
+#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
best_rd = INT64_MAX;
for (motion_mode = SIMPLE_TRANSLATION;
- motion_mode < (allow_motvar ? MOTION_MODES : 1); motion_mode++) {
- int64_t tmp_rd = INT64_MAX, tmp_dist;
+ motion_mode <= last_motion_mode_allowed; motion_mode++) {
+ int64_t tmp_rd = INT64_MAX;
int tmp_rate;
+ int64_t tmp_dist;
#if CONFIG_EXT_INTER
int tmp_rate2 =
motion_mode != SIMPLE_TRANSLATION ? rate2_bmc_nocoeff : rate2_nocoeff;
@@ -7757,7 +7773,51 @@
#if CONFIG_WARPED_MOTION
if (mbmi->motion_mode == WARPED_CAUSAL) {
- // TODO(yuec): Add code
+#if CONFIG_EXT_INTER
+ *mbmi = best_bmc_mbmi;
+ mbmi->motion_mode = WARPED_CAUSAL;
+#endif // CONFIG_EXT_INTER
+ mbmi->wm_params[0].wmtype = DEFAULT_WMTYPE;
+#if CONFIG_DUAL_FILTER
+ mbmi->interp_filter[0] = cm->interp_filter == SWITCHABLE
+ ? EIGHTTAP_REGULAR
+ : cm->interp_filter;
+ mbmi->interp_filter[1] = cm->interp_filter == SWITCHABLE
+ ? EIGHTTAP_REGULAR
+ : cm->interp_filter;
+#else
+ mbmi->interp_filter = cm->interp_filter == SWITCHABLE ? EIGHTTAP_REGULAR
+ : cm->interp_filter;
+#endif // CONFIG_DUAL_FILTER
+
+ if (find_projection(mbmi->num_proj_ref[0], pts, pts_inref,
+ &mbmi->wm_params[0]) == 0) {
+ int plane;
+#if CONFIG_AOM_HIGHBITDEPTH
+ int use_hbd = xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH;
+#endif // CONFIG_AOM_HIGHBITDEPTH
+
+ for (plane = 0; plane < 3; ++plane) {
+ const struct macroblockd_plane *pd = &xd->plane[plane];
+
+ av1_warp_plane(&mbmi->wm_params[0],
+#if CONFIG_AOM_HIGHBITDEPTH
+ xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH, xd->bd,
+#endif // CONFIG_AOM_HIGHBITDEPTH
+ pd->pre[0].buf0, pd->pre[0].width, pd->pre[0].height,
+ pd->pre[0].stride, pd->dst.buf,
+ (mi_col * MI_SIZE) >> pd->subsampling_x,
+ (mi_row * MI_SIZE) >> pd->subsampling_y,
+ (xd->n8_w * 8) >> pd->subsampling_x,
+ (xd->n8_h * 8) >> pd->subsampling_y, pd->dst.stride,
+ pd->subsampling_x, pd->subsampling_y, 16, 16, 0);
+ }
+
+ model_rd_for_sb(cpi, bsize, x, xd, 0, MAX_MB_PLANE - 1, &tmp_rate,
+ &tmp_dist, &skip_txfm_sb, &skip_sse_sb);
+ } else {
+ continue;
+ }
}
#endif // CONFIG_WARPED_MOTION
x->skip = 0;
@@ -7766,8 +7826,21 @@
rd_stats->sse = 0;
rd_stats->skip = 1;
rd_stats->rate = tmp_rate2;
- if (allow_motvar)
- rd_stats->rate += cpi->motion_mode_cost[bsize][mbmi->motion_mode];
+ if (last_motion_mode_allowed > SIMPLE_TRANSLATION) {
+#if CONFIG_WARPED_MOTION && CONFIG_MOTION_VAR
+ if (last_motion_mode_allowed == WARPED_CAUSAL)
+#endif // CONFIG_WARPED_MOTION && CONFIG_MOTION_VAR
+ rd_stats->rate += cpi->motion_mode_cost[bsize][mbmi->motion_mode];
+#if CONFIG_WARPED_MOTION && CONFIG_MOTION_VAR
+ else
+ rd_stats->rate += cpi->motion_mode_cost1[bsize][mbmi->motion_mode];
+#endif // CONFIG_WARPED_MOTION && CONFIG_MOTION_VAR
+ }
+#if CONFIG_WARPED_MOTION
+ if (mbmi->motion_mode == WARPED_CAUSAL) {
+ rd_stats->rate -= rs;
+ }
+#endif // CONFIG_WARPED_MOTION
#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
if (!skip_txfm_sb) {
int64_t rdcosty = INT64_MAX;
@@ -9259,7 +9332,7 @@
}
if (tmp_alt_rd < INT64_MAX) {
-#if CONFIG_MOTION_VAR
+#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
tmp_alt_rd = RDCOST(x->rdmult, x->rddiv, tmp_rd_stats.rate,
tmp_rd_stats.dist);
#else
@@ -9279,7 +9352,7 @@
av1_cost_bit(av1_get_skip_prob(cm, xd), 1) -
tmp_rd_stats_y.rate - tmp_rd_stats_uv.rate,
tmp_rd_stats.sse);
-#endif // CONFIG_MOTION_VAR
+#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
}
if (tmp_ref_rd > tmp_alt_rd) {
@@ -9345,11 +9418,11 @@
rate2 += ref_costs_single[ref_frame];
}
-#if CONFIG_MOTION_VAR
+#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
if (ref_frame == INTRA_FRAME) {
#else
if (!disable_skip) {
-#endif // CONFIG_MOTION_VAR
+#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
if (skippable) {
// Back out the coefficient coding costs
rate2 -= (rate_y + rate_uv);
@@ -9385,7 +9458,7 @@
// Calculate the final RD estimate for this mode.
this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
-#if CONFIG_MOTION_VAR
+#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
} else {
this_skip2 = mbmi->skip;
this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
@@ -9393,7 +9466,7 @@
rate_y = 0;
rate_uv = 0;
}
-#endif // CONFIG_MOTION_VAR
+#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
}
if (ref_frame == INTRA_FRAME) {
@@ -9440,8 +9513,15 @@
*returnrate_nocoef -= av1_cost_bit(av1_get_intra_inter_prob(cm, xd),
mbmi->ref_frame[0] != INTRA_FRAME);
#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
- if (is_inter_block(mbmi) && is_motion_variation_allowed(mbmi))
+#if CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
+ if (motion_mode_allowed(mbmi) == WARPED_CAUSAL)
+#endif // CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
*returnrate_nocoef -= cpi->motion_mode_cost[bsize][mbmi->motion_mode];
+#if CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
+ else if (motion_mode_allowed(mbmi) == OBMC_CAUSAL)
+ *returnrate_nocoef -=
+ cpi->motion_mode_cost1[bsize][mbmi->motion_mode];
+#endif // CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION
#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
#endif // CONFIG_SUPERTX
rd_cost->dist = distortion2;
@@ -9514,7 +9594,35 @@
}
if (is_inter_mode(mbmi->mode)) {
- av1_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
+#if CONFIG_WARPED_MOTION
+ if (mbmi->motion_mode == WARPED_CAUSAL) {
+ int plane;
+#if CONFIG_AOM_HIGHBITDEPTH
+ int use_hbd = xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH;
+#endif // CONFIG_AOM_HIGHBITDEPTH
+ assert(!has_second_ref(mbmi));
+
+ for (plane = 0; plane < 3; ++plane) {
+ const struct macroblockd_plane *pd = &xd->plane[plane];
+
+ av1_warp_plane(&mbmi->wm_params[0],
+#if CONFIG_AOM_HIGHBITDEPTH
+ xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH, xd->bd,
+#endif // CONFIG_AOM_HIGHBITDEPTH
+ pd->pre[0].buf0, pd->pre[0].width, pd->pre[0].height,
+ pd->pre[0].stride, pd->dst.buf,
+ ((mi_col * MI_SIZE) >> pd->subsampling_x),
+ ((mi_row * MI_SIZE) >> pd->subsampling_y),
+ xd->n8_w * (8 >> pd->subsampling_x),
+ xd->n8_h * (8 >> pd->subsampling_y), pd->dst.stride,
+ pd->subsampling_x, pd->subsampling_y, 16, 16, 0);
+ }
+ } else {
+#endif // CONFIG_WARPED_MOTION
+ av1_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
+#if CONFIG_WARPED_MOTION
+ }
+#endif // CONFIG_WARPED_MOTION
#if CONFIG_MOTION_VAR
if (mbmi->motion_mode == OBMC_CAUSAL)
av1_build_obmc_inter_prediction(cm, xd, mi_row, mi_col, dst_buf1,
@@ -10181,6 +10289,10 @@
mbmi->interinter_compound = COMPOUND_AVERAGE;
mbmi->use_wedge_interintra = 0;
#endif // CONFIG_EXT_INTER
+#if CONFIG_WARPED_MOTION
+ mbmi->num_proj_ref[0] = 0;
+ mbmi->num_proj_ref[1] = 0;
+#endif // CONFIG_WARPED_MOTION
for (i = 0; i < 4; i++) {
int j;