Support affine/homography models for global motion
With this patch affine or homography models can be enabled
by simply changing the value of the GLOBAL_TRANS_TYPES
macro in common/mv.h to 4 and 5 respectively. Currently
it is left at supporting only rotzoom. There is a small
gain with enabling affine.
Also refactors costing to change based on the model type.
Change-Id: I46c1759de06c42c176c64ec21307ff347ddcc259
diff --git a/av1/common/mv.h b/av1/common/mv.h
index a591329..cd4b4e6 100644
--- a/av1/common/mv.h
+++ b/av1/common/mv.h
@@ -55,14 +55,14 @@
typedef enum {
IDENTITY = 0, // identity transformation, 0-parameter
TRANSLATION = 1, // translational motion 2-parameter
- ROTZOOM = 2, // simplified affine with rotation and zoom only, 4-parameter
+ ROTZOOM = 2, // simplified affine with rotation + zoom only, 4-parameter
AFFINE = 3, // affine, 6-parameter
HOMOGRAPHY = 4, // homography, 8-parameter
TRANS_TYPES = 5,
} TransformationType;
/* clang-format on */
-// Number of types used for global motion (must be <= TRANS_TYPES)
+// Number of types used for global motion (must be >= 3 and <= TRANS_TYPES)
#define GLOBAL_TRANS_TYPES 3
// number of parameters used by each transformation in TransformationTypes
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index e4873ab..47ca2fc 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -4896,28 +4896,32 @@
for (frame = LAST_FRAME; frame <= ALTREF_FRAME; ++frame) {
ref_buf = get_ref_frame_buffer(cpi, frame);
if (ref_buf) {
+ TransformationType model;
aom_clear_system_state();
- if (compute_global_motion_feature_based(GLOBAL_TRANS_TYPES - 1,
- cpi->Source, ref_buf,
+ for (model = ROTZOOM; model < GLOBAL_TRANS_TYPES; ++model) {
+ if (compute_global_motion_feature_based(model, cpi->Source, ref_buf,
#if CONFIG_AOM_HIGHBITDEPTH
- cpi->common.bit_depth,
+ cpi->common.bit_depth,
#endif // CONFIG_AOM_HIGHBITDEPTH
- params)) {
- convert_model_to_params(params, &cm->global_motion[frame]);
- if (cm->global_motion[frame].wmtype != IDENTITY) {
- erroradvantage = refine_integerized_param(
- &cm->global_motion[frame], cm->global_motion[frame].wmtype,
+ params)) {
+ convert_model_to_params(params, &cm->global_motion[frame]);
+ if (cm->global_motion[frame].wmtype != IDENTITY) {
+ erroradvantage = refine_integerized_param(
+ &cm->global_motion[frame], cm->global_motion[frame].wmtype,
#if CONFIG_AOM_HIGHBITDEPTH
- xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH, xd->bd,
+ xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH, xd->bd,
#endif // CONFIG_AOM_HIGHBITDEPTH
- ref_buf->y_buffer, ref_buf->y_width, ref_buf->y_height,
- ref_buf->y_stride, cpi->Source->y_buffer, cpi->Source->y_width,
- cpi->Source->y_height, cpi->Source->y_stride, 3);
- if (erroradvantage >
- gm_advantage_thresh[cm->global_motion[frame].wmtype]) {
- set_default_gmparams(&cm->global_motion[frame]);
+ ref_buf->y_buffer, ref_buf->y_width, ref_buf->y_height,
+ ref_buf->y_stride, cpi->Source->y_buffer,
+ cpi->Source->y_width, cpi->Source->y_height,
+ cpi->Source->y_stride, 3);
+ if (erroradvantage >
+ gm_advantage_thresh[cm->global_motion[frame].wmtype]) {
+ set_default_gmparams(&cm->global_motion[frame]);
+ }
}
}
+ if (cm->global_motion[frame].wmtype != IDENTITY) break;
}
aom_clear_system_state();
}
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index b21727b..1123cf5 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -2884,14 +2884,14 @@
}
#if CONFIG_GLOBAL_MOTION
-#define MIN_GLOBAL_MOTION_BLKS 4
static int recode_loop_test_global_motion(AV1_COMP *cpi) {
+ static const int min_blocks[TRANS_TYPES] = { 0, 2, 4, 6, 8 };
int i;
int recode = 0;
AV1_COMMON *const cm = &cpi->common;
for (i = LAST_FRAME; i <= ALTREF_FRAME; ++i) {
if (cm->global_motion[i].wmtype != IDENTITY &&
- cpi->global_motion_used[i] < MIN_GLOBAL_MOTION_BLKS) {
+ cpi->global_motion_used[i] < min_blocks[cm->global_motion[i].wmtype]) {
set_default_gmparams(&cm->global_motion[i]);
#if CONFIG_REF_MV
recode = 1;
diff --git a/av1/encoder/ransac.c b/av1/encoder/ransac.c
index 9c19903..8bacfe5 100644
--- a/av1/encoder/ransac.c
+++ b/av1/encoder/ransac.c
@@ -151,7 +151,6 @@
*number_of_inliers = 0;
if (npoints < minpts * MINPTS_MULTIPLIER || npoints == 0) {
- printf("Cannot find motion with %d matches\n", npoints);
return 1;
}
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index b7faf03..3b62c1c 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -4333,29 +4333,22 @@
#endif // CONFIG_EXT_INTER
#if CONFIG_GLOBAL_MOTION
-#define GLOBAL_MOTION_COST_AMORTIZATION_BLKS 8
-
-#if GLOBAL_MOTION_COST_AMORTIZATION_BLKS > 0
-static int get_gmbitcost(const AV1_COMP *const cpi,
- const WarpedMotionParams *gm) {
+static int GLOBAL_MOTION_RATE(const AV1_COMP *const cpi, int ref) {
+ static const int gm_amortization_blks[TRANS_TYPES] = { 4, 6, 8, 10, 12 };
static const int gm_params_cost[TRANS_TYPES] = {
GM_IDENTITY_BITS, GM_TRANSLATION_BITS, GM_ROTZOOM_BITS,
GM_AFFINE_BITS, GM_HOMOGRAPHY_BITS,
};
- const int cost = (gm_params_cost[gm->wmtype] << AV1_PROB_COST_SHIFT) +
- cpi->gmtype_cost[gm->wmtype];
+ const WarpedMotionParams *gm = &cpi->common.global_motion[(ref)];
assert(gm->wmtype < GLOBAL_TRANS_TYPES);
- return cost;
+ if (cpi->global_motion_used[ref] >= gm_amortization_blks[gm->wmtype]) {
+ return 0;
+ } else {
+ const int cost = (gm_params_cost[gm->wmtype] << AV1_PROB_COST_SHIFT) +
+ cpi->gmtype_cost[gm->wmtype];
+ return cost / gm_amortization_blks[gm->wmtype];
+ }
}
-
-#define GLOBAL_MOTION_RATE(ref) \
- (cpi->global_motion_used[ref] >= GLOBAL_MOTION_COST_AMORTIZATION_BLKS \
- ? 0 \
- : get_gmbitcost(cpi, &cm->global_motion[(ref)]) / \
- GLOBAL_MOTION_COST_AMORTIZATION_BLKS)
-#else
-#define GLOBAL_MOTION_RATE(ref) 0
-#endif // GLOBAL_MOTION_COST_AMORTIZATION_BLKS > 0
#endif // CONFIG_GLOBAL_MOTION
static int set_and_cost_bmi_mvs(const AV1_COMP *const cpi, MACROBLOCK *x,
@@ -4369,9 +4362,6 @@
#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;
@@ -4427,13 +4417,13 @@
gm_get_motion_vector(&cpi->common.global_motion[mbmi->ref_frame[0]],
cpi->common.allow_high_precision_mv)
.as_int;
- thismvcost += GLOBAL_MOTION_RATE(mbmi->ref_frame[0]);
+ thismvcost += GLOBAL_MOTION_RATE(cpi, mbmi->ref_frame[0]);
if (is_compound) {
this_mv[1].as_int =
gm_get_motion_vector(&cpi->common.global_motion[mbmi->ref_frame[1]],
cpi->common.allow_high_precision_mv)
.as_int;
- thismvcost += GLOBAL_MOTION_RATE(mbmi->ref_frame[1]);
+ thismvcost += GLOBAL_MOTION_RATE(cpi, mbmi->ref_frame[1]);
}
#else // CONFIG_GLOBAL_MOTION
this_mv[0].as_int = 0;
@@ -8059,9 +8049,9 @@
#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
#if CONFIG_GLOBAL_MOTION
if (this_mode == ZEROMV) {
- rd_stats->rate += GLOBAL_MOTION_RATE(mbmi->ref_frame[0]);
+ rd_stats->rate += GLOBAL_MOTION_RATE(cpi, mbmi->ref_frame[0]);
if (is_comp_pred)
- rd_stats->rate += GLOBAL_MOTION_RATE(mbmi->ref_frame[1]);
+ rd_stats->rate += GLOBAL_MOTION_RATE(cpi, mbmi->ref_frame[1]);
}
#endif // CONFIG_GLOBAL_MOTION