svc: Fix interface to svc for compound prediction
For layered encoding in nonrd: rework/refactor the
compound prediction mode and extend interface to
allow for using any combination of the reference pairs:
({last_golden}, {last_last2}, {last_altref}).
Added testcase for this to svc_datarate_test.cc.
No change in behavior for 1 layer/non-svc.
Change-Id: Ie26db5988af4f8d93ce4ff92b9805640e3e7bc7a
diff --git a/aom/aomcx.h b/aom/aomcx.h
index e7ea71f..e92c0a7 100644
--- a/aom/aomcx.h
+++ b/aom/aomcx.h
@@ -1502,8 +1502,10 @@
int reference[7]; /**< Reference flag for each of the 7 references. */
/*! Buffer slot index for each of 7 references. */
int ref_idx[7];
- int refresh[8]; /**< Refresh flag for each of the 8 slots. */
- int use_comp_pred; /**< Use compound prediction. */
+ int refresh[8]; /**< Refresh flag for each of the 8 slots. */
+ // Use compound prediction for the ref_frame pairs GOLDEN_LAST (0),
+ // LAST2_LAST (1), and ALTREF_LAST (2).
+ int ref_frame_comp[3]; /**<Compound reference flag. */
} aom_svc_ref_frame_config_t;
/*!\cond */
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index 5f82e10..2109f54 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -3241,7 +3241,9 @@
}
for (unsigned int i = 0; i < REF_FRAMES; ++i)
cpi->svc.refresh[i] = data->refresh[i];
- cpi->svc.use_comp_pred = data->use_comp_pred;
+ cpi->svc.ref_frame_comp[0] = data->ref_frame_comp[0];
+ cpi->svc.ref_frame_comp[1] = data->ref_frame_comp[1];
+ cpi->svc.ref_frame_comp[2] = data->ref_frame_comp[2];
cpi->svc.use_flexible_mode = 1;
cpi->svc.ksvc_fixed_mode = 0;
return AOM_CODEC_OK;
diff --git a/av1/encoder/nonrd_pickmode.c b/av1/encoder/nonrd_pickmode.c
index c114920..3402acb 100644
--- a/av1/encoder/nonrd_pickmode.c
+++ b/av1/encoder/nonrd_pickmode.c
@@ -2307,7 +2307,7 @@
void setup_compound_prediction(AV1_COMP *cpi, MACROBLOCK *x,
struct buf_2d yv12_mb[8][MAX_MB_PLANE],
- int *use_ref_frame_mask, int flag_comp_nonrd,
+ int *use_ref_frame_mask, int flag_comp,
int *ref_mv_idx) {
AV1_COMMON *const cm = &cpi->common;
MACROBLOCKD *const xd = &x->e_mbd;
@@ -2315,9 +2315,9 @@
MB_MODE_INFO_EXT *const mbmi_ext = &x->mbmi_ext;
MV_REFERENCE_FRAME rf[2] = { LAST_FRAME, GOLDEN_FRAME };
MV_REFERENCE_FRAME ref_frame_comp;
- if (flag_comp_nonrd == 1) {
+ if (flag_comp == 1) {
rf[1] = LAST2_FRAME;
- } else if (flag_comp_nonrd == 2) {
+ } else if (flag_comp == 2) {
rf[1] = ALTREF_FRAME;
}
if (!use_ref_frame_mask[rf[1]]) {
@@ -2340,8 +2340,8 @@
*ref_mv_idx = mbmi->ref_mv_idx + 1;
}
-static void set_compound_mode(MACROBLOCK *x, int idx, int num_inter_modes,
- int ref_frame, int ref_frame2, int ref_mv_idx,
+static void set_compound_mode(MACROBLOCK *x, int comp_index, int ref_frame,
+ int ref_frame2, int ref_mv_idx,
int_mv frame_mv[MB_MODE_COUNT][REF_FRAMES],
PREDICTION_MODE *this_mode) {
MACROBLOCKD *const xd = &x->e_mbd;
@@ -2353,16 +2353,16 @@
mi->comp_group_idx = 0;
mi->interinter_comp.type = COMPOUND_AVERAGE;
MV_REFERENCE_FRAME ref_frame_comp = av1_ref_frame_type(mi->ref_frame);
- if (idx == num_inter_modes) {
+ if (comp_index % 3 == 0) {
frame_mv[*this_mode][ref_frame].as_int = 0;
frame_mv[*this_mode][ref_frame2].as_int = 0;
- } else if (idx == num_inter_modes + 1) {
+ } else if (comp_index % 3 == 1) {
*this_mode = NEAREST_NEARESTMV;
frame_mv[*this_mode][ref_frame].as_int =
xd->ref_mv_stack[ref_frame_comp][0].this_mv.as_int;
frame_mv[*this_mode][ref_frame2].as_int =
xd->ref_mv_stack[ref_frame_comp][0].comp_mv.as_int;
- } else if (idx == num_inter_modes + 2) {
+ } else if (comp_index % 3 == 2) {
*this_mode = NEAR_NEARMV;
frame_mv[*this_mode][ref_frame].as_int =
xd->ref_mv_stack[ref_frame_comp][ref_mv_idx].this_mv.as_int;
@@ -2387,6 +2387,7 @@
#endif
MV_REFERENCE_FRAME ref_frame, ref_frame2;
int_mv frame_mv[MB_MODE_COUNT][REF_FRAMES];
+ int_mv frame_mv_best[MB_MODE_COUNT][REF_FRAMES];
uint8_t mode_checked[MB_MODE_COUNT][REF_FRAMES];
struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE];
RD_STATS this_rdc, best_rdc;
@@ -2432,7 +2433,8 @@
int force_mv_inter_layer = 0;
int use_modeled_non_rd_cost = 0;
int comp_pred = 0;
- int num_comp_modes = 0;
+ int num_comp_modes_ref = 0;
+ int tot_num_comp_modes = 9;
int ref_mv_idx = 0;
#if CONFIG_AV1_TEMPORAL_DENOISING
const int denoise_recheck_zeromv = 1;
@@ -2509,15 +2511,19 @@
get_ref_frame_use_mask(cpi, x, mi, mi_row, mi_col, bsize, gf_temporal_ref,
use_ref_frame_mask, &force_skip_low_temp_var);
- // Compound modes: LAST_GOLDEN/LAST_LAST2/LAST_ALTREF for 0/NEARESST/NEAR.
- // For now to reduce slowdowm, use only 0/0 for blocks above 16x16
+ // Compound modes per reference pair (GOLDEN_LAST/LAST2_LAST/ALTREF_LAST):
+ // (0_0)/(NEAREST_NEAREST)/(NEAR_NEAR).
+ // For now to reduce slowdowm, use only (0,0) for blocks above 16x16
// for non-svc case or on enhancement layers for svc.
if (cpi->sf.rt_sf.use_comp_ref_nonrd && is_comp_ref_allowed(bsize)) {
- if (cpi->ppi->use_svc && cpi->svc.use_comp_pred &&
- cpi->svc.temporal_layer_id == 0)
- num_comp_modes = 3;
+ if (cpi->ppi->use_svc && cpi->svc.temporal_layer_id == 0)
+ num_comp_modes_ref = 2;
else if (bsize > BLOCK_16X16)
- num_comp_modes = 1;
+ num_comp_modes_ref = 1;
+ else
+ tot_num_comp_modes = 0;
+ } else {
+ tot_num_comp_modes = 0;
}
for (MV_REFERENCE_FRAME ref_frame_iter = LAST_FRAME;
@@ -2566,7 +2572,7 @@
tx_mode_to_biggest_tx_size[txfm_params->tx_mode_search_type]),
TX_16X16);
- for (int idx = 0; idx < num_inter_modes + num_comp_modes; ++idx) {
+ for (int idx = 0; idx < num_inter_modes + tot_num_comp_modes; ++idx) {
const struct segmentation *const seg = &cm->seg;
int rate_mv = 0;
@@ -2580,25 +2586,43 @@
av1_invalid_rd_stats(&nonskip_rdc);
if (idx >= num_inter_modes) {
+ int comp_index = idx - num_inter_modes;
+ if (comp_index % 3 == 0) {
+ int i = 0;
+ ref_mv_idx = 0;
+ // Only needs to be done once per reference pair.
+ if (comp_index == 3) i = 1;
+ if (comp_index == 6) i = 2;
+ if (cpi->sf.rt_sf.ref_frame_comp_nonrd[i])
+ setup_compound_prediction(cpi, x, yv12_mb, use_ref_frame_mask, i,
+ &ref_mv_idx);
+ }
+ // num_comp_modes_ref == 1 only do (0,0)
+ if (num_comp_modes_ref == 1 && comp_index % 3 != 0) continue;
+ // num_comp_modes_ref == 2 only do (0,0) and (NEAREST_NEAREST)
+ if (num_comp_modes_ref == 2 && comp_index % 3 == 2) continue;
ref_frame = LAST_FRAME;
- if (cpi->sf.rt_sf.ref_frame_comp_nonrd == 2) {
- ref_frame2 = ALTREF_FRAME;
- if (!(cpi->ref_frame_flags & AOM_ALT_FLAG)) continue;
- } else if (cpi->sf.rt_sf.ref_frame_comp_nonrd == 1) {
+ ref_frame2 = GOLDEN_FRAME;
+ if (comp_index >= 0 && comp_index < 3) {
+ // comp_index = 0,1,2 for (0/NEAREST/NEAR) for GOLDEN_LAST.
+ if (cpi->sf.rt_sf.ref_frame_comp_nonrd[0] == 0 ||
+ !(cpi->ref_frame_flags & AOM_GOLD_FLAG))
+ continue;
+ } else if (comp_index >= 3 && comp_index < 6) {
+ // comp_index = 3,4,5 for (0/NEAREST/NEAR) for LAST2_LAST.
ref_frame2 = LAST2_FRAME;
- if (!(cpi->ref_frame_flags & AOM_LAST2_FLAG)) continue;
- } else {
- ref_frame2 = GOLDEN_FRAME;
- if (!(cpi->ref_frame_flags & AOM_GOLD_FLAG)) continue;
+ if (cpi->sf.rt_sf.ref_frame_comp_nonrd[1] == 0 ||
+ !(cpi->ref_frame_flags & AOM_LAST2_FLAG))
+ continue;
+ } else if (comp_index >= 6 && comp_index < 9) {
+ // comp_index = 6,7,8 for (0/NEAREST/NEAR) for ALTREF_LAST.
+ ref_frame2 = ALTREF_FRAME;
+ if (cpi->sf.rt_sf.ref_frame_comp_nonrd[2] == 0 ||
+ !(cpi->ref_frame_flags & AOM_ALT_FLAG))
+ continue;
}
- if (idx == num_inter_modes) {
- // Only needs to be done once on first compound mode.
- setup_compound_prediction(cpi, x, yv12_mb, use_ref_frame_mask,
- cpi->sf.rt_sf.ref_frame_comp_nonrd,
- &ref_mv_idx);
- }
- set_compound_mode(x, idx, num_inter_modes, ref_frame, ref_frame2,
- ref_mv_idx, frame_mv, &this_mode);
+ set_compound_mode(x, comp_index, ref_frame, ref_frame2, ref_mv_idx,
+ frame_mv, &this_mode);
if (this_mode != GLOBAL_GLOBALMV &&
frame_mv[this_mode][ref_frame].as_int == 0 &&
frame_mv[this_mode][ref_frame2].as_int == 0)
@@ -2890,6 +2914,13 @@
best_pickmode.best_mode_initial_skip_flag =
(nonskip_rdc.rate == INT_MAX && this_rdc.skip_txfm);
+ // This is needed for the compoune modes.
+ frame_mv_best[this_mode][ref_frame].as_int =
+ frame_mv[this_mode][ref_frame].as_int;
+ if (ref_frame2 > NONE_FRAME)
+ frame_mv_best[this_mode][ref_frame2].as_int =
+ frame_mv[this_mode][ref_frame2].as_int;
+
if (reuse_inter_pred) {
free_pred_buffer(best_pickmode.best_pred);
best_pickmode.best_pred = this_mode_pred;
@@ -2912,13 +2943,14 @@
memset(mi->inter_tx_size, mi->tx_size, sizeof(mi->inter_tx_size));
mi->ref_frame[0] = best_pickmode.best_ref_frame;
mi->mv[0].as_int =
- frame_mv[best_pickmode.best_mode][best_pickmode.best_ref_frame].as_int;
+ frame_mv_best[best_pickmode.best_mode][best_pickmode.best_ref_frame]
+ .as_int;
mi->mv[1].as_int = 0;
if (best_pickmode.best_second_ref_frame > INTRA_FRAME) {
mi->ref_frame[1] = best_pickmode.best_second_ref_frame;
- mi->mv[1].as_int =
- frame_mv[best_pickmode.best_mode][best_pickmode.best_second_ref_frame]
- .as_int;
+ mi->mv[1].as_int = frame_mv_best[best_pickmode.best_mode]
+ [best_pickmode.best_second_ref_frame]
+ .as_int;
}
// Perform intra prediction search, if the best SAD is above a certain
// threshold.
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index da31d50..a19974a 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -2530,7 +2530,7 @@
ext_flags->ref_frame_flags ^= AOM_ALT_FLAG;
if (cpi->sf.rt_sf.use_golden_frame)
ext_flags->ref_frame_flags ^= AOM_GOLD_FLAG;
- if (cpi->sf.rt_sf.ref_frame_comp_nonrd == 1)
+ if (cpi->sf.rt_sf.ref_frame_comp_nonrd[1])
ext_flags->ref_frame_flags ^= AOM_LAST2_FLAG;
const int sh = 7 - gld_fixed_slot;
// Moving index slot for last: 0 - (sh - 1).
@@ -2549,14 +2549,14 @@
// Moving index for alt_ref, lag behind LAST by lag_alt frames.
if (cm->current_frame.frame_number > lag_alt)
alt_ref_idx = ((cm->current_frame.frame_number - lag_alt) % sh);
- if (cpi->sf.rt_sf.ref_frame_comp_nonrd == 1) {
+ if (cpi->sf.rt_sf.ref_frame_comp_nonrd[1]) {
// Moving index for LAST2, lag behind LAST by 2 frames.
if (cm->current_frame.frame_number > 2)
last2_idx = ((cm->current_frame.frame_number - 2) % sh);
}
svc->ref_idx[0] = last_idx; // LAST
svc->ref_idx[1] = last_idx_refresh; // LAST2 (for refresh of last).
- if (cpi->sf.rt_sf.ref_frame_comp_nonrd == 1) {
+ if (cpi->sf.rt_sf.ref_frame_comp_nonrd[1]) {
svc->ref_idx[1] = last2_idx; // LAST2
svc->ref_idx[2] = last_idx_refresh; // LAST3 (for refresh of last).
}
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index d1d7b80..4a2035c 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -1207,7 +1207,7 @@
} else {
if (speed >= 7) {
sf->rt_sf.use_comp_ref_nonrd = 1;
- sf->rt_sf.ref_frame_comp_nonrd = 2; // LAST_ALTREF
+ sf->rt_sf.ref_frame_comp_nonrd[2] = 1; // LAST_ALTREF
}
if (speed == 8 && !cpi->ppi->use_svc) {
sf->rt_sf.short_circuit_low_temp_var = 0;
@@ -1230,17 +1230,18 @@
sf->rt_sf.estimate_motion_for_var_based_partition = 0;
}
}
- // TODO(marpan): Fix this for SVC: allow for any combination
- // of the 3 reference pairs for compound prediction in nonrd.
- if (cpi->ppi->use_svc && cpi->svc.use_comp_pred &&
- (cpi->svc.reference[GOLDEN_FRAME - 1] == 1 ||
- cpi->svc.reference[LAST2_FRAME - 1] == 1 ||
- cpi->svc.reference[ALTREF_FRAME - 1] == 1)) {
- sf->rt_sf.use_comp_ref_nonrd = 1;
- sf->rt_sf.ref_frame_comp_nonrd =
- (cpi->svc.reference[GOLDEN_FRAME - 1] == 1)
- ? 0
- : ((cpi->svc.reference[LAST2_FRAME - 1] == 1) ? 1 : 2);
+ if (cpi->ppi->use_svc) {
+ sf->rt_sf.use_comp_ref_nonrd = 0;
+ if (cpi->svc.ref_frame_comp[0] || cpi->svc.ref_frame_comp[1] ||
+ cpi->svc.ref_frame_comp[2]) {
+ sf->rt_sf.use_comp_ref_nonrd = 1;
+ sf->rt_sf.ref_frame_comp_nonrd[0] =
+ cpi->svc.ref_frame_comp[0] && cpi->svc.reference[GOLDEN_FRAME - 1];
+ sf->rt_sf.ref_frame_comp_nonrd[1] =
+ cpi->svc.ref_frame_comp[1] && cpi->svc.reference[LAST2_FRAME - 1];
+ sf->rt_sf.ref_frame_comp_nonrd[2] =
+ cpi->svc.ref_frame_comp[2] && cpi->svc.reference[ALTREF_FRAME - 1];
+ }
}
}
@@ -1314,7 +1315,10 @@
sf->rt_sf.check_intra_pred_nonrd = 1;
sf->rt_sf.estimate_motion_for_var_based_partition = 1;
sf->rt_sf.hybrid_intra_pickmode = 1;
- sf->rt_sf.use_comp_ref_nonrd = 1;
+ sf->rt_sf.use_comp_ref_nonrd = 0;
+ sf->rt_sf.ref_frame_comp_nonrd[0] = 0;
+ sf->rt_sf.ref_frame_comp_nonrd[1] = 0;
+ sf->rt_sf.ref_frame_comp_nonrd[2] = 0;
sf->rt_sf.use_nonrd_filter_search = 1;
sf->tx_sf.intra_tx_size_search_init_depth_sqr = 1;
@@ -1394,7 +1398,6 @@
sf->rt_sf.mode_search_skip_flags |= FLAG_SKIP_INTRA_DIRMISMATCH;
sf->rt_sf.num_inter_modes_for_tx_search = 5;
sf->rt_sf.skip_interp_filter_search = 1;
- sf->rt_sf.use_comp_ref_nonrd = 0;
sf->rt_sf.use_real_time_ref_set = 1;
sf->rt_sf.use_simple_rd_model = 1;
@@ -1444,9 +1447,6 @@
sf->rt_sf.reuse_inter_pred_nonrd = 0;
sf->rt_sf.short_circuit_low_temp_var = 0;
sf->rt_sf.skip_interp_filter_search = 0;
- sf->rt_sf.use_comp_ref_nonrd = 0;
- // 1 for LAST_LAST2, otherwise LAST_GOLDEN.
- sf->rt_sf.ref_frame_comp_nonrd = 0;
// For spatial layers, only LAST and GOLDEN are currently used in the SVC
// for nonrd. The flag use_nonrd_altref_frame can disable GOLDEN in the
// get_ref_frame_flags() for some patterns, so disable it here for
@@ -1790,7 +1790,6 @@
rt_sf->use_nonrd_altref_frame = 0;
rt_sf->use_golden_frame = 0;
rt_sf->use_comp_ref_nonrd = 0;
- rt_sf->ref_frame_comp_nonrd = 0;
rt_sf->use_real_time_ref_set = 0;
rt_sf->short_circuit_low_temp_var = 0;
rt_sf->use_modeled_non_rd_cost = 0;
diff --git a/av1/encoder/speed_features.h b/av1/encoder/speed_features.h
index 39ddb12..80a649b 100644
--- a/av1/encoder/speed_features.h
+++ b/av1/encoder/speed_features.h
@@ -1210,8 +1210,8 @@
int use_comp_ref_nonrd;
// Reference frames for compound prediction for nonrd pickmode:
- // LAST_GOLDEN (0, default), LAST_LAST2 (1), or LAST_ALTREF (2).
- int ref_frame_comp_nonrd;
+ // LAST_GOLDEN (0), LAST_LAST2 (1), or LAST_ALTREF (2).
+ int ref_frame_comp_nonrd[3];
// use reduced ref set for real-time mode
int use_real_time_ref_set;
diff --git a/av1/encoder/svc_layercontext.c b/av1/encoder/svc_layercontext.c
index f74af68..d456d9d 100644
--- a/av1/encoder/svc_layercontext.c
+++ b/av1/encoder/svc_layercontext.c
@@ -86,6 +86,9 @@
if (svc->number_spatial_layers == 3) {
svc->downsample_filter_type[0] = EIGHTTAP_SMOOTH;
}
+ svc->ref_frame_comp[0] = 0;
+ svc->ref_frame_comp[1] = 0;
+ svc->ref_frame_comp[2] = 0;
}
// Update the layer context from a change_config() call.
diff --git a/av1/encoder/svc_layercontext.h b/av1/encoder/svc_layercontext.h
index bda7be9..a1dff40 100644
--- a/av1/encoder/svc_layercontext.h
+++ b/av1/encoder/svc_layercontext.h
@@ -99,7 +99,7 @@
int non_reference_frame;
int use_flexible_mode;
int ksvc_fixed_mode;
- int use_comp_pred;
+ int ref_frame_comp[3];
/*!\endcond */
/*!
diff --git a/examples/svc_encoder_rtc.c b/examples/svc_encoder_rtc.c
index cd179bd..73c46df 100644
--- a/examples/svc_encoder_rtc.c
+++ b/examples/svc_encoder_rtc.c
@@ -568,7 +568,9 @@
layer_id->spatial_layer_id = spatial_layer_id;
int lag_index = 0;
int base_count = superframe_cnt >> 2;
- ref_frame_config->use_comp_pred = 0;
+ ref_frame_config->ref_frame_comp[0] = 0; // GOLDEN_LAST
+ ref_frame_config->ref_frame_comp[1] = 0; // LAST2_LAST
+ ref_frame_config->ref_frame_comp[2] = 0; // ALTREF_LAST
// Set the reference map buffer idx for the 7 references:
// LAST_FRAME (0), LAST2_FRAME(1), LAST3_FRAME(2), GOLDEN_FRAME(3),
// BWDREF_FRAME(4), ALTREF2_FRAME(5), ALTREF_FRAME(6).
diff --git a/test/svc_datarate_test.cc b/test/svc_datarate_test.cc
index d2839cc..2ba1156 100644
--- a/test/svc_datarate_test.cc
+++ b/test/svc_datarate_test.cc
@@ -81,6 +81,7 @@
set_frame_level_er_ = 0;
multi_ref_ = 0;
use_fixed_mode_svc_ = 0;
+ comp_pred_ = 0;
}
virtual void PreEncodeFrameHook(::libaom_test::VideoSource *video,
@@ -110,7 +111,7 @@
// buffer index.
frame_flags_ =
set_layer_pattern(video->frame(), &layer_id_, &ref_frame_config_,
- spatial_layer_id, multi_ref_);
+ spatial_layer_id, multi_ref_, comp_pred_);
encoder->Control(AV1E_SET_SVC_LAYER_ID, &layer_id_);
// The SET_SVC_REF_FRAME_CONFIG api is for the flexible SVC mode
// (i.e., use_fixed_mode_svc == 0).
@@ -172,7 +173,8 @@
// Layer pattern configuration.
virtual int set_layer_pattern(int frame_cnt, aom_svc_layer_id_t *layer_id,
aom_svc_ref_frame_config_t *ref_frame_config,
- int spatial_layer, int multi_ref) {
+ int spatial_layer, int multi_ref,
+ int comp_pred) {
int lag_index = 0;
int base_count = frame_cnt >> 2;
layer_id->spatial_layer_id = spatial_layer;
@@ -184,6 +186,11 @@
ref_frame_config->reference[i] = 0;
}
for (int i = 0; i < REF_FRAMES; i++) ref_frame_config->refresh[i] = 0;
+ if (comp_pred) {
+ ref_frame_config->ref_frame_comp[0] = 1; // GOLDEN_LAST
+ ref_frame_config->ref_frame_comp[1] = 1; // LAST2_LAST
+ ref_frame_config->ref_frame_comp[2] = 1; // ALTREF_LAST
+ }
// Set layer_flags to 0 when using ref_frame_config->reference.
int layer_flags = 0;
// Always reference LAST.
@@ -1132,6 +1139,40 @@
EXPECT_EQ((int)GetMismatchFrames(), 0);
}
+ virtual void BasicRateTargetingSVC3TL1SLMultiRefCompoundTest() {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_dropframe_thresh = 0;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.rc_end_usage = AOM_CBR;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.g_error_resilient = 0;
+
+ ::libaom_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30,
+ 1, 0, 400);
+ cfg_.g_w = 640;
+ cfg_.g_h = 480;
+ const int bitrate_array[2] = { 400, 800 };
+ cfg_.rc_target_bitrate = bitrate_array[GET_PARAM(4)];
+ ResetModel();
+ multi_ref_ = 1;
+ comp_pred_ = 1;
+ number_temporal_layers_ = 3;
+ number_spatial_layers_ = 1;
+ target_layer_bitrate_[0] = 50 * cfg_.rc_target_bitrate / 100;
+ target_layer_bitrate_[1] = 70 * cfg_.rc_target_bitrate / 100;
+ target_layer_bitrate_[2] = cfg_.rc_target_bitrate;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ for (int i = 0; i < number_temporal_layers_ * number_spatial_layers_; i++) {
+ ASSERT_GE(effective_datarate_tl[i], target_layer_bitrate_[i] * 0.80)
+ << " The datarate for the file is lower than target by too much!";
+ ASSERT_LE(effective_datarate_tl[i], target_layer_bitrate_[i] * 1.60)
+ << " The datarate for the file is greater than target by too much!";
+ }
+ }
+
int layer_frame_cnt_;
int superframe_cnt_;
int number_temporal_layers_;
@@ -1150,6 +1191,7 @@
int set_frame_level_er_;
int multi_ref_;
int use_fixed_mode_svc_;
+ int comp_pred_;
};
// Check basic rate targeting for CBR, for 3 temporal layers, 1 spatial.
@@ -1260,6 +1302,13 @@
BasicRateTargetingSVC3TL1SLDropAllEnhFrameERTest();
}
+// Check basic rate targeting for CBR, for 3 temporal layers, 1 spatial layer,
+// with compound prediction on, for pattern with two additional refereces
+// (golden and altref), both updated on base TLO frames.
+TEST_P(DatarateTestSVC, BasicRateTargetingSVC3TL1SLMultiRefCompound) {
+ BasicRateTargetingSVC3TL1SLMultiRefCompoundTest();
+}
+
AV1_INSTANTIATE_TEST_SUITE(DatarateTestSVC,
::testing::Values(::libaom_test::kRealTime),
::testing::Range(7, 10),