/* * 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, 0u); 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