1 /*
2 * Copyright (c) 2013 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
11 #include "call/rampup_tests.h"
12
13 #include <memory>
14
15 #include "absl/flags/flag.h"
16 #include "api/rtc_event_log/rtc_event_log_factory.h"
17 #include "api/rtc_event_log_output_file.h"
18 #include "api/task_queue/default_task_queue_factory.h"
19 #include "api/task_queue/task_queue_base.h"
20 #include "api/task_queue/task_queue_factory.h"
21 #include "call/fake_network_pipe.h"
22 #include "rtc_base/checks.h"
23 #include "rtc_base/logging.h"
24 #include "rtc_base/platform_thread.h"
25 #include "rtc_base/string_encode.h"
26 #include "rtc_base/task_queue_for_test.h"
27 #include "rtc_base/time_utils.h"
28 #include "test/encoder_settings.h"
29 #include "test/field_trial.h"
30 #include "test/gtest.h"
31 #include "test/testsupport/perf_test.h"
32
33 ABSL_FLAG(std::string,
34 ramp_dump_name,
35 "",
36 "Filename for dumped received RTP stream.");
37
38 namespace webrtc {
39 namespace {
40
41 constexpr TimeDelta kPollInterval = TimeDelta::Millis(20);
42 static const int kExpectedHighVideoBitrateBps = 80000;
43 static const int kExpectedHighAudioBitrateBps = 30000;
44 static const int kLowBandwidthLimitBps = 20000;
45 // Set target detected bitrate to slightly larger than the target bitrate to
46 // avoid flakiness.
47 static const int kLowBitrateMarginBps = 2000;
48
GenerateSsrcs(size_t num_streams,uint32_t ssrc_offset)49 std::vector<uint32_t> GenerateSsrcs(size_t num_streams, uint32_t ssrc_offset) {
50 std::vector<uint32_t> ssrcs;
51 for (size_t i = 0; i != num_streams; ++i)
52 ssrcs.push_back(static_cast<uint32_t>(ssrc_offset + i));
53 return ssrcs;
54 }
55 } // namespace
56
RampUpTester(size_t num_video_streams,size_t num_audio_streams,size_t num_flexfec_streams,unsigned int start_bitrate_bps,int64_t min_run_time_ms,const std::string & extension_type,bool rtx,bool red,bool report_perf_stats,TaskQueueBase * task_queue)57 RampUpTester::RampUpTester(size_t num_video_streams,
58 size_t num_audio_streams,
59 size_t num_flexfec_streams,
60 unsigned int start_bitrate_bps,
61 int64_t min_run_time_ms,
62 const std::string& extension_type,
63 bool rtx,
64 bool red,
65 bool report_perf_stats,
66 TaskQueueBase* task_queue)
67 : EndToEndTest(test::CallTest::kLongTimeoutMs),
68 clock_(Clock::GetRealTimeClock()),
69 num_video_streams_(num_video_streams),
70 num_audio_streams_(num_audio_streams),
71 num_flexfec_streams_(num_flexfec_streams),
72 rtx_(rtx),
73 red_(red),
74 report_perf_stats_(report_perf_stats),
75 sender_call_(nullptr),
76 send_stream_(nullptr),
77 send_transport_(nullptr),
78 send_simulated_network_(nullptr),
79 start_bitrate_bps_(start_bitrate_bps),
80 min_run_time_ms_(min_run_time_ms),
81 expected_bitrate_bps_(0),
82 test_start_ms_(-1),
83 ramp_up_finished_ms_(-1),
84 extension_type_(extension_type),
85 video_ssrcs_(GenerateSsrcs(num_video_streams_, 100)),
86 video_rtx_ssrcs_(GenerateSsrcs(num_video_streams_, 200)),
87 audio_ssrcs_(GenerateSsrcs(num_audio_streams_, 300)),
88 task_queue_(task_queue) {
89 if (red_)
90 EXPECT_EQ(0u, num_flexfec_streams_);
91 EXPECT_LE(num_audio_streams_, 1u);
92 }
93
94 RampUpTester::~RampUpTester() = default;
95
ModifySenderBitrateConfig(BitrateConstraints * bitrate_config)96 void RampUpTester::ModifySenderBitrateConfig(
97 BitrateConstraints* bitrate_config) {
98 if (start_bitrate_bps_ != 0) {
99 bitrate_config->start_bitrate_bps = start_bitrate_bps_;
100 }
101 bitrate_config->min_bitrate_bps = 10000;
102 }
103
OnVideoStreamsCreated(VideoSendStream * send_stream,const std::vector<VideoReceiveStream * > & receive_streams)104 void RampUpTester::OnVideoStreamsCreated(
105 VideoSendStream* send_stream,
106 const std::vector<VideoReceiveStream*>& receive_streams) {
107 send_stream_ = send_stream;
108 }
109
CreateSendTransport(TaskQueueBase * task_queue,Call * sender_call)110 std::unique_ptr<test::PacketTransport> RampUpTester::CreateSendTransport(
111 TaskQueueBase* task_queue,
112 Call* sender_call) {
113 auto network = std::make_unique<SimulatedNetwork>(forward_transport_config_);
114 send_simulated_network_ = network.get();
115 auto send_transport = std::make_unique<test::PacketTransport>(
116 task_queue, sender_call, this, test::PacketTransport::kSender,
117 test::CallTest::payload_type_map_,
118 std::make_unique<FakeNetworkPipe>(Clock::GetRealTimeClock(),
119 std::move(network)));
120 send_transport_ = send_transport.get();
121 return send_transport;
122 }
123
GetNumVideoStreams() const124 size_t RampUpTester::GetNumVideoStreams() const {
125 return num_video_streams_;
126 }
127
GetNumAudioStreams() const128 size_t RampUpTester::GetNumAudioStreams() const {
129 return num_audio_streams_;
130 }
131
GetNumFlexfecStreams() const132 size_t RampUpTester::GetNumFlexfecStreams() const {
133 return num_flexfec_streams_;
134 }
135
136 class RampUpTester::VideoStreamFactory
137 : public VideoEncoderConfig::VideoStreamFactoryInterface {
138 public:
VideoStreamFactory()139 VideoStreamFactory() {}
140
141 private:
CreateEncoderStreams(int width,int height,const VideoEncoderConfig & encoder_config)142 std::vector<VideoStream> CreateEncoderStreams(
143 int width,
144 int height,
145 const VideoEncoderConfig& encoder_config) override {
146 std::vector<VideoStream> streams =
147 test::CreateVideoStreams(width, height, encoder_config);
148 if (encoder_config.number_of_streams == 1) {
149 streams[0].target_bitrate_bps = streams[0].max_bitrate_bps = 2000000;
150 }
151 return streams;
152 }
153 };
154
ModifyVideoConfigs(VideoSendStream::Config * send_config,std::vector<VideoReceiveStream::Config> * receive_configs,VideoEncoderConfig * encoder_config)155 void RampUpTester::ModifyVideoConfigs(
156 VideoSendStream::Config* send_config,
157 std::vector<VideoReceiveStream::Config>* receive_configs,
158 VideoEncoderConfig* encoder_config) {
159 send_config->suspend_below_min_bitrate = true;
160 encoder_config->number_of_streams = num_video_streams_;
161 encoder_config->max_bitrate_bps = 2000000;
162 encoder_config->video_stream_factory =
163 new rtc::RefCountedObject<RampUpTester::VideoStreamFactory>();
164 if (num_video_streams_ == 1) {
165 // For single stream rampup until 1mbps
166 expected_bitrate_bps_ = kSingleStreamTargetBps;
167 } else {
168 // To ensure simulcast rate allocation.
169 send_config->rtp.payload_name = "VP8";
170 encoder_config->codec_type = kVideoCodecVP8;
171 std::vector<VideoStream> streams = test::CreateVideoStreams(
172 test::CallTest::kDefaultWidth, test::CallTest::kDefaultHeight,
173 *encoder_config);
174 // For multi stream rampup until all streams are being sent. That means
175 // enough bitrate to send all the target streams plus the min bitrate of
176 // the last one.
177 expected_bitrate_bps_ = streams.back().min_bitrate_bps;
178 for (size_t i = 0; i < streams.size() - 1; ++i) {
179 expected_bitrate_bps_ += streams[i].target_bitrate_bps;
180 }
181 }
182
183 send_config->rtp.extensions.clear();
184
185 bool remb;
186 bool transport_cc;
187 if (extension_type_ == RtpExtension::kAbsSendTimeUri) {
188 remb = true;
189 transport_cc = false;
190 send_config->rtp.extensions.push_back(
191 RtpExtension(extension_type_.c_str(), kAbsSendTimeExtensionId));
192 } else if (extension_type_ == RtpExtension::kTransportSequenceNumberUri) {
193 remb = false;
194 transport_cc = true;
195 send_config->rtp.extensions.push_back(RtpExtension(
196 extension_type_.c_str(), kTransportSequenceNumberExtensionId));
197 } else {
198 remb = true;
199 transport_cc = false;
200 send_config->rtp.extensions.push_back(RtpExtension(
201 extension_type_.c_str(), kTransmissionTimeOffsetExtensionId));
202 }
203
204 send_config->rtp.nack.rtp_history_ms = test::CallTest::kNackRtpHistoryMs;
205 send_config->rtp.ssrcs = video_ssrcs_;
206 if (rtx_) {
207 send_config->rtp.rtx.payload_type = test::CallTest::kSendRtxPayloadType;
208 send_config->rtp.rtx.ssrcs = video_rtx_ssrcs_;
209 }
210 if (red_) {
211 send_config->rtp.ulpfec.ulpfec_payload_type =
212 test::CallTest::kUlpfecPayloadType;
213 send_config->rtp.ulpfec.red_payload_type = test::CallTest::kRedPayloadType;
214 if (rtx_) {
215 send_config->rtp.ulpfec.red_rtx_payload_type =
216 test::CallTest::kRtxRedPayloadType;
217 }
218 }
219
220 size_t i = 0;
221 for (VideoReceiveStream::Config& recv_config : *receive_configs) {
222 recv_config.rtp.transport_cc = transport_cc;
223 recv_config.rtp.extensions = send_config->rtp.extensions;
224 recv_config.decoders.reserve(1);
225 recv_config.decoders[0].payload_type = send_config->rtp.payload_type;
226 recv_config.decoders[0].video_format =
227 SdpVideoFormat(send_config->rtp.payload_name);
228
229 recv_config.rtp.remote_ssrc = video_ssrcs_[i];
230 recv_config.rtp.nack.rtp_history_ms = send_config->rtp.nack.rtp_history_ms;
231
232 if (red_) {
233 recv_config.rtp.red_payload_type =
234 send_config->rtp.ulpfec.red_payload_type;
235 recv_config.rtp.ulpfec_payload_type =
236 send_config->rtp.ulpfec.ulpfec_payload_type;
237 if (rtx_) {
238 recv_config.rtp.rtx_associated_payload_types
239 [send_config->rtp.ulpfec.red_rtx_payload_type] =
240 send_config->rtp.ulpfec.red_payload_type;
241 }
242 }
243
244 if (rtx_) {
245 recv_config.rtp.rtx_ssrc = video_rtx_ssrcs_[i];
246 recv_config.rtp
247 .rtx_associated_payload_types[send_config->rtp.rtx.payload_type] =
248 send_config->rtp.payload_type;
249 }
250 ++i;
251 }
252
253 RTC_DCHECK_LE(num_flexfec_streams_, 1);
254 if (num_flexfec_streams_ == 1) {
255 send_config->rtp.flexfec.payload_type = test::CallTest::kFlexfecPayloadType;
256 send_config->rtp.flexfec.ssrc = test::CallTest::kFlexfecSendSsrc;
257 send_config->rtp.flexfec.protected_media_ssrcs = {video_ssrcs_[0]};
258 }
259 }
260
ModifyAudioConfigs(AudioSendStream::Config * send_config,std::vector<AudioReceiveStream::Config> * receive_configs)261 void RampUpTester::ModifyAudioConfigs(
262 AudioSendStream::Config* send_config,
263 std::vector<AudioReceiveStream::Config>* receive_configs) {
264 if (num_audio_streams_ == 0)
265 return;
266
267 EXPECT_NE(RtpExtension::kTimestampOffsetUri, extension_type_)
268 << "Audio BWE not supported with toffset.";
269 EXPECT_NE(RtpExtension::kAbsSendTimeUri, extension_type_)
270 << "Audio BWE not supported with abs-send-time.";
271
272 send_config->rtp.ssrc = audio_ssrcs_[0];
273 send_config->rtp.extensions.clear();
274
275 send_config->min_bitrate_bps = 6000;
276 send_config->max_bitrate_bps = 60000;
277
278 bool transport_cc = false;
279 if (extension_type_ == RtpExtension::kTransportSequenceNumberUri) {
280 transport_cc = true;
281 send_config->rtp.extensions.push_back(RtpExtension(
282 extension_type_.c_str(), kTransportSequenceNumberExtensionId));
283 }
284
285 for (AudioReceiveStream::Config& recv_config : *receive_configs) {
286 recv_config.rtp.transport_cc = transport_cc;
287 recv_config.rtp.extensions = send_config->rtp.extensions;
288 recv_config.rtp.remote_ssrc = send_config->rtp.ssrc;
289 }
290 }
291
ModifyFlexfecConfigs(std::vector<FlexfecReceiveStream::Config> * receive_configs)292 void RampUpTester::ModifyFlexfecConfigs(
293 std::vector<FlexfecReceiveStream::Config>* receive_configs) {
294 if (num_flexfec_streams_ == 0)
295 return;
296 RTC_DCHECK_EQ(1, num_flexfec_streams_);
297 (*receive_configs)[0].payload_type = test::CallTest::kFlexfecPayloadType;
298 (*receive_configs)[0].remote_ssrc = test::CallTest::kFlexfecSendSsrc;
299 (*receive_configs)[0].protected_media_ssrcs = {video_ssrcs_[0]};
300 (*receive_configs)[0].local_ssrc = video_ssrcs_[0];
301 if (extension_type_ == RtpExtension::kAbsSendTimeUri) {
302 (*receive_configs)[0].transport_cc = false;
303 (*receive_configs)[0].rtp_header_extensions.push_back(
304 RtpExtension(extension_type_.c_str(), kAbsSendTimeExtensionId));
305 } else if (extension_type_ == RtpExtension::kTransportSequenceNumberUri) {
306 (*receive_configs)[0].transport_cc = true;
307 (*receive_configs)[0].rtp_header_extensions.push_back(RtpExtension(
308 extension_type_.c_str(), kTransportSequenceNumberExtensionId));
309 }
310 }
311
OnCallsCreated(Call * sender_call,Call * receiver_call)312 void RampUpTester::OnCallsCreated(Call* sender_call, Call* receiver_call) {
313 RTC_DCHECK(sender_call);
314 sender_call_ = sender_call;
315 pending_task_ = RepeatingTaskHandle::Start(task_queue_, [this] {
316 PollStats();
317 return kPollInterval;
318 });
319 }
320
PollStats()321 void RampUpTester::PollStats() {
322 RTC_DCHECK_RUN_ON(task_queue_);
323
324 Call::Stats stats = sender_call_->GetStats();
325 EXPECT_GE(expected_bitrate_bps_, 0);
326
327 if (stats.send_bandwidth_bps >= expected_bitrate_bps_ &&
328 (min_run_time_ms_ == -1 ||
329 clock_->TimeInMilliseconds() - test_start_ms_ >= min_run_time_ms_)) {
330 ramp_up_finished_ms_ = clock_->TimeInMilliseconds();
331 observation_complete_.Set();
332 pending_task_.Stop();
333 }
334 }
335
ReportResult(const std::string & measurement,size_t value,const std::string & units) const336 void RampUpTester::ReportResult(const std::string& measurement,
337 size_t value,
338 const std::string& units) const {
339 webrtc::test::PrintResult(
340 measurement, "",
341 ::testing::UnitTest::GetInstance()->current_test_info()->name(), value,
342 units, false);
343 }
344
AccumulateStats(const VideoSendStream::StreamStats & stream,size_t * total_packets_sent,size_t * total_sent,size_t * padding_sent,size_t * media_sent) const345 void RampUpTester::AccumulateStats(const VideoSendStream::StreamStats& stream,
346 size_t* total_packets_sent,
347 size_t* total_sent,
348 size_t* padding_sent,
349 size_t* media_sent) const {
350 *total_packets_sent += stream.rtp_stats.transmitted.packets +
351 stream.rtp_stats.retransmitted.packets +
352 stream.rtp_stats.fec.packets;
353 *total_sent += stream.rtp_stats.transmitted.TotalBytes() +
354 stream.rtp_stats.retransmitted.TotalBytes() +
355 stream.rtp_stats.fec.TotalBytes();
356 *padding_sent += stream.rtp_stats.transmitted.padding_bytes +
357 stream.rtp_stats.retransmitted.padding_bytes +
358 stream.rtp_stats.fec.padding_bytes;
359 *media_sent += stream.rtp_stats.MediaPayloadBytes();
360 }
361
TriggerTestDone()362 void RampUpTester::TriggerTestDone() {
363 RTC_DCHECK_GE(test_start_ms_, 0);
364
365 // Stop polling stats.
366 // Corner case for field_trials=WebRTC-QuickPerfTest/Enabled/
367 SendTask(RTC_FROM_HERE, task_queue_, [this] { pending_task_.Stop(); });
368
369 // TODO(holmer): Add audio send stats here too when those APIs are available.
370 if (!send_stream_)
371 return;
372
373 VideoSendStream::Stats send_stats = send_stream_->GetStats();
374 send_stream_ = nullptr; // To avoid dereferencing a bad pointer.
375
376 size_t total_packets_sent = 0;
377 size_t total_sent = 0;
378 size_t padding_sent = 0;
379 size_t media_sent = 0;
380 for (uint32_t ssrc : video_ssrcs_) {
381 AccumulateStats(send_stats.substreams[ssrc], &total_packets_sent,
382 &total_sent, &padding_sent, &media_sent);
383 }
384
385 size_t rtx_total_packets_sent = 0;
386 size_t rtx_total_sent = 0;
387 size_t rtx_padding_sent = 0;
388 size_t rtx_media_sent = 0;
389 for (uint32_t rtx_ssrc : video_rtx_ssrcs_) {
390 AccumulateStats(send_stats.substreams[rtx_ssrc], &rtx_total_packets_sent,
391 &rtx_total_sent, &rtx_padding_sent, &rtx_media_sent);
392 }
393
394 if (report_perf_stats_) {
395 ReportResult("ramp-up-media-sent", media_sent, "bytes");
396 ReportResult("ramp-up-padding-sent", padding_sent, "bytes");
397 ReportResult("ramp-up-rtx-media-sent", rtx_media_sent, "bytes");
398 ReportResult("ramp-up-rtx-padding-sent", rtx_padding_sent, "bytes");
399 if (ramp_up_finished_ms_ >= 0) {
400 ReportResult("ramp-up-time", ramp_up_finished_ms_ - test_start_ms_,
401 "milliseconds");
402 }
403 ReportResult("ramp-up-average-network-latency",
404 send_transport_->GetAverageDelayMs(), "milliseconds");
405 }
406 }
407
PerformTest()408 void RampUpTester::PerformTest() {
409 test_start_ms_ = clock_->TimeInMilliseconds();
410 EXPECT_TRUE(Wait()) << "Timed out while waiting for ramp-up to complete.";
411 TriggerTestDone();
412 }
413
RampUpDownUpTester(size_t num_video_streams,size_t num_audio_streams,size_t num_flexfec_streams,unsigned int start_bitrate_bps,const std::string & extension_type,bool rtx,bool red,const std::vector<int> & loss_rates,bool report_perf_stats,TaskQueueBase * task_queue)414 RampUpDownUpTester::RampUpDownUpTester(size_t num_video_streams,
415 size_t num_audio_streams,
416 size_t num_flexfec_streams,
417 unsigned int start_bitrate_bps,
418 const std::string& extension_type,
419 bool rtx,
420 bool red,
421 const std::vector<int>& loss_rates,
422 bool report_perf_stats,
423 TaskQueueBase* task_queue)
424 : RampUpTester(num_video_streams,
425 num_audio_streams,
426 num_flexfec_streams,
427 start_bitrate_bps,
428 0,
429 extension_type,
430 rtx,
431 red,
432 report_perf_stats,
433 task_queue),
434 link_rates_({4 * GetExpectedHighBitrate() / (3 * 1000),
435 kLowBandwidthLimitBps / 1000,
436 4 * GetExpectedHighBitrate() / (3 * 1000), 0}),
437 test_state_(kFirstRampup),
438 next_state_(kTransitionToNextState),
439 state_start_ms_(clock_->TimeInMilliseconds()),
440 interval_start_ms_(clock_->TimeInMilliseconds()),
441 sent_bytes_(0),
442 loss_rates_(loss_rates) {
443 forward_transport_config_.link_capacity_kbps = link_rates_[test_state_];
444 forward_transport_config_.queue_delay_ms = 100;
445 forward_transport_config_.loss_percent = loss_rates_[test_state_];
446 }
447
~RampUpDownUpTester()448 RampUpDownUpTester::~RampUpDownUpTester() {}
449
PollStats()450 void RampUpDownUpTester::PollStats() {
451 if (test_state_ == kTestEnd) {
452 pending_task_.Stop();
453 }
454
455 int transmit_bitrate_bps = 0;
456 bool suspended = false;
457 if (num_video_streams_ > 0 && send_stream_) {
458 webrtc::VideoSendStream::Stats stats = send_stream_->GetStats();
459 for (const auto& it : stats.substreams) {
460 transmit_bitrate_bps += it.second.total_bitrate_bps;
461 }
462 suspended = stats.suspended;
463 }
464 if (num_audio_streams_ > 0 && sender_call_) {
465 // An audio send stream doesn't have bitrate stats, so the call send BW is
466 // currently used instead.
467 transmit_bitrate_bps = sender_call_->GetStats().send_bandwidth_bps;
468 }
469
470 EvolveTestState(transmit_bitrate_bps, suspended);
471 }
472
ModifyReceiverBitrateConfig(BitrateConstraints * bitrate_config)473 void RampUpDownUpTester::ModifyReceiverBitrateConfig(
474 BitrateConstraints* bitrate_config) {
475 bitrate_config->min_bitrate_bps = 10000;
476 }
477
GetModifierString() const478 std::string RampUpDownUpTester::GetModifierString() const {
479 std::string str("_");
480 if (num_video_streams_ > 0) {
481 str += rtc::ToString(num_video_streams_);
482 str += "stream";
483 str += (num_video_streams_ > 1 ? "s" : "");
484 str += "_";
485 }
486 if (num_audio_streams_ > 0) {
487 str += rtc::ToString(num_audio_streams_);
488 str += "stream";
489 str += (num_audio_streams_ > 1 ? "s" : "");
490 str += "_";
491 }
492 str += (rtx_ ? "" : "no");
493 str += "rtx_";
494 str += (red_ ? "" : "no");
495 str += "red";
496 return str;
497 }
498
GetExpectedHighBitrate() const499 int RampUpDownUpTester::GetExpectedHighBitrate() const {
500 int expected_bitrate_bps = 0;
501 if (num_audio_streams_ > 0)
502 expected_bitrate_bps += kExpectedHighAudioBitrateBps;
503 if (num_video_streams_ > 0)
504 expected_bitrate_bps += kExpectedHighVideoBitrateBps;
505 return expected_bitrate_bps;
506 }
507
GetFecBytes() const508 size_t RampUpDownUpTester::GetFecBytes() const {
509 size_t flex_fec_bytes = 0;
510 if (num_flexfec_streams_ > 0) {
511 webrtc::VideoSendStream::Stats stats = send_stream_->GetStats();
512 for (const auto& kv : stats.substreams)
513 flex_fec_bytes += kv.second.rtp_stats.fec.TotalBytes();
514 }
515 return flex_fec_bytes;
516 }
517
ExpectingFec() const518 bool RampUpDownUpTester::ExpectingFec() const {
519 return num_flexfec_streams_ > 0 && forward_transport_config_.loss_percent > 0;
520 }
521
EvolveTestState(int bitrate_bps,bool suspended)522 void RampUpDownUpTester::EvolveTestState(int bitrate_bps, bool suspended) {
523 int64_t now = clock_->TimeInMilliseconds();
524 switch (test_state_) {
525 case kFirstRampup:
526 EXPECT_FALSE(suspended);
527 if (bitrate_bps >= GetExpectedHighBitrate()) {
528 if (report_perf_stats_) {
529 webrtc::test::PrintResult("ramp_up_down_up", GetModifierString(),
530 "first_rampup", now - state_start_ms_, "ms",
531 false);
532 }
533 // Apply loss during the transition between states if FEC is enabled.
534 forward_transport_config_.loss_percent = loss_rates_[test_state_];
535 test_state_ = kTransitionToNextState;
536 next_state_ = kLowRate;
537 }
538 break;
539 case kLowRate: {
540 // Audio streams are never suspended.
541 bool check_suspend_state = num_video_streams_ > 0;
542 if (bitrate_bps < kLowBandwidthLimitBps + kLowBitrateMarginBps &&
543 suspended == check_suspend_state) {
544 if (report_perf_stats_) {
545 webrtc::test::PrintResult("ramp_up_down_up", GetModifierString(),
546 "rampdown", now - state_start_ms_, "ms",
547 false);
548 }
549 // Apply loss during the transition between states if FEC is enabled.
550 forward_transport_config_.loss_percent = loss_rates_[test_state_];
551 test_state_ = kTransitionToNextState;
552 next_state_ = kSecondRampup;
553 }
554 break;
555 }
556 case kSecondRampup:
557 if (bitrate_bps >= GetExpectedHighBitrate() && !suspended) {
558 if (report_perf_stats_) {
559 webrtc::test::PrintResult("ramp_up_down_up", GetModifierString(),
560 "second_rampup", now - state_start_ms_,
561 "ms", false);
562 ReportResult("ramp-up-down-up-average-network-latency",
563 send_transport_->GetAverageDelayMs(), "milliseconds");
564 }
565 // Apply loss during the transition between states if FEC is enabled.
566 forward_transport_config_.loss_percent = loss_rates_[test_state_];
567 test_state_ = kTransitionToNextState;
568 next_state_ = kTestEnd;
569 }
570 break;
571 case kTestEnd:
572 observation_complete_.Set();
573 break;
574 case kTransitionToNextState:
575 if (!ExpectingFec() || GetFecBytes() > 0) {
576 test_state_ = next_state_;
577 forward_transport_config_.link_capacity_kbps = link_rates_[test_state_];
578 // No loss while ramping up and down as it may affect the BWE
579 // negatively, making the test flaky.
580 forward_transport_config_.loss_percent = 0;
581 state_start_ms_ = now;
582 interval_start_ms_ = now;
583 sent_bytes_ = 0;
584 send_simulated_network_->SetConfig(forward_transport_config_);
585 }
586 break;
587 }
588 }
589
590 class RampUpTest : public test::CallTest {
591 public:
RampUpTest()592 RampUpTest()
593 : task_queue_factory_(CreateDefaultTaskQueueFactory()),
594 rtc_event_log_factory_(task_queue_factory_.get()) {
595 std::string dump_name(absl::GetFlag(FLAGS_ramp_dump_name));
596 if (!dump_name.empty()) {
597 send_event_log_ = rtc_event_log_factory_.CreateRtcEventLog(
598 RtcEventLog::EncodingType::Legacy);
599 recv_event_log_ = rtc_event_log_factory_.CreateRtcEventLog(
600 RtcEventLog::EncodingType::Legacy);
601 bool event_log_started =
602 send_event_log_->StartLogging(
603 std::make_unique<RtcEventLogOutputFile>(
604 dump_name + ".send.rtc.dat", RtcEventLog::kUnlimitedOutput),
605 RtcEventLog::kImmediateOutput) &&
606 recv_event_log_->StartLogging(
607 std::make_unique<RtcEventLogOutputFile>(
608 dump_name + ".recv.rtc.dat", RtcEventLog::kUnlimitedOutput),
609 RtcEventLog::kImmediateOutput);
610 RTC_DCHECK(event_log_started);
611 }
612 }
613
614 private:
615 const std::unique_ptr<TaskQueueFactory> task_queue_factory_;
616 RtcEventLogFactory rtc_event_log_factory_;
617 };
618
619 static const uint32_t kStartBitrateBps = 60000;
620
TEST_F(RampUpTest,UpDownUpAbsSendTimeSimulcastRedRtx)621 TEST_F(RampUpTest, UpDownUpAbsSendTimeSimulcastRedRtx) {
622 std::vector<int> loss_rates = {0, 0, 0, 0};
623 RampUpDownUpTester test(3, 0, 0, kStartBitrateBps,
624 RtpExtension::kAbsSendTimeUri, true, true, loss_rates,
625 true, task_queue());
626 RunBaseTest(&test);
627 }
628
629 // TODO(bugs.webrtc.org/8878)
630 #if defined(WEBRTC_MAC)
631 #define MAYBE_UpDownUpTransportSequenceNumberRtx \
632 DISABLED_UpDownUpTransportSequenceNumberRtx
633 #else
634 #define MAYBE_UpDownUpTransportSequenceNumberRtx \
635 UpDownUpTransportSequenceNumberRtx
636 #endif
TEST_F(RampUpTest,MAYBE_UpDownUpTransportSequenceNumberRtx)637 TEST_F(RampUpTest, MAYBE_UpDownUpTransportSequenceNumberRtx) {
638 std::vector<int> loss_rates = {0, 0, 0, 0};
639 RampUpDownUpTester test(3, 0, 0, kStartBitrateBps,
640 RtpExtension::kTransportSequenceNumberUri, true,
641 false, loss_rates, true, task_queue());
642 RunBaseTest(&test);
643 }
644
645 // TODO(holmer): Tests which don't report perf stats should be moved to a
646 // different executable since they per definition are not perf tests.
647 // This test is disabled because it crashes on Linux, and is flaky on other
648 // platforms. See: crbug.com/webrtc/7919
TEST_F(RampUpTest,DISABLED_UpDownUpTransportSequenceNumberPacketLoss)649 TEST_F(RampUpTest, DISABLED_UpDownUpTransportSequenceNumberPacketLoss) {
650 std::vector<int> loss_rates = {20, 0, 0, 0};
651 RampUpDownUpTester test(1, 0, 1, kStartBitrateBps,
652 RtpExtension::kTransportSequenceNumberUri, true,
653 false, loss_rates, false, task_queue());
654 RunBaseTest(&test);
655 }
656
657 // TODO(bugs.webrtc.org/8878)
658 #if defined(WEBRTC_MAC)
659 #define MAYBE_UpDownUpAudioVideoTransportSequenceNumberRtx \
660 DISABLED_UpDownUpAudioVideoTransportSequenceNumberRtx
661 #else
662 #define MAYBE_UpDownUpAudioVideoTransportSequenceNumberRtx \
663 UpDownUpAudioVideoTransportSequenceNumberRtx
664 #endif
TEST_F(RampUpTest,MAYBE_UpDownUpAudioVideoTransportSequenceNumberRtx)665 TEST_F(RampUpTest, MAYBE_UpDownUpAudioVideoTransportSequenceNumberRtx) {
666 test::ScopedFieldTrials field_trials("WebRTC-Audio-SendSideBwe/Enabled/");
667 std::vector<int> loss_rates = {0, 0, 0, 0};
668 RampUpDownUpTester test(3, 1, 0, kStartBitrateBps,
669 RtpExtension::kTransportSequenceNumberUri, true,
670 false, loss_rates, false, task_queue());
671 RunBaseTest(&test);
672 }
673
TEST_F(RampUpTest,UpDownUpAudioTransportSequenceNumberRtx)674 TEST_F(RampUpTest, UpDownUpAudioTransportSequenceNumberRtx) {
675 test::ScopedFieldTrials field_trials("WebRTC-Audio-SendSideBwe/Enabled/");
676 std::vector<int> loss_rates = {0, 0, 0, 0};
677 RampUpDownUpTester test(0, 1, 0, kStartBitrateBps,
678 RtpExtension::kTransportSequenceNumberUri, true,
679 false, loss_rates, false, task_queue());
680 RunBaseTest(&test);
681 }
682
TEST_F(RampUpTest,TOffsetSimulcastRedRtx)683 TEST_F(RampUpTest, TOffsetSimulcastRedRtx) {
684 RampUpTester test(3, 0, 0, 0, 0, RtpExtension::kTimestampOffsetUri, true,
685 true, true, task_queue());
686 RunBaseTest(&test);
687 }
688
TEST_F(RampUpTest,AbsSendTime)689 TEST_F(RampUpTest, AbsSendTime) {
690 RampUpTester test(1, 0, 0, 0, 0, RtpExtension::kAbsSendTimeUri, false, false,
691 false, task_queue());
692 RunBaseTest(&test);
693 }
694
TEST_F(RampUpTest,AbsSendTimeSimulcastRedRtx)695 TEST_F(RampUpTest, AbsSendTimeSimulcastRedRtx) {
696 RampUpTester test(3, 0, 0, 0, 0, RtpExtension::kAbsSendTimeUri, true, true,
697 true, task_queue());
698 RunBaseTest(&test);
699 }
700
TEST_F(RampUpTest,TransportSequenceNumber)701 TEST_F(RampUpTest, TransportSequenceNumber) {
702 RampUpTester test(1, 0, 0, 0, 0, RtpExtension::kTransportSequenceNumberUri,
703 false, false, false, task_queue());
704 RunBaseTest(&test);
705 }
706
TEST_F(RampUpTest,TransportSequenceNumberSimulcast)707 TEST_F(RampUpTest, TransportSequenceNumberSimulcast) {
708 RampUpTester test(3, 0, 0, 0, 0, RtpExtension::kTransportSequenceNumberUri,
709 false, false, false, task_queue());
710 RunBaseTest(&test);
711 }
712
TEST_F(RampUpTest,TransportSequenceNumberSimulcastRedRtx)713 TEST_F(RampUpTest, TransportSequenceNumberSimulcastRedRtx) {
714 RampUpTester test(3, 0, 0, 0, 0, RtpExtension::kTransportSequenceNumberUri,
715 true, true, true, task_queue());
716 RunBaseTest(&test);
717 }
718
TEST_F(RampUpTest,AudioTransportSequenceNumber)719 TEST_F(RampUpTest, AudioTransportSequenceNumber) {
720 RampUpTester test(0, 1, 0, 300000, 10000,
721 RtpExtension::kTransportSequenceNumberUri, false, false,
722 false, task_queue());
723 RunBaseTest(&test);
724 }
725 } // namespace webrtc
726