Adds support to change transport routes in Scenario tests.

This CL makes it possible to change transport routes while running
a scenario based test.

To make this possible in a consistent manner, the scenario test
framework is modified to only allow shared transport for all streams
between two CallClients. This is what typically is done in practice and
it is quite complex to even reason about the implications of using
mixed transports for a single call.

Bug: webrtc:9718
Change-Id: Ib836928feed98aa2bbbe0295e158157a6518348b
Reviewed-on: https://webrtc-review.googlesource.com/c/107200
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Reviewed-by: Björn Terelius <terelius@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25287}
This commit is contained in:
Sebastian Jansson 2018-10-22 11:49:03 +02:00 committed by Commit Bot
parent 8d33c0c104
commit 800e121dca
15 changed files with 300 additions and 266 deletions

View File

@ -106,9 +106,7 @@ SendAudioStream::SendAudioStream(
} }
if (field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")) { if (field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")) {
TimeDelta min_frame_length = config.encoder.initial_frame_length; TimeDelta min_frame_length = config.encoder.initial_frame_length;
;
TimeDelta max_frame_length = config.encoder.initial_frame_length; TimeDelta max_frame_length = config.encoder.initial_frame_length;
;
if (field_trial::IsEnabled("WebRTC-Audio-FrameLengthAdaptation") && if (field_trial::IsEnabled("WebRTC-Audio-FrameLengthAdaptation") &&
!config.adapt.frame.min_rate_for_20_ms.IsZero()) { !config.adapt.frame.min_rate_for_20_ms.IsZero()) {
if (!config.adapt.frame.min_rate_for_60_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 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; min_rate += total_overhead / max_frame_length;
max_rate += total_overhead / min_frame_length; max_rate += total_overhead / min_frame_length;
} }
@ -138,7 +137,7 @@ SendAudioStream::SendAudioStream(
send_stream_ = sender_->call_->CreateAudioSendStream(send_config); send_stream_ = sender_->call_->CreateAudioSendStream(send_config);
if (field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")) { if (field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")) {
sender->call_->OnAudioTransportOverheadChanged( sender->call_->OnAudioTransportOverheadChanged(
config.stream.packet_overhead.bytes()); sender_->transport_.packet_overhead().bytes());
} }
} }
@ -150,15 +149,6 @@ void SendAudioStream::Start() {
send_stream_->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( ReceiveAudioStream::ReceiveAudioStream(
CallClient* receiver, CallClient* receiver,
AudioStreamConfig config, AudioStreamConfig config,
@ -170,6 +160,7 @@ ReceiveAudioStream::ReceiveAudioStream(
recv_config.rtp.local_ssrc = CallTest::kReceiverLocalAudioSsrc; recv_config.rtp.local_ssrc = CallTest::kReceiverLocalAudioSsrc;
recv_config.rtcp_send_transport = feedback_transport; recv_config.rtcp_send_transport = feedback_transport;
recv_config.rtp.remote_ssrc = send_stream->ssrc_; 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) { if (config.stream.in_bandwidth_estimation) {
recv_config.rtp.transport_cc = true; recv_config.rtp.transport_cc = true;
recv_config.rtp.extensions = { recv_config.rtp.extensions = {
@ -185,49 +176,21 @@ ReceiveAudioStream::~ReceiveAudioStream() {
receiver_->call_->DestroyAudioReceiveStream(receive_stream_); 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() = default;
AudioStreamPair::AudioStreamPair( AudioStreamPair::AudioStreamPair(
CallClient* sender, CallClient* sender,
std::vector<NetworkNode*> send_link,
uint64_t send_receiver_id,
rtc::scoped_refptr<AudioEncoderFactory> encoder_factory, rtc::scoped_refptr<AudioEncoderFactory> encoder_factory,
CallClient* receiver, CallClient* receiver,
std::vector<NetworkNode*> return_link,
uint64_t return_receiver_id,
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory, rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
AudioStreamConfig config) AudioStreamConfig config)
: config_(config), : config_(config),
send_link_(send_link), send_stream_(sender, config, encoder_factory, &sender->transport_),
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_),
receive_stream_(receiver, receive_stream_(receiver,
config, config,
&send_stream_, &send_stream_,
decoder_factory, decoder_factory,
&return_transport_) { &receiver->transport_) {}
NetworkNode::Route(send_transport_.ReceiverId(), send_link_,
&receive_stream_);
NetworkNode::Route(return_transport_.ReceiverId(), return_link_,
&send_stream_);
}
} // namespace test } // namespace test
} // namespace webrtc } // namespace webrtc

View File

@ -24,7 +24,7 @@ namespace test {
// SendAudioStream represents sending of audio. It can be used for starting the // SendAudioStream represents sending of audio. It can be used for starting the
// stream if neccessary. // stream if neccessary.
class SendAudioStream : public NetworkReceiverInterface { class SendAudioStream {
public: public:
RTC_DISALLOW_COPY_AND_ASSIGN(SendAudioStream); RTC_DISALLOW_COPY_AND_ASSIGN(SendAudioStream);
~SendAudioStream(); ~SendAudioStream();
@ -38,11 +38,6 @@ class SendAudioStream : public NetworkReceiverInterface {
AudioStreamConfig config, AudioStreamConfig config,
rtc::scoped_refptr<AudioEncoderFactory> encoder_factory, rtc::scoped_refptr<AudioEncoderFactory> encoder_factory,
Transport* send_transport); 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; AudioSendStream* send_stream_ = nullptr;
CallClient* const sender_; CallClient* const sender_;
const AudioStreamConfig config_; const AudioStreamConfig config_;
@ -50,7 +45,7 @@ class SendAudioStream : public NetworkReceiverInterface {
}; };
// ReceiveAudioStream represents an audio receiver. It can't be used directly. // ReceiveAudioStream represents an audio receiver. It can't be used directly.
class ReceiveAudioStream : public NetworkReceiverInterface { class ReceiveAudioStream {
public: public:
RTC_DISALLOW_COPY_AND_ASSIGN(ReceiveAudioStream); RTC_DISALLOW_COPY_AND_ASSIGN(ReceiveAudioStream);
~ReceiveAudioStream(); ~ReceiveAudioStream();
@ -63,9 +58,6 @@ class ReceiveAudioStream : public NetworkReceiverInterface {
SendAudioStream* send_stream, SendAudioStream* send_stream,
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory, rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
Transport* feedback_transport); Transport* feedback_transport);
bool TryDeliverPacket(rtc::CopyOnWriteBuffer packet,
uint64_t receiver,
Timestamp at_time) override;
AudioReceiveStream* receive_stream_ = nullptr; AudioReceiveStream* receive_stream_ = nullptr;
CallClient* const receiver_; CallClient* const receiver_;
const AudioStreamConfig config_; const AudioStreamConfig config_;
@ -84,23 +76,13 @@ class AudioStreamPair {
private: private:
friend class Scenario; friend class Scenario;
AudioStreamPair(CallClient* sender, AudioStreamPair(CallClient* sender,
std::vector<NetworkNode*> send_link,
uint64_t send_receiver_id,
rtc::scoped_refptr<AudioEncoderFactory> encoder_factory, rtc::scoped_refptr<AudioEncoderFactory> encoder_factory,
CallClient* receiver, CallClient* receiver,
std::vector<NetworkNode*> return_link,
uint64_t return_receiver_id,
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory, rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
AudioStreamConfig config); AudioStreamConfig config);
private: private:
const AudioStreamConfig config_; const AudioStreamConfig config_;
std::vector<NetworkNode*> send_link_;
std::vector<NetworkNode*> return_link_;
NetworkNodeTransport send_transport_;
NetworkNodeTransport return_transport_;
SendAudioStream send_stream_; SendAudioStream send_stream_;
ReceiveAudioStream receive_stream_; ReceiveAudioStream receive_stream_;
}; };

View File

@ -21,6 +21,39 @@ namespace webrtc {
namespace test { namespace test {
namespace { namespace {
const char* kPriorityStreamId = "priority-track"; 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<AudioState> 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( LoggingNetworkControllerFactory::LoggingNetworkControllerFactory(
@ -107,17 +140,13 @@ CallClient::CallClient(Clock* clock,
std::string log_filename, std::string log_filename,
CallClientConfig config) CallClientConfig config)
: clock_(clock), : clock_(clock),
network_controller_factory_(log_filename, config.transport) { network_controller_factory_(log_filename, config.transport),
CallConfig call_config(network_controller_factory_.GetEventLog()); fake_audio_setup_(InitAudio()),
call_config.bitrate_config.max_bitrate_bps = call_(CreateCall(config,
config.transport.rates.max_rate.bps_or(-1); &network_controller_factory_,
call_config.bitrate_config.min_bitrate_bps = fake_audio_setup_.audio_state)),
config.transport.rates.min_rate.bps(); transport_(clock_, call_.get()),
call_config.bitrate_config.start_bitrate_bps = header_parser_(RtpHeaderParser::Create()) {
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));
if (!config.priority_target_rate.IsZero() && if (!config.priority_target_rate.IsZero() &&
config.priority_target_rate.IsFinite()) { config.priority_target_rate.IsFinite()) {
call_->SetBitrateAllocationStrategy( call_->SetBitrateAllocationStrategy(
@ -126,12 +155,13 @@ CallClient::CallClient(Clock* clock,
} }
} // namespace test } // namespace test
CallClient::~CallClient() {} CallClient::~CallClient() {
delete header_parser_;
}
void CallClient::DeliverPacket(MediaType media_type, void CallClient::DeliverPacket(MediaType media_type,
rtc::CopyOnWriteBuffer packet, rtc::CopyOnWriteBuffer packet,
Timestamp at_time) { Timestamp at_time) {
call_->Receiver()->DeliverPacket(media_type, packet, at_time.us());
} }
ColumnPrinter CallClient::StatsPrinter() { ColumnPrinter CallClient::StatsPrinter() {
@ -149,6 +179,26 @@ Call::Stats CallClient::GetStats() {
return call_->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() { uint32_t CallClient::GetNextVideoSsrc() {
RTC_CHECK_LT(next_video_ssrc_index_, CallTest::kNumSsrcs); RTC_CHECK_LT(next_video_ssrc_index_, CallTest::kNumSsrcs);
return CallTest::kVideoSendSsrcs[next_video_ssrc_index_++]; return CallTest::kVideoSendSsrcs[next_video_ssrc_index_++];
@ -170,21 +220,7 @@ std::string CallClient::GetNextPriorityId() {
return kPriorityStreamId; return kPriorityStreamId;
} }
rtc::scoped_refptr<AudioState> CallClient::InitAudio() { CallClientPair::~CallClientPair() = default;
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;
}
} // namespace test } // namespace test
} // namespace webrtc } // namespace webrtc

View File

@ -17,8 +17,10 @@
#include "logging/rtc_event_log/rtc_event_log.h" #include "logging/rtc_event_log/rtc_event_log.h"
#include "modules/audio_device/include/test_audio_device.h" #include "modules/audio_device/include/test_audio_device.h"
#include "modules/congestion_controller/test/controller_printer.h" #include "modules/congestion_controller/test/controller_printer.h"
#include "modules/rtp_rtcp/include/rtp_header_parser.h"
#include "rtc_base/constructormagic.h" #include "rtc_base/constructormagic.h"
#include "test/scenario/column_printer.h" #include "test/scenario/column_printer.h"
#include "test/scenario/network_node.h"
#include "test/scenario/scenario_config.h" #include "test/scenario/scenario_config.h"
namespace webrtc { namespace webrtc {
@ -45,10 +47,15 @@ class LoggingNetworkControllerFactory
FILE* cc_out_ = nullptr; FILE* cc_out_ = nullptr;
}; };
struct CallClientFakeAudio {
rtc::scoped_refptr<AudioProcessing> apm;
rtc::scoped_refptr<TestAudioDeviceModule> fake_audio_device;
rtc::scoped_refptr<AudioState> audio_state;
};
// CallClient represents a participant in a call scenario. It is created by the // 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 // Scenario class and is used as sender and receiver when setting up a media
// stream session. // stream session.
class CallClient { class CallClient : public NetworkReceiverInterface {
public: public:
CallClient(Clock* clock, std::string log_filename, CallClientConfig config); CallClient(Clock* clock, std::string log_filename, CallClientConfig config);
RTC_DISALLOW_COPY_AND_ASSIGN(CallClient); RTC_DISALLOW_COPY_AND_ASSIGN(CallClient);
@ -56,15 +63,24 @@ class CallClient {
~CallClient(); ~CallClient();
ColumnPrinter StatsPrinter(); ColumnPrinter StatsPrinter();
Call::Stats GetStats(); 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: private:
friend class Scenario; friend class Scenario;
friend class CallClientPair;
friend class SendVideoStream; friend class SendVideoStream;
friend class VideoStreamPair;
friend class ReceiveVideoStream; friend class ReceiveVideoStream;
friend class SendAudioStream; friend class SendAudioStream;
friend class ReceiveAudioStream; friend class ReceiveAudioStream;
friend class AudioStreamPair;
friend class NetworkNodeTransport; friend class NetworkNodeTransport;
// TODO(srte): Consider using the Columnprinter interface for this.
void DeliverPacket(MediaType media_type, void DeliverPacket(MediaType media_type,
rtc::CopyOnWriteBuffer packet, rtc::CopyOnWriteBuffer packet,
Timestamp at_time); Timestamp at_time);
@ -75,18 +91,37 @@ class CallClient {
Clock* clock_; Clock* clock_;
LoggingNetworkControllerFactory network_controller_factory_; LoggingNetworkControllerFactory network_controller_factory_;
CallClientFakeAudio fake_audio_setup_;
std::unique_ptr<Call> call_; std::unique_ptr<Call> call_;
NetworkNodeTransport transport_;
rtc::scoped_refptr<AudioState> InitAudio(); RtpHeaderParser* const header_parser_;
rtc::scoped_refptr<AudioProcessing> apm_;
rtc::scoped_refptr<TestAudioDeviceModule> fake_audio_device_;
std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory_; std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory_;
// Stores the configured overhead per known incomming route. This is used to
// subtract the overhead before processing.
std::map<uint64_t, DataSize> route_overhead_;
int next_video_ssrc_index_ = 0; int next_video_ssrc_index_ = 0;
int next_rtx_ssrc_index_ = 0; int next_rtx_ssrc_index_ = 0;
int next_audio_ssrc_index_ = 0; int next_audio_ssrc_index_ = 0;
int next_priority_index_ = 0; int next_priority_index_ = 0;
std::map<uint32_t, MediaType> ssrc_media_types_;
};
class CallClientPair {
public:
RTC_DISALLOW_COPY_AND_ASSIGN(CallClientPair);
~CallClientPair();
CallClient* first() { return first_; }
CallClient* second() { return second_; }
std::pair<CallClient*, CallClient*> forward() { return {first(), second()}; }
std::pair<CallClient*, CallClient*> 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 test
} // namespace webrtc } // namespace webrtc

View File

@ -170,21 +170,16 @@ SimulationNode::SimulationNode(
simulated_network_(simulation), simulated_network_(simulation),
config_(config) {} config_(config) {}
NetworkNodeTransport::NetworkNodeTransport(CallClient* sender, NetworkNodeTransport::NetworkNodeTransport(const Clock* sender_clock,
NetworkNode* send_net, Call* sender_call)
uint64_t receiver, : sender_clock_(sender_clock), sender_call_(sender_call) {}
DataSize packet_overhead)
: sender_(sender),
send_net_(send_net),
receiver_id_(receiver),
packet_overhead_(packet_overhead) {}
NetworkNodeTransport::~NetworkNodeTransport() = default; NetworkNodeTransport::~NetworkNodeTransport() = default;
bool NetworkNodeTransport::SendRtp(const uint8_t* packet, bool NetworkNodeTransport::SendRtp(const uint8_t* packet,
size_t length, size_t length,
const PacketOptions& options) { const PacketOptions& options) {
int64_t send_time_ms = sender_->clock_->TimeInMilliseconds(); int64_t send_time_ms = sender_clock_->TimeInMilliseconds();
rtc::SentPacket sent_packet; rtc::SentPacket sent_packet;
sent_packet.packet_id = options.packet_id; sent_packet.packet_id = options.packet_id;
sent_packet.info.included_in_feedback = options.included_in_feedback; 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.send_time_ms = send_time_ms;
sent_packet.info.packet_size_bytes = length; sent_packet.info.packet_size_bytes = length;
sent_packet.info.packet_type = rtc::PacketType::kData; 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); Timestamp send_time = Timestamp::ms(send_time_ms);
rtc::CritScope crit(&crit_sect_);
if (!send_net_)
return false;
rtc::CopyOnWriteBuffer buffer(packet, length, rtc::CopyOnWriteBuffer buffer(packet, length,
length + packet_overhead_.bytes()); length + packet_overhead_.bytes());
buffer.SetSize(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) { bool NetworkNodeTransport::SendRtcp(const uint8_t* packet, size_t length) {
rtc::CopyOnWriteBuffer buffer(packet, 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()); buffer.SetSize(length + packet_overhead_.bytes());
if (!send_net_)
return false;
return send_net_->TryDeliverPacket(buffer, receiver_id_, send_time); return send_net_->TryDeliverPacket(buffer, receiver_id_, send_time);
} }
uint64_t NetworkNodeTransport::ReceiverId() const { void NetworkNodeTransport::Connect(NetworkNode* send_node,
return receiver_id_; 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, CrossTrafficSource::CrossTrafficSource(NetworkReceiverInterface* target,

View File

@ -18,10 +18,10 @@
#include "api/call/transport.h" #include "api/call/transport.h"
#include "api/units/timestamp.h" #include "api/units/timestamp.h"
#include "call/call.h"
#include "call/simulated_network.h" #include "call/simulated_network.h"
#include "rtc_base/constructormagic.h" #include "rtc_base/constructormagic.h"
#include "rtc_base/copyonwritebuffer.h" #include "rtc_base/copyonwritebuffer.h"
#include "test/scenario/call_client.h"
#include "test/scenario/column_printer.h" #include "test/scenario/column_printer.h"
#include "test/scenario/scenario_config.h" #include "test/scenario/scenario_config.h"
@ -119,23 +119,30 @@ class SimulationNode : public NetworkNode {
class NetworkNodeTransport : public Transport { class NetworkNodeTransport : public Transport {
public: public:
NetworkNodeTransport(CallClient* sender, NetworkNodeTransport(const Clock* sender_clock, Call* sender_call);
NetworkNode* send_net,
uint64_t receiver,
DataSize packet_overhead);
~NetworkNodeTransport() override; ~NetworkNodeTransport() override;
bool SendRtp(const uint8_t* packet, bool SendRtp(const uint8_t* packet,
size_t length, size_t length,
const PacketOptions& options) override; const PacketOptions& options) override;
bool SendRtcp(const uint8_t* packet, size_t length) 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: private:
CallClient* const sender_; rtc::CriticalSection crit_sect_;
NetworkNode* const send_net_; const Clock* const sender_clock_;
const uint64_t receiver_id_; Call* const sender_call_;
const DataSize packet_overhead_; 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 // CrossTrafficSource is created by a Scenario and generates cross traffic. It

View File

@ -123,14 +123,50 @@ CallClient* Scenario::CreateClient(
return CreateClient(name, config); return CreateClient(name, config);
} }
CallClientPair* Scenario::CreateRoutes(CallClient* first,
std::vector<NetworkNode*> send_link,
CallClient* second,
std::vector<NetworkNode*> 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<NetworkNode*> send_link,
DataSize first_overhead,
CallClient* second,
std::vector<NetworkNode*> 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<CallClient*, CallClient*> clients,
std::vector<NetworkNode*> over_nodes) {
ChangeRoute(clients, over_nodes, DataSize::bytes(PacketOverhead::kDefault));
}
void Scenario::ChangeRoute(std::pair<CallClient*, CallClient*> clients,
std::vector<NetworkNode*> 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( SimulatedTimeClient* Scenario::CreateSimulatedTimeClient(
std::string name, std::string name,
SimulatedTimeClientConfig config, SimulatedTimeClientConfig config,
std::vector<PacketStreamConfig> stream_configs, std::vector<PacketStreamConfig> stream_configs,
std::vector<NetworkNode*> send_link, std::vector<NetworkNode*> send_link,
std::vector<NetworkNode*> return_link) { std::vector<NetworkNode*> return_link) {
uint64_t send_id = next_receiver_id_++; uint64_t send_id = next_route_id_++;
uint64_t return_id = next_receiver_id_++; uint64_t return_id = next_route_id_++;
SimulatedTimeClient* client = new SimulatedTimeClient( SimulatedTimeClient* client = new SimulatedTimeClient(
GetFullPathOrEmpty(name), config, stream_configs, send_link, return_link, GetFullPathOrEmpty(name), config, stream_configs, send_link, return_link,
send_id, return_id, Now()); send_id, return_id, Now());
@ -179,21 +215,21 @@ NetworkNode* Scenario::CreateNetworkNode(
void Scenario::TriggerPacketBurst(std::vector<NetworkNode*> over_nodes, void Scenario::TriggerPacketBurst(std::vector<NetworkNode*> over_nodes,
size_t num_packets, size_t num_packets,
size_t packet_size) { size_t packet_size) {
int64_t receiver_id = next_receiver_id_++; int64_t route_id = next_route_id_++;
NetworkNode::Route(receiver_id, over_nodes, &null_receiver_); NetworkNode::Route(route_id, over_nodes, &null_receiver_);
for (size_t i = 0; i < num_packets; ++i) for (size_t i = 0; i < num_packets; ++i)
over_nodes[0]->TryDeliverPacket(rtc::CopyOnWriteBuffer(packet_size), over_nodes[0]->TryDeliverPacket(rtc::CopyOnWriteBuffer(packet_size),
receiver_id, Now()); route_id, Now());
} }
void Scenario::NetworkDelayedAction(std::vector<NetworkNode*> over_nodes, void Scenario::NetworkDelayedAction(std::vector<NetworkNode*> over_nodes,
size_t packet_size, size_t packet_size,
std::function<void()> action) { std::function<void()> action) {
int64_t receiver_id = next_receiver_id_++; int64_t route_id = next_route_id_++;
action_receivers_.emplace_back(new ActionReceiver(action)); action_receivers_.emplace_back(new ActionReceiver(action));
NetworkNode::Route(receiver_id, over_nodes, action_receivers_.back().get()); NetworkNode::Route(route_id, over_nodes, action_receivers_.back().get());
over_nodes[0]->TryDeliverPacket(rtc::CopyOnWriteBuffer(packet_size), over_nodes[0]->TryDeliverPacket(rtc::CopyOnWriteBuffer(packet_size), route_id,
receiver_id, Now()); Now());
} }
CrossTrafficSource* Scenario::CreateCrossTraffic( CrossTrafficSource* Scenario::CreateCrossTraffic(
@ -207,65 +243,46 @@ CrossTrafficSource* Scenario::CreateCrossTraffic(
CrossTrafficSource* Scenario::CreateCrossTraffic( CrossTrafficSource* Scenario::CreateCrossTraffic(
std::vector<NetworkNode*> over_nodes, std::vector<NetworkNode*> over_nodes,
CrossTrafficConfig config) { CrossTrafficConfig config) {
int64_t receiver_id = next_receiver_id_++; int64_t route_id = next_route_id_++;
cross_traffic_sources_.emplace_back( 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(); 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, Every(config.min_packet_interval,
[this, node](TimeDelta delta) { node->Process(Now(), delta); }); [this, node](TimeDelta delta) { node->Process(Now(), delta); });
return node; return node;
} }
VideoStreamPair* Scenario::CreateVideoStream( VideoStreamPair* Scenario::CreateVideoStream(
CallClient* sender, std::pair<CallClient*, CallClient*> clients,
std::vector<NetworkNode*> send_link,
CallClient* receiver,
std::vector<NetworkNode*> return_link,
std::function<void(VideoStreamConfig*)> config_modifier) { std::function<void(VideoStreamConfig*)> config_modifier) {
VideoStreamConfig config; VideoStreamConfig config;
config_modifier(&config); config_modifier(&config);
return CreateVideoStream(sender, send_link, receiver, return_link, config); return CreateVideoStream(clients, config);
} }
VideoStreamPair* Scenario::CreateVideoStream( VideoStreamPair* Scenario::CreateVideoStream(
CallClient* sender, std::pair<CallClient*, CallClient*> clients,
std::vector<NetworkNode*> send_link,
CallClient* receiver,
std::vector<NetworkNode*> return_link,
VideoStreamConfig config) { VideoStreamConfig config) {
uint64_t send_receiver_id = next_receiver_id_++;
uint64_t return_receiver_id = next_receiver_id_++;
video_streams_.emplace_back( video_streams_.emplace_back(
new VideoStreamPair(sender, send_link, send_receiver_id, receiver, new VideoStreamPair(clients.first, clients.second, config));
return_link, return_receiver_id, config));
return video_streams_.back().get(); return video_streams_.back().get();
} }
AudioStreamPair* Scenario::CreateAudioStream( AudioStreamPair* Scenario::CreateAudioStream(
CallClient* sender, std::pair<CallClient*, CallClient*> clients,
std::vector<NetworkNode*> send_link,
CallClient* receiver,
std::vector<NetworkNode*> return_link,
std::function<void(AudioStreamConfig*)> config_modifier) { std::function<void(AudioStreamConfig*)> config_modifier) {
AudioStreamConfig config; AudioStreamConfig config;
config_modifier(&config); config_modifier(&config);
return CreateAudioStream(sender, send_link, receiver, return_link, config); return CreateAudioStream(clients, config);
} }
AudioStreamPair* Scenario::CreateAudioStream( AudioStreamPair* Scenario::CreateAudioStream(
CallClient* sender, std::pair<CallClient*, CallClient*> clients,
std::vector<NetworkNode*> send_link,
CallClient* receiver,
std::vector<NetworkNode*> return_link,
AudioStreamConfig config) { AudioStreamConfig config) {
uint64_t send_receiver_id = next_receiver_id_++; audio_streams_.emplace_back(
uint64_t return_receiver_id = next_receiver_id_++; new AudioStreamPair(clients.first, audio_encoder_factory_, clients.second,
audio_decoder_factory_, config));
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));
return audio_streams_.back().get(); return audio_streams_.back().get();
} }

View File

@ -78,6 +78,25 @@ class Scenario {
std::string name, std::string name,
std::function<void(CallClientConfig*)> config_modifier); std::function<void(CallClientConfig*)> config_modifier);
CallClientPair* CreateRoutes(CallClient* first,
std::vector<NetworkNode*> send_link,
CallClient* second,
std::vector<NetworkNode*> return_link);
CallClientPair* CreateRoutes(CallClient* first,
std::vector<NetworkNode*> send_link,
DataSize first_overhead,
CallClient* second,
std::vector<NetworkNode*> return_link,
DataSize second_overhead);
void ChangeRoute(std::pair<CallClient*, CallClient*> clients,
std::vector<NetworkNode*> over_nodes);
void ChangeRoute(std::pair<CallClient*, CallClient*> clients,
std::vector<NetworkNode*> over_nodes,
DataSize overhead);
SimulatedTimeClient* CreateSimulatedTimeClient( SimulatedTimeClient* CreateSimulatedTimeClient(
std::string name, std::string name,
SimulatedTimeClientConfig config, SimulatedTimeClientConfig config,
@ -86,27 +105,17 @@ class Scenario {
std::vector<NetworkNode*> return_link); std::vector<NetworkNode*> return_link);
VideoStreamPair* CreateVideoStream( VideoStreamPair* CreateVideoStream(
CallClient* sender, std::pair<CallClient*, CallClient*> clients,
std::vector<NetworkNode*> send_link,
CallClient* receiver,
std::vector<NetworkNode*> return_link,
std::function<void(VideoStreamConfig*)> config_modifier); std::function<void(VideoStreamConfig*)> config_modifier);
VideoStreamPair* CreateVideoStream(CallClient* sender, VideoStreamPair* CreateVideoStream(
std::vector<NetworkNode*> send_link, std::pair<CallClient*, CallClient*> clients,
CallClient* receiver,
std::vector<NetworkNode*> return_link,
VideoStreamConfig config); VideoStreamConfig config);
AudioStreamPair* CreateAudioStream( AudioStreamPair* CreateAudioStream(
CallClient* sender, std::pair<CallClient*, CallClient*> clients,
std::vector<NetworkNode*> send_link,
CallClient* receiver,
std::vector<NetworkNode*> return_link,
std::function<void(AudioStreamConfig*)> config_modifier); std::function<void(AudioStreamConfig*)> config_modifier);
AudioStreamPair* CreateAudioStream(CallClient* sender, AudioStreamPair* CreateAudioStream(
std::vector<NetworkNode*> send_link, std::pair<CallClient*, CallClient*> clients,
CallClient* receiver,
std::vector<NetworkNode*> return_link,
AudioStreamConfig config); AudioStreamConfig config);
CrossTrafficSource* CreateCrossTraffic( CrossTrafficSource* CreateCrossTraffic(
@ -167,6 +176,7 @@ class Scenario {
rtc::FakeClock event_log_fake_clock_; rtc::FakeClock event_log_fake_clock_;
std::vector<std::unique_ptr<CallClient>> clients_; std::vector<std::unique_ptr<CallClient>> clients_;
std::vector<std::unique_ptr<CallClientPair>> client_pairs_;
std::vector<std::unique_ptr<NetworkNode>> network_nodes_; std::vector<std::unique_ptr<NetworkNode>> network_nodes_;
std::vector<std::unique_ptr<CrossTrafficSource>> cross_traffic_sources_; std::vector<std::unique_ptr<CrossTrafficSource>> cross_traffic_sources_;
std::vector<std::unique_ptr<VideoStreamPair>> video_streams_; std::vector<std::unique_ptr<VideoStreamPair>> video_streams_;
@ -179,7 +189,7 @@ class Scenario {
std::vector<std::unique_ptr<PendingActivity>> pending_activities_; std::vector<std::unique_ptr<PendingActivity>> pending_activities_;
std::vector<std::unique_ptr<StatesPrinter>> printers_; std::vector<std::unique_ptr<StatesPrinter>> printers_;
int64_t next_receiver_id_ = 40000; int64_t next_route_id_ = 40000;
rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory_; rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory_;
rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory_; rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory_;

View File

@ -28,7 +28,12 @@ struct PacketOverhead {
static constexpr size_t kIpv6 = 40; static constexpr size_t kIpv6 = 40;
static constexpr size_t kUdp = 8; static constexpr size_t kUdp = 8;
static constexpr size_t kSrtp = 10; 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; static constexpr size_t kDefault = kIpv4 + kUdp + kSrtp;
}; };
struct TransportControllerConfig { struct TransportControllerConfig {
@ -117,7 +122,6 @@ struct VideoStreamConfig {
TimeDelta nack_history_time = TimeDelta::ms(1000); TimeDelta nack_history_time = TimeDelta::ms(1000);
bool use_flexfec = false; bool use_flexfec = false;
bool use_ulpfec = false; bool use_ulpfec = false;
DataSize packet_overhead = DataSize::bytes(PacketOverhead::kDefault);
} stream; } stream;
struct Renderer { struct Renderer {
enum Type { kFake } type = kFake; enum Type { kFake } type = kFake;
@ -159,7 +163,6 @@ struct AudioStreamConfig {
~Stream(); ~Stream();
bool in_bandwidth_estimation = false; bool in_bandwidth_estimation = false;
bool rate_allocation_priority = false; bool rate_allocation_priority = false;
DataSize packet_overhead = DataSize::bytes(PacketOverhead::kDefault);
} stream; } stream;
struct Render { struct Render {
std::string sync_group; std::string sync_group;

View File

@ -167,12 +167,13 @@ TEST_P(BbrScenarioTest, ReceivesVideo) {
net_conf.simulation.delay_std_dev = conf_.scenario.delay_noise; net_conf.simulation.delay_std_dev = conf_.scenario.delay_noise;
SimulationNode* send_net = s.CreateSimulationNode(net_conf); SimulationNode* send_net = s.CreateSimulationNode(net_conf);
SimulationNode* ret_net = s.CreateSimulationNode(net_conf); SimulationNode* ret_net = s.CreateSimulationNode(net_conf);
VideoStreamPair* alice_video = s.CreateVideoStream( auto route = s.CreateRoutes(alice, {send_net}, bob, {ret_net});
alice, {send_net}, bob, {ret_net}, [&](VideoStreamConfig* c) {
VideoStreamPair* alice_video =
s.CreateVideoStream(route->forward(), [&](VideoStreamConfig* c) {
c->encoder.fake.max_rate = DataRate::kbps(1800); c->encoder.fake.max_rate = DataRate::kbps(1800);
}); });
s.CreateAudioStream(alice, {send_net}, bob, {ret_net}, s.CreateAudioStream(route->forward(), [&](AudioStreamConfig* c) {
[&](AudioStreamConfig* c) {
if (conf_.tuning.use_bbr) { if (conf_.tuning.use_bbr) {
c->stream.in_bandwidth_estimation = true; c->stream.in_bandwidth_estimation = true;
c->encoder.fixed_rate = DataRate::kbps(31); c->encoder.fixed_rate = DataRate::kbps(31);
@ -181,12 +182,11 @@ TEST_P(BbrScenarioTest, ReceivesVideo) {
VideoStreamPair* bob_video = nullptr; VideoStreamPair* bob_video = nullptr;
if (conf_.scenario.return_traffic) { if (conf_.scenario.return_traffic) {
bob_video = s.CreateVideoStream( bob_video =
bob, {ret_net}, alice, {send_net}, [&](VideoStreamConfig* c) { s.CreateVideoStream(route->reverse(), [&](VideoStreamConfig* c) {
c->encoder.fake.max_rate = DataRate::kbps(1800); c->encoder.fake.max_rate = DataRate::kbps(1800);
}); });
s.CreateAudioStream(bob, {ret_net}, alice, {send_net}, s.CreateAudioStream(route->reverse(), [&](AudioStreamConfig* c) {
[&](AudioStreamConfig* c) {
if (conf_.tuning.use_bbr) { if (conf_.tuning.use_bbr) {
c->stream.in_bandwidth_estimation = true; c->stream.in_bandwidth_estimation = true;
c->encoder.fixed_rate = DataRate::kbps(31); c->encoder.fixed_rate = DataRate::kbps(31);

View File

@ -21,18 +21,19 @@ TEST(ScenarioTest, StartsAndStopsWithoutErrors) {
NetworkNodeConfig network_config; NetworkNodeConfig network_config;
auto alice_net = s.CreateSimulationNode(network_config); auto alice_net = s.CreateSimulationNode(network_config);
auto bob_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; VideoStreamConfig video_stream_config;
s.CreateVideoStream(alice, {alice_net}, bob, {bob_net}, video_stream_config); s.CreateVideoStream(route->forward(), video_stream_config);
s.CreateVideoStream(bob, {bob_net}, alice, {alice_net}, video_stream_config); s.CreateVideoStream(route->reverse(), video_stream_config);
AudioStreamConfig audio_stream_config; AudioStreamConfig audio_stream_config;
audio_stream_config.encoder.min_rate = DataRate::kbps(6); audio_stream_config.encoder.min_rate = DataRate::kbps(6);
audio_stream_config.encoder.max_rate = DataRate::kbps(64); audio_stream_config.encoder.max_rate = DataRate::kbps(64);
audio_stream_config.encoder.allocate_bitrate = true; audio_stream_config.encoder.allocate_bitrate = true;
audio_stream_config.stream.in_bandwidth_estimation = false; audio_stream_config.stream.in_bandwidth_estimation = false;
s.CreateAudioStream(alice, {alice_net}, bob, {bob_net}, audio_stream_config); s.CreateAudioStream(route->forward(), audio_stream_config);
s.CreateAudioStream(bob, {bob_net}, alice, {alice_net}, audio_stream_config); s.CreateAudioStream(route->reverse(), audio_stream_config);
CrossTrafficConfig cross_traffic_config; CrossTrafficConfig cross_traffic_config;
s.CreateCrossTraffic({alice_net}, cross_traffic_config); s.CreateCrossTraffic({alice_net}, cross_traffic_config);

View File

@ -252,11 +252,12 @@ SimulatedTimeClient::SimulatedTimeClient(
return_link_(return_link), return_link_(return_link),
sender_(send_link.front(), send_receiver_id), sender_(send_link.front(), send_receiver_id),
feedback_(config, return_receiver_id, return_link.front()) { 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; NetworkControllerConfig initial_config;
initial_config.constraints.at_time = at_time; initial_config.constraints = current_contraints_;
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;
congestion_controller_ = network_controller_factory_.Create(initial_config); congestion_controller_ = network_controller_factory_.Create(initial_config);
for (auto& stream_config : stream_configs) for (auto& stream_config : stream_configs)
packet_streams_.emplace_back(new PacketStream(stream_config)); 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 { TimeDelta SimulatedTimeClient::GetNetworkControllerProcessInterval() const {
return network_controller_factory_.GetProcessInterval(); return network_controller_factory_.GetProcessInterval();
} }

View File

@ -129,6 +129,7 @@ class SimulatedTimeClient : NetworkReceiverInterface {
void CongestionProcess(Timestamp at_time); void CongestionProcess(Timestamp at_time);
void PacerProcess(Timestamp at_time); void PacerProcess(Timestamp at_time);
void ProcessFrames(Timestamp at_time); void ProcessFrames(Timestamp at_time);
void TriggerFakeReroute(Timestamp at_time);
TimeDelta GetNetworkControllerProcessInterval() const; TimeDelta GetNetworkControllerProcessInterval() const;
double target_rate_kbps() const; double target_rate_kbps() const;
@ -144,6 +145,7 @@ class SimulatedTimeClient : NetworkReceiverInterface {
std::vector<NetworkNode*> return_link_; std::vector<NetworkNode*> return_link_;
SimulatedSender sender_; SimulatedSender sender_;
SimulatedFeedback feedback_; SimulatedFeedback feedback_;
TargetRateConstraints current_contraints_;
DataRate target_rate_ = DataRate::Infinity(); DataRate target_rate_ = DataRate::Infinity();
FILE* packet_log_ = nullptr; FILE* packet_log_ = nullptr;

View File

@ -234,16 +234,6 @@ void SendVideoStream::Start() {
video_capturer_->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) { void SendVideoStream::SetCaptureFramerate(int framerate) {
RTC_CHECK(frame_generator_) RTC_CHECK(frame_generator_)
<< "Framerate change only implemented for generators"; << "Framerate change only implemented for generators";
@ -300,11 +290,14 @@ ReceiveVideoStream::ReceiveVideoStream(CallClient* receiver,
recv_config.renderer = renderer_.get(); recv_config.renderer = renderer_.get();
if (config.stream.use_rtx) { if (config.stream.use_rtx) {
recv_config.rtp.rtx_ssrc = send_stream->rtx_ssrcs_[chosen_stream]; 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 recv_config.rtp
.rtx_associated_payload_types[CallTest::kSendRtxPayloadType] = .rtx_associated_payload_types[CallTest::kSendRtxPayloadType] =
CodecTypeToPayloadType(config.encoder.codec); CodecTypeToPayloadType(config.encoder.codec);
} }
recv_config.rtp.remote_ssrc = send_stream->ssrcs_[chosen_stream]; recv_config.rtp.remote_ssrc = send_stream->ssrcs_[chosen_stream];
receiver->ssrc_media_types_[recv_config.rtp.remote_ssrc] = MediaType::VIDEO;
VideoReceiveStream::Decoder decoder = VideoReceiveStream::Decoder decoder =
CreateMatchingDecoder(CodecTypeToPayloadType(config.encoder.codec), CreateMatchingDecoder(CodecTypeToPayloadType(config.encoder.codec),
CodecTypeToPayloadString(config.encoder.codec)); CodecTypeToPayloadString(config.encoder.codec));
@ -316,6 +309,7 @@ ReceiveVideoStream::ReceiveVideoStream(CallClient* receiver,
FlexfecReceiveStream::Config flexfec_config(feedback_transport); FlexfecReceiveStream::Config flexfec_config(feedback_transport);
flexfec_config.payload_type = CallTest::kFlexfecPayloadType; flexfec_config.payload_type = CallTest::kFlexfecPayloadType;
flexfec_config.remote_ssrc = CallTest::kFlexfecSendSsrc; 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.protected_media_ssrcs = send_stream->rtx_ssrcs_;
flexfec_config.local_ssrc = recv_config.rtp.local_ssrc; flexfec_config.local_ssrc = recv_config.rtp.local_ssrc;
flecfec_stream_ = flecfec_stream_ =
@ -337,46 +331,18 @@ ReceiveVideoStream::~ReceiveVideoStream() {
receiver_->call_->DestroyFlexfecReceiveStream(flecfec_stream_); 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() = default;
VideoStreamPair::VideoStreamPair(CallClient* sender, VideoStreamPair::VideoStreamPair(CallClient* sender,
std::vector<NetworkNode*> send_link,
uint64_t send_receiver_id,
CallClient* receiver, CallClient* receiver,
std::vector<NetworkNode*> return_link,
uint64_t return_receiver_id,
VideoStreamConfig config) VideoStreamConfig config)
: config_(config), : config_(config),
send_link_(send_link), send_stream_(sender, config, &sender->transport_),
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_),
receive_stream_(receiver, receive_stream_(receiver,
config, config,
&send_stream_, &send_stream_,
/*chosen_stream=*/0, /*chosen_stream=*/0,
&return_transport_) { &receiver->transport_) {}
NetworkNode::Route(send_transport_.ReceiverId(), send_link_,
&receive_stream_);
NetworkNode::Route(return_transport_.ReceiverId(), return_link_,
&send_stream_);
}
} // namespace test } // namespace test
} // namespace webrtc } // namespace webrtc

View File

@ -25,7 +25,7 @@ namespace webrtc {
namespace test { namespace test {
// SendVideoStream provides an interface for changing parameters and retrieving // SendVideoStream provides an interface for changing parameters and retrieving
// states at run time. // states at run time.
class SendVideoStream : public NetworkReceiverInterface { class SendVideoStream {
public: public:
RTC_DISALLOW_COPY_AND_ASSIGN(SendVideoStream); RTC_DISALLOW_COPY_AND_ASSIGN(SendVideoStream);
~SendVideoStream(); ~SendVideoStream();
@ -43,9 +43,6 @@ class SendVideoStream : public NetworkReceiverInterface {
SendVideoStream(CallClient* sender, SendVideoStream(CallClient* sender,
VideoStreamConfig config, VideoStreamConfig config,
Transport* send_transport); Transport* send_transport);
bool TryDeliverPacket(rtc::CopyOnWriteBuffer packet,
uint64_t receiver,
Timestamp at_time) override;
std::vector<uint32_t> ssrcs_; std::vector<uint32_t> ssrcs_;
std::vector<uint32_t> rtx_ssrcs_; std::vector<uint32_t> rtx_ssrcs_;
@ -55,10 +52,12 @@ class SendVideoStream : public NetworkReceiverInterface {
std::unique_ptr<VideoEncoderFactory> encoder_factory_; std::unique_ptr<VideoEncoderFactory> encoder_factory_;
std::unique_ptr<TestVideoCapturer> video_capturer_; std::unique_ptr<TestVideoCapturer> video_capturer_;
FrameGeneratorCapturer* frame_generator_ = nullptr; 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. // ReceiveVideoStream represents a video receiver. It can't be used directly.
class ReceiveVideoStream : public NetworkReceiverInterface { class ReceiveVideoStream {
public: public:
RTC_DISALLOW_COPY_AND_ASSIGN(ReceiveVideoStream); RTC_DISALLOW_COPY_AND_ASSIGN(ReceiveVideoStream);
~ReceiveVideoStream(); ~ReceiveVideoStream();
@ -71,9 +70,7 @@ class ReceiveVideoStream : public NetworkReceiverInterface {
SendVideoStream* send_stream, SendVideoStream* send_stream,
size_t chosen_stream, size_t chosen_stream,
Transport* feedback_transport); Transport* feedback_transport);
bool TryDeliverPacket(rtc::CopyOnWriteBuffer packet,
uint64_t receiver,
Timestamp at_time) override;
VideoReceiveStream* receive_stream_ = nullptr; VideoReceiveStream* receive_stream_ = nullptr;
FlexfecReceiveStream* flecfec_stream_ = nullptr; FlexfecReceiveStream* flecfec_stream_ = nullptr;
std::unique_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> renderer_; std::unique_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> renderer_;
@ -95,18 +92,10 @@ class VideoStreamPair {
private: private:
friend class Scenario; friend class Scenario;
VideoStreamPair(CallClient* sender, VideoStreamPair(CallClient* sender,
std::vector<NetworkNode*> send_link,
uint64_t send_receiver_id,
CallClient* receiver, CallClient* receiver,
std::vector<NetworkNode*> return_link,
uint64_t return_receiver_id,
VideoStreamConfig config); VideoStreamConfig config);
const VideoStreamConfig config_; const VideoStreamConfig config_;
std::vector<NetworkNode*> send_link_;
std::vector<NetworkNode*> return_link_;
NetworkNodeTransport send_transport_;
NetworkNodeTransport return_transport_;
SendVideoStream send_stream_; SendVideoStream send_stream_;
ReceiveVideoStream receive_stream_; ReceiveVideoStream receive_stream_;