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 "testing/gtest/include/gtest/gtest.h"
12 #include "webrtc/base/checks.h"
13 #include "webrtc/base/common.h"
14 #include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h"
15 #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
16 #include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
17 #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
18 #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
19 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
20 #include "webrtc/test/testsupport/perf_test.h"
21 #include "webrtc/video/rampup_tests.h"
22
23 namespace webrtc {
24 namespace {
25
26 static const int kMaxPacketSize = 1500;
27
GenerateSsrcs(size_t num_streams,uint32_t ssrc_offset)28 std::vector<uint32_t> GenerateSsrcs(size_t num_streams,
29 uint32_t ssrc_offset) {
30 std::vector<uint32_t> ssrcs;
31 for (size_t i = 0; i != num_streams; ++i)
32 ssrcs.push_back(static_cast<uint32_t>(ssrc_offset + i));
33 return ssrcs;
34 }
35 } // namespace
36
StreamObserver(const SsrcMap & rtx_media_ssrcs,newapi::Transport * feedback_transport,Clock * clock,RemoteBitrateEstimatorFactory * rbe_factory,RateControlType control_type)37 StreamObserver::StreamObserver(const SsrcMap& rtx_media_ssrcs,
38 newapi::Transport* feedback_transport,
39 Clock* clock,
40 RemoteBitrateEstimatorFactory* rbe_factory,
41 RateControlType control_type)
42 : clock_(clock),
43 test_done_(EventWrapper::Create()),
44 rtp_parser_(RtpHeaderParser::Create()),
45 feedback_transport_(feedback_transport),
46 receive_stats_(ReceiveStatistics::Create(clock)),
47 payload_registry_(
48 new RTPPayloadRegistry(RTPPayloadStrategy::CreateStrategy(false))),
49 crit_(CriticalSectionWrapper::CreateCriticalSection()),
50 expected_bitrate_bps_(0),
51 start_bitrate_bps_(0),
52 rtx_media_ssrcs_(rtx_media_ssrcs),
53 total_sent_(0),
54 padding_sent_(0),
55 rtx_media_sent_(0),
56 total_packets_sent_(0),
57 padding_packets_sent_(0),
58 rtx_media_packets_sent_(0),
59 test_start_ms_(clock_->TimeInMilliseconds()),
60 ramp_up_finished_ms_(0) {
61 // Ideally we would only have to instantiate an RtcpSender, an
62 // RtpHeaderParser and a RemoteBitrateEstimator here, but due to the current
63 // state of the RTP module we need a full module and receive statistics to
64 // be able to produce an RTCP with REMB.
65 RtpRtcp::Configuration config;
66 config.receive_statistics = receive_stats_.get();
67 feedback_transport_.Enable();
68 config.outgoing_transport = &feedback_transport_;
69 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
70 rtp_rtcp_->SetREMBStatus(true);
71 rtp_rtcp_->SetRTCPStatus(kRtcpNonCompound);
72 rtp_parser_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
73 kAbsSendTimeExtensionId);
74 rtp_parser_->RegisterRtpHeaderExtension(kRtpExtensionTransmissionTimeOffset,
75 kTransmissionTimeOffsetExtensionId);
76 const uint32_t kRemoteBitrateEstimatorMinBitrateBps = 30000;
77 remote_bitrate_estimator_.reset(
78 rbe_factory->Create(this, clock, control_type,
79 kRemoteBitrateEstimatorMinBitrateBps));
80 }
81
set_expected_bitrate_bps(unsigned int expected_bitrate_bps)82 void StreamObserver::set_expected_bitrate_bps(
83 unsigned int expected_bitrate_bps) {
84 CriticalSectionScoped lock(crit_.get());
85 expected_bitrate_bps_ = expected_bitrate_bps;
86 }
87
set_start_bitrate_bps(unsigned int start_bitrate_bps)88 void StreamObserver::set_start_bitrate_bps(unsigned int start_bitrate_bps) {
89 CriticalSectionScoped lock(crit_.get());
90 start_bitrate_bps_ = start_bitrate_bps;
91 }
92
OnReceiveBitrateChanged(const std::vector<unsigned int> & ssrcs,unsigned int bitrate)93 void StreamObserver::OnReceiveBitrateChanged(
94 const std::vector<unsigned int>& ssrcs, unsigned int bitrate) {
95 CriticalSectionScoped lock(crit_.get());
96 DCHECK_GT(expected_bitrate_bps_, 0u);
97 if (start_bitrate_bps_ != 0) {
98 // For tests with an explicitly set start bitrate, verify the first
99 // bitrate estimate is close to the start bitrate and lower than the
100 // test target bitrate. This is to verify a call respects the configured
101 // start bitrate, but due to the BWE implementation we can't guarantee the
102 // first estimate really is as high as the start bitrate.
103 EXPECT_GT(bitrate, 0.9 * start_bitrate_bps_);
104 start_bitrate_bps_ = 0;
105 }
106 if (bitrate >= expected_bitrate_bps_) {
107 ramp_up_finished_ms_ = clock_->TimeInMilliseconds();
108 // Just trigger if there was any rtx padding packet.
109 if (rtx_media_ssrcs_.empty() || rtx_media_sent_ > 0) {
110 TriggerTestDone();
111 }
112 }
113 rtp_rtcp_->SetREMBData(bitrate, ssrcs);
114 rtp_rtcp_->Process();
115 }
116
SendRtp(const uint8_t * packet,size_t length)117 bool StreamObserver::SendRtp(const uint8_t* packet, size_t length) {
118 CriticalSectionScoped lock(crit_.get());
119 RTPHeader header;
120 EXPECT_TRUE(rtp_parser_->Parse(packet, length, &header));
121 receive_stats_->IncomingPacket(header, length, false);
122 payload_registry_->SetIncomingPayloadType(header);
123 remote_bitrate_estimator_->IncomingPacket(
124 clock_->TimeInMilliseconds(), length - 12, header);
125 if (remote_bitrate_estimator_->TimeUntilNextProcess() <= 0) {
126 remote_bitrate_estimator_->Process();
127 }
128 total_sent_ += length;
129 padding_sent_ += header.paddingLength;
130 ++total_packets_sent_;
131 if (header.paddingLength > 0)
132 ++padding_packets_sent_;
133 if (rtx_media_ssrcs_.find(header.ssrc) != rtx_media_ssrcs_.end()) {
134 rtx_media_sent_ += length - header.headerLength - header.paddingLength;
135 if (header.paddingLength == 0)
136 ++rtx_media_packets_sent_;
137 uint8_t restored_packet[kMaxPacketSize];
138 uint8_t* restored_packet_ptr = restored_packet;
139 size_t restored_length = length;
140 payload_registry_->RestoreOriginalPacket(&restored_packet_ptr,
141 packet,
142 &restored_length,
143 rtx_media_ssrcs_[header.ssrc],
144 header);
145 length = restored_length;
146 EXPECT_TRUE(rtp_parser_->Parse(
147 restored_packet, static_cast<int>(length), &header));
148 } else {
149 rtp_rtcp_->SetRemoteSSRC(header.ssrc);
150 }
151 return true;
152 }
153
SendRtcp(const uint8_t * packet,size_t length)154 bool StreamObserver::SendRtcp(const uint8_t* packet, size_t length) {
155 return true;
156 }
157
Wait()158 EventTypeWrapper StreamObserver::Wait() {
159 return test_done_->Wait(test::CallTest::kLongTimeoutMs);
160 }
161
ReportResult(const std::string & measurement,size_t value,const std::string & units)162 void StreamObserver::ReportResult(const std::string& measurement,
163 size_t value,
164 const std::string& units) {
165 webrtc::test::PrintResult(
166 measurement, "",
167 ::testing::UnitTest::GetInstance()->current_test_info()->name(),
168 value, units, false);
169 }
170
TriggerTestDone()171 void StreamObserver::TriggerTestDone() EXCLUSIVE_LOCKS_REQUIRED(crit_) {
172 ReportResult("ramp-up-total-sent", total_sent_, "bytes");
173 ReportResult("ramp-up-padding-sent", padding_sent_, "bytes");
174 ReportResult("ramp-up-rtx-media-sent", rtx_media_sent_, "bytes");
175 ReportResult("ramp-up-total-packets-sent", total_packets_sent_, "packets");
176 ReportResult("ramp-up-padding-packets-sent",
177 padding_packets_sent_,
178 "packets");
179 ReportResult("ramp-up-rtx-packets-sent",
180 rtx_media_packets_sent_,
181 "packets");
182 ReportResult("ramp-up-time",
183 ramp_up_finished_ms_ - test_start_ms_,
184 "milliseconds");
185 test_done_->Set();
186 }
187
LowRateStreamObserver(newapi::Transport * feedback_transport,Clock * clock,size_t number_of_streams,bool rtx_used)188 LowRateStreamObserver::LowRateStreamObserver(
189 newapi::Transport* feedback_transport,
190 Clock* clock,
191 size_t number_of_streams,
192 bool rtx_used)
193 : clock_(clock),
194 number_of_streams_(number_of_streams),
195 rtx_used_(rtx_used),
196 test_done_(EventWrapper::Create()),
197 rtp_parser_(RtpHeaderParser::Create()),
198 feedback_transport_(feedback_transport),
199 receive_stats_(ReceiveStatistics::Create(clock)),
200 crit_(CriticalSectionWrapper::CreateCriticalSection()),
201 send_stream_(nullptr),
202 test_state_(kFirstRampup),
203 state_start_ms_(clock_->TimeInMilliseconds()),
204 interval_start_ms_(state_start_ms_),
205 last_remb_bps_(0),
206 sent_bytes_(0),
207 total_overuse_bytes_(0),
208 suspended_in_stats_(false) {
209 RtpRtcp::Configuration config;
210 config.receive_statistics = receive_stats_.get();
211 feedback_transport_.Enable();
212 config.outgoing_transport = &feedback_transport_;
213 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
214 rtp_rtcp_->SetREMBStatus(true);
215 rtp_rtcp_->SetRTCPStatus(kRtcpNonCompound);
216 rtp_parser_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
217 kAbsSendTimeExtensionId);
218 AbsoluteSendTimeRemoteBitrateEstimatorFactory rbe_factory;
219 const uint32_t kRemoteBitrateEstimatorMinBitrateBps = 10000;
220 remote_bitrate_estimator_.reset(
221 rbe_factory.Create(this, clock, kAimdControl,
222 kRemoteBitrateEstimatorMinBitrateBps));
223 forward_transport_config_.link_capacity_kbps =
224 kHighBandwidthLimitBps / 1000;
225 forward_transport_config_.queue_length_packets = 100; // Something large.
226 test::DirectTransport::SetConfig(forward_transport_config_);
227 test::DirectTransport::SetReceiver(this);
228 }
229
SetSendStream(VideoSendStream * send_stream)230 void LowRateStreamObserver::SetSendStream(VideoSendStream* send_stream) {
231 CriticalSectionScoped lock(crit_.get());
232 send_stream_ = send_stream;
233 }
234
OnReceiveBitrateChanged(const std::vector<unsigned int> & ssrcs,unsigned int bitrate)235 void LowRateStreamObserver::OnReceiveBitrateChanged(
236 const std::vector<unsigned int>& ssrcs,
237 unsigned int bitrate) {
238 CriticalSectionScoped lock(crit_.get());
239 rtp_rtcp_->SetREMBData(bitrate, ssrcs);
240 rtp_rtcp_->Process();
241 last_remb_bps_ = bitrate;
242 }
243
SendRtp(const uint8_t * data,size_t length)244 bool LowRateStreamObserver::SendRtp(const uint8_t* data, size_t length) {
245 CriticalSectionScoped lock(crit_.get());
246 sent_bytes_ += length;
247 int64_t now_ms = clock_->TimeInMilliseconds();
248 if (now_ms > interval_start_ms_ + 1000) { // Let at least 1 second pass.
249 // Verify that the send rate was about right.
250 unsigned int average_rate_bps = static_cast<unsigned int>(sent_bytes_) *
251 8 * 1000 / (now_ms - interval_start_ms_);
252 // TODO(holmer): Why is this failing?
253 // EXPECT_LT(average_rate_bps, last_remb_bps_ * 1.1);
254 if (average_rate_bps > last_remb_bps_ * 1.1) {
255 total_overuse_bytes_ +=
256 sent_bytes_ -
257 last_remb_bps_ / 8 * (now_ms - interval_start_ms_) / 1000;
258 }
259 EvolveTestState(average_rate_bps);
260 interval_start_ms_ = now_ms;
261 sent_bytes_ = 0;
262 }
263 return test::DirectTransport::SendRtp(data, length);
264 }
265
DeliverPacket(const uint8_t * packet,size_t length)266 PacketReceiver::DeliveryStatus LowRateStreamObserver::DeliverPacket(
267 const uint8_t* packet, size_t length) {
268 CriticalSectionScoped lock(crit_.get());
269 RTPHeader header;
270 EXPECT_TRUE(rtp_parser_->Parse(packet, length, &header));
271 receive_stats_->IncomingPacket(header, length, false);
272 remote_bitrate_estimator_->IncomingPacket(
273 clock_->TimeInMilliseconds(), length - 12, header);
274 if (remote_bitrate_estimator_->TimeUntilNextProcess() <= 0) {
275 remote_bitrate_estimator_->Process();
276 }
277 suspended_in_stats_ = send_stream_->GetStats().suspended;
278 return DELIVERY_OK;
279 }
280
SendRtcp(const uint8_t * packet,size_t length)281 bool LowRateStreamObserver::SendRtcp(const uint8_t* packet, size_t length) {
282 return true;
283 }
284
GetModifierString()285 std::string LowRateStreamObserver::GetModifierString() {
286 std::string str("_");
287 char temp_str[5];
288 sprintf(temp_str, "%i",
289 static_cast<int>(number_of_streams_));
290 str += std::string(temp_str);
291 str += "stream";
292 str += (number_of_streams_ > 1 ? "s" : "");
293 str += "_";
294 str += (rtx_used_ ? "" : "no");
295 str += "rtx";
296 return str;
297 }
298
EvolveTestState(unsigned int bitrate_bps)299 void LowRateStreamObserver::EvolveTestState(unsigned int bitrate_bps) {
300 int64_t now = clock_->TimeInMilliseconds();
301 CriticalSectionScoped lock(crit_.get());
302 DCHECK(send_stream_ != nullptr);
303 switch (test_state_) {
304 case kFirstRampup: {
305 EXPECT_FALSE(suspended_in_stats_);
306 if (bitrate_bps > kExpectedHighBitrateBps) {
307 // The first ramp-up has reached the target bitrate. Change the
308 // channel limit, and move to the next test state.
309 forward_transport_config_.link_capacity_kbps =
310 kLowBandwidthLimitBps / 1000;
311 test::DirectTransport::SetConfig(forward_transport_config_);
312 test_state_ = kLowRate;
313 webrtc::test::PrintResult("ramp_up_down_up",
314 GetModifierString(),
315 "first_rampup",
316 now - state_start_ms_,
317 "ms",
318 false);
319 state_start_ms_ = now;
320 interval_start_ms_ = now;
321 sent_bytes_ = 0;
322 }
323 break;
324 }
325 case kLowRate: {
326 if (bitrate_bps < kExpectedLowBitrateBps && suspended_in_stats_) {
327 // The ramp-down was successful. Change the channel limit back to a
328 // high value, and move to the next test state.
329 forward_transport_config_.link_capacity_kbps =
330 kHighBandwidthLimitBps / 1000;
331 test::DirectTransport::SetConfig(forward_transport_config_);
332 test_state_ = kSecondRampup;
333 webrtc::test::PrintResult("ramp_up_down_up",
334 GetModifierString(),
335 "rampdown",
336 now - state_start_ms_,
337 "ms",
338 false);
339 state_start_ms_ = now;
340 interval_start_ms_ = now;
341 sent_bytes_ = 0;
342 }
343 break;
344 }
345 case kSecondRampup: {
346 if (bitrate_bps > kExpectedHighBitrateBps && !suspended_in_stats_) {
347 webrtc::test::PrintResult("ramp_up_down_up",
348 GetModifierString(),
349 "second_rampup",
350 now - state_start_ms_,
351 "ms",
352 false);
353 webrtc::test::PrintResult("ramp_up_down_up",
354 GetModifierString(),
355 "total_overuse",
356 total_overuse_bytes_,
357 "bytes",
358 false);
359 test_done_->Set();
360 }
361 break;
362 }
363 }
364 }
365
Wait()366 EventTypeWrapper LowRateStreamObserver::Wait() {
367 return test_done_->Wait(test::CallTest::kLongTimeoutMs);
368 }
369
RunRampUpTest(bool rtx,size_t num_streams,unsigned int start_bitrate_bps,const std::string & extension_type)370 void RampUpTest::RunRampUpTest(bool rtx,
371 size_t num_streams,
372 unsigned int start_bitrate_bps,
373 const std::string& extension_type) {
374 std::vector<uint32_t> ssrcs(GenerateSsrcs(num_streams, 100));
375 std::vector<uint32_t> rtx_ssrcs(GenerateSsrcs(num_streams, 200));
376 StreamObserver::SsrcMap rtx_ssrc_map;
377 if (rtx) {
378 for (size_t i = 0; i < ssrcs.size(); ++i)
379 rtx_ssrc_map[rtx_ssrcs[i]] = ssrcs[i];
380 }
381
382 CreateSendConfig(num_streams);
383
384 rtc::scoped_ptr<RemoteBitrateEstimatorFactory> rbe_factory;
385 RateControlType control_type;
386 if (extension_type == RtpExtension::kAbsSendTime) {
387 control_type = kAimdControl;
388 rbe_factory.reset(new AbsoluteSendTimeRemoteBitrateEstimatorFactory);
389 send_config_.rtp.extensions.push_back(RtpExtension(
390 extension_type.c_str(), kAbsSendTimeExtensionId));
391 } else {
392 control_type = kMimdControl;
393 rbe_factory.reset(new RemoteBitrateEstimatorFactory);
394 send_config_.rtp.extensions.push_back(RtpExtension(
395 extension_type.c_str(), kTransmissionTimeOffsetExtensionId));
396 }
397
398 test::DirectTransport receiver_transport;
399 StreamObserver stream_observer(rtx_ssrc_map,
400 &receiver_transport,
401 Clock::GetRealTimeClock(),
402 rbe_factory.get(),
403 control_type);
404
405 Call::Config call_config(&stream_observer);
406 if (start_bitrate_bps != 0) {
407 call_config.bitrate_config.start_bitrate_bps = start_bitrate_bps;
408 stream_observer.set_start_bitrate_bps(start_bitrate_bps);
409 }
410
411 CreateSenderCall(call_config);
412
413 receiver_transport.SetReceiver(sender_call_->Receiver());
414
415 if (num_streams == 1) {
416 encoder_config_.streams[0].target_bitrate_bps = 2000000;
417 encoder_config_.streams[0].max_bitrate_bps = 2000000;
418 }
419
420 send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
421 send_config_.rtp.ssrcs = ssrcs;
422 if (rtx) {
423 send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
424 send_config_.rtp.rtx.ssrcs = rtx_ssrcs;
425 }
426
427 if (num_streams == 1) {
428 // For single stream rampup until 1mbps
429 stream_observer.set_expected_bitrate_bps(kSingleStreamTargetBps);
430 } else {
431 // For multi stream rampup until all streams are being sent. That means
432 // enough birate to send all the target streams plus the min bitrate of
433 // the last one.
434 int expected_bitrate_bps = encoder_config_.streams.back().min_bitrate_bps;
435 for (size_t i = 0; i < encoder_config_.streams.size() - 1; ++i) {
436 expected_bitrate_bps += encoder_config_.streams[i].target_bitrate_bps;
437 }
438 stream_observer.set_expected_bitrate_bps(expected_bitrate_bps);
439 }
440
441 CreateStreams();
442 CreateFrameGeneratorCapturer();
443
444 Start();
445
446 EXPECT_EQ(kEventSignaled, stream_observer.Wait());
447
448 Stop();
449 DestroyStreams();
450 }
451
RunRampUpDownUpTest(size_t number_of_streams,bool rtx)452 void RampUpTest::RunRampUpDownUpTest(size_t number_of_streams, bool rtx) {
453 test::DirectTransport receiver_transport;
454 LowRateStreamObserver stream_observer(
455 &receiver_transport, Clock::GetRealTimeClock(), number_of_streams, rtx);
456
457 Call::Config call_config(&stream_observer);
458 CreateSenderCall(call_config);
459 receiver_transport.SetReceiver(sender_call_->Receiver());
460
461 CreateSendConfig(number_of_streams);
462
463 send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
464 send_config_.rtp.extensions.push_back(RtpExtension(
465 RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
466 send_config_.suspend_below_min_bitrate = true;
467 if (rtx) {
468 send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
469 send_config_.rtp.rtx.ssrcs = GenerateSsrcs(number_of_streams, 200);
470 }
471
472 CreateStreams();
473 stream_observer.SetSendStream(send_stream_);
474
475 CreateFrameGeneratorCapturer();
476
477 Start();
478
479 EXPECT_EQ(kEventSignaled, stream_observer.Wait());
480
481 Stop();
482 DestroyStreams();
483 }
484
TEST_F(RampUpTest,SingleStream)485 TEST_F(RampUpTest, SingleStream) {
486 RunRampUpTest(false, 1, 0, RtpExtension::kTOffset);
487 }
488
TEST_F(RampUpTest,Simulcast)489 TEST_F(RampUpTest, Simulcast) {
490 RunRampUpTest(false, 3, 0, RtpExtension::kTOffset);
491 }
492
TEST_F(RampUpTest,SimulcastWithRtx)493 TEST_F(RampUpTest, SimulcastWithRtx) {
494 RunRampUpTest(true, 3, 0, RtpExtension::kTOffset);
495 }
496
TEST_F(RampUpTest,SingleStreamWithHighStartBitrate)497 TEST_F(RampUpTest, SingleStreamWithHighStartBitrate) {
498 RunRampUpTest(false, 1, 0.9 * kSingleStreamTargetBps, RtpExtension::kTOffset);
499 }
500
TEST_F(RampUpTest,UpDownUpOneStream)501 TEST_F(RampUpTest, UpDownUpOneStream) { RunRampUpDownUpTest(1, false); }
502
TEST_F(RampUpTest,UpDownUpThreeStreams)503 TEST_F(RampUpTest, UpDownUpThreeStreams) { RunRampUpDownUpTest(3, false); }
504
TEST_F(RampUpTest,UpDownUpOneStreamRtx)505 TEST_F(RampUpTest, UpDownUpOneStreamRtx) { RunRampUpDownUpTest(1, true); }
506
TEST_F(RampUpTest,UpDownUpThreeStreamsRtx)507 TEST_F(RampUpTest, UpDownUpThreeStreamsRtx) { RunRampUpDownUpTest(3, true); }
508
TEST_F(RampUpTest,AbsSendTimeSingleStream)509 TEST_F(RampUpTest, AbsSendTimeSingleStream) {
510 RunRampUpTest(false, 1, 0, RtpExtension::kAbsSendTime);
511 }
512
TEST_F(RampUpTest,AbsSendTimeSimulcast)513 TEST_F(RampUpTest, AbsSendTimeSimulcast) {
514 RunRampUpTest(false, 3, 0, RtpExtension::kAbsSendTime);
515 }
516
TEST_F(RampUpTest,AbsSendTimeSimulcastWithRtx)517 TEST_F(RampUpTest, AbsSendTimeSimulcastWithRtx) {
518 RunRampUpTest(true, 3, 0, RtpExtension::kAbsSendTime);
519 }
520
TEST_F(RampUpTest,AbsSendTimeSingleStreamWithHighStartBitrate)521 TEST_F(RampUpTest, AbsSendTimeSingleStreamWithHighStartBitrate) {
522 RunRampUpTest(false, 1, 0.9 * kSingleStreamTargetBps,
523 RtpExtension::kAbsSendTime);
524 }
525 } // namespace webrtc
526