blob: 644cb701968f9e3fe4a0d9acd5d4b66e41b2cd3c [file] [log] [blame]
pbos@webrtc.org744fbc72013-09-10 09:26:25 +00001/*
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 */
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000010
11#include "testing/gtest/include/gtest/gtest.h"
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000012#include "webrtc/base/common.h"
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000013#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h"
14#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000015#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000016#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
17#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
18#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000019#include "webrtc/test/testsupport/perf_test.h"
stefan@webrtc.org3d7da882014-07-08 13:59:46 +000020#include "webrtc/video/rampup_tests.h"
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000021
22namespace webrtc {
pbos@webrtc.org29023282013-09-11 10:14:56 +000023namespace {
stefan@webrtc.org3d7da882014-07-08 13:59:46 +000024
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +000025static const int kMaxPacketSize = 1500;
pbos@webrtc.org29023282013-09-11 10:14:56 +000026
stefan@webrtc.org3d7da882014-07-08 13:59:46 +000027std::vector<uint32_t> GenerateSsrcs(size_t num_streams,
28 uint32_t ssrc_offset) {
29 std::vector<uint32_t> ssrcs;
30 for (size_t i = 0; i != num_streams; ++i)
31 ssrcs.push_back(static_cast<uint32_t>(ssrc_offset + i));
32 return ssrcs;
33}
mflodman@webrtc.orgeb16b812014-06-16 08:57:39 +000034} // namespace
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +000035
stefan@webrtc.org3d7da882014-07-08 13:59:46 +000036StreamObserver::StreamObserver(const SsrcMap& rtx_media_ssrcs,
37 newapi::Transport* feedback_transport,
38 Clock* clock,
39 RemoteBitrateEstimatorFactory* rbe_factory,
40 RateControlType control_type)
41 : clock_(clock),
42 test_done_(EventWrapper::Create()),
43 rtp_parser_(RtpHeaderParser::Create()),
44 feedback_transport_(feedback_transport),
45 receive_stats_(ReceiveStatistics::Create(clock)),
46 payload_registry_(
47 new RTPPayloadRegistry(RTPPayloadStrategy::CreateStrategy(false))),
48 crit_(CriticalSectionWrapper::CreateCriticalSection()),
49 expected_bitrate_bps_(0),
50 start_bitrate_bps_(0),
51 rtx_media_ssrcs_(rtx_media_ssrcs),
52 total_sent_(0),
53 padding_sent_(0),
54 rtx_media_sent_(0),
55 total_packets_sent_(0),
56 padding_packets_sent_(0),
57 rtx_media_packets_sent_(0),
58 test_start_ms_(clock_->TimeInMilliseconds()),
59 ramp_up_finished_ms_(0) {
60 // Ideally we would only have to instantiate an RtcpSender, an
61 // RtpHeaderParser and a RemoteBitrateEstimator here, but due to the current
62 // state of the RTP module we need a full module and receive statistics to
63 // be able to produce an RTCP with REMB.
64 RtpRtcp::Configuration config;
65 config.receive_statistics = receive_stats_.get();
66 feedback_transport_.Enable();
67 config.outgoing_transport = &feedback_transport_;
68 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
69 rtp_rtcp_->SetREMBStatus(true);
70 rtp_rtcp_->SetRTCPStatus(kRtcpNonCompound);
71 rtp_parser_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
72 kAbsSendTimeExtensionId);
73 rtp_parser_->RegisterRtpHeaderExtension(kRtpExtensionTransmissionTimeOffset,
74 kTransmissionTimeOffsetExtensionId);
75 const uint32_t kRemoteBitrateEstimatorMinBitrateBps = 30000;
76 remote_bitrate_estimator_.reset(
77 rbe_factory->Create(this, clock, control_type,
78 kRemoteBitrateEstimatorMinBitrateBps));
79}
80
81void StreamObserver::set_expected_bitrate_bps(
82 unsigned int expected_bitrate_bps) {
83 CriticalSectionScoped lock(crit_.get());
84 expected_bitrate_bps_ = expected_bitrate_bps;
85}
86
87void StreamObserver::set_start_bitrate_bps(unsigned int start_bitrate_bps) {
88 CriticalSectionScoped lock(crit_.get());
89 start_bitrate_bps_ = start_bitrate_bps;
90}
91
92void StreamObserver::OnReceiveBitrateChanged(
93 const std::vector<unsigned int>& ssrcs, unsigned int bitrate) {
94 CriticalSectionScoped lock(crit_.get());
95 assert(expected_bitrate_bps_ > 0);
96 if (start_bitrate_bps_ != 0) {
97 // For tests with an explicitly set start bitrate, verify the first
98 // bitrate estimate is close to the start bitrate and lower than the
99 // test target bitrate. This is to verify a call respects the configured
100 // start bitrate, but due to the BWE implementation we can't guarantee the
101 // first estimate really is as high as the start bitrate.
102 EXPECT_GT(bitrate, 0.9 * start_bitrate_bps_);
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000103 start_bitrate_bps_ = 0;
104 }
105 if (bitrate >= expected_bitrate_bps_) {
106 ramp_up_finished_ms_ = clock_->TimeInMilliseconds();
107 // Just trigger if there was any rtx padding packet.
108 if (rtx_media_ssrcs_.empty() || rtx_media_sent_ > 0) {
109 TriggerTestDone();
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000110 }
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000111 }
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +0000112 rtp_rtcp_->SetREMBData(bitrate, ssrcs);
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000113 rtp_rtcp_->Process();
114}
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000115
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000116bool StreamObserver::SendRtp(const uint8_t* packet, size_t length) {
117 CriticalSectionScoped lock(crit_.get());
118 RTPHeader header;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000119 bool parse_succeeded = rtp_parser_->Parse(packet, length, &header);
120 RTC_UNUSED(parse_succeeded);
121 assert(parse_succeeded);
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000122 receive_stats_->IncomingPacket(header, length, false);
123 payload_registry_->SetIncomingPayloadType(header);
124 remote_bitrate_estimator_->IncomingPacket(
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000125 clock_->TimeInMilliseconds(), length - 12, header);
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000126 if (remote_bitrate_estimator_->TimeUntilNextProcess() <= 0) {
127 remote_bitrate_estimator_->Process();
128 }
129 total_sent_ += length;
130 padding_sent_ += header.paddingLength;
131 ++total_packets_sent_;
132 if (header.paddingLength > 0)
133 ++padding_packets_sent_;
134 if (rtx_media_ssrcs_.find(header.ssrc) != rtx_media_ssrcs_.end()) {
135 rtx_media_sent_ += length - header.headerLength - header.paddingLength;
136 if (header.paddingLength == 0)
137 ++rtx_media_packets_sent_;
138 uint8_t restored_packet[kMaxPacketSize];
139 uint8_t* restored_packet_ptr = restored_packet;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000140 size_t restored_length = length;
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000141 payload_registry_->RestoreOriginalPacket(&restored_packet_ptr,
142 packet,
143 &restored_length,
144 rtx_media_ssrcs_[header.ssrc],
145 header);
146 length = restored_length;
147 EXPECT_TRUE(rtp_parser_->Parse(
148 restored_packet, static_cast<int>(length), &header));
149 } else {
150 rtp_rtcp_->SetRemoteSSRC(header.ssrc);
151 }
152 return true;
153}
154
155bool StreamObserver::SendRtcp(const uint8_t* packet, size_t length) {
156 return true;
157}
158
pbos@webrtc.org32452b22014-10-22 12:15:24 +0000159EventTypeWrapper StreamObserver::Wait() {
160 return test_done_->Wait(test::CallTest::kLongTimeoutMs);
161}
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000162
163void StreamObserver::ReportResult(const std::string& measurement,
164 size_t value,
165 const std::string& units) {
166 webrtc::test::PrintResult(
167 measurement, "",
168 ::testing::UnitTest::GetInstance()->current_test_info()->name(),
169 value, units, false);
170}
171
172void StreamObserver::TriggerTestDone() EXCLUSIVE_LOCKS_REQUIRED(crit_) {
173 ReportResult("ramp-up-total-sent", total_sent_, "bytes");
174 ReportResult("ramp-up-padding-sent", padding_sent_, "bytes");
175 ReportResult("ramp-up-rtx-media-sent", rtx_media_sent_, "bytes");
176 ReportResult("ramp-up-total-packets-sent", total_packets_sent_, "packets");
177 ReportResult("ramp-up-padding-packets-sent",
178 padding_packets_sent_,
179 "packets");
180 ReportResult("ramp-up-rtx-packets-sent",
181 rtx_media_packets_sent_,
182 "packets");
183 ReportResult("ramp-up-time",
184 ramp_up_finished_ms_ - test_start_ms_,
185 "milliseconds");
186 test_done_->Set();
187}
188
189LowRateStreamObserver::LowRateStreamObserver(
190 newapi::Transport* feedback_transport,
191 Clock* clock,
192 size_t number_of_streams,
193 bool rtx_used)
194 : clock_(clock),
195 number_of_streams_(number_of_streams),
196 rtx_used_(rtx_used),
197 test_done_(EventWrapper::Create()),
198 rtp_parser_(RtpHeaderParser::Create()),
199 feedback_transport_(feedback_transport),
200 receive_stats_(ReceiveStatistics::Create(clock)),
201 crit_(CriticalSectionWrapper::CreateCriticalSection()),
202 send_stream_(NULL),
203 test_state_(kFirstRampup),
204 state_start_ms_(clock_->TimeInMilliseconds()),
205 interval_start_ms_(state_start_ms_),
206 last_remb_bps_(0),
207 sent_bytes_(0),
208 total_overuse_bytes_(0),
209 suspended_in_stats_(false) {
210 RtpRtcp::Configuration config;
211 config.receive_statistics = receive_stats_.get();
212 feedback_transport_.Enable();
213 config.outgoing_transport = &feedback_transport_;
214 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
215 rtp_rtcp_->SetREMBStatus(true);
216 rtp_rtcp_->SetRTCPStatus(kRtcpNonCompound);
217 rtp_parser_->RegisterRtpHeaderExtension(kRtpExtensionTransmissionTimeOffset,
218 kTransmissionTimeOffsetExtensionId);
219 AbsoluteSendTimeRemoteBitrateEstimatorFactory rbe_factory;
220 const uint32_t kRemoteBitrateEstimatorMinBitrateBps = 10000;
221 remote_bitrate_estimator_.reset(
222 rbe_factory.Create(this, clock, kMimdControl,
223 kRemoteBitrateEstimatorMinBitrateBps));
224 forward_transport_config_.link_capacity_kbps =
225 kHighBandwidthLimitBps / 1000;
stefan@webrtc.orgb8e9e442014-07-09 11:29:06 +0000226 forward_transport_config_.queue_length_packets = 100; // Something large.
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000227 test::DirectTransport::SetConfig(forward_transport_config_);
228 test::DirectTransport::SetReceiver(this);
229}
230
231void LowRateStreamObserver::SetSendStream(const VideoSendStream* send_stream) {
232 CriticalSectionScoped lock(crit_.get());
233 send_stream_ = send_stream;
234}
235
236void LowRateStreamObserver::OnReceiveBitrateChanged(
237 const std::vector<unsigned int>& ssrcs,
238 unsigned int bitrate) {
239 CriticalSectionScoped lock(crit_.get());
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +0000240 rtp_rtcp_->SetREMBData(bitrate, ssrcs);
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000241 rtp_rtcp_->Process();
242 last_remb_bps_ = bitrate;
243}
244
245bool LowRateStreamObserver::SendRtp(const uint8_t* data, size_t length) {
246 CriticalSectionScoped lock(crit_.get());
247 sent_bytes_ += length;
248 int64_t now_ms = clock_->TimeInMilliseconds();
249 if (now_ms > interval_start_ms_ + 1000) { // Let at least 1 second pass.
250 // Verify that the send rate was about right.
251 unsigned int average_rate_bps = static_cast<unsigned int>(sent_bytes_) *
252 8 * 1000 / (now_ms - interval_start_ms_);
253 // TODO(holmer): Why is this failing?
254 // EXPECT_LT(average_rate_bps, last_remb_bps_ * 1.1);
255 if (average_rate_bps > last_remb_bps_ * 1.1) {
256 total_overuse_bytes_ +=
257 sent_bytes_ -
258 last_remb_bps_ / 8 * (now_ms - interval_start_ms_) / 1000;
mflodman@webrtc.orgeb16b812014-06-16 08:57:39 +0000259 }
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000260 EvolveTestState(average_rate_bps);
261 interval_start_ms_ = now_ms;
262 sent_bytes_ = 0;
263 }
264 return test::DirectTransport::SendRtp(data, length);
265}
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000266
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000267PacketReceiver::DeliveryStatus LowRateStreamObserver::DeliverPacket(
268 const uint8_t* packet, size_t length) {
269 CriticalSectionScoped lock(crit_.get());
270 RTPHeader header;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000271 bool parse_succeeded = rtp_parser_->Parse(packet, length, &header);
272 RTC_UNUSED(parse_succeeded);
273 assert(parse_succeeded);
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000274 receive_stats_->IncomingPacket(header, length, false);
275 remote_bitrate_estimator_->IncomingPacket(
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000276 clock_->TimeInMilliseconds(), length - 12, header);
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000277 if (remote_bitrate_estimator_->TimeUntilNextProcess() <= 0) {
278 remote_bitrate_estimator_->Process();
279 }
280 suspended_in_stats_ = send_stream_->GetStats().suspended;
281 return DELIVERY_OK;
282}
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000283
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000284bool LowRateStreamObserver::SendRtcp(const uint8_t* packet, size_t length) {
285 return true;
286}
andresp@webrtc.orgc1480792014-03-20 03:23:55 +0000287
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000288std::string LowRateStreamObserver::GetModifierString() {
289 std::string str("_");
290 char temp_str[5];
291 sprintf(temp_str, "%i",
292 static_cast<int>(number_of_streams_));
293 str += std::string(temp_str);
294 str += "stream";
295 str += (number_of_streams_ > 1 ? "s" : "");
296 str += "_";
297 str += (rtx_used_ ? "" : "no");
298 str += "rtx";
299 return str;
300}
andresp@webrtc.orgc1480792014-03-20 03:23:55 +0000301
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000302void LowRateStreamObserver::EvolveTestState(unsigned int bitrate_bps) {
303 int64_t now = clock_->TimeInMilliseconds();
304 CriticalSectionScoped lock(crit_.get());
305 assert(send_stream_ != NULL);
306 switch (test_state_) {
307 case kFirstRampup: {
308 EXPECT_FALSE(suspended_in_stats_);
309 if (bitrate_bps > kExpectedHighBitrateBps) {
310 // The first ramp-up has reached the target bitrate. Change the
311 // channel limit, and move to the next test state.
312 forward_transport_config_.link_capacity_kbps =
313 kLowBandwidthLimitBps / 1000;
314 test::DirectTransport::SetConfig(forward_transport_config_);
315 test_state_ = kLowRate;
316 webrtc::test::PrintResult("ramp_up_down_up",
317 GetModifierString(),
318 "first_rampup",
319 now - state_start_ms_,
320 "ms",
321 false);
322 state_start_ms_ = now;
323 interval_start_ms_ = now;
324 sent_bytes_ = 0;
andresp@webrtc.orgc1480792014-03-20 03:23:55 +0000325 }
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000326 break;
pbos@webrtc.orgf577ae92014-03-19 08:43:57 +0000327 }
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000328 case kLowRate: {
329 if (bitrate_bps < kExpectedLowBitrateBps && suspended_in_stats_) {
330 // The ramp-down was successful. Change the channel limit back to a
331 // high value, and move to the next test state.
332 forward_transport_config_.link_capacity_kbps =
333 kHighBandwidthLimitBps / 1000;
334 test::DirectTransport::SetConfig(forward_transport_config_);
335 test_state_ = kSecondRampup;
336 webrtc::test::PrintResult("ramp_up_down_up",
337 GetModifierString(),
338 "rampdown",
339 now - state_start_ms_,
340 "ms",
341 false);
342 state_start_ms_ = now;
343 interval_start_ms_ = now;
344 sent_bytes_ = 0;
345 }
346 break;
347 }
348 case kSecondRampup: {
349 if (bitrate_bps > kExpectedHighBitrateBps && !suspended_in_stats_) {
350 webrtc::test::PrintResult("ramp_up_down_up",
351 GetModifierString(),
352 "second_rampup",
353 now - state_start_ms_,
354 "ms",
355 false);
356 webrtc::test::PrintResult("ramp_up_down_up",
357 GetModifierString(),
358 "total_overuse",
359 total_overuse_bytes_,
360 "bytes",
361 false);
362 test_done_->Set();
363 }
364 break;
365 }
366 }
367}
pbos@webrtc.orgf577ae92014-03-19 08:43:57 +0000368
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000369EventTypeWrapper LowRateStreamObserver::Wait() {
370 return test_done_->Wait(test::CallTest::kLongTimeoutMs);
371}
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000372
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000373void RampUpTest::RunRampUpTest(bool rtx,
374 size_t num_streams,
375 unsigned int start_bitrate_bps,
376 const std::string& extension_type) {
377 std::vector<uint32_t> ssrcs(GenerateSsrcs(num_streams, 100));
378 std::vector<uint32_t> rtx_ssrcs(GenerateSsrcs(num_streams, 200));
379 StreamObserver::SsrcMap rtx_ssrc_map;
380 if (rtx) {
381 for (size_t i = 0; i < ssrcs.size(); ++i)
382 rtx_ssrc_map[rtx_ssrcs[i]] = ssrcs[i];
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000383 }
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000384
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000385 CreateSendConfig(num_streams);
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000386
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000387 scoped_ptr<RemoteBitrateEstimatorFactory> rbe_factory;
388 RateControlType control_type;
389 if (extension_type == RtpExtension::kAbsSendTime) {
390 control_type = kAimdControl;
391 rbe_factory.reset(new AbsoluteSendTimeRemoteBitrateEstimatorFactory);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000392 send_config_.rtp.extensions.push_back(RtpExtension(
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000393 extension_type.c_str(), kAbsSendTimeExtensionId));
394 } else {
395 control_type = kMimdControl;
396 rbe_factory.reset(new RemoteBitrateEstimatorFactory);
397 send_config_.rtp.extensions.push_back(RtpExtension(
398 extension_type.c_str(), kTransmissionTimeOffsetExtensionId));
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000399 }
400
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000401 test::DirectTransport receiver_transport;
402 StreamObserver stream_observer(rtx_ssrc_map,
403 &receiver_transport,
404 Clock::GetRealTimeClock(),
405 rbe_factory.get(),
406 control_type);
407
408 Call::Config call_config(&stream_observer);
409 if (start_bitrate_bps != 0) {
pbos@webrtc.orga73a6782014-10-14 11:52:10 +0000410 call_config.stream_start_bitrate_bps = start_bitrate_bps;
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000411 stream_observer.set_start_bitrate_bps(start_bitrate_bps);
andresp@webrtc.orga714eaf2014-03-17 15:34:57 +0000412 }
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000413
414 CreateSenderCall(call_config);
415
416 receiver_transport.SetReceiver(sender_call_->Receiver());
417
418 if (num_streams == 1) {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000419 encoder_config_.streams[0].target_bitrate_bps = 2000000;
420 encoder_config_.streams[0].max_bitrate_bps = 2000000;
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000421 }
422
423 send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
424 send_config_.rtp.ssrcs = ssrcs;
425 if (rtx) {
426 send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
427 send_config_.rtp.rtx.ssrcs = rtx_ssrcs;
428 send_config_.rtp.rtx.pad_with_redundant_payloads = true;
429 }
430
431 if (num_streams == 1) {
432 // For single stream rampup until 1mbps
433 stream_observer.set_expected_bitrate_bps(kSingleStreamTargetBps);
434 } else {
435 // For multi stream rampup until all streams are being sent. That means
436 // enough birate to send all the target streams plus the min bitrate of
437 // the last one.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000438 int expected_bitrate_bps = encoder_config_.streams.back().min_bitrate_bps;
439 for (size_t i = 0; i < encoder_config_.streams.size() - 1; ++i) {
440 expected_bitrate_bps += encoder_config_.streams[i].target_bitrate_bps;
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000441 }
442 stream_observer.set_expected_bitrate_bps(expected_bitrate_bps);
443 }
444
445 CreateStreams();
446 CreateFrameGeneratorCapturer();
447
448 Start();
449
450 EXPECT_EQ(kEventSignaled, stream_observer.Wait());
451
452 Stop();
453 DestroyStreams();
454}
455
456void RampUpTest::RunRampUpDownUpTest(size_t number_of_streams, bool rtx) {
457 test::DirectTransport receiver_transport;
458 LowRateStreamObserver stream_observer(
459 &receiver_transport, Clock::GetRealTimeClock(), number_of_streams, rtx);
460
461 Call::Config call_config(&stream_observer);
462 CreateSenderCall(call_config);
463 receiver_transport.SetReceiver(sender_call_->Receiver());
464
465 CreateSendConfig(number_of_streams);
466
467 send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
468 send_config_.rtp.extensions.push_back(RtpExtension(
469 RtpExtension::kTOffset, kTransmissionTimeOffsetExtensionId));
470 send_config_.suspend_below_min_bitrate = true;
471 if (rtx) {
472 send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
473 send_config_.rtp.rtx.ssrcs = GenerateSsrcs(number_of_streams, 200);
474 send_config_.rtp.rtx.pad_with_redundant_payloads = true;
475 }
476
477 CreateStreams();
478 stream_observer.SetSendStream(send_stream_);
479
480 CreateFrameGeneratorCapturer();
481
482 Start();
483
484 EXPECT_EQ(kEventSignaled, stream_observer.Wait());
485
486 Stop();
487 DestroyStreams();
488}
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000489
stefan@webrtc.orgcb254aa2014-06-12 15:12:25 +0000490TEST_F(RampUpTest, SingleStream) {
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000491 RunRampUpTest(false, 1, 0, RtpExtension::kTOffset);
andresp@webrtc.orgc1480792014-03-20 03:23:55 +0000492}
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000493
stefan@webrtc.orgcb254aa2014-06-12 15:12:25 +0000494TEST_F(RampUpTest, Simulcast) {
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000495 RunRampUpTest(false, 3, 0, RtpExtension::kTOffset);
andresp@webrtc.orgc1480792014-03-20 03:23:55 +0000496}
497
stefan@webrtc.orgcb254aa2014-06-12 15:12:25 +0000498TEST_F(RampUpTest, SimulcastWithRtx) {
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000499 RunRampUpTest(true, 3, 0, RtpExtension::kTOffset);
mflodman@webrtc.orgeb16b812014-06-16 08:57:39 +0000500}
501
502TEST_F(RampUpTest, SingleStreamWithHighStartBitrate) {
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000503 RunRampUpTest(false, 1, 0.9 * kSingleStreamTargetBps, RtpExtension::kTOffset);
andresp@webrtc.orgc1480792014-03-20 03:23:55 +0000504}
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000505
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000506TEST_F(RampUpTest, UpDownUpOneStream) { RunRampUpDownUpTest(1, false); }
507
henrik.lundin@webrtc.org6ea4f632014-03-13 09:21:26 +0000508TEST_F(RampUpTest, UpDownUpThreeStreams) { RunRampUpDownUpTest(3, false); }
henrik.lundin@webrtc.org998cb8f2014-03-06 09:12:00 +0000509
henrik.lundin@webrtc.org6ea4f632014-03-13 09:21:26 +0000510TEST_F(RampUpTest, UpDownUpOneStreamRtx) { RunRampUpDownUpTest(1, true); }
henrik.lundin@webrtc.org998cb8f2014-03-06 09:12:00 +0000511
henrik.lundin@webrtc.org6ea4f632014-03-13 09:21:26 +0000512TEST_F(RampUpTest, UpDownUpThreeStreamsRtx) { RunRampUpDownUpTest(3, true); }
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000513
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000514} // namespace webrtc