Add gm parameter coding based on ref parameters
Change-Id: Ic2344a6475b967fa07f70b3ffad2714de657bb49
diff --git a/aom_dsp/binary_codes_reader.c b/aom_dsp/binary_codes_reader.c
index 0bbcffa..4664ff5 100644
--- a/aom_dsp/binary_codes_reader.c
+++ b/aom_dsp/binary_codes_reader.c
@@ -108,3 +108,12 @@
return inv_recenter_finite_nonneg(n, ref,
aom_read_primitive_subexpfin(r, n, k));
}
+
+// Decode finite subexponential code that for a symbol v in [-(n-1), n-1] with
+// parameter k based on a reference ref also in [-(n-1), n-1].
+int16_t aom_read_signed_primitive_refsubexpfin(aom_reader *r, uint16_t n,
+ uint16_t k, int16_t ref) {
+ ref += n - 1;
+ const uint16_t scaled_n = (n << 1) - 1;
+ return aom_read_primitive_refsubexpfin(r, scaled_n, k, ref) - n + 1;
+}
diff --git a/aom_dsp/binary_codes_reader.h b/aom_dsp/binary_codes_reader.h
index d1c4d4c..738d91d 100644
--- a/aom_dsp/binary_codes_reader.h
+++ b/aom_dsp/binary_codes_reader.h
@@ -29,6 +29,8 @@
uint16_t aom_read_primitive_subexpfin(aom_reader *r, uint16_t n, uint16_t k);
uint16_t aom_read_primitive_refsubexpfin(aom_reader *r, uint16_t n, uint16_t k,
uint16_t ref);
+int16_t aom_read_signed_primitive_refsubexpfin(aom_reader *r, uint16_t n,
+ uint16_t k, int16_t ref);
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/aom_dsp/binary_codes_writer.c b/aom_dsp/binary_codes_writer.c
index 9edb018..91e807b 100644
--- a/aom_dsp/binary_codes_writer.c
+++ b/aom_dsp/binary_codes_writer.c
@@ -184,11 +184,28 @@
// based on a reference ref also in [0, n-1].
// Recenters symbol around r first and then uses a finite subexponential code.
void aom_write_primitive_refsubexpfin(aom_writer *w, uint16_t n, uint16_t k,
- uint16_t ref, uint16_t v) {
+ int16_t ref, int16_t v) {
aom_write_primitive_subexpfin(w, n, k, recenter_finite_nonneg(n, ref, v));
}
+void aom_write_signed_primitive_refsubexpfin(aom_writer *w, uint16_t n,
+ uint16_t k, uint16_t ref,
+ uint16_t v) {
+ ref += n - 1;
+ v += n - 1;
+ const uint16_t scaled_n = (n << 1) - 1;
+ aom_write_primitive_refsubexpfin(w, scaled_n, k, ref, v);
+}
+
int aom_count_primitive_refsubexpfin(uint16_t n, uint16_t k, uint16_t ref,
uint16_t v) {
return aom_count_primitive_subexpfin(n, k, recenter_finite_nonneg(n, ref, v));
}
+
+int aom_count_signed_primitive_refsubexpfin(uint16_t n, uint16_t k, int16_t ref,
+ int16_t v) {
+ ref += n - 1;
+ v += n - 1;
+ const uint16_t scaled_n = (n << 1) - 1;
+ return aom_count_primitive_refsubexpfin(scaled_n, k, ref, v);
+}
diff --git a/aom_dsp/binary_codes_writer.h b/aom_dsp/binary_codes_writer.h
index d80de9e..ab5ccbf 100644
--- a/aom_dsp/binary_codes_writer.h
+++ b/aom_dsp/binary_codes_writer.h
@@ -47,6 +47,12 @@
void aom_write_primitive_refsubexpfin(aom_writer *w, uint16_t n, uint16_t k,
uint16_t ref, uint16_t v);
+// Finite subexponential code that codes a symbol v in [-(n-1), n-1] with
+// parameter k based on a reference ref also in [-(n-1), n-1].
+void aom_write_signed_primitive_refsubexpfin(aom_writer *w, uint16_t n,
+ uint16_t k, int16_t ref,
+ int16_t v);
+
// Functions that counts bits for the above primitives
int aom_count_primitive_symmetric(int16_t v, unsigned int mag_bits);
int aom_count_primitive_quniform(uint16_t n, uint16_t v);
@@ -55,6 +61,8 @@
int aom_count_primitive_subexpfin(uint16_t n, uint16_t k, uint16_t v);
int aom_count_primitive_refsubexpfin(uint16_t n, uint16_t k, uint16_t ref,
uint16_t v);
+int aom_count_signed_primitive_refsubexpfin(uint16_t n, uint16_t k, int16_t ref,
+ int16_t v);
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/av1/common/mv.h b/av1/common/mv.h
index 67f36b6..d516934 100644
--- a/av1/common/mv.h
+++ b/av1/common/mv.h
@@ -121,6 +121,7 @@
//
// XX_MIN, XX_MAX are also computed to avoid repeated computation
+#define SUBEXPFIN_K 3
#define GM_TRANS_PREC_BITS 6
#define GM_ABS_TRANS_BITS 12
#define GM_ABS_TRANS_ONLY_BITS (GM_ABS_TRANS_BITS - GM_TRANS_PREC_BITS + 3)
diff --git a/av1/common/onyxc_int.h b/av1/common/onyxc_int.h
index f5558b2..7079cdd 100644
--- a/av1/common/onyxc_int.h
+++ b/av1/common/onyxc_int.h
@@ -108,6 +108,9 @@
MV_REF *mvs;
int mi_rows;
int mi_cols;
+#if CONFIG_GLOBAL_MOTION
+ WarpedMotionParams global_motion[TOTAL_REFS_PER_FRAME];
+#endif // CONFIG_GLOBAL_MOTION
aom_codec_frame_buffer_t raw_frame_buffer;
YV12_BUFFER_CONFIG buf;
#if CONFIG_TEMPMV_SIGNALING
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index a209d6d..1ae815a 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -4401,12 +4401,14 @@
#if CONFIG_GLOBAL_MOTION
static void read_global_motion_params(WarpedMotionParams *params,
+ WarpedMotionParams *ref_params,
aom_prob *probs, aom_reader *r,
int allow_hp) {
TransformationType type =
aom_read_tree(r, av1_global_motion_types_tree, probs, ACCT_STR);
int trans_bits;
int trans_dec_factor;
+ int trans_prec_diff;
set_default_gmparams(params);
params->wmtype = type;
switch (type) {
@@ -4415,26 +4417,39 @@
case VERTRAPEZOID:
if (type != HORTRAPEZOID)
params->wmmat[6] =
- aom_read_primitive_symmetric(r, GM_ABS_ROW3HOMO_BITS) *
+ aom_read_signed_primitive_refsubexpfin(
+ r, GM_ROW3HOMO_MAX + 1, SUBEXPFIN_K,
+ (ref_params->wmmat[6] >> GM_ROW3HOMO_PREC_DIFF)) *
GM_ROW3HOMO_DECODE_FACTOR;
if (type != VERTRAPEZOID)
params->wmmat[7] =
- aom_read_primitive_symmetric(r, GM_ABS_ROW3HOMO_BITS) *
+ aom_read_signed_primitive_refsubexpfin(
+ r, GM_ROW3HOMO_MAX + 1, SUBEXPFIN_K,
+ (ref_params->wmmat[7] >> GM_ROW3HOMO_PREC_DIFF)) *
GM_ROW3HOMO_DECODE_FACTOR;
case AFFINE:
case ROTZOOM:
- params->wmmat[2] = aom_read_primitive_symmetric(r, GM_ABS_ALPHA_BITS) *
+ params->wmmat[2] = aom_read_signed_primitive_refsubexpfin(
+ r, GM_ALPHA_MAX + 1, SUBEXPFIN_K,
+ (ref_params->wmmat[2] >> GM_ALPHA_PREC_DIFF) -
+ (1 << GM_ALPHA_PREC_BITS)) *
GM_ALPHA_DECODE_FACTOR +
(1 << WARPEDMODEL_PREC_BITS);
if (type != VERTRAPEZOID)
- params->wmmat[3] = aom_read_primitive_symmetric(r, GM_ABS_ALPHA_BITS) *
+ params->wmmat[3] = aom_read_signed_primitive_refsubexpfin(
+ r, GM_ALPHA_MAX + 1, SUBEXPFIN_K,
+ (ref_params->wmmat[3] >> GM_ALPHA_PREC_DIFF)) *
GM_ALPHA_DECODE_FACTOR;
if (type >= AFFINE) {
if (type != HORTRAPEZOID)
- params->wmmat[4] =
- aom_read_primitive_symmetric(r, GM_ABS_ALPHA_BITS) *
- GM_ALPHA_DECODE_FACTOR;
- params->wmmat[5] = aom_read_primitive_symmetric(r, GM_ABS_ALPHA_BITS) *
+ params->wmmat[4] = aom_read_signed_primitive_refsubexpfin(
+ r, GM_ALPHA_MAX + 1, SUBEXPFIN_K,
+ (ref_params->wmmat[4] >> GM_ALPHA_PREC_DIFF)) *
+ GM_ALPHA_DECODE_FACTOR;
+ params->wmmat[5] = aom_read_signed_primitive_refsubexpfin(
+ r, GM_ALPHA_MAX + 1, SUBEXPFIN_K,
+ (ref_params->wmmat[5] >> GM_ALPHA_PREC_DIFF) -
+ (1 << GM_ALPHA_PREC_BITS)) *
GM_ALPHA_DECODE_FACTOR +
(1 << WARPEDMODEL_PREC_BITS);
} else {
@@ -4448,11 +4463,17 @@
trans_dec_factor = (type == TRANSLATION)
? GM_TRANS_ONLY_DECODE_FACTOR * (1 << !allow_hp)
: GM_TRANS_DECODE_FACTOR;
- params->wmmat[0] =
- aom_read_primitive_symmetric(r, trans_bits) * trans_dec_factor;
- params->wmmat[1] =
- aom_read_primitive_symmetric(r, trans_bits) * trans_dec_factor;
- break;
+ trans_prec_diff = (type == TRANSLATION)
+ ? GM_TRANS_ONLY_PREC_DIFF + !allow_hp
+ : GM_TRANS_PREC_DIFF;
+ params->wmmat[0] = aom_read_signed_primitive_refsubexpfin(
+ r, (1 << trans_bits) + 1, SUBEXPFIN_K,
+ (ref_params->wmmat[0] >> trans_prec_diff)) *
+ trans_dec_factor;
+ params->wmmat[1] = aom_read_signed_primitive_refsubexpfin(
+ r, (1 << trans_bits) + 1, SUBEXPFIN_K,
+ (ref_params->wmmat[1] >> trans_prec_diff)) *
+ trans_dec_factor;
case IDENTITY: break;
default: assert(0);
}
@@ -4463,9 +4484,9 @@
static void read_global_motion(AV1_COMMON *cm, aom_reader *r) {
int frame;
for (frame = LAST_FRAME; frame <= ALTREF_FRAME; ++frame) {
- read_global_motion_params(&cm->global_motion[frame],
- cm->fc->global_motion_types_prob, r,
- cm->allow_high_precision_mv);
+ read_global_motion_params(
+ &cm->global_motion[frame], &cm->prev_frame->global_motion[frame],
+ cm->fc->global_motion_types_prob, r, cm->allow_high_precision_mv);
/*
printf("Dec Ref %d [%d/%d]: %d %d %d %d\n",
frame, cm->current_video_frame, cm->show_frame,
@@ -4475,6 +4496,8 @@
cm->global_motion[frame].wmmat[3]);
*/
}
+ memcpy(cm->cur_frame->global_motion, cm->global_motion,
+ TOTAL_REFS_PER_FRAME * sizeof(WarpedMotionParams));
}
#endif // CONFIG_GLOBAL_MOTION
@@ -4824,6 +4847,11 @@
new_fb = get_frame_new_buffer(cm);
xd->cur_buf = new_fb;
#if CONFIG_GLOBAL_MOTION
+ int i;
+ for (i = LAST_FRAME; i <= ALTREF_FRAME; ++i) {
+ set_default_gmparams(&cm->global_motion[i]);
+ set_default_gmparams(&cm->cur_frame->global_motion[i]);
+ }
xd->global_motion = cm->global_motion;
#endif // CONFIG_GLOBAL_MOTION
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 382d5cc..8ebbedc 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -4598,6 +4598,7 @@
#if CONFIG_GLOBAL_MOTION
static void write_global_motion_params(WarpedMotionParams *params,
+ WarpedMotionParams *ref_params,
aom_prob *probs, aom_writer *w,
int allow_hp) {
TransformationType type = params->wmtype;
@@ -4610,31 +4611,40 @@
case HORTRAPEZOID:
case VERTRAPEZOID:
if (type != HORTRAPEZOID)
- aom_write_primitive_symmetric(
- w, (params->wmmat[6] >> GM_ROW3HOMO_PREC_DIFF),
- GM_ABS_ROW3HOMO_BITS);
+ aom_write_signed_primitive_refsubexpfin(
+ w, GM_ROW3HOMO_MAX + 1, SUBEXPFIN_K,
+ (ref_params->wmmat[6] >> GM_ROW3HOMO_PREC_DIFF),
+ (params->wmmat[6] >> GM_ROW3HOMO_PREC_DIFF));
if (type != VERTRAPEZOID)
- aom_write_primitive_symmetric(
- w, (params->wmmat[7] >> GM_ROW3HOMO_PREC_DIFF),
- GM_ABS_ROW3HOMO_BITS);
+ aom_write_signed_primitive_refsubexpfin(
+ w, GM_ROW3HOMO_MAX + 1, SUBEXPFIN_K,
+ (ref_params->wmmat[7] >> GM_ROW3HOMO_PREC_DIFF),
+ (params->wmmat[7] >> GM_ROW3HOMO_PREC_DIFF));
// fallthrough intended
case AFFINE:
case ROTZOOM:
- aom_write_primitive_symmetric(
- w,
- (params->wmmat[2] >> GM_ALPHA_PREC_DIFF) - (1 << GM_ALPHA_PREC_BITS),
- GM_ABS_ALPHA_BITS);
+ aom_write_signed_primitive_refsubexpfin(
+ w, GM_ALPHA_MAX + 1, SUBEXPFIN_K,
+ (ref_params->wmmat[2] >> GM_ALPHA_PREC_DIFF) -
+ (1 << GM_ALPHA_PREC_BITS),
+ (params->wmmat[2] >> GM_ALPHA_PREC_DIFF) - (1 << GM_ALPHA_PREC_BITS));
if (type != VERTRAPEZOID)
- aom_write_primitive_symmetric(
- w, (params->wmmat[3] >> GM_ALPHA_PREC_DIFF), GM_ABS_ALPHA_BITS);
+ aom_write_signed_primitive_refsubexpfin(
+ w, GM_ALPHA_MAX + 1, SUBEXPFIN_K,
+ (ref_params->wmmat[3] >> GM_ALPHA_PREC_DIFF),
+ (params->wmmat[3] >> GM_ALPHA_PREC_DIFF));
if (type >= AFFINE) {
if (type != HORTRAPEZOID)
- aom_write_primitive_symmetric(
- w, (params->wmmat[4] >> GM_ALPHA_PREC_DIFF), GM_ABS_ALPHA_BITS);
- aom_write_primitive_symmetric(w,
- (params->wmmat[5] >> GM_ALPHA_PREC_DIFF) -
- (1 << GM_ALPHA_PREC_BITS),
- GM_ABS_ALPHA_BITS);
+ aom_write_signed_primitive_refsubexpfin(
+ w, GM_ALPHA_MAX + 1, SUBEXPFIN_K,
+ (ref_params->wmmat[4] >> GM_ALPHA_PREC_DIFF),
+ (params->wmmat[4] >> GM_ALPHA_PREC_DIFF));
+ aom_write_signed_primitive_refsubexpfin(
+ w, GM_ALPHA_MAX + 1, SUBEXPFIN_K,
+ (ref_params->wmmat[5] >> GM_ALPHA_PREC_DIFF) -
+ (1 << GM_ALPHA_PREC_BITS),
+ (params->wmmat[5] >> GM_ALPHA_PREC_DIFF) -
+ (1 << GM_ALPHA_PREC_BITS));
}
// fallthrough intended
case TRANSLATION:
@@ -4643,10 +4653,14 @@
trans_prec_diff = (type == TRANSLATION)
? GM_TRANS_ONLY_PREC_DIFF + !allow_hp
: GM_TRANS_PREC_DIFF;
- aom_write_primitive_symmetric(w, (params->wmmat[0] >> trans_prec_diff),
- trans_bits);
- aom_write_primitive_symmetric(w, (params->wmmat[1] >> trans_prec_diff),
- trans_bits);
+ aom_write_signed_primitive_refsubexpfin(
+ w, (1 << trans_bits) + 1, SUBEXPFIN_K,
+ (ref_params->wmmat[0] >> trans_prec_diff),
+ (params->wmmat[0] >> trans_prec_diff));
+ aom_write_signed_primitive_refsubexpfin(
+ w, (1 << trans_bits) + 1, SUBEXPFIN_K,
+ (ref_params->wmmat[1] >> trans_prec_diff),
+ (params->wmmat[1] >> trans_prec_diff));
break;
case IDENTITY: break;
default: assert(0);
@@ -4665,9 +4679,9 @@
set_default_gmparams(&cm->global_motion[frame]);
}
#endif
- write_global_motion_params(&cm->global_motion[frame],
- cm->fc->global_motion_types_prob, w,
- cm->allow_high_precision_mv);
+ write_global_motion_params(
+ &cm->global_motion[frame], &cm->prev_frame->global_motion[frame],
+ cm->fc->global_motion_types_prob, w, cm->allow_high_precision_mv);
/*
printf("Frame %d/%d: Enc Ref %d (used %d): %d %d %d %d\n",
cm->current_video_frame, cm->show_frame, frame,
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index 1158dc9..3d77f6c 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -18,6 +18,7 @@
#include "./aom_config.h"
#include "aom_dsp/aom_dsp_common.h"
+#include "aom_dsp/binary_codes_writer.h"
#include "aom_ports/mem.h"
#include "aom_ports/aom_timer.h"
#include "aom_ports/system_state.h"
@@ -5022,36 +5023,65 @@
#endif
#if CONFIG_GLOBAL_MOTION
-static int gm_get_params_cost(WarpedMotionParams *gm) {
+static int gm_get_params_cost(WarpedMotionParams *gm,
+ WarpedMotionParams *ref_gm, int allow_hp) {
assert(gm->wmtype < GLOBAL_TRANS_TYPES);
int params_cost = 0;
+ int trans_bits, trans_prec_diff;
switch (gm->wmtype) {
case HOMOGRAPHY:
case HORTRAPEZOID:
case VERTRAPEZOID:
if (gm->wmtype != HORTRAPEZOID)
- params_cost += gm->wmmat[6] == 0 ? 1 : (GM_ABS_ROW3HOMO_BITS + 2);
+ params_cost += aom_count_signed_primitive_refsubexpfin(
+ GM_ROW3HOMO_MAX + 1, SUBEXPFIN_K,
+ (ref_gm->wmmat[6] >> GM_ROW3HOMO_PREC_DIFF),
+ (gm->wmmat[6] >> GM_ROW3HOMO_PREC_DIFF));
if (gm->wmtype != VERTRAPEZOID)
- params_cost += gm->wmmat[7] == 0 ? 1 : (GM_ABS_ROW3HOMO_BITS + 2);
+ params_cost += aom_count_signed_primitive_refsubexpfin(
+ GM_ROW3HOMO_MAX + 1, SUBEXPFIN_K,
+ (ref_gm->wmmat[7] >> GM_ROW3HOMO_PREC_DIFF),
+ (gm->wmmat[7] >> GM_ROW3HOMO_PREC_DIFF));
// Fallthrough intended
case AFFINE:
case ROTZOOM:
- params_cost += gm->wmmat[2] == (1 << WARPEDMODEL_PREC_BITS)
- ? 1
- : (GM_ABS_ALPHA_BITS + 2);
+ params_cost += aom_count_signed_primitive_refsubexpfin(
+ GM_ALPHA_MAX + 1, SUBEXPFIN_K,
+ (ref_gm->wmmat[2] >> GM_ALPHA_PREC_DIFF) - (1 << GM_ALPHA_PREC_BITS),
+ (gm->wmmat[2] >> GM_ALPHA_PREC_DIFF) - (1 << GM_ALPHA_PREC_BITS));
if (gm->wmtype != VERTRAPEZOID)
- params_cost += gm->wmmat[3] == 0 ? 1 : (GM_ABS_ALPHA_BITS + 2);
+ params_cost += aom_count_signed_primitive_refsubexpfin(
+ GM_ALPHA_MAX + 1, SUBEXPFIN_K,
+ (ref_gm->wmmat[3] >> GM_ALPHA_PREC_DIFF),
+ (gm->wmmat[3] >> GM_ALPHA_PREC_DIFF));
if (gm->wmtype >= AFFINE) {
if (gm->wmtype != HORTRAPEZOID)
- params_cost += gm->wmmat[4] == 0 ? 1 : (GM_ABS_ALPHA_BITS + 2);
- params_cost += gm->wmmat[5] == (1 << WARPEDMODEL_PREC_BITS)
- ? 1
- : (GM_ABS_ALPHA_BITS + 2);
+ params_cost += aom_count_signed_primitive_refsubexpfin(
+ GM_ALPHA_MAX + 1, SUBEXPFIN_K,
+ (ref_gm->wmmat[4] >> GM_ALPHA_PREC_DIFF),
+ (gm->wmmat[4] >> GM_ALPHA_PREC_DIFF));
+ params_cost += aom_count_signed_primitive_refsubexpfin(
+ GM_ALPHA_MAX + 1, SUBEXPFIN_K,
+ (ref_gm->wmmat[5] >> GM_ALPHA_PREC_DIFF) -
+ (1 << GM_ALPHA_PREC_BITS),
+ (gm->wmmat[5] >> GM_ALPHA_PREC_DIFF) - (1 << GM_ALPHA_PREC_BITS));
}
// Fallthrough intended
case TRANSLATION:
- params_cost += gm->wmmat[0] == 0 ? 1 : (GM_ABS_TRANS_BITS + 2);
- params_cost += gm->wmmat[1] == 0 ? 1 : (GM_ABS_TRANS_BITS + 2);
+ trans_bits = (gm->wmtype == TRANSLATION)
+ ? GM_ABS_TRANS_ONLY_BITS - !allow_hp
+ : GM_ABS_TRANS_BITS;
+ trans_prec_diff = (gm->wmtype == TRANSLATION)
+ ? GM_TRANS_ONLY_PREC_DIFF + !allow_hp
+ : GM_TRANS_PREC_DIFF;
+ params_cost += aom_count_signed_primitive_refsubexpfin(
+ (1 << trans_bits) + 1, SUBEXPFIN_K,
+ (ref_gm->wmmat[0] >> trans_prec_diff),
+ (gm->wmmat[0] >> trans_prec_diff));
+ params_cost += aom_count_signed_primitive_refsubexpfin(
+ (1 << trans_bits) + 1, SUBEXPFIN_K,
+ (ref_gm->wmmat[1] >> trans_prec_diff),
+ (gm->wmmat[1] >> trans_prec_diff));
// Fallthrough intended
case IDENTITY: break;
default: assert(0);
@@ -5170,12 +5200,16 @@
aom_clear_system_state();
}
cpi->gmparams_cost[frame] =
- gm_get_params_cost(&cm->global_motion[frame]) +
+ gm_get_params_cost(&cm->global_motion[frame],
+ &cm->prev_frame->global_motion[frame],
+ cm->allow_high_precision_mv) +
cpi->gmtype_cost[cm->global_motion[frame].wmtype] -
cpi->gmtype_cost[IDENTITY];
}
cpi->global_motion_search_done = 1;
}
+ memcpy(cm->cur_frame->global_motion, cm->global_motion,
+ TOTAL_REFS_PER_FRAME * sizeof(WarpedMotionParams));
#endif // CONFIG_GLOBAL_MOTION
for (i = 0; i < MAX_SEGMENTS; ++i) {