• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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