diff --git a/test/scenario/audio_stream.cc b/test/scenario/audio_stream.cc index 21acebb2ae..8871728988 100644 --- a/test/scenario/audio_stream.cc +++ b/test/scenario/audio_stream.cc @@ -106,9 +106,7 @@ SendAudioStream::SendAudioStream( } if (field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")) { TimeDelta min_frame_length = config.encoder.initial_frame_length; - ; TimeDelta max_frame_length = config.encoder.initial_frame_length; - ; if (field_trial::IsEnabled("WebRTC-Audio-FrameLengthAdaptation") && !config.adapt.frame.min_rate_for_20_ms.IsZero()) { if (!config.adapt.frame.min_rate_for_60_ms.IsZero()) { @@ -118,7 +116,8 @@ SendAudioStream::SendAudioStream( } } DataSize rtp_overhead = DataSize::bytes(12); - DataSize total_overhead = config.stream.packet_overhead + rtp_overhead; + DataSize total_overhead = + sender_->transport_.packet_overhead() + rtp_overhead; min_rate += total_overhead / max_frame_length; max_rate += total_overhead / min_frame_length; } @@ -138,7 +137,7 @@ SendAudioStream::SendAudioStream( send_stream_ = sender_->call_->CreateAudioSendStream(send_config); if (field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")) { sender->call_->OnAudioTransportOverheadChanged( - config.stream.packet_overhead.bytes()); + sender_->transport_.packet_overhead().bytes()); } } @@ -150,15 +149,6 @@ void SendAudioStream::Start() { send_stream_->Start(); } -bool SendAudioStream::TryDeliverPacket(rtc::CopyOnWriteBuffer packet, - uint64_t receiver, - Timestamp at_time) { - // Removes added overhead before delivering RTCP packet to sender. - RTC_DCHECK_GE(packet.size(), config_.stream.packet_overhead.bytes()); - packet.SetSize(packet.size() - config_.stream.packet_overhead.bytes()); - sender_->DeliverPacket(MediaType::AUDIO, packet, at_time); - return true; -} ReceiveAudioStream::ReceiveAudioStream( CallClient* receiver, AudioStreamConfig config, @@ -170,6 +160,7 @@ ReceiveAudioStream::ReceiveAudioStream( recv_config.rtp.local_ssrc = CallTest::kReceiverLocalAudioSsrc; recv_config.rtcp_send_transport = feedback_transport; recv_config.rtp.remote_ssrc = send_stream->ssrc_; + receiver->ssrc_media_types_[recv_config.rtp.remote_ssrc] = MediaType::AUDIO; if (config.stream.in_bandwidth_estimation) { recv_config.rtp.transport_cc = true; recv_config.rtp.extensions = { @@ -185,49 +176,21 @@ ReceiveAudioStream::~ReceiveAudioStream() { receiver_->call_->DestroyAudioReceiveStream(receive_stream_); } -bool ReceiveAudioStream::TryDeliverPacket(rtc::CopyOnWriteBuffer packet, - uint64_t receiver, - Timestamp at_time) { - RTC_DCHECK_GE(packet.size(), config_.stream.packet_overhead.bytes()); - packet.SetSize(packet.size() - config_.stream.packet_overhead.bytes()); - receiver_->DeliverPacket(MediaType::AUDIO, packet, at_time); - return true; -} - AudioStreamPair::~AudioStreamPair() = default; AudioStreamPair::AudioStreamPair( CallClient* sender, - std::vector send_link, - uint64_t send_receiver_id, rtc::scoped_refptr encoder_factory, CallClient* receiver, - std::vector return_link, - uint64_t return_receiver_id, rtc::scoped_refptr decoder_factory, AudioStreamConfig config) : config_(config), - send_link_(send_link), - return_link_(return_link), - send_transport_(sender, - send_link.front(), - send_receiver_id, - config.stream.packet_overhead), - return_transport_(receiver, - return_link.front(), - return_receiver_id, - config.stream.packet_overhead), - send_stream_(sender, config, encoder_factory, &send_transport_), + send_stream_(sender, config, encoder_factory, &sender->transport_), receive_stream_(receiver, config, &send_stream_, decoder_factory, - &return_transport_) { - NetworkNode::Route(send_transport_.ReceiverId(), send_link_, - &receive_stream_); - NetworkNode::Route(return_transport_.ReceiverId(), return_link_, - &send_stream_); -} + &receiver->transport_) {} } // namespace test } // namespace webrtc diff --git a/test/scenario/audio_stream.h b/test/scenario/audio_stream.h index 17b8bc370e..06a91dbd2e 100644 --- a/test/scenario/audio_stream.h +++ b/test/scenario/audio_stream.h @@ -24,7 +24,7 @@ namespace test { // SendAudioStream represents sending of audio. It can be used for starting the // stream if neccessary. -class SendAudioStream : public NetworkReceiverInterface { +class SendAudioStream { public: RTC_DISALLOW_COPY_AND_ASSIGN(SendAudioStream); ~SendAudioStream(); @@ -38,11 +38,6 @@ class SendAudioStream : public NetworkReceiverInterface { AudioStreamConfig config, rtc::scoped_refptr encoder_factory, Transport* send_transport); - // Handles RTCP feedback for this stream. - bool TryDeliverPacket(rtc::CopyOnWriteBuffer packet, - uint64_t receiver, - Timestamp at_time) override; - AudioSendStream* send_stream_ = nullptr; CallClient* const sender_; const AudioStreamConfig config_; @@ -50,7 +45,7 @@ class SendAudioStream : public NetworkReceiverInterface { }; // ReceiveAudioStream represents an audio receiver. It can't be used directly. -class ReceiveAudioStream : public NetworkReceiverInterface { +class ReceiveAudioStream { public: RTC_DISALLOW_COPY_AND_ASSIGN(ReceiveAudioStream); ~ReceiveAudioStream(); @@ -63,9 +58,6 @@ class ReceiveAudioStream : public NetworkReceiverInterface { SendAudioStream* send_stream, rtc::scoped_refptr decoder_factory, Transport* feedback_transport); - bool TryDeliverPacket(rtc::CopyOnWriteBuffer packet, - uint64_t receiver, - Timestamp at_time) override; AudioReceiveStream* receive_stream_ = nullptr; CallClient* const receiver_; const AudioStreamConfig config_; @@ -84,23 +76,13 @@ class AudioStreamPair { private: friend class Scenario; AudioStreamPair(CallClient* sender, - std::vector send_link, - uint64_t send_receiver_id, rtc::scoped_refptr encoder_factory, - CallClient* receiver, - std::vector return_link, - uint64_t return_receiver_id, rtc::scoped_refptr decoder_factory, AudioStreamConfig config); private: const AudioStreamConfig config_; - std::vector send_link_; - std::vector return_link_; - NetworkNodeTransport send_transport_; - NetworkNodeTransport return_transport_; - SendAudioStream send_stream_; ReceiveAudioStream receive_stream_; }; diff --git a/test/scenario/call_client.cc b/test/scenario/call_client.cc index 47cc3bc57b..92c582e4d8 100644 --- a/test/scenario/call_client.cc +++ b/test/scenario/call_client.cc @@ -21,6 +21,39 @@ namespace webrtc { namespace test { namespace { const char* kPriorityStreamId = "priority-track"; + +CallClientFakeAudio InitAudio() { + CallClientFakeAudio setup; + auto capturer = TestAudioDeviceModule::CreatePulsedNoiseCapturer(256, 48000); + auto renderer = TestAudioDeviceModule::CreateDiscardRenderer(48000); + setup.fake_audio_device = TestAudioDeviceModule::CreateTestAudioDeviceModule( + std::move(capturer), std::move(renderer), 1.f); + setup.apm = AudioProcessingBuilder().Create(); + setup.fake_audio_device->Init(); + AudioState::Config audio_state_config; + audio_state_config.audio_mixer = AudioMixerImpl::Create(); + audio_state_config.audio_processing = setup.apm; + audio_state_config.audio_device_module = setup.fake_audio_device; + setup.audio_state = AudioState::Create(audio_state_config); + setup.fake_audio_device->RegisterAudioCallback( + setup.audio_state->audio_transport()); + return setup; +} + +Call* CreateCall(CallClientConfig config, + LoggingNetworkControllerFactory* network_controller_factory_, + rtc::scoped_refptr audio_state) { + CallConfig call_config(network_controller_factory_->GetEventLog()); + call_config.bitrate_config.max_bitrate_bps = + config.transport.rates.max_rate.bps_or(-1); + call_config.bitrate_config.min_bitrate_bps = + config.transport.rates.min_rate.bps(); + call_config.bitrate_config.start_bitrate_bps = + config.transport.rates.start_rate.bps(); + call_config.network_controller_factory = network_controller_factory_; + call_config.audio_state = audio_state; + return Call::Create(call_config); +} } LoggingNetworkControllerFactory::LoggingNetworkControllerFactory( @@ -107,17 +140,13 @@ CallClient::CallClient(Clock* clock, std::string log_filename, CallClientConfig config) : clock_(clock), - network_controller_factory_(log_filename, config.transport) { - CallConfig call_config(network_controller_factory_.GetEventLog()); - call_config.bitrate_config.max_bitrate_bps = - config.transport.rates.max_rate.bps_or(-1); - call_config.bitrate_config.min_bitrate_bps = - config.transport.rates.min_rate.bps(); - call_config.bitrate_config.start_bitrate_bps = - config.transport.rates.start_rate.bps(); - call_config.network_controller_factory = &network_controller_factory_; - call_config.audio_state = InitAudio(); - call_.reset(Call::Create(call_config)); + network_controller_factory_(log_filename, config.transport), + fake_audio_setup_(InitAudio()), + call_(CreateCall(config, + &network_controller_factory_, + fake_audio_setup_.audio_state)), + transport_(clock_, call_.get()), + header_parser_(RtpHeaderParser::Create()) { if (!config.priority_target_rate.IsZero() && config.priority_target_rate.IsFinite()) { call_->SetBitrateAllocationStrategy( @@ -126,12 +155,13 @@ CallClient::CallClient(Clock* clock, } } // namespace test -CallClient::~CallClient() {} +CallClient::~CallClient() { + delete header_parser_; +} void CallClient::DeliverPacket(MediaType media_type, rtc::CopyOnWriteBuffer packet, Timestamp at_time) { - call_->Receiver()->DeliverPacket(media_type, packet, at_time.us()); } ColumnPrinter CallClient::StatsPrinter() { @@ -149,6 +179,26 @@ Call::Stats CallClient::GetStats() { return call_->GetStats(); } +bool CallClient::TryDeliverPacket(rtc::CopyOnWriteBuffer packet, + uint64_t receiver, + Timestamp at_time) { + // Removes added overhead before delivering packet to sender. + RTC_DCHECK_GE(packet.size(), route_overhead_.at(receiver).bytes()); + packet.SetSize(packet.size() - route_overhead_.at(receiver).bytes()); + + MediaType media_type = MediaType::ANY; + if (!RtpHeaderParser::IsRtcp(packet.cdata(), packet.size())) { + RTPHeader header; + bool success = + header_parser_->Parse(packet.cdata(), packet.size(), &header); + if (!success) + return false; + media_type = ssrc_media_types_[header.ssrc]; + } + call_->Receiver()->DeliverPacket(media_type, packet, at_time.us()); + return true; +} + uint32_t CallClient::GetNextVideoSsrc() { RTC_CHECK_LT(next_video_ssrc_index_, CallTest::kNumSsrcs); return CallTest::kVideoSendSsrcs[next_video_ssrc_index_++]; @@ -170,21 +220,7 @@ std::string CallClient::GetNextPriorityId() { return kPriorityStreamId; } -rtc::scoped_refptr CallClient::InitAudio() { - auto capturer = TestAudioDeviceModule::CreatePulsedNoiseCapturer(256, 48000); - auto renderer = TestAudioDeviceModule::CreateDiscardRenderer(48000); - fake_audio_device_ = TestAudioDeviceModule::CreateTestAudioDeviceModule( - std::move(capturer), std::move(renderer), 1.f); - apm_ = AudioProcessingBuilder().Create(); - fake_audio_device_->Init(); - AudioState::Config audio_state_config; - audio_state_config.audio_mixer = AudioMixerImpl::Create(); - audio_state_config.audio_processing = apm_; - audio_state_config.audio_device_module = fake_audio_device_; - auto audio_state = AudioState::Create(audio_state_config); - fake_audio_device_->RegisterAudioCallback(audio_state->audio_transport()); - return audio_state; -} +CallClientPair::~CallClientPair() = default; } // namespace test } // namespace webrtc diff --git a/test/scenario/call_client.h b/test/scenario/call_client.h index 80e2faf162..48400cd1c8 100644 --- a/test/scenario/call_client.h +++ b/test/scenario/call_client.h @@ -17,8 +17,10 @@ #include "logging/rtc_event_log/rtc_event_log.h" #include "modules/audio_device/include/test_audio_device.h" #include "modules/congestion_controller/test/controller_printer.h" +#include "modules/rtp_rtcp/include/rtp_header_parser.h" #include "rtc_base/constructormagic.h" #include "test/scenario/column_printer.h" +#include "test/scenario/network_node.h" #include "test/scenario/scenario_config.h" namespace webrtc { @@ -45,10 +47,15 @@ class LoggingNetworkControllerFactory FILE* cc_out_ = nullptr; }; +struct CallClientFakeAudio { + rtc::scoped_refptr apm; + rtc::scoped_refptr fake_audio_device; + rtc::scoped_refptr audio_state; +}; // CallClient represents a participant in a call scenario. It is created by the // Scenario class and is used as sender and receiver when setting up a media // stream session. -class CallClient { +class CallClient : public NetworkReceiverInterface { public: CallClient(Clock* clock, std::string log_filename, CallClientConfig config); RTC_DISALLOW_COPY_AND_ASSIGN(CallClient); @@ -56,15 +63,24 @@ class CallClient { ~CallClient(); ColumnPrinter StatsPrinter(); Call::Stats GetStats(); + DataRate send_bandwidth() { + return DataRate::bps(GetStats().send_bandwidth_bps); + } + + bool TryDeliverPacket(rtc::CopyOnWriteBuffer packet, + uint64_t receiver, + Timestamp at_time) override; private: friend class Scenario; + friend class CallClientPair; friend class SendVideoStream; + friend class VideoStreamPair; friend class ReceiveVideoStream; friend class SendAudioStream; friend class ReceiveAudioStream; + friend class AudioStreamPair; friend class NetworkNodeTransport; - // TODO(srte): Consider using the Columnprinter interface for this. void DeliverPacket(MediaType media_type, rtc::CopyOnWriteBuffer packet, Timestamp at_time); @@ -75,18 +91,37 @@ class CallClient { Clock* clock_; LoggingNetworkControllerFactory network_controller_factory_; + CallClientFakeAudio fake_audio_setup_; std::unique_ptr call_; - - rtc::scoped_refptr InitAudio(); - - rtc::scoped_refptr apm_; - rtc::scoped_refptr fake_audio_device_; + NetworkNodeTransport transport_; + RtpHeaderParser* const header_parser_; std::unique_ptr fec_controller_factory_; + // Stores the configured overhead per known incomming route. This is used to + // subtract the overhead before processing. + std::map route_overhead_; int next_video_ssrc_index_ = 0; int next_rtx_ssrc_index_ = 0; int next_audio_ssrc_index_ = 0; int next_priority_index_ = 0; + std::map ssrc_media_types_; +}; + +class CallClientPair { + public: + RTC_DISALLOW_COPY_AND_ASSIGN(CallClientPair); + ~CallClientPair(); + CallClient* first() { return first_; } + CallClient* second() { return second_; } + std::pair forward() { return {first(), second()}; } + std::pair reverse() { return {second(), first()}; } + + private: + friend class Scenario; + CallClientPair(CallClient* first, CallClient* second) + : first_(first), second_(second) {} + CallClient* const first_; + CallClient* const second_; }; } // namespace test } // namespace webrtc diff --git a/test/scenario/network_node.cc b/test/scenario/network_node.cc index 87fc32a5d5..b39d67bd25 100644 --- a/test/scenario/network_node.cc +++ b/test/scenario/network_node.cc @@ -170,21 +170,16 @@ SimulationNode::SimulationNode( simulated_network_(simulation), config_(config) {} -NetworkNodeTransport::NetworkNodeTransport(CallClient* sender, - NetworkNode* send_net, - uint64_t receiver, - DataSize packet_overhead) - : sender_(sender), - send_net_(send_net), - receiver_id_(receiver), - packet_overhead_(packet_overhead) {} +NetworkNodeTransport::NetworkNodeTransport(const Clock* sender_clock, + Call* sender_call) + : sender_clock_(sender_clock), sender_call_(sender_call) {} NetworkNodeTransport::~NetworkNodeTransport() = default; bool NetworkNodeTransport::SendRtp(const uint8_t* packet, size_t length, const PacketOptions& options) { - int64_t send_time_ms = sender_->clock_->TimeInMilliseconds(); + int64_t send_time_ms = sender_clock_->TimeInMilliseconds(); rtc::SentPacket sent_packet; sent_packet.packet_id = options.packet_id; sent_packet.info.included_in_feedback = options.included_in_feedback; @@ -192,9 +187,12 @@ bool NetworkNodeTransport::SendRtp(const uint8_t* packet, sent_packet.send_time_ms = send_time_ms; sent_packet.info.packet_size_bytes = length; sent_packet.info.packet_type = rtc::PacketType::kData; - sender_->call_->OnSentPacket(sent_packet); + sender_call_->OnSentPacket(sent_packet); Timestamp send_time = Timestamp::ms(send_time_ms); + rtc::CritScope crit(&crit_sect_); + if (!send_net_) + return false; rtc::CopyOnWriteBuffer buffer(packet, length, length + packet_overhead_.bytes()); buffer.SetSize(length + packet_overhead_.bytes()); @@ -203,13 +201,29 @@ bool NetworkNodeTransport::SendRtp(const uint8_t* packet, bool NetworkNodeTransport::SendRtcp(const uint8_t* packet, size_t length) { rtc::CopyOnWriteBuffer buffer(packet, length); - Timestamp send_time = Timestamp::ms(sender_->clock_->TimeInMilliseconds()); + Timestamp send_time = Timestamp::ms(sender_clock_->TimeInMilliseconds()); + rtc::CritScope crit(&crit_sect_); buffer.SetSize(length + packet_overhead_.bytes()); + if (!send_net_) + return false; return send_net_->TryDeliverPacket(buffer, receiver_id_, send_time); } -uint64_t NetworkNodeTransport::ReceiverId() const { - return receiver_id_; +void NetworkNodeTransport::Connect(NetworkNode* send_node, + uint64_t receiver_id, + DataSize packet_overhead) { + rtc::CritScope crit(&crit_sect_); + send_net_ = send_node; + receiver_id_ = receiver_id; + packet_overhead_ = packet_overhead; + + rtc::NetworkRoute route; + route.connected = true; + route.local_network_id = receiver_id; + route.remote_network_id = receiver_id; + std::string transport_name = "dummy"; + sender_call_->GetTransportControllerSend()->OnNetworkRouteChanged( + transport_name, route); } CrossTrafficSource::CrossTrafficSource(NetworkReceiverInterface* target, diff --git a/test/scenario/network_node.h b/test/scenario/network_node.h index af6db0a009..4e90f6f252 100644 --- a/test/scenario/network_node.h +++ b/test/scenario/network_node.h @@ -18,10 +18,10 @@ #include "api/call/transport.h" #include "api/units/timestamp.h" +#include "call/call.h" #include "call/simulated_network.h" #include "rtc_base/constructormagic.h" #include "rtc_base/copyonwritebuffer.h" -#include "test/scenario/call_client.h" #include "test/scenario/column_printer.h" #include "test/scenario/scenario_config.h" @@ -119,23 +119,30 @@ class SimulationNode : public NetworkNode { class NetworkNodeTransport : public Transport { public: - NetworkNodeTransport(CallClient* sender, - NetworkNode* send_net, - uint64_t receiver, - DataSize packet_overhead); + NetworkNodeTransport(const Clock* sender_clock, Call* sender_call); ~NetworkNodeTransport() override; bool SendRtp(const uint8_t* packet, size_t length, const PacketOptions& options) override; bool SendRtcp(const uint8_t* packet, size_t length) override; - uint64_t ReceiverId() const; + + void Connect(NetworkNode* send_node, + uint64_t receiver_id, + DataSize packet_overhead); + + DataSize packet_overhead() { + rtc::CritScope crit(&crit_sect_); + return packet_overhead_; + } private: - CallClient* const sender_; - NetworkNode* const send_net_; - const uint64_t receiver_id_; - const DataSize packet_overhead_; + rtc::CriticalSection crit_sect_; + const Clock* const sender_clock_; + Call* const sender_call_; + NetworkNode* send_net_ RTC_GUARDED_BY(crit_sect_) = nullptr; + uint64_t receiver_id_ RTC_GUARDED_BY(crit_sect_) = 0; + DataSize packet_overhead_ RTC_GUARDED_BY(crit_sect_) = DataSize::Zero(); }; // CrossTrafficSource is created by a Scenario and generates cross traffic. It diff --git a/test/scenario/scenario.cc b/test/scenario/scenario.cc index 2395a7a41e..e77e3087af 100644 --- a/test/scenario/scenario.cc +++ b/test/scenario/scenario.cc @@ -123,14 +123,50 @@ CallClient* Scenario::CreateClient( return CreateClient(name, config); } +CallClientPair* Scenario::CreateRoutes(CallClient* first, + std::vector send_link, + CallClient* second, + std::vector return_link) { + return CreateRoutes(first, send_link, + DataSize::bytes(PacketOverhead::kDefault), second, + return_link, DataSize::bytes(PacketOverhead::kDefault)); +} + +CallClientPair* Scenario::CreateRoutes(CallClient* first, + std::vector send_link, + DataSize first_overhead, + CallClient* second, + std::vector return_link, + DataSize second_overhead) { + CallClientPair* client_pair = new CallClientPair(first, second); + ChangeRoute(client_pair->forward(), send_link, first_overhead); + ChangeRoute(client_pair->reverse(), return_link, second_overhead); + client_pairs_.emplace_back(client_pair); + return client_pair; +} + +void Scenario::ChangeRoute(std::pair clients, + std::vector over_nodes) { + ChangeRoute(clients, over_nodes, DataSize::bytes(PacketOverhead::kDefault)); +} + +void Scenario::ChangeRoute(std::pair clients, + std::vector over_nodes, + DataSize overhead) { + uint64_t route_id = next_route_id_++; + clients.second->route_overhead_.insert({route_id, overhead}); + NetworkNode::Route(route_id, over_nodes, clients.second); + clients.first->transport_.Connect(over_nodes.front(), route_id, overhead); +} + SimulatedTimeClient* Scenario::CreateSimulatedTimeClient( std::string name, SimulatedTimeClientConfig config, std::vector stream_configs, std::vector send_link, std::vector return_link) { - uint64_t send_id = next_receiver_id_++; - uint64_t return_id = next_receiver_id_++; + uint64_t send_id = next_route_id_++; + uint64_t return_id = next_route_id_++; SimulatedTimeClient* client = new SimulatedTimeClient( GetFullPathOrEmpty(name), config, stream_configs, send_link, return_link, send_id, return_id, Now()); @@ -179,21 +215,21 @@ NetworkNode* Scenario::CreateNetworkNode( void Scenario::TriggerPacketBurst(std::vector over_nodes, size_t num_packets, size_t packet_size) { - int64_t receiver_id = next_receiver_id_++; - NetworkNode::Route(receiver_id, over_nodes, &null_receiver_); + int64_t route_id = next_route_id_++; + NetworkNode::Route(route_id, over_nodes, &null_receiver_); for (size_t i = 0; i < num_packets; ++i) over_nodes[0]->TryDeliverPacket(rtc::CopyOnWriteBuffer(packet_size), - receiver_id, Now()); + route_id, Now()); } void Scenario::NetworkDelayedAction(std::vector over_nodes, size_t packet_size, std::function action) { - int64_t receiver_id = next_receiver_id_++; + int64_t route_id = next_route_id_++; action_receivers_.emplace_back(new ActionReceiver(action)); - NetworkNode::Route(receiver_id, over_nodes, action_receivers_.back().get()); - over_nodes[0]->TryDeliverPacket(rtc::CopyOnWriteBuffer(packet_size), - receiver_id, Now()); + NetworkNode::Route(route_id, over_nodes, action_receivers_.back().get()); + over_nodes[0]->TryDeliverPacket(rtc::CopyOnWriteBuffer(packet_size), route_id, + Now()); } CrossTrafficSource* Scenario::CreateCrossTraffic( @@ -207,65 +243,46 @@ CrossTrafficSource* Scenario::CreateCrossTraffic( CrossTrafficSource* Scenario::CreateCrossTraffic( std::vector over_nodes, CrossTrafficConfig config) { - int64_t receiver_id = next_receiver_id_++; + int64_t route_id = next_route_id_++; cross_traffic_sources_.emplace_back( - new CrossTrafficSource(over_nodes.front(), receiver_id, config)); + new CrossTrafficSource(over_nodes.front(), route_id, config)); CrossTrafficSource* node = cross_traffic_sources_.back().get(); - NetworkNode::Route(receiver_id, over_nodes, &null_receiver_); + NetworkNode::Route(route_id, over_nodes, &null_receiver_); Every(config.min_packet_interval, [this, node](TimeDelta delta) { node->Process(Now(), delta); }); return node; } VideoStreamPair* Scenario::CreateVideoStream( - CallClient* sender, - std::vector send_link, - CallClient* receiver, - std::vector return_link, + std::pair clients, std::function config_modifier) { VideoStreamConfig config; config_modifier(&config); - return CreateVideoStream(sender, send_link, receiver, return_link, config); + return CreateVideoStream(clients, config); } VideoStreamPair* Scenario::CreateVideoStream( - CallClient* sender, - std::vector send_link, - CallClient* receiver, - std::vector return_link, + std::pair clients, VideoStreamConfig config) { - uint64_t send_receiver_id = next_receiver_id_++; - uint64_t return_receiver_id = next_receiver_id_++; - video_streams_.emplace_back( - new VideoStreamPair(sender, send_link, send_receiver_id, receiver, - return_link, return_receiver_id, config)); + new VideoStreamPair(clients.first, clients.second, config)); return video_streams_.back().get(); } AudioStreamPair* Scenario::CreateAudioStream( - CallClient* sender, - std::vector send_link, - CallClient* receiver, - std::vector return_link, + std::pair clients, std::function config_modifier) { AudioStreamConfig config; config_modifier(&config); - return CreateAudioStream(sender, send_link, receiver, return_link, config); + return CreateAudioStream(clients, config); } AudioStreamPair* Scenario::CreateAudioStream( - CallClient* sender, - std::vector send_link, - CallClient* receiver, - std::vector return_link, + std::pair clients, AudioStreamConfig config) { - uint64_t send_receiver_id = next_receiver_id_++; - uint64_t return_receiver_id = next_receiver_id_++; - - audio_streams_.emplace_back(new AudioStreamPair( - sender, send_link, send_receiver_id, audio_encoder_factory_, receiver, - return_link, return_receiver_id, audio_decoder_factory_, config)); + audio_streams_.emplace_back( + new AudioStreamPair(clients.first, audio_encoder_factory_, clients.second, + audio_decoder_factory_, config)); return audio_streams_.back().get(); } diff --git a/test/scenario/scenario.h b/test/scenario/scenario.h index 05876ac49c..5ee017c806 100644 --- a/test/scenario/scenario.h +++ b/test/scenario/scenario.h @@ -78,6 +78,25 @@ class Scenario { std::string name, std::function config_modifier); + CallClientPair* CreateRoutes(CallClient* first, + std::vector send_link, + CallClient* second, + std::vector return_link); + + CallClientPair* CreateRoutes(CallClient* first, + std::vector send_link, + DataSize first_overhead, + CallClient* second, + std::vector return_link, + DataSize second_overhead); + + void ChangeRoute(std::pair clients, + std::vector over_nodes); + + void ChangeRoute(std::pair clients, + std::vector over_nodes, + DataSize overhead); + SimulatedTimeClient* CreateSimulatedTimeClient( std::string name, SimulatedTimeClientConfig config, @@ -86,28 +105,18 @@ class Scenario { std::vector return_link); VideoStreamPair* CreateVideoStream( - CallClient* sender, - std::vector send_link, - CallClient* receiver, - std::vector return_link, + std::pair clients, std::function config_modifier); - VideoStreamPair* CreateVideoStream(CallClient* sender, - std::vector send_link, - CallClient* receiver, - std::vector return_link, - VideoStreamConfig config); + VideoStreamPair* CreateVideoStream( + std::pair clients, + VideoStreamConfig config); AudioStreamPair* CreateAudioStream( - CallClient* sender, - std::vector send_link, - CallClient* receiver, - std::vector return_link, + std::pair clients, std::function config_modifier); - AudioStreamPair* CreateAudioStream(CallClient* sender, - std::vector send_link, - CallClient* receiver, - std::vector return_link, - AudioStreamConfig config); + AudioStreamPair* CreateAudioStream( + std::pair clients, + AudioStreamConfig config); CrossTrafficSource* CreateCrossTraffic( std::vector over_nodes, @@ -167,6 +176,7 @@ class Scenario { rtc::FakeClock event_log_fake_clock_; std::vector> clients_; + std::vector> client_pairs_; std::vector> network_nodes_; std::vector> cross_traffic_sources_; std::vector> video_streams_; @@ -179,7 +189,7 @@ class Scenario { std::vector> pending_activities_; std::vector> printers_; - int64_t next_receiver_id_ = 40000; + int64_t next_route_id_ = 40000; rtc::scoped_refptr audio_decoder_factory_; rtc::scoped_refptr audio_encoder_factory_; diff --git a/test/scenario/scenario_config.h b/test/scenario/scenario_config.h index 7bcc8f90df..8606d5f437 100644 --- a/test/scenario/scenario_config.h +++ b/test/scenario/scenario_config.h @@ -28,7 +28,12 @@ struct PacketOverhead { static constexpr size_t kIpv6 = 40; static constexpr size_t kUdp = 8; static constexpr size_t kSrtp = 10; - static constexpr size_t kTurn = 4; + static constexpr size_t kStun = 4; + // TURN messages can be sent either with or without an establieshed channel. + // In the latter case, a TURN Send/Data Indication is sent which has + // significantly more overhead. + static constexpr size_t kTurnChannelMessage = 4; + static constexpr size_t kTurnIndicationMessage = 36; static constexpr size_t kDefault = kIpv4 + kUdp + kSrtp; }; struct TransportControllerConfig { @@ -117,7 +122,6 @@ struct VideoStreamConfig { TimeDelta nack_history_time = TimeDelta::ms(1000); bool use_flexfec = false; bool use_ulpfec = false; - DataSize packet_overhead = DataSize::bytes(PacketOverhead::kDefault); } stream; struct Renderer { enum Type { kFake } type = kFake; @@ -159,7 +163,6 @@ struct AudioStreamConfig { ~Stream(); bool in_bandwidth_estimation = false; bool rate_allocation_priority = false; - DataSize packet_overhead = DataSize::bytes(PacketOverhead::kDefault); } stream; struct Render { std::string sync_group; diff --git a/test/scenario/scenario_tests/bbr_performance.cc b/test/scenario/scenario_tests/bbr_performance.cc index e87cc68dd3..28cabc070f 100644 --- a/test/scenario/scenario_tests/bbr_performance.cc +++ b/test/scenario/scenario_tests/bbr_performance.cc @@ -167,31 +167,31 @@ TEST_P(BbrScenarioTest, ReceivesVideo) { net_conf.simulation.delay_std_dev = conf_.scenario.delay_noise; SimulationNode* send_net = s.CreateSimulationNode(net_conf); SimulationNode* ret_net = s.CreateSimulationNode(net_conf); - VideoStreamPair* alice_video = s.CreateVideoStream( - alice, {send_net}, bob, {ret_net}, [&](VideoStreamConfig* c) { + auto route = s.CreateRoutes(alice, {send_net}, bob, {ret_net}); + + VideoStreamPair* alice_video = + s.CreateVideoStream(route->forward(), [&](VideoStreamConfig* c) { c->encoder.fake.max_rate = DataRate::kbps(1800); }); - s.CreateAudioStream(alice, {send_net}, bob, {ret_net}, - [&](AudioStreamConfig* c) { - if (conf_.tuning.use_bbr) { - c->stream.in_bandwidth_estimation = true; - c->encoder.fixed_rate = DataRate::kbps(31); - } - }); + s.CreateAudioStream(route->forward(), [&](AudioStreamConfig* c) { + if (conf_.tuning.use_bbr) { + c->stream.in_bandwidth_estimation = true; + c->encoder.fixed_rate = DataRate::kbps(31); + } + }); VideoStreamPair* bob_video = nullptr; if (conf_.scenario.return_traffic) { - bob_video = s.CreateVideoStream( - bob, {ret_net}, alice, {send_net}, [&](VideoStreamConfig* c) { + bob_video = + s.CreateVideoStream(route->reverse(), [&](VideoStreamConfig* c) { c->encoder.fake.max_rate = DataRate::kbps(1800); }); - s.CreateAudioStream(bob, {ret_net}, alice, {send_net}, - [&](AudioStreamConfig* c) { - if (conf_.tuning.use_bbr) { - c->stream.in_bandwidth_estimation = true; - c->encoder.fixed_rate = DataRate::kbps(31); - } - }); + s.CreateAudioStream(route->reverse(), [&](AudioStreamConfig* c) { + if (conf_.tuning.use_bbr) { + c->stream.in_bandwidth_estimation = true; + c->encoder.fixed_rate = DataRate::kbps(31); + } + }); } CrossTrafficConfig cross_config; cross_config.peak_rate = conf_.scenario.cross_traffic; diff --git a/test/scenario/scenario_unittest.cc b/test/scenario/scenario_unittest.cc index 87647a4fdd..97285d3914 100644 --- a/test/scenario/scenario_unittest.cc +++ b/test/scenario/scenario_unittest.cc @@ -21,18 +21,19 @@ TEST(ScenarioTest, StartsAndStopsWithoutErrors) { NetworkNodeConfig network_config; auto alice_net = s.CreateSimulationNode(network_config); auto bob_net = s.CreateSimulationNode(network_config); + auto route = s.CreateRoutes(alice, {alice_net}, bob, {bob_net}); VideoStreamConfig video_stream_config; - s.CreateVideoStream(alice, {alice_net}, bob, {bob_net}, video_stream_config); - s.CreateVideoStream(bob, {bob_net}, alice, {alice_net}, video_stream_config); + s.CreateVideoStream(route->forward(), video_stream_config); + s.CreateVideoStream(route->reverse(), video_stream_config); AudioStreamConfig audio_stream_config; audio_stream_config.encoder.min_rate = DataRate::kbps(6); audio_stream_config.encoder.max_rate = DataRate::kbps(64); audio_stream_config.encoder.allocate_bitrate = true; audio_stream_config.stream.in_bandwidth_estimation = false; - s.CreateAudioStream(alice, {alice_net}, bob, {bob_net}, audio_stream_config); - s.CreateAudioStream(bob, {bob_net}, alice, {alice_net}, audio_stream_config); + s.CreateAudioStream(route->forward(), audio_stream_config); + s.CreateAudioStream(route->reverse(), audio_stream_config); CrossTrafficConfig cross_traffic_config; s.CreateCrossTraffic({alice_net}, cross_traffic_config); diff --git a/test/scenario/simulated_time.cc b/test/scenario/simulated_time.cc index f29a82c455..29de1109b8 100644 --- a/test/scenario/simulated_time.cc +++ b/test/scenario/simulated_time.cc @@ -252,11 +252,12 @@ SimulatedTimeClient::SimulatedTimeClient( return_link_(return_link), sender_(send_link.front(), send_receiver_id), feedback_(config, return_receiver_id, return_link.front()) { + current_contraints_.at_time = at_time; + current_contraints_.starting_rate = config.transport.rates.start_rate; + current_contraints_.min_data_rate = config.transport.rates.min_rate; + current_contraints_.max_data_rate = config.transport.rates.max_rate; NetworkControllerConfig initial_config; - initial_config.constraints.at_time = at_time; - initial_config.constraints.starting_rate = config.transport.rates.start_rate; - initial_config.constraints.min_data_rate = config.transport.rates.min_rate; - initial_config.constraints.max_data_rate = config.transport.rates.max_rate; + initial_config.constraints = current_contraints_; congestion_controller_ = network_controller_factory_.Create(initial_config); for (auto& stream_config : stream_configs) packet_streams_.emplace_back(new PacketStream(stream_config)); @@ -336,6 +337,14 @@ void SimulatedTimeClient::ProcessFrames(Timestamp at_time) { } } +void SimulatedTimeClient::TriggerFakeReroute(Timestamp at_time) { + NetworkRouteChange msg; + msg.at_time = at_time; + msg.constraints = current_contraints_; + msg.constraints.at_time = at_time; + Update(congestion_controller_->OnNetworkRouteChange(msg)); +} + TimeDelta SimulatedTimeClient::GetNetworkControllerProcessInterval() const { return network_controller_factory_.GetProcessInterval(); } diff --git a/test/scenario/simulated_time.h b/test/scenario/simulated_time.h index b9c6de124d..42f176e18b 100644 --- a/test/scenario/simulated_time.h +++ b/test/scenario/simulated_time.h @@ -129,6 +129,7 @@ class SimulatedTimeClient : NetworkReceiverInterface { void CongestionProcess(Timestamp at_time); void PacerProcess(Timestamp at_time); void ProcessFrames(Timestamp at_time); + void TriggerFakeReroute(Timestamp at_time); TimeDelta GetNetworkControllerProcessInterval() const; double target_rate_kbps() const; @@ -144,6 +145,7 @@ class SimulatedTimeClient : NetworkReceiverInterface { std::vector return_link_; SimulatedSender sender_; SimulatedFeedback feedback_; + TargetRateConstraints current_contraints_; DataRate target_rate_ = DataRate::Infinity(); FILE* packet_log_ = nullptr; diff --git a/test/scenario/video_stream.cc b/test/scenario/video_stream.cc index b85034ffb2..914d981908 100644 --- a/test/scenario/video_stream.cc +++ b/test/scenario/video_stream.cc @@ -234,16 +234,6 @@ void SendVideoStream::Start() { video_capturer_->Start(); } -bool SendVideoStream::TryDeliverPacket(rtc::CopyOnWriteBuffer packet, - uint64_t receiver, - Timestamp at_time) { - // Removes added overhead before delivering RTCP packet to sender. - RTC_DCHECK_GE(packet.size(), config_.stream.packet_overhead.bytes()); - packet.SetSize(packet.size() - config_.stream.packet_overhead.bytes()); - sender_->DeliverPacket(MediaType::VIDEO, packet, at_time); - return true; -} - void SendVideoStream::SetCaptureFramerate(int framerate) { RTC_CHECK(frame_generator_) << "Framerate change only implemented for generators"; @@ -300,11 +290,14 @@ ReceiveVideoStream::ReceiveVideoStream(CallClient* receiver, recv_config.renderer = renderer_.get(); if (config.stream.use_rtx) { recv_config.rtp.rtx_ssrc = send_stream->rtx_ssrcs_[chosen_stream]; + receiver->ssrc_media_types_[recv_config.rtp.rtx_ssrc] = MediaType::VIDEO; recv_config.rtp .rtx_associated_payload_types[CallTest::kSendRtxPayloadType] = CodecTypeToPayloadType(config.encoder.codec); } recv_config.rtp.remote_ssrc = send_stream->ssrcs_[chosen_stream]; + receiver->ssrc_media_types_[recv_config.rtp.remote_ssrc] = MediaType::VIDEO; + VideoReceiveStream::Decoder decoder = CreateMatchingDecoder(CodecTypeToPayloadType(config.encoder.codec), CodecTypeToPayloadString(config.encoder.codec)); @@ -316,6 +309,7 @@ ReceiveVideoStream::ReceiveVideoStream(CallClient* receiver, FlexfecReceiveStream::Config flexfec_config(feedback_transport); flexfec_config.payload_type = CallTest::kFlexfecPayloadType; flexfec_config.remote_ssrc = CallTest::kFlexfecSendSsrc; + receiver->ssrc_media_types_[flexfec_config.remote_ssrc] = MediaType::VIDEO; flexfec_config.protected_media_ssrcs = send_stream->rtx_ssrcs_; flexfec_config.local_ssrc = recv_config.rtp.local_ssrc; flecfec_stream_ = @@ -337,46 +331,18 @@ ReceiveVideoStream::~ReceiveVideoStream() { receiver_->call_->DestroyFlexfecReceiveStream(flecfec_stream_); } -bool ReceiveVideoStream::TryDeliverPacket(rtc::CopyOnWriteBuffer packet, - uint64_t receiver, - Timestamp at_time) { - RTC_DCHECK_GE(packet.size(), config_.stream.packet_overhead.bytes()); - packet.SetSize(packet.size() - config_.stream.packet_overhead.bytes()); - receiver_->DeliverPacket(MediaType::VIDEO, packet, at_time); - return true; -} - VideoStreamPair::~VideoStreamPair() = default; VideoStreamPair::VideoStreamPair(CallClient* sender, - std::vector send_link, - uint64_t send_receiver_id, CallClient* receiver, - std::vector return_link, - uint64_t return_receiver_id, VideoStreamConfig config) : config_(config), - send_link_(send_link), - return_link_(return_link), - send_transport_(sender, - send_link.front(), - send_receiver_id, - config.stream.packet_overhead), - return_transport_(receiver, - return_link.front(), - return_receiver_id, - config.stream.packet_overhead), - send_stream_(sender, config, &send_transport_), + send_stream_(sender, config, &sender->transport_), receive_stream_(receiver, config, &send_stream_, /*chosen_stream=*/0, - &return_transport_) { - NetworkNode::Route(send_transport_.ReceiverId(), send_link_, - &receive_stream_); - NetworkNode::Route(return_transport_.ReceiverId(), return_link_, - &send_stream_); -} + &receiver->transport_) {} } // namespace test } // namespace webrtc diff --git a/test/scenario/video_stream.h b/test/scenario/video_stream.h index e6696183a7..1b5b20a8ca 100644 --- a/test/scenario/video_stream.h +++ b/test/scenario/video_stream.h @@ -25,7 +25,7 @@ namespace webrtc { namespace test { // SendVideoStream provides an interface for changing parameters and retrieving // states at run time. -class SendVideoStream : public NetworkReceiverInterface { +class SendVideoStream { public: RTC_DISALLOW_COPY_AND_ASSIGN(SendVideoStream); ~SendVideoStream(); @@ -43,9 +43,6 @@ class SendVideoStream : public NetworkReceiverInterface { SendVideoStream(CallClient* sender, VideoStreamConfig config, Transport* send_transport); - bool TryDeliverPacket(rtc::CopyOnWriteBuffer packet, - uint64_t receiver, - Timestamp at_time) override; std::vector ssrcs_; std::vector rtx_ssrcs_; @@ -55,10 +52,12 @@ class SendVideoStream : public NetworkReceiverInterface { std::unique_ptr encoder_factory_; std::unique_ptr video_capturer_; FrameGeneratorCapturer* frame_generator_ = nullptr; + int next_local_network_id_ = 0; + int next_remote_network_id_ = 0; }; // ReceiveVideoStream represents a video receiver. It can't be used directly. -class ReceiveVideoStream : public NetworkReceiverInterface { +class ReceiveVideoStream { public: RTC_DISALLOW_COPY_AND_ASSIGN(ReceiveVideoStream); ~ReceiveVideoStream(); @@ -71,9 +70,7 @@ class ReceiveVideoStream : public NetworkReceiverInterface { SendVideoStream* send_stream, size_t chosen_stream, Transport* feedback_transport); - bool TryDeliverPacket(rtc::CopyOnWriteBuffer packet, - uint64_t receiver, - Timestamp at_time) override; + VideoReceiveStream* receive_stream_ = nullptr; FlexfecReceiveStream* flecfec_stream_ = nullptr; std::unique_ptr> renderer_; @@ -95,18 +92,10 @@ class VideoStreamPair { private: friend class Scenario; VideoStreamPair(CallClient* sender, - std::vector send_link, - uint64_t send_receiver_id, CallClient* receiver, - std::vector return_link, - uint64_t return_receiver_id, VideoStreamConfig config); const VideoStreamConfig config_; - std::vector send_link_; - std::vector return_link_; - NetworkNodeTransport send_transport_; - NetworkNodeTransport return_transport_; SendVideoStream send_stream_; ReceiveVideoStream receive_stream_;