diff --git a/test/peer_scenario/tests/BUILD.gn b/test/peer_scenario/tests/BUILD.gn index ba6ec20e84..fb2948922a 100644 --- a/test/peer_scenario/tests/BUILD.gn +++ b/test/peer_scenario/tests/BUILD.gn @@ -12,6 +12,7 @@ if (rtc_include_tests) { rtc_library("tests") { testonly = true sources = [ + "bwe_ramp_up_test.cc", "peer_scenario_quality_test.cc", "remote_estimate_test.cc", "unsignaled_stream_test.cc", @@ -20,10 +21,14 @@ if (rtc_include_tests) { "..:peer_scenario", "../../:field_trial", "../../:test_support", + "../../../api:rtc_stats_api", + "../../../api/units:data_rate", + "../../../api/units:time_delta", "../../../media:rtc_media_base", "../../../media:stream_params", "../../../modules/rtp_rtcp:rtp_rtcp_format", "../../../pc:media_session", + "../../../pc:pc_test_utils", "../../../pc:session_description", ] } diff --git a/test/peer_scenario/tests/bwe_ramp_up_test.cc b/test/peer_scenario/tests/bwe_ramp_up_test.cc new file mode 100644 index 0000000000..6f3d597390 --- /dev/null +++ b/test/peer_scenario/tests/bwe_ramp_up_test.cc @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2023 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "api/stats/rtcstats_objects.h" +#include "api/units/data_rate.h" +#include "api/units/time_delta.h" +#include "modules/rtp_rtcp/include/rtp_header_extension_map.h" +#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" +#include "modules/rtp_rtcp/source/rtp_util.h" +#include "pc/media_session.h" +#include "pc/test/mock_peer_connection_observers.h" +#include "test/gmock.h" +#include "test/gtest.h" +#include "test/peer_scenario/peer_scenario.h" +#include "test/peer_scenario/peer_scenario_client.h" + +namespace webrtc { +namespace test { + +using ::testing::SizeIs; + +rtc::scoped_refptr GetStatsAndProcess( + PeerScenario& s, + PeerScenarioClient* client) { + auto stats_collector = + rtc::make_ref_counted(); + client->pc()->GetStats(stats_collector.get()); + s.ProcessMessages(TimeDelta::Millis(0)); + RTC_CHECK(stats_collector->called()); + return stats_collector->report(); +} + +DataRate GetAvailableSendBitrate( + const rtc::scoped_refptr& report) { + auto stats = report->GetStatsOfType(); + if (stats.empty()) { + return DataRate::Zero(); + } + return DataRate::BitsPerSec(*stats[0]->available_outgoing_bitrate); +} + +// Test that caller BWE can rampup even if callee can not demux incoming RTP +// packets. +TEST(BweRampupTest, RampUpWithUndemuxableRtpPackets) { + PeerScenario s(*test_info_); + + PeerScenarioClient::Config config = PeerScenarioClient::Config(); + config.disable_encryption = true; + PeerScenarioClient* caller = s.CreateClient(config); + PeerScenarioClient* callee = s.CreateClient(config); + + auto send_node = s.net()->NodeBuilder().Build().node; + auto ret_node = s.net()->NodeBuilder().Build().node; + + s.net()->CreateRoute(caller->endpoint(), {send_node}, callee->endpoint()); + s.net()->CreateRoute(callee->endpoint(), {ret_node}, caller->endpoint()); + + auto signaling = s.ConnectSignaling(caller, callee, {send_node}, {ret_node}); + PeerScenarioClient::VideoSendTrackConfig video_conf; + video_conf.generator.squares_video->framerate = 15; + + PeerScenarioClient::VideoSendTrack track = + caller->CreateVideo("VIDEO", video_conf); + + signaling.StartIceSignaling(); + + std::atomic offer_exchange_done(false); + signaling.NegotiateSdp( + [&](SessionDescriptionInterface* offer) { + RtpHeaderExtensionMap extension_map( + cricket::GetFirstVideoContentDescription(offer->description()) + ->rtp_header_extensions()); + ASSERT_TRUE(extension_map.IsRegistered(kRtpExtensionMid)); + const std::string video_mid = + cricket::GetFirstVideoContent(offer->description())->mid(); + send_node->router()->SetFilter([extension_map, video_mid, &send_node]( + const EmulatedIpPacket& packet) { + if (IsRtpPacket(packet.data)) { + // Replace Mid with another. This should lead to that packets + // can not be demuxed by the callee, but BWE should still + // function. + RtpPacket parsed_packet; + parsed_packet.IdentifyExtensions(extension_map); + EXPECT_TRUE(parsed_packet.Parse(packet.data)); + std::string mid; + if (parsed_packet.GetExtension(&mid)) { + if (mid == video_mid) { + parsed_packet.SetExtension("x"); + EmulatedIpPacket updated_packet(packet.from, packet.to, + parsed_packet.Buffer(), + packet.arrival_time); + send_node->OnPacketReceived(std::move(updated_packet)); + return false; + } + } + } + return true; + }); + }, + [&](const SessionDescriptionInterface& answer) { + offer_exchange_done = true; + }); + // Wait for SDP negotiation and the packet filter to be setup. + s.WaitAndProcess(&offer_exchange_done); + + DataRate initial_bwe = GetAvailableSendBitrate(GetStatsAndProcess(s, caller)); + s.ProcessMessages(TimeDelta::Seconds(2)); + + auto callee_inbound_stats = + GetStatsAndProcess(s, callee)->GetStatsOfType(); + ASSERT_THAT(callee_inbound_stats, SizeIs(1)); + ASSERT_EQ(*callee_inbound_stats[0]->frames_received, 0); + + DataRate final_bwe = GetAvailableSendBitrate(GetStatsAndProcess(s, caller)); + // Ensure BWE has increased from the initial BWE. BWE will not increase unless + // RTCP feedback is recevied. The increase is just an arbitrary value to + // ensure BWE has increased beyond noise levels. + EXPECT_GT(final_bwe, initial_bwe + DataRate::KilobitsPerSec(345)); +} +} // namespace test +} // namespace webrtc