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
diff --git a/av1/common/common_data.h b/av1/common/common_data.h
index f487bb8..f862d63 100644
--- a/av1/common/common_data.h
+++ b/av1/common/common_data.h
@@ -1933,6 +1933,14 @@
#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 5476f59..1aa08a4 100644
--- a/av1/common/convolve.c
+++ b/av1/common/convolve.c
@@ -361,10 +361,27 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 c43f649..61f290a 100644
--- a/av1/common/convolve.h
+++ b/av1/common/convolve.h
@@ -35,6 +35,10 @@
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 91f1f16..5e2e815 100644
--- a/av1/common/enums.h
+++ b/av1/common/enums.h
@@ -103,6 +103,16 @@
#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 5eba691..30e1d72 100644
--- a/av1/common/reconinter.c
+++ b/av1/common/reconinter.c
@@ -1104,6 +1104,60 @@
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 @@
#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 @@
#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