blob: a50ebb49d0bac66745584093bcd053942945efc8 [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 */
10#include <assert.h>
11
12#include <map>
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +000013#include <string>
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000014#include <vector>
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000015
16#include "testing/gtest/include/gtest/gtest.h"
17
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000018#include "webrtc/call.h"
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000019#include "webrtc/common.h"
20#include "webrtc/experiments.h"
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000021#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
22#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h"
23#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000024#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000025#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
26#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
27#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
28#include "webrtc/system_wrappers/interface/event_wrapper.h"
29#include "webrtc/system_wrappers/interface/scoped_ptr.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000030#include "webrtc/test/direct_transport.h"
31#include "webrtc/test/fake_decoder.h"
32#include "webrtc/test/fake_encoder.h"
33#include "webrtc/test/frame_generator_capturer.h"
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000034#include "webrtc/test/testsupport/perf_test.h"
pbos@webrtc.org27326b62013-11-20 12:17:04 +000035#include "webrtc/video/transport_adapter.h"
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000036
37namespace webrtc {
38
pbos@webrtc.org29023282013-09-11 10:14:56 +000039namespace {
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +000040static const int kAbsoluteSendTimeExtensionId = 7;
41static const int kMaxPacketSize = 1500;
pbos@webrtc.org29023282013-09-11 10:14:56 +000042
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000043class StreamObserver : public newapi::Transport, public RemoteBitrateObserver {
44 public:
45 typedef std::map<uint32_t, int> BytesSentMap;
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000046 typedef std::map<uint32_t, uint32_t> SsrcMap;
andresp@webrtc.orga714eaf2014-03-17 15:34:57 +000047 StreamObserver(const SsrcMap& rtx_media_ssrcs,
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000048 newapi::Transport* feedback_transport,
49 Clock* clock)
50 : critical_section_(CriticalSectionWrapper::CreateCriticalSection()),
andresp@webrtc.orga714eaf2014-03-17 15:34:57 +000051 test_done_(EventWrapper::Create()),
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000052 rtp_parser_(RtpHeaderParser::Create()),
pbos@webrtc.org27326b62013-11-20 12:17:04 +000053 feedback_transport_(feedback_transport),
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000054 receive_stats_(ReceiveStatistics::Create(clock)),
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +000055 payload_registry_(
56 new RTPPayloadRegistry(-1,
57 RTPPayloadStrategy::CreateStrategy(false))),
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000058 clock_(clock),
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000059 rtx_media_ssrcs_(rtx_media_ssrcs),
60 total_sent_(0),
61 padding_sent_(0),
62 rtx_media_sent_(0),
63 total_packets_sent_(0),
64 padding_packets_sent_(0),
65 rtx_media_packets_sent_(0) {
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000066 // Ideally we would only have to instantiate an RtcpSender, an
67 // RtpHeaderParser and a RemoteBitrateEstimator here, but due to the current
68 // state of the RTP module we need a full module and receive statistics to
69 // be able to produce an RTCP with REMB.
70 RtpRtcp::Configuration config;
71 config.receive_statistics = receive_stats_.get();
sprang@webrtc.orgd9b95602014-01-27 13:03:02 +000072 feedback_transport_.Enable();
pbos@webrtc.org27326b62013-11-20 12:17:04 +000073 config.outgoing_transport = &feedback_transport_;
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000074 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
75 rtp_rtcp_->SetREMBStatus(true);
76 rtp_rtcp_->SetRTCPStatus(kRtcpNonCompound);
pbos@webrtc.org5ab75672013-12-16 12:24:44 +000077 rtp_parser_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
78 kAbsoluteSendTimeExtensionId);
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000079 AbsoluteSendTimeRemoteBitrateEstimatorFactory rbe_factory;
henrik.lundin@webrtc.orge9abd592013-12-13 08:42:42 +000080 const uint32_t kRemoteBitrateEstimatorMinBitrateBps = 30000;
81 remote_bitrate_estimator_.reset(
82 rbe_factory.Create(this, clock, kRemoteBitrateEstimatorMinBitrateBps));
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000083 }
84
85 virtual void OnReceiveBitrateChanged(const std::vector<unsigned int>& ssrcs,
86 unsigned int bitrate) {
87 CriticalSectionScoped lock(critical_section_.get());
andresp@webrtc.orga714eaf2014-03-17 15:34:57 +000088 if (bitrate >= kExpectedBitrateBps) {
89 // Just trigger if there was any rtx padding packet.
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000090 if (rtx_media_ssrcs_.empty() || rtx_media_sent_ > 0) {
andresp@webrtc.orga714eaf2014-03-17 15:34:57 +000091 TriggerTestDone();
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000092 }
93 }
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000094 rtp_rtcp_->SetREMBData(
95 bitrate, static_cast<uint8_t>(ssrcs.size()), &ssrcs[0]);
96 rtp_rtcp_->Process();
97 }
98
pbos@webrtc.org27326b62013-11-20 12:17:04 +000099 virtual bool SendRtp(const uint8_t* packet, size_t length) OVERRIDE {
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000100 CriticalSectionScoped lock(critical_section_.get());
101 RTPHeader header;
102 EXPECT_TRUE(rtp_parser_->Parse(packet, static_cast<int>(length), &header));
103 receive_stats_->IncomingPacket(header, length, false);
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000104 payload_registry_->SetIncomingPayloadType(header);
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000105 remote_bitrate_estimator_->IncomingPacket(
106 clock_->TimeInMilliseconds(), static_cast<int>(length - 12), header);
107 if (remote_bitrate_estimator_->TimeUntilNextProcess() <= 0) {
108 remote_bitrate_estimator_->Process();
109 }
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000110 total_sent_ += length;
111 padding_sent_ += header.paddingLength;
112 ++total_packets_sent_;
113 if (header.paddingLength > 0)
114 ++padding_packets_sent_;
115 if (rtx_media_ssrcs_.find(header.ssrc) != rtx_media_ssrcs_.end()) {
116 rtx_media_sent_ += length - header.headerLength - header.paddingLength;
117 if (header.paddingLength == 0)
118 ++rtx_media_packets_sent_;
119 uint8_t restored_packet[kMaxPacketSize];
120 uint8_t* restored_packet_ptr = restored_packet;
121 int restored_length = static_cast<int>(length);
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +0000122 payload_registry_->RestoreOriginalPacket(&restored_packet_ptr,
123 packet,
124 &restored_length,
125 rtx_media_ssrcs_[header.ssrc],
126 header);
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000127 length = restored_length;
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +0000128 EXPECT_TRUE(rtp_parser_->Parse(
129 restored_packet, static_cast<int>(length), &header));
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000130 } else {
131 rtp_rtcp_->SetRemoteSSRC(header.ssrc);
132 }
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000133 return true;
134 }
135
pbos@webrtc.org27326b62013-11-20 12:17:04 +0000136 virtual bool SendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000137 return true;
138 }
139
andresp@webrtc.orga714eaf2014-03-17 15:34:57 +0000140 EventTypeWrapper Wait() { return test_done_->Wait(120 * 1000); }
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000141
142 private:
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000143 static const unsigned int kExpectedBitrateBps = 1200000;
144
andresp@webrtc.orga714eaf2014-03-17 15:34:57 +0000145 void ReportResult(const std::string& measurement,
146 size_t value,
147 const std::string& units) {
148 webrtc::test::PrintResult(
149 measurement, "",
150 ::testing::UnitTest::GetInstance()->current_test_info()->name(),
151 value, units, false);
152 }
153
154 void TriggerTestDone() {
155 ReportResult("total-sent", total_sent_, "bytes");
156 ReportResult("padding-sent", padding_sent_, "bytes");
157 ReportResult("rtx-media-sent", rtx_media_sent_, "bytes");
158 ReportResult("total-packets-sent", total_packets_sent_, "packets");
159 ReportResult("padding-packets-sent", padding_packets_sent_, "packets");
160 ReportResult("rtx-packets-sent", rtx_media_packets_sent_, "packets");
161 test_done_->Set();
162 }
163
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000164 scoped_ptr<CriticalSectionWrapper> critical_section_;
andresp@webrtc.orga714eaf2014-03-17 15:34:57 +0000165 scoped_ptr<EventWrapper> test_done_;
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000166 scoped_ptr<RtpHeaderParser> rtp_parser_;
167 scoped_ptr<RtpRtcp> rtp_rtcp_;
pbos@webrtc.org27326b62013-11-20 12:17:04 +0000168 internal::TransportAdapter feedback_transport_;
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000169 scoped_ptr<ReceiveStatistics> receive_stats_;
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000170 scoped_ptr<RTPPayloadRegistry> payload_registry_;
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000171 scoped_ptr<RemoteBitrateEstimator> remote_bitrate_estimator_;
172 Clock* clock_;
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000173 SsrcMap rtx_media_ssrcs_;
174 size_t total_sent_;
175 size_t padding_sent_;
176 size_t rtx_media_sent_;
177 int total_packets_sent_;
178 int padding_packets_sent_;
179 int rtx_media_packets_sent_;
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000180};
181
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000182class LowRateStreamObserver : public test::DirectTransport,
183 public RemoteBitrateObserver,
184 public PacketReceiver {
185 public:
186 LowRateStreamObserver(newapi::Transport* feedback_transport,
187 Clock* clock,
188 size_t number_of_streams,
189 bool rtx_used)
190 : critical_section_(CriticalSectionWrapper::CreateCriticalSection()),
191 test_done_(EventWrapper::Create()),
192 rtp_parser_(RtpHeaderParser::Create()),
193 feedback_transport_(feedback_transport),
194 receive_stats_(ReceiveStatistics::Create(clock)),
195 clock_(clock),
196 test_state_(kFirstRampup),
197 state_start_ms_(clock_->TimeInMilliseconds()),
198 interval_start_ms_(state_start_ms_),
199 last_remb_bps_(0),
200 sent_bytes_(0),
201 total_overuse_bytes_(0),
202 number_of_streams_(number_of_streams),
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000203 rtx_used_(rtx_used),
204 send_stream_(NULL),
henrik.lundin@webrtc.org54464e62014-03-13 15:39:27 +0000205 suspended_in_stats_(false) {
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000206 RtpRtcp::Configuration config;
207 config.receive_statistics = receive_stats_.get();
208 feedback_transport_.Enable();
209 config.outgoing_transport = &feedback_transport_;
210 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
211 rtp_rtcp_->SetREMBStatus(true);
212 rtp_rtcp_->SetRTCPStatus(kRtcpNonCompound);
213 rtp_parser_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
214 kAbsoluteSendTimeExtensionId);
215 AbsoluteSendTimeRemoteBitrateEstimatorFactory rbe_factory;
216 const uint32_t kRemoteBitrateEstimatorMinBitrateBps = 10000;
217 remote_bitrate_estimator_.reset(
218 rbe_factory.Create(this, clock, kRemoteBitrateEstimatorMinBitrateBps));
219 forward_transport_config_.link_capacity_kbps =
220 kHighBandwidthLimitBps / 1000;
221 forward_transport_config_.queue_length = 100; // Something large.
222 test::DirectTransport::SetConfig(forward_transport_config_);
223 test::DirectTransport::SetReceiver(this);
224 }
225
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000226 virtual void SetSendStream(const VideoSendStream* send_stream) {
227 send_stream_ = send_stream;
228 }
229
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000230 virtual void OnReceiveBitrateChanged(const std::vector<unsigned int>& ssrcs,
231 unsigned int bitrate) {
232 CriticalSectionScoped lock(critical_section_.get());
233 rtp_rtcp_->SetREMBData(
234 bitrate, static_cast<uint8_t>(ssrcs.size()), &ssrcs[0]);
235 rtp_rtcp_->Process();
236 last_remb_bps_ = bitrate;
237 }
238
239 virtual bool SendRtp(const uint8_t* data, size_t length) OVERRIDE {
240 sent_bytes_ += length;
241 int64_t now_ms = clock_->TimeInMilliseconds();
242 if (now_ms > interval_start_ms_ + 1000) { // Let at least 1 second pass.
243 // Verify that the send rate was about right.
244 unsigned int average_rate_bps = static_cast<unsigned int>(sent_bytes_) *
245 8 * 1000 / (now_ms - interval_start_ms_);
246 // TODO(holmer): Why is this failing?
247 // EXPECT_LT(average_rate_bps, last_remb_bps_ * 1.1);
248 if (average_rate_bps > last_remb_bps_ * 1.1) {
249 total_overuse_bytes_ +=
250 sent_bytes_ -
251 last_remb_bps_ / 8 * (now_ms - interval_start_ms_) / 1000;
252 }
253 EvolveTestState(average_rate_bps);
254 interval_start_ms_ = now_ms;
255 sent_bytes_ = 0;
256 }
257 return test::DirectTransport::SendRtp(data, length);
258 }
259
260 virtual bool DeliverPacket(const uint8_t* packet, size_t length) OVERRIDE {
261 CriticalSectionScoped lock(critical_section_.get());
262 RTPHeader header;
263 EXPECT_TRUE(rtp_parser_->Parse(packet, static_cast<int>(length), &header));
264 receive_stats_->IncomingPacket(header, length, false);
265 remote_bitrate_estimator_->IncomingPacket(
266 clock_->TimeInMilliseconds(), static_cast<int>(length - 12), header);
267 if (remote_bitrate_estimator_->TimeUntilNextProcess() <= 0) {
268 remote_bitrate_estimator_->Process();
269 }
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000270 suspended_in_stats_ = send_stream_->GetStats().suspended;
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000271 return true;
272 }
273
274 virtual bool SendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
275 return true;
276 }
277
278 // Produces a string similar to "1stream_nortx", depending on the values of
279 // number_of_streams_ and rtx_used_;
280 std::string GetModifierString() {
281 std::string str("_");
282 char temp_str[5];
283 sprintf(temp_str, "%zu", number_of_streams_);
284 str += std::string(temp_str);
285 str += "stream";
286 str += (number_of_streams_ > 1 ? "s" : "");
287 str += "_";
288 str += (rtx_used_ ? "" : "no");
289 str += "rtx";
290 return str;
291 }
292
293 // This method defines the state machine for the ramp up-down-up test.
294 void EvolveTestState(unsigned int bitrate_bps) {
295 int64_t now = clock_->TimeInMilliseconds();
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000296 assert(send_stream_ != NULL);
297 CriticalSectionScoped lock(critical_section_.get());
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000298 switch (test_state_) {
299 case kFirstRampup: {
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000300 EXPECT_FALSE(suspended_in_stats_);
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000301 if (bitrate_bps > kExpectedHighBitrateBps) {
302 // The first ramp-up has reached the target bitrate. Change the
303 // channel limit, and move to the next test state.
304 forward_transport_config_.link_capacity_kbps =
305 kLowBandwidthLimitBps / 1000;
306 test::DirectTransport::SetConfig(forward_transport_config_);
307 test_state_ = kLowRate;
308 webrtc::test::PrintResult("ramp_up_down_up",
309 GetModifierString(),
310 "first_rampup",
311 now - state_start_ms_,
312 "ms",
313 false);
314 state_start_ms_ = now;
315 interval_start_ms_ = now;
316 sent_bytes_ = 0;
317 }
318 break;
319 }
320 case kLowRate: {
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000321 if (bitrate_bps < kExpectedLowBitrateBps && suspended_in_stats_) {
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000322 // The ramp-down was successful. Change the channel limit back to a
323 // high value, and move to the next test state.
324 forward_transport_config_.link_capacity_kbps =
325 kHighBandwidthLimitBps / 1000;
326 test::DirectTransport::SetConfig(forward_transport_config_);
327 test_state_ = kSecondRampup;
328 webrtc::test::PrintResult("ramp_up_down_up",
329 GetModifierString(),
330 "rampdown",
331 now - state_start_ms_,
332 "ms",
333 false);
334 state_start_ms_ = now;
335 interval_start_ms_ = now;
336 sent_bytes_ = 0;
337 }
338 break;
339 }
340 case kSecondRampup: {
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000341 if (bitrate_bps > kExpectedHighBitrateBps && !suspended_in_stats_) {
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000342 webrtc::test::PrintResult("ramp_up_down_up",
343 GetModifierString(),
344 "second_rampup",
345 now - state_start_ms_,
346 "ms",
347 false);
348 webrtc::test::PrintResult("ramp_up_down_up",
349 GetModifierString(),
350 "total_overuse",
351 total_overuse_bytes_,
352 "bytes",
353 false);
354 test_done_->Set();
355 }
356 break;
357 }
358 }
359 }
360
361 EventTypeWrapper Wait() { return test_done_->Wait(120 * 1000); }
362
363 private:
364 static const unsigned int kHighBandwidthLimitBps = 80000;
365 static const unsigned int kExpectedHighBitrateBps = 60000;
366 static const unsigned int kLowBandwidthLimitBps = 20000;
367 static const unsigned int kExpectedLowBitrateBps = 20000;
368 enum TestStates { kFirstRampup, kLowRate, kSecondRampup };
369
370 scoped_ptr<CriticalSectionWrapper> critical_section_;
371 scoped_ptr<EventWrapper> test_done_;
372 scoped_ptr<RtpHeaderParser> rtp_parser_;
373 scoped_ptr<RtpRtcp> rtp_rtcp_;
374 internal::TransportAdapter feedback_transport_;
375 scoped_ptr<ReceiveStatistics> receive_stats_;
376 scoped_ptr<RemoteBitrateEstimator> remote_bitrate_estimator_;
377 Clock* clock_;
378 FakeNetworkPipe::Config forward_transport_config_;
379 TestStates test_state_;
380 int64_t state_start_ms_;
381 int64_t interval_start_ms_;
382 unsigned int last_remb_bps_;
383 size_t sent_bytes_;
384 size_t total_overuse_bytes_;
385 const size_t number_of_streams_;
386 const bool rtx_used_;
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000387 const VideoSendStream* send_stream_;
388 bool suspended_in_stats_ GUARDED_BY(critical_section_);
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000389};
390}
391
392class RampUpTest : public ::testing::Test {
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000393 public:
394 virtual void SetUp() { reserved_ssrcs_.clear(); }
395
396 protected:
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000397 void RunRampUpTest(bool pacing, bool rtx) {
398 const size_t kNumberOfStreams = 3;
andresp@webrtc.orga714eaf2014-03-17 15:34:57 +0000399 std::vector<uint32_t> ssrcs(GenerateSsrcs(kNumberOfStreams, 100));
400 std::vector<uint32_t> rtx_ssrcs(GenerateSsrcs(kNumberOfStreams, 200));
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000401 StreamObserver::SsrcMap rtx_ssrc_map;
402 if (rtx) {
403 for (size_t i = 0; i < ssrcs.size(); ++i)
andresp@webrtc.orga714eaf2014-03-17 15:34:57 +0000404 rtx_ssrc_map[rtx_ssrcs[i]] = ssrcs[i];
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000405 }
406 test::DirectTransport receiver_transport;
andresp@webrtc.orga714eaf2014-03-17 15:34:57 +0000407 StreamObserver stream_observer(rtx_ssrc_map,
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +0000408 &receiver_transport,
409 Clock::GetRealTimeClock());
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000410
411 Call::Config call_config(&stream_observer);
412 webrtc::Config webrtc_config;
413 call_config.webrtc_config = &webrtc_config;
414 webrtc_config.Set<PaddingStrategy>(new PaddingStrategy(rtx));
415 scoped_ptr<Call> call(Call::Create(call_config));
416 VideoSendStream::Config send_config = call->GetDefaultSendConfig();
417
418 receiver_transport.SetReceiver(call->Receiver());
419
420 test::FakeEncoder encoder(Clock::GetRealTimeClock());
421 send_config.encoder = &encoder;
422 send_config.internal_source = false;
423 test::FakeEncoder::SetCodecSettings(&send_config.codec, kNumberOfStreams);
424 send_config.codec.plType = 125;
425 send_config.pacing = pacing;
426 send_config.rtp.nack.rtp_history_ms = 1000;
andresp@webrtc.orga714eaf2014-03-17 15:34:57 +0000427 send_config.rtp.ssrcs = ssrcs;
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000428 if (rtx) {
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +0000429 send_config.rtp.rtx.payload_type = 96;
andresp@webrtc.orga714eaf2014-03-17 15:34:57 +0000430 send_config.rtp.rtx.ssrcs = rtx_ssrcs;
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000431 }
432 send_config.rtp.extensions.push_back(
pbos@webrtc.org5ab75672013-12-16 12:24:44 +0000433 RtpExtension(RtpExtension::kAbsSendTime, kAbsoluteSendTimeExtensionId));
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000434
435 VideoSendStream* send_stream = call->CreateVideoSendStream(send_config);
436
437 scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
438 test::FrameGeneratorCapturer::Create(send_stream->Input(),
439 send_config.codec.width,
440 send_config.codec.height,
441 30,
442 Clock::GetRealTimeClock()));
443
444 send_stream->StartSending();
445 frame_generator_capturer->Start();
446
447 EXPECT_EQ(kEventSignaled, stream_observer.Wait());
448
449 frame_generator_capturer->Stop();
450 send_stream->StopSending();
451
452 call->DestroyVideoSendStream(send_stream);
453 }
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000454
455 void RunRampUpDownUpTest(size_t number_of_streams, bool rtx) {
456 std::vector<uint32_t> ssrcs;
457 for (size_t i = 0; i < number_of_streams; ++i)
458 ssrcs.push_back(static_cast<uint32_t>(i + 1));
459 test::DirectTransport receiver_transport;
460 LowRateStreamObserver stream_observer(
461 &receiver_transport, Clock::GetRealTimeClock(), number_of_streams, rtx);
462
463 Call::Config call_config(&stream_observer);
464 webrtc::Config webrtc_config;
465 call_config.webrtc_config = &webrtc_config;
466 webrtc_config.Set<PaddingStrategy>(new PaddingStrategy(rtx));
467 scoped_ptr<Call> call(Call::Create(call_config));
468 VideoSendStream::Config send_config = call->GetDefaultSendConfig();
469
470 receiver_transport.SetReceiver(call->Receiver());
471
472 test::FakeEncoder encoder(Clock::GetRealTimeClock());
473 send_config.encoder = &encoder;
474 send_config.internal_source = false;
475 test::FakeEncoder::SetCodecSettings(&send_config.codec, number_of_streams);
476 send_config.codec.plType = 125;
477 send_config.codec.startBitrate =
478 send_config.codec.simulcastStream[0].minBitrate;
479 send_config.rtp.nack.rtp_history_ms = 1000;
480 send_config.rtp.ssrcs.insert(
481 send_config.rtp.ssrcs.begin(), ssrcs.begin(), ssrcs.end());
482 send_config.rtp.extensions.push_back(
483 RtpExtension(RtpExtension::kAbsSendTime, kAbsoluteSendTimeExtensionId));
484 send_config.suspend_below_min_bitrate = true;
485
486 VideoSendStream* send_stream = call->CreateVideoSendStream(send_config);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000487 stream_observer.SetSendStream(send_stream);
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000488
489 scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
490 test::FrameGeneratorCapturer::Create(send_stream->Input(),
491 send_config.codec.width,
492 send_config.codec.height,
493 30,
494 Clock::GetRealTimeClock()));
495
496 send_stream->StartSending();
497 frame_generator_capturer->Start();
498
499 EXPECT_EQ(kEventSignaled, stream_observer.Wait());
500
henrik.lundin@webrtc.org54464e62014-03-13 15:39:27 +0000501 stream_observer.StopSending();
502 receiver_transport.StopSending();
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000503 frame_generator_capturer->Stop();
504 send_stream->StopSending();
505
506 call->DestroyVideoSendStream(send_stream);
507 }
508
andresp@webrtc.orga714eaf2014-03-17 15:34:57 +0000509 private:
510 std::vector<uint32_t> GenerateSsrcs(size_t num_streams,
511 uint32_t ssrc_offset) {
512 std::vector<uint32_t> ssrcs;
513 for (size_t i = 0; i != num_streams; ++i)
514 ssrcs.push_back(static_cast<uint32_t>(ssrc_offset + i));
515 return ssrcs;
516 }
517
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000518 std::map<uint32_t, bool> reserved_ssrcs_;
519};
520
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +0000521TEST_F(RampUpTest, WithoutPacing) { RunRampUpTest(false, false); }
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000522
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +0000523TEST_F(RampUpTest, WithPacing) { RunRampUpTest(true, false); }
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000524
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +0000525TEST_F(RampUpTest, WithPacingAndRtx) { RunRampUpTest(true, true); }
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000526
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000527TEST_F(RampUpTest, UpDownUpOneStream) { RunRampUpDownUpTest(1, false); }
528
henrik.lundin@webrtc.org6ea4f632014-03-13 09:21:26 +0000529TEST_F(RampUpTest, UpDownUpThreeStreams) { RunRampUpDownUpTest(3, false); }
henrik.lundin@webrtc.org998cb8f2014-03-06 09:12:00 +0000530
henrik.lundin@webrtc.org6ea4f632014-03-13 09:21:26 +0000531TEST_F(RampUpTest, UpDownUpOneStreamRtx) { RunRampUpDownUpTest(1, true); }
henrik.lundin@webrtc.org998cb8f2014-03-06 09:12:00 +0000532
henrik.lundin@webrtc.org6ea4f632014-03-13 09:21:26 +0000533TEST_F(RampUpTest, UpDownUpThreeStreamsRtx) { RunRampUpDownUpTest(3, true); }
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000534
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000535} // namespace webrtc