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),