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) {