diff --git a/test/video_codec_tester.cc b/test/video_codec_tester.cc index 37ae712f77..e7674dfdab 100644 --- a/test/video_codec_tester.cc +++ b/test/video_codec_tester.cc @@ -1111,8 +1111,6 @@ class Encoder : public EncodedImageCallback { int result = encoder_->InitEncode(&vc, ves); RTC_CHECK(result == WEBRTC_VIDEO_CODEC_OK); - - SetRates(es); } void SetRates(const EncodingSettings& es) { @@ -1261,6 +1259,29 @@ void ConfigureSimulcast(VideoCodec* vc) { } } +void SetDefaultCodecSpecificSettings(VideoCodec* vc, int num_temporal_layers) { + switch (vc->codecType) { + case kVideoCodecVP8: + *(vc->VP8()) = VideoEncoder::GetDefaultVp8Settings(); + vc->VP8()->SetNumberOfTemporalLayers(num_temporal_layers); + break; + case kVideoCodecVP9: { + *(vc->VP9()) = VideoEncoder::GetDefaultVp9Settings(); + vc->VP9()->SetNumberOfTemporalLayers(num_temporal_layers); + } break; + case kVideoCodecH264: { + *(vc->H264()) = VideoEncoder::GetDefaultH264Settings(); + vc->H264()->SetNumberOfTemporalLayers(num_temporal_layers); + } break; + case kVideoCodecAV1: + case kVideoCodecH265: + break; + case kVideoCodecGeneric: + case kVideoCodecMultiplex: + RTC_CHECK_NOTREACHED(); + } +} + std::tuple, ScalabilityMode> SplitBitrateAndUpdateScalabilityMode(std::string codec_type, ScalabilityMode scalability_mode, @@ -1272,11 +1293,11 @@ SplitBitrateAndUpdateScalabilityMode(std::string codec_type, int num_temporal_layers = ScalabilityModeToNumTemporalLayers(scalability_mode); - if (bitrates_kbps.size() > 1 || - (num_spatial_layers == 1 && num_temporal_layers == 1)) { - RTC_CHECK(bitrates_kbps.size() == - static_cast(num_spatial_layers * num_temporal_layers)) - << "bitrates must be provided for all layers"; + int num_bitrates = static_cast(bitrates_kbps.size()); + RTC_CHECK(num_bitrates == 1 || num_bitrates == num_spatial_layers || + num_bitrates == num_spatial_layers * num_temporal_layers); + + if (num_bitrates == num_spatial_layers * num_temporal_layers) { std::vector bitrates; for (const auto& bitrate_kbps : bitrates_kbps) { bitrates.push_back(DataRate::KilobitsPerSec(bitrate_kbps)); @@ -1284,59 +1305,93 @@ SplitBitrateAndUpdateScalabilityMode(std::string codec_type, return std::make_tuple(bitrates, scalability_mode); } + int total_bitrate_kbps = + std::accumulate(bitrates_kbps.begin(), bitrates_kbps.end(), 0); + VideoCodec vc; vc.codecType = PayloadStringToCodecType(codec_type); vc.width = width; vc.height = height; - vc.startBitrate = bitrates_kbps.front(); - vc.maxBitrate = bitrates_kbps.front(); + vc.startBitrate = total_bitrate_kbps; + vc.maxBitrate = total_bitrate_kbps; vc.minBitrate = 0; vc.maxFramerate = static_cast(framerate_fps); vc.numberOfSimulcastStreams = 0; vc.mode = webrtc::VideoCodecMode::kRealtimeVideo; vc.SetScalabilityMode(scalability_mode); + SetDefaultCodecSpecificSettings(&vc, num_temporal_layers); - switch (vc.codecType) { - case kVideoCodecVP8: - // TODO(webrtc:14852): Configure simulcast. - *(vc.VP8()) = VideoEncoder::GetDefaultVp8Settings(); - vc.VP8()->SetNumberOfTemporalLayers(num_temporal_layers); - ConfigureSimulcast(&vc); - break; - case kVideoCodecVP9: { - *(vc.VP9()) = VideoEncoder::GetDefaultVp9Settings(); - vc.VP9()->SetNumberOfTemporalLayers(num_temporal_layers); - const std::vector spatialLayers = GetVp9SvcConfig(vc); - for (size_t i = 0; i < spatialLayers.size(); ++i) { - vc.spatialLayers[i] = spatialLayers[i]; - vc.spatialLayers[i].active = true; - } - } break; - case kVideoCodecAV1: { - bool result = - SetAv1SvcConfig(vc, num_spatial_layers, num_temporal_layers); - RTC_CHECK(result) << "SetAv1SvcConfig failed"; - } break; - case kVideoCodecH264: { - *(vc.H264()) = VideoEncoder::GetDefaultH264Settings(); - vc.H264()->SetNumberOfTemporalLayers(num_temporal_layers); - ConfigureSimulcast(&vc); - } break; - case kVideoCodecH265: - break; - case kVideoCodecGeneric: - case kVideoCodecMultiplex: - RTC_CHECK_NOTREACHED(); - } + if (num_bitrates == num_spatial_layers) { + switch (vc.codecType) { + case kVideoCodecVP8: + case kVideoCodecH264: + case kVideoCodecH265: + vc.numberOfSimulcastStreams = num_spatial_layers; + for (int sidx = 0; sidx < num_spatial_layers; ++sidx) { + SimulcastStream* ss = &vc.simulcastStream[sidx]; + ss->width = width >> (num_spatial_layers - sidx - 1); + ss->height = height >> (num_spatial_layers - sidx - 1); + ss->maxFramerate = vc.maxFramerate; + ss->numberOfTemporalLayers = num_temporal_layers; + ss->maxBitrate = bitrates_kbps[sidx]; + ss->targetBitrate = bitrates_kbps[sidx]; + ss->minBitrate = 0; + ss->qpMax = 0; + ss->active = true; + } + break; + case kVideoCodecVP9: + case kVideoCodecAV1: + for (int sidx = num_spatial_layers - 1; sidx >= 0; --sidx) { + SpatialLayer* ss = &vc.spatialLayers[sidx]; + ss->width = width >> (num_spatial_layers - sidx - 1); + ss->height = height >> (num_spatial_layers - sidx - 1); + ss->maxFramerate = vc.maxFramerate; + ss->numberOfTemporalLayers = num_temporal_layers; + ss->maxBitrate = bitrates_kbps[sidx]; + ss->targetBitrate = bitrates_kbps[sidx]; + ss->minBitrate = 0; + ss->qpMax = 0; + ss->active = true; + } + break; + case kVideoCodecGeneric: + case kVideoCodecMultiplex: + RTC_CHECK_NOTREACHED(); + } + } else { + switch (vc.codecType) { + case kVideoCodecVP8: + case kVideoCodecH264: + case kVideoCodecH265: + ConfigureSimulcast(&vc); + break; + case kVideoCodecVP9: { + const std::vector spatialLayers = GetVp9SvcConfig(vc); + for (size_t i = 0; i < spatialLayers.size(); ++i) { + vc.spatialLayers[i] = spatialLayers[i]; + vc.spatialLayers[i].active = true; + } + } break; + case kVideoCodecAV1: { + bool result = + SetAv1SvcConfig(vc, num_spatial_layers, num_temporal_layers); + RTC_CHECK(result) << "SetAv1SvcConfig failed"; + } break; + case kVideoCodecGeneric: + case kVideoCodecMultiplex: + RTC_CHECK_NOTREACHED(); + } - if (*vc.GetScalabilityMode() != scalability_mode) { - RTC_LOG(LS_WARNING) << "Scalability mode changed from " - << ScalabilityModeToString(scalability_mode) << " to " - << ScalabilityModeToString(*vc.GetScalabilityMode()); - num_spatial_layers = - ScalabilityModeToNumSpatialLayers(*vc.GetScalabilityMode()); - num_temporal_layers = - ScalabilityModeToNumTemporalLayers(*vc.GetScalabilityMode()); + if (*vc.GetScalabilityMode() != scalability_mode) { + RTC_LOG(LS_WARNING) << "Scalability mode changed from " + << ScalabilityModeToString(scalability_mode) << " to " + << ScalabilityModeToString(*vc.GetScalabilityMode()); + num_spatial_layers = + ScalabilityModeToNumSpatialLayers(*vc.GetScalabilityMode()); + num_temporal_layers = + ScalabilityModeToNumTemporalLayers(*vc.GetScalabilityMode()); + } } std::unique_ptr bitrate_allocator = @@ -1344,7 +1399,7 @@ SplitBitrateAndUpdateScalabilityMode(std::string codec_type, vc); VideoBitrateAllocation bitrate_allocation = bitrate_allocator->Allocate(VideoBitrateAllocationParameters( - 1000 * bitrates_kbps.front(), framerate_fps)); + 1000 * total_bitrate_kbps, framerate_fps)); std::vector bitrates; for (int sidx = 0; sidx < num_spatial_layers; ++sidx) { diff --git a/test/video_codec_tester_unittest.cc b/test/video_codec_tester_unittest.cc index ad1e9e3b03..fdd7b37a00 100644 --- a/test/video_codec_tester_unittest.cc +++ b/test/video_codec_tester_unittest.cc @@ -675,5 +675,137 @@ INSTANTIATE_TEST_SUITE_P( std::make_tuple(PacingSettings{.mode = PacingMode::kConstantRate, .constant_rate = Frequency::Hertz(20)}, /*expected_delta_ms=*/50))); + +struct EncodingSettingsTestParameters { + std::string codec_type; + std::string scalability_mode; + std::vector bitrate_kbps; + std::vector expected_bitrate_kbps; +}; + +class VideoCodecTesterTestEncodingSettings + : public ::testing::TestWithParam {}; + +TEST_P(VideoCodecTesterTestEncodingSettings, CreateEncodingSettings) { + EncodingSettingsTestParameters test_params = GetParam(); + std::map encoding_settings = + VideoCodecTester::CreateEncodingSettings( + test_params.codec_type, test_params.scalability_mode, /*width=*/1280, + /*height=*/720, test_params.bitrate_kbps, /*framerate_fps=*/30, + /*num_frames=*/1); + ASSERT_THAT(encoding_settings, SizeIs(1)); + const std::map& layers_settings = + encoding_settings.begin()->second.layers_settings; + std::vector configured_bitrate_kbps; + std::transform(layers_settings.begin(), layers_settings.end(), + std::back_inserter(configured_bitrate_kbps), + [](const auto& layer_settings) { + return layer_settings.second.bitrate.kbps(); + }); + EXPECT_EQ(configured_bitrate_kbps, test_params.expected_bitrate_kbps); +} + +INSTANTIATE_TEST_SUITE_P( + Vp8, + VideoCodecTesterTestEncodingSettings, + Values(EncodingSettingsTestParameters{.codec_type = "VP8", + .scalability_mode = "L1T1", + .bitrate_kbps = {1}, + .expected_bitrate_kbps = {1}}, + EncodingSettingsTestParameters{.codec_type = "VP8", + .scalability_mode = "L1T1", + .bitrate_kbps = {10000}, + .expected_bitrate_kbps = {10000}}, + EncodingSettingsTestParameters{ + .codec_type = "VP8", + .scalability_mode = "L1T3", + .bitrate_kbps = {1000}, + .expected_bitrate_kbps = {400, 200, 400}}, + EncodingSettingsTestParameters{ + .codec_type = "VP8", + .scalability_mode = "S3T3", + .bitrate_kbps = {100}, + .expected_bitrate_kbps = {40, 20, 40, 0, 0, 0, 0, 0, 0}}, + EncodingSettingsTestParameters{ + .codec_type = "VP8", + .scalability_mode = "S3T3", + .bitrate_kbps = {10000}, + .expected_bitrate_kbps = {60, 30, 60, 200, 100, 200, 1000, 500, + 1000}}, + EncodingSettingsTestParameters{ + .codec_type = "VP8", + .scalability_mode = "S3T3", + .bitrate_kbps = {100, 200, 300, 400, 500, 600, 700, 800, 900}, + .expected_bitrate_kbps = {100, 200, 300, 400, 500, 600, 700, 800, + 900}})); + +INSTANTIATE_TEST_SUITE_P( + Vp9, + VideoCodecTesterTestEncodingSettings, + Values(EncodingSettingsTestParameters{.codec_type = "VP9", + .scalability_mode = "L1T1", + .bitrate_kbps = {1}, + .expected_bitrate_kbps = {1}}, + EncodingSettingsTestParameters{.codec_type = "VP9", + .scalability_mode = "L1T1", + .bitrate_kbps = {10000}, + .expected_bitrate_kbps = {10000}}, + EncodingSettingsTestParameters{ + .codec_type = "VP9", + .scalability_mode = "L1T3", + .bitrate_kbps = {1000}, + .expected_bitrate_kbps = {540, 163, 297}}, + EncodingSettingsTestParameters{ + .codec_type = "VP9", + .scalability_mode = "L3T3", + .bitrate_kbps = {100}, + .expected_bitrate_kbps = {54, 16, 30, 0, 0, 0, 0, 0, 0}}, + EncodingSettingsTestParameters{ + .codec_type = "VP9", + .scalability_mode = "L3T3", + .bitrate_kbps = {10000}, + .expected_bitrate_kbps = {77, 23, 42, 226, 68, 124, 823, 249, + 452}}, + EncodingSettingsTestParameters{ + .codec_type = "VP9", + .scalability_mode = "L3T3", + .bitrate_kbps = {100, 200, 300, 400, 500, 600, 700, 800, 900}, + .expected_bitrate_kbps = {100, 200, 300, 400, 500, 600, 700, 800, + 900}})); + +INSTANTIATE_TEST_SUITE_P( + Av1, + VideoCodecTesterTestEncodingSettings, + Values(EncodingSettingsTestParameters{.codec_type = "AV1", + .scalability_mode = "L1T1", + .bitrate_kbps = {1}, + .expected_bitrate_kbps = {1}}, + EncodingSettingsTestParameters{.codec_type = "AV1", + .scalability_mode = "L1T1", + .bitrate_kbps = {10000}, + .expected_bitrate_kbps = {10000}}, + EncodingSettingsTestParameters{ + .codec_type = "AV1", + .scalability_mode = "L1T3", + .bitrate_kbps = {1000}, + .expected_bitrate_kbps = {540, 163, 297}}, + EncodingSettingsTestParameters{ + .codec_type = "AV1", + .scalability_mode = "L3T3", + .bitrate_kbps = {100}, + .expected_bitrate_kbps = {54, 16, 30, 0, 0, 0, 0, 0, 0}}, + EncodingSettingsTestParameters{ + .codec_type = "AV1", + .scalability_mode = "L3T3", + .bitrate_kbps = {10000}, + .expected_bitrate_kbps = {77, 23, 42, 226, 68, 124, 823, 249, + 452}}, + EncodingSettingsTestParameters{ + .codec_type = "AV1", + .scalability_mode = "L3T3", + .bitrate_kbps = {100, 200, 300, 400, 500, 600, 700, 800, 900}, + .expected_bitrate_kbps = {100, 200, 300, 400, 500, 600, 700, 800, + 900}})); + } // namespace test } // namespace webrtc