From c8ab6c449c84f17fabf8da58456d396bdb5da762 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Bostr=C3=B6m?= Date: Fri, 17 Mar 2023 08:57:08 +0100 Subject: [PATCH] Exercise AV1 simulcast paths in tests. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is something we get "for free" with the "WebRTC-AllowDisablingLegacyScalability" field trial that has been wired up to support VP9 simulcast. This test works and passes, however the ramp-up time is pretty bad. - VP9 simulcast takes approximately 4 seconds to ramp up. - VP9 SVC takes approximately 16 seconds to ramp up. - AV1 simulcast takes approximately 22 seconds to ramp up. A TODO is added (webrtc:15006) and the test is given extra timeout, a full minute to get bytes flowing on all layers. Despite ramp-up being bad, it's important to test that AV1 simulcast is in fact working to avoid regressions due to obsolete assumptions about which codec do or do not support simulcast. AV1 simulcast is an opt-in feature so there is no harm in the API not being perfect yet. Bug: webrtc:15005, webrtc:15006 Change-Id: If0158d172647f0462bd6db802406249d93e01871 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/297982 Reviewed-by: Ilya Nikolaevskiy Commit-Queue: Henrik Boström Reviewed-by: Erik Språng Cr-Commit-Position: refs/heads/main@{#39586} --- pc/peer_connection_simulcast_unittest.cc | 77 ++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/pc/peer_connection_simulcast_unittest.cc b/pc/peer_connection_simulcast_unittest.cc index 1e8955be03..238c0ae804 100644 --- a/pc/peer_connection_simulcast_unittest.cc +++ b/pc/peer_connection_simulcast_unittest.cc @@ -1490,4 +1490,81 @@ TEST_F(PeerConnectionSimulcastWithMediaFlowTests, EXPECT_THAT(*outbound_rtps[2]->scalability_mode, StrEq("L1T3")); } +// TODO(https://crbug.com/webrtc/15005): A field trial shouldn't be needed to +// get spec-compliant behavior! The same field trial is also used for VP9 +// simulcast (https://crbug.com/webrtc/14884). +TEST_F(PeerConnectionSimulcastWithMediaFlowTests, + SendingThreeEncodings_AV1_Simulcast) { + test::ScopedFieldTrials field_trials( + "WebRTC-AllowDisablingLegacyScalability/Enabled/"); + + rtc::scoped_refptr local_pc_wrapper = CreatePc(); + rtc::scoped_refptr remote_pc_wrapper = CreatePc(); + ExchangeIceCandidates(local_pc_wrapper, remote_pc_wrapper); + + std::vector layers = + CreateLayers({"f", "h", "q"}, /*active=*/true); + rtc::scoped_refptr transceiver = + AddTransceiverWithSimulcastLayers(local_pc_wrapper, remote_pc_wrapper, + layers); + std::vector codecs = + GetCapabilitiesAndRestrictToCodec(local_pc_wrapper, "AV1"); + transceiver->SetCodecPreferences(codecs); + + // Opt-in to spec-compliant simulcast by explicitly setting the + // `scalability_mode`. + rtc::scoped_refptr sender = transceiver->sender(); + RtpParameters parameters = sender->GetParameters(); + ASSERT_EQ(parameters.encodings.size(), 3u); + parameters.encodings[0].scalability_mode = "L1T3"; + parameters.encodings[1].scalability_mode = "L1T3"; + parameters.encodings[2].scalability_mode = "L1T3"; + sender->SetParameters(parameters); + + NegotiateWithSimulcastTweaks(local_pc_wrapper, remote_pc_wrapper, layers); + local_pc_wrapper->WaitForConnection(); + remote_pc_wrapper->WaitForConnection(); + + // GetParameters() does not report any fallback. + parameters = sender->GetParameters(); + ASSERT_EQ(parameters.encodings.size(), 3u); + EXPECT_THAT(parameters.encodings[0].scalability_mode, + Optional(std::string("L1T3"))); + EXPECT_THAT(parameters.encodings[1].scalability_mode, + Optional(std::string("L1T3"))); + EXPECT_THAT(parameters.encodings[2].scalability_mode, + Optional(std::string("L1T3"))); + + // Wait until media is flowing on all three layers. + // Ramp up time is needed before all three layers are sending. + // + // This test is given 2X timeout because AV1 simulcast ramp-up time is + // terrible compared to other codecs. + // TODO(https://crbug.com/webrtc/15006): Improve the ramp-up time and stop + // giving this test extra long timeout. + EXPECT_TRUE_WAIT(HasOutboundRtpBytesSent(local_pc_wrapper, 3u), + (2 * kLongTimeoutForRampingUp).ms()); + // Sometimes additional ramp up is needed to get the expected resolutions. If + // that has not happened yet we log (`log_during_ramp_up=true`). + EXPECT_TRUE_WAIT(HasOutboundRtpExpectedResolutions( + local_pc_wrapper, + {{"f", 320, 180}, {"h", 640, 360}, {"q", 1280, 720}}, + /*log_during_ramp_up=*/true), + kLongTimeoutForRampingUp.ms()); + // Verify codec and scalability mode. + rtc::scoped_refptr report = GetStats(local_pc_wrapper); + std::vector outbound_rtps = + report->GetStatsOfType(); + ASSERT_THAT(outbound_rtps, SizeIs(3u)); + EXPECT_THAT(GetCurrentCodecMimeType(report, *outbound_rtps[0]), + StrCaseEq("video/AV1")); + EXPECT_THAT(GetCurrentCodecMimeType(report, *outbound_rtps[1]), + StrCaseEq("video/AV1")); + EXPECT_THAT(GetCurrentCodecMimeType(report, *outbound_rtps[2]), + StrCaseEq("video/AV1")); + EXPECT_THAT(*outbound_rtps[0]->scalability_mode, StrEq("L1T3")); + EXPECT_THAT(*outbound_rtps[1]->scalability_mode, StrEq("L1T3")); + EXPECT_THAT(*outbound_rtps[2]->scalability_mode, StrEq("L1T3")); +} + } // namespace webrtc