blob: 92c582e4d8404c5c48c094f583feb55ec9bb4769 [file] [log] [blame]
Sebastian Jansson98b07e92018-09-27 13:47:01 +02001/*
2 * Copyright 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10#include "test/scenario/call_client.h"
11
12#include <utility>
13
14#include "logging/rtc_event_log/output/rtc_event_log_output_file.h"
15#include "modules/audio_mixer/audio_mixer_impl.h"
16#include "modules/congestion_controller/bbr/test/bbr_printer.h"
17#include "modules/congestion_controller/goog_cc/test/goog_cc_printer.h"
18#include "test/call_test.h"
19
20namespace webrtc {
21namespace test {
22namespace {
23const char* kPriorityStreamId = "priority-track";
Sebastian Jansson800e1212018-10-22 11:49:03 +020024
25CallClientFakeAudio InitAudio() {
26 CallClientFakeAudio setup;
27 auto capturer = TestAudioDeviceModule::CreatePulsedNoiseCapturer(256, 48000);
28 auto renderer = TestAudioDeviceModule::CreateDiscardRenderer(48000);
29 setup.fake_audio_device = TestAudioDeviceModule::CreateTestAudioDeviceModule(
30 std::move(capturer), std::move(renderer), 1.f);
31 setup.apm = AudioProcessingBuilder().Create();
32 setup.fake_audio_device->Init();
33 AudioState::Config audio_state_config;
34 audio_state_config.audio_mixer = AudioMixerImpl::Create();
35 audio_state_config.audio_processing = setup.apm;
36 audio_state_config.audio_device_module = setup.fake_audio_device;
37 setup.audio_state = AudioState::Create(audio_state_config);
38 setup.fake_audio_device->RegisterAudioCallback(
39 setup.audio_state->audio_transport());
40 return setup;
41}
42
43Call* CreateCall(CallClientConfig config,
44 LoggingNetworkControllerFactory* network_controller_factory_,
45 rtc::scoped_refptr<AudioState> audio_state) {
46 CallConfig call_config(network_controller_factory_->GetEventLog());
47 call_config.bitrate_config.max_bitrate_bps =
48 config.transport.rates.max_rate.bps_or(-1);
49 call_config.bitrate_config.min_bitrate_bps =
50 config.transport.rates.min_rate.bps();
51 call_config.bitrate_config.start_bitrate_bps =
52 config.transport.rates.start_rate.bps();
53 call_config.network_controller_factory = network_controller_factory_;
54 call_config.audio_state = audio_state;
55 return Call::Create(call_config);
56}
Sebastian Jansson98b07e92018-09-27 13:47:01 +020057}
58
59LoggingNetworkControllerFactory::LoggingNetworkControllerFactory(
60 std::string filename,
61 TransportControllerConfig config) {
62 if (filename.empty()) {
63 event_log_ = RtcEventLog::CreateNull();
64 } else {
65 event_log_ = RtcEventLog::Create(RtcEventLog::EncodingType::Legacy);
66 bool success = event_log_->StartLogging(
67 absl::make_unique<RtcEventLogOutputFile>(filename + ".rtc.dat",
68 RtcEventLog::kUnlimitedOutput),
69 RtcEventLog::kImmediateOutput);
70 RTC_CHECK(success);
71 cc_out_ = fopen((filename + ".cc_state.txt").c_str(), "w");
72 switch (config.cc) {
73 case TransportControllerConfig::CongestionController::kBbr: {
74 auto bbr_printer = absl::make_unique<BbrStatePrinter>();
75 cc_factory_.reset(new BbrDebugFactory(bbr_printer.get()));
76 cc_printer_.reset(
77 new ControlStatePrinter(cc_out_, std::move(bbr_printer)));
78 break;
79 }
80 case TransportControllerConfig::CongestionController::kGoogCc: {
81 auto goog_printer = absl::make_unique<GoogCcStatePrinter>();
82 cc_factory_.reset(
83 new GoogCcDebugFactory(event_log_.get(), goog_printer.get()));
84 cc_printer_.reset(
85 new ControlStatePrinter(cc_out_, std::move(goog_printer)));
86 break;
87 }
88 case TransportControllerConfig::CongestionController::kGoogCcFeedback: {
89 auto goog_printer = absl::make_unique<GoogCcStatePrinter>();
90 cc_factory_.reset(new GoogCcFeedbackDebugFactory(event_log_.get(),
91 goog_printer.get()));
92 cc_printer_.reset(
93 new ControlStatePrinter(cc_out_, std::move(goog_printer)));
94 break;
95 }
96 }
97 cc_printer_->PrintHeaders();
98 }
99 if (!cc_factory_) {
100 switch (config.cc) {
101 case TransportControllerConfig::CongestionController::kBbr:
102 cc_factory_.reset(new BbrNetworkControllerFactory());
103 break;
104 case TransportControllerConfig::CongestionController::kGoogCcFeedback:
105 cc_factory_.reset(
106 new GoogCcFeedbackNetworkControllerFactory(event_log_.get()));
107 break;
108 case TransportControllerConfig::CongestionController::kGoogCc:
109 cc_factory_.reset(new GoogCcNetworkControllerFactory(event_log_.get()));
110 break;
111 }
112 }
113}
114
115LoggingNetworkControllerFactory::~LoggingNetworkControllerFactory() {
116 if (cc_out_)
117 fclose(cc_out_);
118}
119
120void LoggingNetworkControllerFactory::LogCongestionControllerStats(
121 Timestamp at_time) {
122 if (cc_printer_)
123 cc_printer_->PrintState(at_time);
124}
125
126RtcEventLog* LoggingNetworkControllerFactory::GetEventLog() const {
127 return event_log_.get();
128}
129
130std::unique_ptr<NetworkControllerInterface>
131LoggingNetworkControllerFactory::Create(NetworkControllerConfig config) {
132 return cc_factory_->Create(config);
133}
134
135TimeDelta LoggingNetworkControllerFactory::GetProcessInterval() const {
136 return cc_factory_->GetProcessInterval();
137}
138
139CallClient::CallClient(Clock* clock,
140 std::string log_filename,
141 CallClientConfig config)
142 : clock_(clock),
Sebastian Jansson800e1212018-10-22 11:49:03 +0200143 network_controller_factory_(log_filename, config.transport),
144 fake_audio_setup_(InitAudio()),
145 call_(CreateCall(config,
146 &network_controller_factory_,
147 fake_audio_setup_.audio_state)),
148 transport_(clock_, call_.get()),
149 header_parser_(RtpHeaderParser::Create()) {
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200150 if (!config.priority_target_rate.IsZero() &&
151 config.priority_target_rate.IsFinite()) {
152 call_->SetBitrateAllocationStrategy(
153 absl::make_unique<rtc::AudioPriorityBitrateAllocationStrategy>(
154 kPriorityStreamId, config.priority_target_rate.bps()));
155 }
156} // namespace test
157
Sebastian Jansson800e1212018-10-22 11:49:03 +0200158CallClient::~CallClient() {
159 delete header_parser_;
160}
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200161
162void CallClient::DeliverPacket(MediaType media_type,
163 rtc::CopyOnWriteBuffer packet,
164 Timestamp at_time) {
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200165}
166
167ColumnPrinter CallClient::StatsPrinter() {
168 return ColumnPrinter::Lambda(
169 "pacer_delay call_send_bw",
170 [this](rtc::SimpleStringBuilder& sb) {
171 Call::Stats call_stats = call_->GetStats();
172 sb.AppendFormat("%.3lf %.0lf", call_stats.pacer_delay_ms / 1000.0,
173 call_stats.send_bandwidth_bps / 8.0);
174 },
175 64);
176}
177
178Call::Stats CallClient::GetStats() {
179 return call_->GetStats();
180}
181
Sebastian Jansson800e1212018-10-22 11:49:03 +0200182bool CallClient::TryDeliverPacket(rtc::CopyOnWriteBuffer packet,
183 uint64_t receiver,
184 Timestamp at_time) {
185 // Removes added overhead before delivering packet to sender.
186 RTC_DCHECK_GE(packet.size(), route_overhead_.at(receiver).bytes());
187 packet.SetSize(packet.size() - route_overhead_.at(receiver).bytes());
188
189 MediaType media_type = MediaType::ANY;
190 if (!RtpHeaderParser::IsRtcp(packet.cdata(), packet.size())) {
191 RTPHeader header;
192 bool success =
193 header_parser_->Parse(packet.cdata(), packet.size(), &header);
194 if (!success)
195 return false;
196 media_type = ssrc_media_types_[header.ssrc];
197 }
198 call_->Receiver()->DeliverPacket(media_type, packet, at_time.us());
199 return true;
200}
201
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200202uint32_t CallClient::GetNextVideoSsrc() {
203 RTC_CHECK_LT(next_video_ssrc_index_, CallTest::kNumSsrcs);
204 return CallTest::kVideoSendSsrcs[next_video_ssrc_index_++];
205}
206
207uint32_t CallClient::GetNextAudioSsrc() {
208 RTC_CHECK_LT(next_audio_ssrc_index_, 1);
209 next_audio_ssrc_index_++;
210 return CallTest::kAudioSendSsrc;
211}
212
213uint32_t CallClient::GetNextRtxSsrc() {
214 RTC_CHECK_LT(next_rtx_ssrc_index_, CallTest::kNumSsrcs);
215 return CallTest::kSendRtxSsrcs[next_rtx_ssrc_index_++];
216}
217
218std::string CallClient::GetNextPriorityId() {
219 RTC_CHECK_LT(next_priority_index_++, 1);
220 return kPriorityStreamId;
221}
222
Sebastian Jansson800e1212018-10-22 11:49:03 +0200223CallClientPair::~CallClientPair() = default;
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200224
225} // namespace test
226} // namespace webrtc