blob: 110bf4bb532335ec955b43f53da27526c6165c5c [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 "rtc_base/random.h"
11
Sebastian Janssonf0d03122018-12-18 15:53:04 +010012#include "modules/congestion_controller/bbr/bbr_factory.h"
Sebastian Jansson98b07e92018-09-27 13:47:01 +020013#include "rtc_base/experiments/field_trial_parser.h"
14#include "rtc_base/experiments/field_trial_units.h"
15#include "test/field_trial.h"
16#include "test/gtest.h"
17#include "test/scenario/scenario.h"
18
19namespace webrtc {
20namespace test {
21namespace {
22constexpr int64_t kRunTimeMs = 60000;
23
24using ::testing::Values;
25using ::testing::Combine;
26using ::testing::tuple;
27using ::testing::make_tuple;
28
29using Codec = VideoStreamConfig::Encoder::Codec;
30using CodecImpl = VideoStreamConfig::Encoder::Implementation;
31
32struct CallTestConfig {
33 struct Scenario {
34 FieldTrialParameter<int> random_seed;
35 FieldTrialFlag return_traffic;
36 FieldTrialParameter<DataRate> capacity;
37 FieldTrialParameter<TimeDelta> propagation_delay;
38 FieldTrialParameter<DataRate> cross_traffic;
39 FieldTrialParameter<TimeDelta> delay_noise;
40 FieldTrialParameter<double> loss_rate;
41 Scenario()
42 : random_seed("rs", 1),
43 return_traffic("ret"),
44 capacity("bw", DataRate::kbps(300)),
45 propagation_delay("dl", TimeDelta::ms(100)),
46 cross_traffic("ct", DataRate::Zero()),
47 delay_noise("dn", TimeDelta::Zero()),
48 loss_rate("pl", 0) {}
49 void Parse(std::string config_str) {
50 ParseFieldTrial(
51 {&random_seed, &return_traffic, &capacity, &propagation_delay,
52 &cross_traffic, &delay_noise, &loss_rate},
53 config_str);
54 }
55 } scenario;
56 struct Tuning {
57 FieldTrialFlag use_bbr;
58 FieldTrialFlag bbr_no_target_rate;
59 FieldTrialOptional<DataSize> bbr_initial_window;
60 FieldTrialParameter<double> bbr_encoder_gain;
61 Tuning()
62 : use_bbr("bbr"),
63 bbr_no_target_rate("notr"),
64 bbr_initial_window("iw", DataSize::bytes(8000)),
65 bbr_encoder_gain("eg", 0.8) {}
66 void Parse(std::string config_str) {
67 ParseFieldTrial(
68 {
69 &use_bbr, &bbr_no_target_rate, &bbr_initial_window,
70 &bbr_encoder_gain,
71 },
72 config_str);
73 }
74 } tuning;
75
76 void Parse(std::string scenario_string, std::string tuning_string) {
77 scenario.Parse(scenario_string);
78 tuning.Parse(tuning_string);
79 scenario_str = scenario_string;
80 tuning_str = tuning_string;
81 }
82 std::string scenario_str;
83 std::string tuning_str;
84
85 std::string BbrTrial() const {
86 char trial_buf[1024];
87 rtc::SimpleStringBuilder trial(trial_buf);
88 trial << "WebRTC-BweBbrConfig/";
89 trial << "encoder_rate_gain_in_probe_rtt:0.5";
90 trial.AppendFormat(",encoder_rate_gain:%.1lf",
91 tuning.bbr_encoder_gain.Get());
92 if (tuning.bbr_no_target_rate)
93 trial << ",pacing_rate_as_target:1";
94 if (tuning.bbr_initial_window)
95 trial << ",initial_cwin:" << tuning.bbr_initial_window->bytes();
96 trial << "/";
97 return trial.str();
98 }
99 std::string FieldTrials() const {
Sebastian Jansson63470292019-02-01 10:13:43 +0100100 std::string trials;
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200101 if (tuning.use_bbr) {
102 trials +=
103 "WebRTC-BweCongestionController/Enabled,BBR/"
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200104 "WebRTC-Pacer-DrainQueue/Disabled/"
105 "WebRTC-Pacer-PadInSilence/Enabled/"
106 "WebRTC-Pacer-BlockAudio/Disabled/"
107 "WebRTC-Audio-SendSideBwe/Enabled/"
108 "WebRTC-SendSideBwe-WithOverhead/Enabled/";
109 trials += BbrTrial();
110 }
111 return trials;
112 }
113
114 std::string Name() const {
115 char raw_name[1024];
116 rtc::SimpleStringBuilder name(raw_name);
117 for (char c : scenario_str + "__tun__" + tuning_str) {
118 if (c == ':') {
119 continue;
120 } else if (c == ',') {
121 name << "_";
122 } else if (c == '%') {
123 name << "p";
124 } else {
125 name << c;
126 }
127 }
128 return name.str();
129 }
130};
131} // namespace
132class BbrScenarioTest
133 : public ::testing::Test,
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200134 public ::testing::WithParamInterface<tuple<std::string, std::string>> {
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200135 public:
136 BbrScenarioTest() {
137 conf_.Parse(::testing::get<0>(GetParam()), ::testing::get<1>(GetParam()));
138 field_trial_.reset(new test::ScopedFieldTrials(conf_.FieldTrials()));
139 }
140 CallTestConfig conf_;
141
142 private:
143 std::unique_ptr<test::ScopedFieldTrials> field_trial_;
144};
145
146TEST_P(BbrScenarioTest, ReceivesVideo) {
Sebastian Janssonf0d03122018-12-18 15:53:04 +0100147 BbrNetworkControllerFactory bbr_factory;
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200148 Scenario s("bbr_test_gen/bbr__" + conf_.Name());
Sebastian Janssonf0d03122018-12-18 15:53:04 +0100149 CallClientConfig call_config;
150 if (conf_.tuning.use_bbr) {
151 call_config.transport.cc =
152 TransportControllerConfig::CongestionController::kInjected;
153 call_config.transport.cc_factory = &bbr_factory;
154 }
155 call_config.transport.rates.min_rate = DataRate::kbps(30);
156 call_config.transport.rates.max_rate = DataRate::kbps(1800);
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200157
Sebastian Janssonf0d03122018-12-18 15:53:04 +0100158 CallClient* alice = s.CreateClient("send", call_config);
159 CallClient* bob = s.CreateClient("return", call_config);
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200160 NetworkNodeConfig net_conf;
161 net_conf.simulation.bandwidth = conf_.scenario.capacity;
162 net_conf.simulation.delay = conf_.scenario.propagation_delay;
163 net_conf.simulation.loss_rate = conf_.scenario.loss_rate;
164 net_conf.simulation.delay_std_dev = conf_.scenario.delay_noise;
165 SimulationNode* send_net = s.CreateSimulationNode(net_conf);
166 SimulationNode* ret_net = s.CreateSimulationNode(net_conf);
Sebastian Jansson800e1212018-10-22 11:49:03 +0200167 auto route = s.CreateRoutes(alice, {send_net}, bob, {ret_net});
168
169 VideoStreamPair* alice_video =
170 s.CreateVideoStream(route->forward(), [&](VideoStreamConfig* c) {
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200171 c->encoder.fake.max_rate = DataRate::kbps(1800);
172 });
Sebastian Jansson800e1212018-10-22 11:49:03 +0200173 s.CreateAudioStream(route->forward(), [&](AudioStreamConfig* c) {
174 if (conf_.tuning.use_bbr) {
175 c->stream.in_bandwidth_estimation = true;
176 c->encoder.fixed_rate = DataRate::kbps(31);
177 }
178 });
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200179
180 VideoStreamPair* bob_video = nullptr;
181 if (conf_.scenario.return_traffic) {
Sebastian Jansson800e1212018-10-22 11:49:03 +0200182 bob_video =
183 s.CreateVideoStream(route->reverse(), [&](VideoStreamConfig* c) {
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200184 c->encoder.fake.max_rate = DataRate::kbps(1800);
185 });
Sebastian Jansson800e1212018-10-22 11:49:03 +0200186 s.CreateAudioStream(route->reverse(), [&](AudioStreamConfig* c) {
187 if (conf_.tuning.use_bbr) {
188 c->stream.in_bandwidth_estimation = true;
189 c->encoder.fixed_rate = DataRate::kbps(31);
190 }
191 });
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200192 }
193 CrossTrafficConfig cross_config;
194 cross_config.peak_rate = conf_.scenario.cross_traffic;
195 cross_config.random_seed = conf_.scenario.random_seed;
196 CrossTrafficSource* cross_traffic =
197 s.CreateCrossTraffic({send_net}, cross_config);
198
199 s.CreatePrinter("send.stats.txt", TimeDelta::ms(100),
200 {alice->StatsPrinter(), alice_video->send()->StatsPrinter(),
201 cross_traffic->StatsPrinter(), send_net->ConfigPrinter()});
202
203 std::vector<ColumnPrinter> return_printers{
204 bob->StatsPrinter(), ColumnPrinter::Fixed("cross_traffic_rate", "0"),
205 ret_net->ConfigPrinter()};
206 if (bob_video)
207 return_printers.push_back(bob_video->send()->StatsPrinter());
208 s.CreatePrinter("return.stats.txt", TimeDelta::ms(100), return_printers);
209
210 s.RunFor(TimeDelta::ms(kRunTimeMs));
211}
212
Mirko Bonadeic84f6612019-01-31 12:20:57 +0100213INSTANTIATE_TEST_SUITE_P(Selected,
214 BbrScenarioTest,
215 Values(make_tuple("rs:1,bw:150,dl:100,ct:100",
216 "bbr")));
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200217
Mirko Bonadeic84f6612019-01-31 12:20:57 +0100218INSTANTIATE_TEST_SUITE_P(
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200219 OneWayTuning,
220 BbrScenarioTest,
221 Values(make_tuple("bw:150,dl:100", "bbr,iw:,eg:100%,notr"),
222 make_tuple("bw:150,dl:100", "bbr,iw:8000,eg:100%,notr"),
223 make_tuple("bw:150,dl:100", "bbr,iw:8000,eg:100%"),
224 make_tuple("bw:150,dl:100", "bbr,iw:8000,eg:80%")));
225
Mirko Bonadeic84f6612019-01-31 12:20:57 +0100226INSTANTIATE_TEST_SUITE_P(OneWayTuned,
227 BbrScenarioTest,
228 Values(make_tuple("bw:150,dl:100", "bbr"),
229 make_tuple("bw:150,dl:100", ""),
230 make_tuple("bw:800,dl:100", "bbr"),
231 make_tuple("bw:800,dl:100", "")));
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200232
Mirko Bonadeic84f6612019-01-31 12:20:57 +0100233INSTANTIATE_TEST_SUITE_P(OneWayDegraded,
234 BbrScenarioTest,
235 Values(make_tuple("bw:150,dl:100,dn:30,pl:5%", "bbr"),
236 make_tuple("bw:150,dl:100,dn:30,pl:5%", ""),
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200237
Mirko Bonadeic84f6612019-01-31 12:20:57 +0100238 make_tuple("bw:150,ct:100,dl:100", "bbr"),
239 make_tuple("bw:150,ct:100,dl:100", ""),
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200240
Mirko Bonadeic84f6612019-01-31 12:20:57 +0100241 make_tuple("bw:800,dl:100,dn:30,pl:5%", "bbr"),
242 make_tuple("bw:800,dl:100,dn:30,pl:5%", ""),
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200243
Mirko Bonadeic84f6612019-01-31 12:20:57 +0100244 make_tuple("bw:800,ct:600,dl:100", "bbr"),
245 make_tuple("bw:800,ct:600,dl:100", "")));
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200246
Mirko Bonadeic84f6612019-01-31 12:20:57 +0100247INSTANTIATE_TEST_SUITE_P(TwoWay,
248 BbrScenarioTest,
249 Values(make_tuple("ret,bw:150,dl:100", "bbr"),
250 make_tuple("ret,bw:150,dl:100", ""),
251 make_tuple("ret,bw:800,dl:100", "bbr"),
252 make_tuple("ret,bw:800,dl:100", ""),
253 make_tuple("ret,bw:150,dl:50", "bbr"),
254 make_tuple("ret,bw:150,dl:50", "")));
Sebastian Jansson98b07e92018-09-27 13:47:01 +0200255} // namespace test
256} // namespace webrtc