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