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