Commit 45390c18 authored by David Barker's avatar David Barker Committed by Debargha Mukherjee

Change gm_get_motion_vector

Since gm_get_motion_vector is trying to give a motion vector for
"the frame as a whole", it makes more sense for it to calculate
the motion of the *center* of the block rather than the top-left
corner of the frame.

In theory, this change should also help the encoder make better
decisions on when to use global motion. It avoids an issue
where, early in the frame, NEARESTMV looks like a good way to use
the global motion vector *without* paying the rate cost applied
to the first few global motion blocks in each frame. This seems
to lead to a better overall result.

Change-Id: Ia5c6259ceb8b4ff3d00a5d553e1d18bdb802da59
parent a0dae601
......@@ -149,18 +149,27 @@ typedef struct {
// Convert a global motion translation vector (which may have more bits than a
// regular motion vector) into a motion vector
static INLINE int_mv gm_get_motion_vector(const WarpedMotionParams *gm,
int allow_hp) {
int allow_hp, int x, int y) {
int_mv res;
res.as_mv.row = allow_hp ? (int16_t)ROUND_POWER_OF_TWO_SIGNED(
gm->wmmat[1], WARPEDMODEL_PREC_BITS - 3)
: (int16_t)ROUND_POWER_OF_TWO_SIGNED(
gm->wmmat[1], WARPEDMODEL_PREC_BITS - 2) *
2;
res.as_mv.col = allow_hp ? (int16_t)ROUND_POWER_OF_TWO_SIGNED(
gm->wmmat[0], WARPEDMODEL_PREC_BITS - 3)
: (int16_t)ROUND_POWER_OF_TWO_SIGNED(
gm->wmmat[0], WARPEDMODEL_PREC_BITS - 2) *
2;
const int32_t *mat = gm->wmmat;
// Project the center point of the frame and use that to derive the
// motion vector. Assume the model is an AFFINE or ROTZOOM model
int xc, yc;
int shift = allow_hp ? WARPEDMODEL_PREC_BITS - 3 : WARPEDMODEL_PREC_BITS - 2;
int scale = allow_hp ? 0 : 1;
if (gm->wmtype == ROTZOOM) {
assert(gm->wmmat[5] == gm->wmmat[2]);
assert(gm->wmmat[4] == -gm->wmmat[3]);
}
xc = mat[2] * x + mat[3] * y + mat[0];
yc = mat[4] * x + mat[5] * y + mat[1];
int tx = (ROUND_POWER_OF_TWO_SIGNED(xc, shift) << scale) - (x << 3);
int ty = (ROUND_POWER_OF_TWO_SIGNED(yc, shift) << scale) - (y << 3);
res.as_mv.row = ty;
res.as_mv.col = tx;
return res;
}
......
......@@ -891,16 +891,22 @@ void av1_find_mv_refs(const AV1_COMMON *cm, const MACROBLOCKD *xd,
#if CONFIG_REF_MV
av1_set_ref_frame(rf, ref_frame);
zeromv[0].as_int = gm_get_motion_vector(&cm->global_motion[rf[0]],
cm->allow_high_precision_mv)
cm->allow_high_precision_mv,
mi_col * MI_SIZE + MI_SIZE / 2,
mi_row * MI_SIZE + MI_SIZE / 2)
.as_int;
zeromv[1].as_int = (rf[1] != NONE_FRAME)
? gm_get_motion_vector(&cm->global_motion[rf[1]],
cm->allow_high_precision_mv)
cm->allow_high_precision_mv,
mi_col * MI_SIZE + MI_SIZE / 2,
mi_row * MI_SIZE + MI_SIZE / 2)
.as_int
: 0;
#else
zeromv[0].as_int = gm_get_motion_vector(&cm->global_motion[ref_frame],
cm->allow_high_precision_mv)
cm->allow_high_precision_mv,
mi_col * MI_SIZE + MI_SIZE / 2,
mi_row * MI_SIZE + MI_SIZE / 2)
.as_int;
zeromv[1].as_int = 0;
#endif // CONFIG_REF_MV
......@@ -987,7 +993,9 @@ void av1_append_sub8x8_mvs_for_idx(const AV1_COMMON *cm, MACROBLOCKD *xd,
#if CONFIG_GLOBAL_MOTION
zeromv.as_int =
gm_get_motion_vector(&cm->global_motion[ref], cm->allow_high_precision_mv)
gm_get_motion_vector(&cm->global_motion[ref], cm->allow_high_precision_mv,
mi_col * MI_SIZE + MI_SIZE / 2,
mi_row * MI_SIZE + MI_SIZE / 2)
.as_int;
#else
zeromv.as_int = 0;
......
......@@ -1271,8 +1271,9 @@ static INLINE int assign_mv(AV1_COMMON *cm, MACROBLOCKD *xd,
PREDICTION_MODE mode,
MV_REFERENCE_FRAME ref_frame[2], int block,
int_mv mv[2], int_mv ref_mv[2],
int_mv nearest_mv[2], int_mv near_mv[2],
int is_compound, int allow_hp, aom_reader *r) {
int_mv nearest_mv[2], int_mv near_mv[2], int mi_row,
int mi_col, int is_compound, int allow_hp,
aom_reader *r) {
int i;
int ret = 1;
#if CONFIG_EC_ADAPT
......@@ -1295,6 +1296,8 @@ static INLINE int assign_mv(AV1_COMMON *cm, MACROBLOCKD *xd,
#endif // CONFIG_REF_MV
(void)ref_frame;
(void)cm;
(void)mi_row;
(void)mi_col;
switch (mode) {
#if CONFIG_EXT_INTER
......@@ -1350,11 +1353,15 @@ static INLINE int assign_mv(AV1_COMMON *cm, MACROBLOCKD *xd,
case ZEROMV: {
#if CONFIG_GLOBAL_MOTION
mv[0].as_int = gm_get_motion_vector(&cm->global_motion[ref_frame[0]],
cm->allow_high_precision_mv)
cm->allow_high_precision_mv,
mi_col * MI_SIZE + MI_SIZE / 2,
mi_row * MI_SIZE + MI_SIZE / 2)
.as_int;
if (is_compound)
mv[1].as_int = gm_get_motion_vector(&cm->global_motion[ref_frame[1]],
cm->allow_high_precision_mv)
cm->allow_high_precision_mv,
mi_col * MI_SIZE + MI_SIZE / 2,
mi_row * MI_SIZE + MI_SIZE / 2)
.as_int;
#else
mv[0].as_int = 0;
......@@ -1503,10 +1510,14 @@ static INLINE int assign_mv(AV1_COMMON *cm, MACROBLOCKD *xd,
assert(is_compound);
#if CONFIG_GLOBAL_MOTION
mv[0].as_int = gm_get_motion_vector(&cm->global_motion[ref_frame[0]],
cm->allow_high_precision_mv)
cm->allow_high_precision_mv,
mi_col * MI_SIZE + MI_SIZE / 2,
mi_row * MI_SIZE + MI_SIZE / 2)
.as_int;
mv[1].as_int = gm_get_motion_vector(&cm->global_motion[ref_frame[1]],
cm->allow_high_precision_mv)
cm->allow_high_precision_mv,
mi_col * MI_SIZE + MI_SIZE / 2,
mi_row * MI_SIZE + MI_SIZE / 2)
.as_int;
#else
mv[0].as_int = 0;
......@@ -1613,11 +1624,16 @@ static void read_inter_block_mode_info(AV1Decoder *const pbi,
av1_set_ref_frame(rf, ref_frame);
#if CONFIG_GLOBAL_MOTION
zeromv[0].as_int = gm_get_motion_vector(&cm->global_motion[rf[0]],
cm->allow_high_precision_mv)
cm->allow_high_precision_mv,
mi_col * MI_SIZE + MI_SIZE / 2,
mi_row * MI_SIZE + MI_SIZE / 2)
.as_int;
zeromv[1].as_int = (rf[1] != NONE_FRAME)
zeromv[1].as_int =
(rf[1] != NONE_FRAME)
? gm_get_motion_vector(&cm->global_motion[rf[1]],
cm->allow_high_precision_mv)
cm->allow_high_precision_mv,
mi_col * MI_SIZE + MI_SIZE / 2,
mi_row * MI_SIZE + MI_SIZE / 2)
.as_int
: 0;
#else
......@@ -1843,7 +1859,8 @@ static void read_inter_block_mode_info(AV1Decoder *const pbi,
#else
ref_mv_s8,
#endif // CONFIG_EXT_INTER
nearest_sub8x8, near_sub8x8, is_compound, allow_hp, r)) {
nearest_sub8x8, near_sub8x8, mi_row, mi_col, is_compound,
allow_hp, r)) {
xd->corrupted |= 1;
break;
};
......@@ -1892,7 +1909,7 @@ static void read_inter_block_mode_info(AV1Decoder *const pbi,
#else
ref_mv,
#endif // CONFIG_EXT_INTER
nearestmv, nearmv, is_compound, allow_hp, r);
nearestmv, nearmv, mi_row, mi_col, is_compound, allow_hp, r);
}
#if CONFIG_EXT_INTER
......
......@@ -1401,6 +1401,8 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const MODE_INFO *mi,
#else
const int unify_bsize = 0;
#endif
(void)mi_row;
(void)mi_col;
if (seg->update_map) {
if (seg->temporal_update) {
......@@ -1792,6 +1794,8 @@ static void write_mb_modes_kf(AV1_COMMON *cm, const MACROBLOCKD *xd,
#else
const int unify_bsize = 0;
#endif
(void)mi_row;
(void)mi_col;
#if CONFIG_EC_ADAPT
FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
......
......@@ -1900,8 +1900,8 @@ static void rd_pick_sb_modes(const AV1_COMP *const cpi, TileDataEnc *tile_data,
} else {
if (bsize >= BLOCK_8X8 || unify_bsize) {
if (segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
av1_rd_pick_inter_mode_sb_seg_skip(cpi, tile_data, x, rd_cost, bsize,
ctx, best_rd);
av1_rd_pick_inter_mode_sb_seg_skip(cpi, tile_data, x, mi_row, mi_col,
rd_cost, bsize, ctx, best_rd);
#if CONFIG_SUPERTX
*totalrate_nocoef = rd_cost->rate;
#endif // CONFIG_SUPERTX
......
This diff is collapsed.
......@@ -159,8 +159,8 @@ void av1_rd_pick_inter_mode_sb(const struct AV1_COMP *cpi,
void av1_rd_pick_inter_mode_sb_seg_skip(
const struct AV1_COMP *cpi, struct TileDataEnc *tile_data,
struct macroblock *x, struct RD_COST *rd_cost, BLOCK_SIZE bsize,
PICK_MODE_CONTEXT *ctx, int64_t best_rd_so_far);
struct macroblock *x, int mi_row, int mi_col, struct RD_COST *rd_cost,
BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx, int64_t best_rd_so_far);
int av1_internal_image_edge(const struct AV1_COMP *cpi);
int av1_active_h_edge(const struct AV1_COMP *cpi, int mi_row, int mi_step);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment