Support ext-skip for both low delay and high delay
For both low delay and high delay scenarios, the reference pair in
skip mode are specified as the closest fwd ref, together with the
closest bwd ref if there is any bwd ref, otherwise with the two
closest fwd refs.
Skip mode by default uses COMPOUND_AVERAGE. When all the reference
frames are on the same side, temporal-distance weighted compound is
considered, and a compound index is signaled to indicate whether
distance-weighted compound or compound-average is usd.
Whether to use distance-weighted compound for skip mode is still
under experimenting, hence a flag is temporarily added:
SKIP_MODE_WITH_JNT_COMP.
Following experimental results are obtained over 30 frames, using the
setup of --disable-ext-partition --disable-ext-partition-types
--disable-txmg --enable-jnt-comp --enable-mfmv --enable-ext-skip:
(1) High Latency:
For Google test sets (lowres/midres), the BDRate coding gain is ~0.2%;
For AWCY, the coding gain is ~0.1%.
(2) Low Latency:
No gain has been observed over Google sets and ~0.1% gain is obtained
only when temporal-distance weighted prediction is used.
Change-Id: I8c433357adebed0126ebfdd5c4d51aa71e64be57
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index e8498fb..702fda2 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -9191,7 +9191,7 @@
mbmi->interintra_mode = (INTERINTRA_MODE)(II_DC_PRED - 1);
#if CONFIG_JNT_COMP
mbmi->comp_group_idx = 0;
- mbmi->compound_idx = 1;
+ mbmi->compound_idx = x->compound_idx;
#endif // CONFIG_JNT_COMP
mbmi->interinter_compound_type = COMPOUND_AVERAGE;
mbmi->motion_mode = SIMPLE_TRANSLATION;
@@ -10618,9 +10618,57 @@
if (cm->skip_mode_flag &&
!segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME) &&
is_comp_ref_allowed(bsize)) {
- // Obtain the rdcost for skip_mode.
- estimate_skip_mode_rdcost(cpi, tile_data, x, bsize, mi_row, mi_col,
- frame_mv, yv12_mb);
+// Obtain the rdcost for skip_mode.
+#if CONFIG_JNT_COMP
+ x->compound_idx = 1; // COMPOUND_AVERAGE
+#if SKIP_MODE_WITH_JNT_COMP
+ const int cur_offset = (int)cm->frame_offset;
+ const int cur_to_fwd = cur_offset - cm->ref_frame_idx_0;
+ const int cur_to_bwd = abs(cm->ref_frame_idx_1 - cur_offset);
+ if (cur_to_fwd != cur_to_bwd && xd->all_one_sided_refs) {
+ // Decide on the JNT_COMP mode.
+ int64_t best_skip_mode_rd = INT64_MAX;
+ int best_compound_idx = 0;
+ int best_skip_mode_rate = 0;
+ int64_t best_skip_mode_sse = 0, best_skip_mode_dist = 0;
+
+ for (int compound_idx = 0; compound_idx < 2; ++compound_idx) {
+ x->compound_idx = compound_idx;
+ estimate_skip_mode_rdcost(cpi, tile_data, x, bsize, mi_row, mi_col,
+ frame_mv, yv12_mb);
+
+ if (x->skip_mode_rdcost >= 0 && x->skip_mode_rdcost < INT64_MAX) {
+ // Update skip mode rdcost.
+ const int comp_index_ctx = get_comp_index_context(cm, xd);
+ x->skip_mode_rate += x->comp_idx_cost[comp_index_ctx][compound_idx];
+ x->skip_mode_rdcost =
+ RDCOST(x->rdmult, x->skip_mode_rate, x->skip_mode_dist);
+
+ if (x->skip_mode_rdcost < best_skip_mode_rd) {
+ best_skip_mode_rd = x->skip_mode_rdcost;
+ best_compound_idx = compound_idx;
+ best_skip_mode_rate = x->skip_mode_rate;
+ best_skip_mode_sse = x->skip_mode_sse;
+ best_skip_mode_dist = x->skip_mode_dist;
+ }
+ }
+ }
+
+ if (best_skip_mode_rd < INT64_MAX) {
+ x->compound_idx = best_compound_idx;
+ x->skip_mode_rdcost = best_skip_mode_rd;
+ x->skip_mode_rate = best_skip_mode_rate;
+ x->skip_mode_sse = best_skip_mode_sse;
+ x->skip_mode_dist = best_skip_mode_dist;
+ }
+ } else {
+#endif // SKIP_MODE_WITH_JNT_COMP
+#endif // CONFIG_JNT_COMP
+ estimate_skip_mode_rdcost(cpi, tile_data, x, bsize, mi_row, mi_col,
+ frame_mv, yv12_mb);
+#if CONFIG_JNT_COMP && SKIP_MODE_WITH_JNT_COMP
+ }
+#endif // CONFIG_JNT_COMP && SKIP_MODE_WITH_JNT_COMP
if (x->skip_mode_rdcost >= 0 && x->skip_mode_rdcost < INT64_MAX) {
// Update skip mode rdcost.
@@ -10668,9 +10716,15 @@
best_mbmode.uv_mode = UV_DC_PRED;
best_mbmode.palette_mode_info.palette_size[0] = 0;
best_mbmode.palette_mode_info.palette_size[1] = 0;
- best_mbmode.interintra_mode = (INTERINTRA_MODE)(II_DC_PRED - 1);
+
+#if CONFIG_JNT_COMP
+ best_mbmode.comp_group_idx = 0;
+ best_mbmode.compound_idx = x->compound_idx;
+#endif // CONFIG_JNT_COMP
best_mbmode.interinter_compound_type = COMPOUND_AVERAGE;
best_mbmode.motion_mode = SIMPLE_TRANSLATION;
+
+ best_mbmode.interintra_mode = (INTERINTRA_MODE)(II_DC_PRED - 1);
#if CONFIG_FILTER_INTRA
best_mbmode.filter_intra_mode_info.use_filter_intra_mode[0] = 0;
best_mbmode.filter_intra_mode_info.use_filter_intra_mode[1] = 0;