From d867c9aa57c8b0e1041e745f8b6b162544b417c5 Mon Sep 17 00:00:00 2001 From: Cheng Chen Date: Mon, 9 Oct 2017 19:03:56 -0700 Subject: [PATCH] JNT_COMP: 1. Init version of experiment JNT_COMP Enable to assign distance based weight for joint compound prediction. (w0, w1) are weights for two predictors of different distance to current frame. Use 4 bit precision for quantized distance weight. e.g. the prediction is generated as value = (w0 * p0 + w1 * p1) >> n w0 + w1 = (1 << n), n = 4; Change-Id: Ib0ff0c41c82b9ebb033f498e90c18a03d18969e4 --- av1/common/common_data.h | 8 ++++ av1/common/convolve.c | 96 +++++++++++++++++++++++++++++++++++++++- av1/common/convolve.h | 4 ++ av1/common/enums.h | 10 +++++ av1/common/reconinter.c | 62 ++++++++++++++++++++++++++ 5 files changed, 179 insertions(+), 1 deletion(-) diff --git a/av1/common/common_data.h b/av1/common/common_data.h index f487bb83a..f862d633e 100644 --- a/av1/common/common_data.h +++ b/av1/common/common_data.h @@ -1933,6 +1933,14 @@ static const BLOCK_SIZE bsize_2_sqr_bsize[BLOCK_SIZES] = { #define EOB_THRESHOLD_NUM 2 #endif +#if CONFIG_JNT_COMP +static const double quant_dist_category[4] = { 1.5, 2.5, 3.5, 255 }; +static const int quant_dist_lookup_table[2][4][2] = { + { { 8, 8 }, { 11, 5 }, { 12, 4 }, { 13, 3 } }, + { { 8, 8 }, { 5, 11 }, { 4, 12 }, { 3, 13 } }, +}; +#endif // CONFIG_JNT_COMP + #ifdef __cplusplus } // extern "C" #endif diff --git a/av1/common/convolve.c b/av1/common/convolve.c index 5476f59a6..1aa08a4d3 100644 --- a/av1/common/convolve.c +++ b/av1/common/convolve.c @@ -361,10 +361,27 @@ void av1_convolve_2d_c(const uint8_t *src, int src_stride, CONV_BUF_TYPE *dst, sum += y_filter[k] * src_vert[(y - fo_vert + k) * im_stride + x]; } CONV_BUF_TYPE res = ROUND_POWER_OF_TWO(sum, conv_params->round_1); +#if CONFIG_JNT_COMP + if (conv_params->bck_offset == -1) { + if (conv_params->do_average) + dst[y * dst_stride + x] += res; + else + dst[y * dst_stride + x] = res; + } else { + if (conv_params->do_average == 0) { + dst[y * dst_stride + x] = res * conv_params->fwd_offset; + } else { + dst[y * dst_stride + x] += res * conv_params->bck_offset; + + dst[y * dst_stride + x] >>= (DIST_PRECISION_BITS - 1); + } + } +#else if (conv_params->do_average) dst[y * dst_stride + x] += res; else dst[y * dst_stride + x] = res; +#endif // CONFIG_JNT_COMP } } } @@ -419,10 +436,27 @@ void av1_convolve_2d_scale_c(const uint8_t *src, int src_stride, sum += y_filter[k] * src_y[(k - fo_vert) * im_stride]; } CONV_BUF_TYPE res = ROUND_POWER_OF_TWO(sum, conv_params->round_1); +#if CONFIG_JNT_COMP + if (conv_params->bck_offset == -1) { + if (conv_params->do_average) + dst[y * dst_stride + x] += res; + else + dst[y * dst_stride + x] = res; + } else { + if (conv_params->do_average == 0) { + dst[y * dst_stride + x] = res * conv_params->fwd_offset; + } else { + dst[y * dst_stride + x] += res * conv_params->bck_offset; + + dst[y * dst_stride + x] >>= (DIST_PRECISION_BITS - 1); + } + } +#else if (conv_params->do_average) dst[y * dst_stride + x] += res; else dst[y * dst_stride + x] = res; +#endif // CONFIG_JNT_COMP } src_vert++; } @@ -481,10 +515,27 @@ void av1_convolve_2d_c(const uint8_t *src, int src_stride, CONV_BUF_TYPE *dst, CONV_BUF_TYPE res = ROUND_POWER_OF_TWO(sum, conv_params->round_1) - ((1 << (offset_bits - conv_params->round_1)) + (1 << (offset_bits - conv_params->round_1 - 1))); +#if CONFIG_JNT_COMP + if (conv_params->fwd_offset == -1) { + if (conv_params->do_average) + dst[y * dst_stride + x] += res; + else + dst[y * dst_stride + x] = res; + } else { + if (conv_params->do_average) { + dst[y * dst_stride + x] += res * conv_params->bck_offset; + + dst[y * dst_stride + x] >>= (DIST_PRECISION_BITS - 1); + } else { + dst[y * dst_stride + x] = res * conv_params->fwd_offset; + } + } +#else if (conv_params->do_average) dst[y * dst_stride + x] += res; else dst[y * dst_stride + x] = res; +#endif // CONFIG_JNT_COMP } } } @@ -545,10 +596,27 @@ void av1_convolve_2d_scale_c(const uint8_t *src, int src_stride, CONV_BUF_TYPE res = ROUND_POWER_OF_TWO(sum, conv_params->round_1) - ((1 << (offset_bits - conv_params->round_1)) + (1 << (offset_bits - conv_params->round_1 - 1))); +#if CONFIG_JNT_COMP + if (conv_params->fwd_offset == -1) { + if (conv_params->do_average) + dst[y * dst_stride + x] += res; + else + dst[y * dst_stride + x] = res; + } else { + if (conv_params->do_average) { + dst[y * dst_stride + x] += res * conv_params->bck_offset; + + dst[y * dst_stride + x] >>= (DIST_PRECISION_BITS - 1); + } else { + dst[y * dst_stride + x] = res * conv_params->fwd_offset; + } + } +#else if (conv_params->do_average) dst[y * dst_stride + x] += res; else dst[y * dst_stride + x] = res; +#endif // CONFIG_JNT_COMP } src_vert++; } @@ -584,7 +652,19 @@ void av1_convolve_2d_facade(const uint8_t *src, int src_stride, uint8_t *dst, transpose_int32(tr_dst, tr_dst_stride, conv_params->dst, conv_params->dst_stride, w, h); - // horizontal and vertical parameters are swapped because of the transpose +// horizontal and vertical parameters are swapped because of the transpose +#if CONFIG_JNT_COMP + if (scaled) + av1_convolve_2d_scale_c(tr_src + fo_horiz * tr_src_stride + fo_vert, + tr_src_stride, tr_dst, tr_dst_stride, h, w, + &filter_params_y, &filter_params_x, subpel_y_q4, + y_step_q4, subpel_x_q4, x_step_q4, conv_params); + else + av1_convolve_2d_c(tr_src + fo_horiz * tr_src_stride + fo_vert, + tr_src_stride, tr_dst, tr_dst_stride, h, w, + &filter_params_y, &filter_params_x, subpel_y_q4, + subpel_x_q4, conv_params); +#else if (scaled) av1_convolve_2d_scale(tr_src + fo_horiz * tr_src_stride + fo_vert, tr_src_stride, tr_dst, tr_dst_stride, h, w, @@ -595,9 +675,22 @@ void av1_convolve_2d_facade(const uint8_t *src, int src_stride, uint8_t *dst, tr_src_stride, tr_dst, tr_dst_stride, h, w, &filter_params_y, &filter_params_x, subpel_y_q4, subpel_x_q4, conv_params); +#endif // CONFIG_JNT_COMP transpose_int32(conv_params->dst, conv_params->dst_stride, tr_dst, tr_dst_stride, h, w); } else { +#if CONFIG_JNT_COMP + if (scaled) + av1_convolve_2d_scale_c(src, src_stride, conv_params->dst, + conv_params->dst_stride, w, h, &filter_params_x, + &filter_params_y, subpel_x_q4, x_step_q4, + subpel_y_q4, y_step_q4, conv_params); + else + av1_convolve_2d_c(src, src_stride, conv_params->dst, + conv_params->dst_stride, w, h, &filter_params_x, + &filter_params_y, subpel_x_q4, subpel_y_q4, + conv_params); +#else if (scaled) av1_convolve_2d_scale(src, src_stride, conv_params->dst, conv_params->dst_stride, w, h, &filter_params_x, @@ -607,6 +700,7 @@ void av1_convolve_2d_facade(const uint8_t *src, int src_stride, uint8_t *dst, av1_convolve_2d(src, src_stride, conv_params->dst, conv_params->dst_stride, w, h, &filter_params_x, &filter_params_y, subpel_x_q4, subpel_y_q4, conv_params); +#endif // CONFIG_JNT_COMP } } diff --git a/av1/common/convolve.h b/av1/common/convolve.h index c43f649e0..61f290adf 100644 --- a/av1/common/convolve.h +++ b/av1/common/convolve.h @@ -35,6 +35,10 @@ typedef struct ConvolveParams { int round_1; int plane; int do_post_rounding; +#if CONFIG_JNT_COMP + int fwd_offset; + int bck_offset; +#endif } ConvolveParams; static INLINE ConvolveParams get_conv_params(int ref, int do_average, diff --git a/av1/common/enums.h b/av1/common/enums.h index 91f1f165f..5e2e8153d 100644 --- a/av1/common/enums.h +++ b/av1/common/enums.h @@ -103,6 +103,16 @@ extern "C" { #define USE_LOOP_FILTER_SUPERBLOCK 1 #endif // CONFIG_LPF_SB +#if CONFIG_JNT_COMP +typedef enum COMPOUND_DIST_WEIGHT_MODE { + DIST, +} COMPOUND_DIST_WEIGHT_MODE; + +#define COMPOUND_WEIGHT_MODE DIST +#define DIST_PRECISION_BITS 4 +#define DIST_PRECISION (1 << DIST_PRECISION_BITS) // 16 +#endif // CONFIG_JNT_COMP + // Bitstream profiles indicated by 2-3 bits in the uncompressed header. // 00: Profile 0. 8-bit 4:2:0 only. // 10: Profile 1. 8-bit 4:4:4, 4:2:2, and 4:4:0. diff --git a/av1/common/reconinter.c b/av1/common/reconinter.c index 5eba69192..30e1d723a 100644 --- a/av1/common/reconinter.c +++ b/av1/common/reconinter.c @@ -1104,6 +1104,60 @@ typedef struct SubpelParams { int subpel_y; } SubpelParams; +#if CONFIG_JNT_COMP +static void jnt_comp_weight_assign(const AV1_COMMON *cm, + const MB_MODE_INFO *mbmi, + ConvolveParams *conv_params, + int is_compound) { + if (is_compound) { + int bck_idx = cm->frame_refs[mbmi->ref_frame[0] - LAST_FRAME].idx; + int fwd_idx = cm->frame_refs[mbmi->ref_frame[1] - LAST_FRAME].idx; + int bck_frame_index = 0, fwd_frame_index = 0; + int cur_frame_index = cm->cur_frame->cur_frame_offset; + + if (bck_idx >= 0) { + bck_frame_index = cm->buffer_pool->frame_bufs[bck_idx].cur_frame_offset; + } + + if (fwd_idx >= 0) { + fwd_frame_index = cm->buffer_pool->frame_bufs[fwd_idx].cur_frame_offset; + } + + conv_params->bck_offset = abs(cur_frame_index - bck_frame_index); + conv_params->fwd_offset = abs(fwd_frame_index - cur_frame_index); + + const double fwd = abs(fwd_frame_index - cur_frame_index); + const double bck = abs(cur_frame_index - bck_frame_index); + int order; + double ratio; + + if (COMPOUND_WEIGHT_MODE == DIST) { + if (fwd > bck) { + ratio = (bck != 0) ? fwd / bck : 5.0; + order = 0; + } else { + ratio = (fwd != 0) ? bck / fwd : 5.0; + order = 1; + } + int quant_dist_idx; + for (quant_dist_idx = 0; quant_dist_idx < 4; ++quant_dist_idx) { + if (ratio < quant_dist_category[quant_dist_idx]) break; + } + conv_params->fwd_offset = + quant_dist_lookup_table[0][quant_dist_idx][order]; + conv_params->bck_offset = + quant_dist_lookup_table[0][quant_dist_idx][1 - order]; + } else { + conv_params->fwd_offset = (DIST_PRECISION >> 1); + conv_params->bck_offset = (DIST_PRECISION >> 1); + } + } else { + conv_params->bck_offset = -1; + conv_params->fwd_offset = -1; + } +} +#endif // CONFIG_JNT_COMP + static INLINE void build_inter_predictors( const AV1_COMMON *cm, MACROBLOCKD *xd, int plane, #if CONFIG_MOTION_VAR @@ -1194,6 +1248,10 @@ static INLINE void build_inter_predictors( #else ConvolveParams conv_params = get_conv_params(0, 0, plane); #endif +#if CONFIG_JNT_COMP + conv_params.fwd_offset = -1; + conv_params.bck_offset = -1; +#endif // CONFIG_JNT_COMP struct buf_2d *const dst_buf = &pd->dst; x = x_base + idx; y = y_base + idy; @@ -1425,6 +1483,10 @@ static INLINE void build_inter_predictors( #if CONFIG_CONVOLVE_ROUND ConvolveParams conv_params = get_conv_params_no_round(ref, ref, plane, tmp_dst, MAX_SB_SIZE); +#if CONFIG_JNT_COMP + jnt_comp_weight_assign(cm, &mi->mbmi, &conv_params, is_compound); +#endif // CONFIG_JNT_COMP + #else ConvolveParams conv_params = get_conv_params(ref, ref, plane); #endif // CONFIG_CONVOLVE_ROUND -- GitLab