rtc-svc: Add example for 3 spatial layers.
Add (3SL, 1TL) case to sample encoder and unittest.
Change-Id: I66ba12b3c9357e136aca5782b0edf7f060de39b8
diff --git a/examples/svc_encoder_rtc.c b/examples/svc_encoder_rtc.c
index a5ab076..d77fa99 100644
--- a/examples/svc_encoder_rtc.c
+++ b/examples/svc_encoder_rtc.c
@@ -30,9 +30,9 @@
void usage_exit(void) { exit(EXIT_FAILURE); }
-static int mode_to_num_temporal_layers[6] = { 1, 2, 3, 3, 2, 1 };
-static int mode_to_num_spatial_layers[6] = { 1, 1, 1, 1, 1, 2 };
-static int mode_to_num_layers[6] = { 1, 2, 3, 3, 2, 2 };
+static int mode_to_num_temporal_layers[7] = { 1, 2, 3, 3, 2, 1, 1 };
+static int mode_to_num_spatial_layers[7] = { 1, 1, 1, 1, 1, 2, 3 };
+static int mode_to_num_layers[7] = { 1, 2, 3, 3, 2, 2, 3 };
// For rate control encoding stats.
struct RateControlMetrics {
@@ -354,19 +354,49 @@
}
break;
case 5:
+ // 2 spatial layers, 1 temporal.
layer_id->temporal_layer_id = 0;
if (layer_id->spatial_layer_id == 0) {
- // Reference LAST, update LAST. Keep LAST and GOLDEN in slots 0 and 3.
- ref_frame_config->ref_idx[0] = 0;
- ref_frame_config->ref_idx[3] = 3;
+ // Reference LAST, update LAST.
ref_frame_config->refresh[0] = 1;
layer_flags |= AOM_EFLAG_NO_REF_GF;
} else if (layer_id->spatial_layer_id == 1) {
- // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 3
- // and GOLDEN to slot 0. Update slot 3 (LAST).
- ref_frame_config->ref_idx[0] = 3;
+ // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 1
+ // and GOLDEN to slot 0. Update slot 1 (LAST).
+ ref_frame_config->ref_idx[0] = 1;
ref_frame_config->ref_idx[3] = 0;
- ref_frame_config->refresh[3] = 1;
+ ref_frame_config->refresh[1] = 1;
+ }
+ break;
+ case 6:
+ // 3 spatial layers, 1 temporal.
+ // Note for this case, we set the buffer idx for all references to be
+ // either LAST or GOLDEN, which are always valid references, since decoder
+ // will check if any of the 7 references is valid scale in
+ // valid_ref_frame_size().
+ layer_id->temporal_layer_id = 0;
+ if (layer_id->spatial_layer_id == 0) {
+ // Reference LAST, update LAST. Set all buffer_idx to 0.
+ for (i = 0; i < INTER_REFS_PER_FRAME; i++)
+ ref_frame_config->ref_idx[i] = 0;
+ ref_frame_config->refresh[0] = 1;
+ layer_flags |= AOM_EFLAG_NO_REF_GF;
+ } else if (layer_id->spatial_layer_id == 1) {
+ // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 1
+ // and GOLDEN (and all other refs) to slot 0.
+ // Update slot 1 (LAST).
+ for (i = 0; i < INTER_REFS_PER_FRAME; i++)
+ ref_frame_config->ref_idx[i] = 0;
+ ref_frame_config->ref_idx[0] = 1;
+ ref_frame_config->refresh[1] = 1;
+ } else if (layer_id->spatial_layer_id == 2) {
+ // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 2
+ // and GOLDEN (and all other refs) to slot 1.
+ // Update slot 2 (LAST).
+ for (i = 0; i < INTER_REFS_PER_FRAME; i++)
+ ref_frame_config->ref_idx[i] = 1;
+ ref_frame_config->ref_idx[0] = 2;
+ ref_frame_config->refresh[2] = 1;
}
break;
default: assert(0); die("Error: Unsupported temporal layering mode!\n");
diff --git a/test/svc_datarate_test.cc b/test/svc_datarate_test.cc
index 1a50f16..a6d3b3d 100644
--- a/test/svc_datarate_test.cc
+++ b/test/svc_datarate_test.cc
@@ -64,8 +64,13 @@
&svc_params_);
encoder->Control(AV1E_SET_SVC_PARAMS, &svc_params_);
}
- if (number_spatial_layers_ == 2)
+ if (number_spatial_layers_ == 2) {
spatial_layer_id = (layer_frame_cnt_ % 2 == 0) ? 0 : 1;
+ } else if (number_spatial_layers_ == 3) {
+ spatial_layer_id = (layer_frame_cnt_ % 3 == 0)
+ ? 0
+ : ((layer_frame_cnt_ - 1) % 3 == 0) ? 1 : 2;
+ }
// Set the reference/update flags, layer_id, and reference_map
// buffer index.
frame_flags_ = set_layer_pattern(video->frame(), &layer_id_,
@@ -152,6 +157,33 @@
ref_frame_config->ref_idx[3] = 0;
ref_frame_config->refresh[3] = 1;
}
+ } else if (number_temporal_layers_ == 1 && number_spatial_layers_ == 3) {
+ // 3 spatial layers, 1 temporal.
+ // Note for this case , we set the buffer idx for all references to be
+ // either LAST or GOLDEN, which are always valid references, since decoder
+ // will check if any of the 7 references is valid scale in
+ // valid_ref_frame_size().
+ layer_id->temporal_layer_id = 0;
+ if (layer_id->spatial_layer_id == 0) {
+ // Reference LAST, update LAST. Set all other buffer_idx to 0.
+ for (int i = 0; i < 7; i++) ref_frame_config->ref_idx[i] = 0;
+ ref_frame_config->refresh[0] = 1;
+ layer_flags |= AOM_EFLAG_NO_REF_GF;
+ } else if (layer_id->spatial_layer_id == 1) {
+ // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 1
+ // and GOLDEN (and all other refs) to slot 0.
+ // Update slot 1 (LAST).
+ for (int i = 0; i < 7; i++) ref_frame_config->ref_idx[i] = 0;
+ ref_frame_config->ref_idx[0] = 1;
+ ref_frame_config->refresh[1] = 1;
+ } else if (layer_id->spatial_layer_id == 2) {
+ // Reference LAST and GOLDEN. Set buffer_idx for LAST to slot 2
+ // and GOLDEN (and all other refs) to slot 1.
+ // Update slot 2 (LAST).
+ for (int i = 0; i < 7; i++) ref_frame_config->ref_idx[i] = 1;
+ ref_frame_config->ref_idx[0] = 2;
+ ref_frame_config->refresh[2] = 1;
+ }
}
return layer_flags;
}
@@ -253,6 +285,37 @@
}
}
+ virtual void BasicRateTargetingSVC1TL3SLTest() {
+ 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_usage = AOM_USAGE_REALTIME;
+ cfg_.g_error_resilient = 1;
+
+ ::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352,
+ 288, 30, 1, 0, 300);
+ const int bitrate_array[2] = { 500, 1000 };
+ cfg_.rc_target_bitrate = bitrate_array[GET_PARAM(4)];
+ ResetModel();
+ number_temporal_layers_ = 1;
+ number_spatial_layers_ = 3;
+ target_layer_bitrate_[0] = 1 * cfg_.rc_target_bitrate / 8;
+ target_layer_bitrate_[1] = 3 * cfg_.rc_target_bitrate / 8;
+ target_layer_bitrate_[2] = 4 * cfg_.rc_target_bitrate / 8;
+ 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.38)
+ << " The datarate for the file is greater than target by too much!";
+ }
+ }
+
int layer_frame_cnt_;
int number_temporal_layers_;
int number_spatial_layers_;
@@ -264,16 +327,21 @@
double effective_datarate_tl[AOM_MAX_LAYERS];
};
-// Check basic rate targeting for CBR, for 3 temporal layers.
+// Check basic rate targeting for CBR, for 3 temporal layers, 1 spatial.
TEST_P(DatarateTestSVC, BasicRateTargetingSVC3TL1SL) {
BasicRateTargetingSVC3TL1SLTest();
}
-// Check basic rate targeting for CBR, for 2 spatial layers.
+// Check basic rate targeting for CBR, for 2 spatial layers, 1 temporal.
TEST_P(DatarateTestSVC, BasicRateTargetingSVC1TL2SL) {
BasicRateTargetingSVC1TL2SLTest();
}
+// Check basic rate targeting for CBR, for 3 spatial layers, 1 temporal.
+TEST_P(DatarateTestSVC, BasicRateTargetingSVC1TL3SL) {
+ BasicRateTargetingSVC1TL3SLTest();
+}
+
AV1_INSTANTIATE_TEST_CASE(DatarateTestSVC,
::testing::Values(::libaom_test::kRealTime),
::testing::Range(7, 9),