blob: f69f8ce97b5ba562fc421d7ae9339fa1626a58cd [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"
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000012#include "webrtc/base/checks.h"
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000013#include "webrtc/base/common.h"
Erik Språng6b8d3552015-09-24 15:06:57 +020014#include "webrtc/base/event.h"
15#include "webrtc/modules/pacing/include/packet_router.h"
Erik Språng468e62a2015-07-06 10:50:47 +020016#include "webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.h"
17#include "webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.h"
Erik Språng6b8d3552015-09-24 15:06:57 +020018#include "webrtc/modules/remote_bitrate_estimator/remote_estimator_proxy.h"
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000019#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h"
20#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000021#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000022#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
23#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
24#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
Erik Språng6b8d3552015-09-24 15:06:57 +020025#include "webrtc/system_wrappers/interface/thread_wrapper.h"
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000026#include "webrtc/test/testsupport/perf_test.h"
stefan@webrtc.org3d7da882014-07-08 13:59:46 +000027#include "webrtc/video/rampup_tests.h"
pbos@webrtc.org744fbc72013-09-10 09:26:25 +000028
29namespace webrtc {
pbos@webrtc.org29023282013-09-11 10:14:56 +000030namespace {
stefan@webrtc.org3d7da882014-07-08 13:59:46 +000031
pbos@webrtc.orgc279a5d2014-01-24 09:30:53 +000032static const int kMaxPacketSize = 1500;
Erik Språng468e62a2015-07-06 10:50:47 +020033const uint32_t kRemoteBitrateEstimatorMinBitrateBps = 30000;
pbos@webrtc.org29023282013-09-11 10:14:56 +000034
stefan@webrtc.org3d7da882014-07-08 13:59:46 +000035std::vector<uint32_t> GenerateSsrcs(size_t num_streams,
36 uint32_t ssrc_offset) {
37 std::vector<uint32_t> ssrcs;
38 for (size_t i = 0; i != num_streams; ++i)
39 ssrcs.push_back(static_cast<uint32_t>(ssrc_offset + i));
40 return ssrcs;
41}
mflodman@webrtc.orgeb16b812014-06-16 08:57:39 +000042} // namespace
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +000043
stefan@webrtc.org3d7da882014-07-08 13:59:46 +000044StreamObserver::StreamObserver(const SsrcMap& rtx_media_ssrcs,
45 newapi::Transport* feedback_transport,
Erik Språng468e62a2015-07-06 10:50:47 +020046 Clock* clock)
stefan@webrtc.org3d7da882014-07-08 13:59:46 +000047 : clock_(clock),
48 test_done_(EventWrapper::Create()),
49 rtp_parser_(RtpHeaderParser::Create()),
50 feedback_transport_(feedback_transport),
51 receive_stats_(ReceiveStatistics::Create(clock)),
52 payload_registry_(
53 new RTPPayloadRegistry(RTPPayloadStrategy::CreateStrategy(false))),
Erik Språng468e62a2015-07-06 10:50:47 +020054 remote_bitrate_estimator_(nullptr),
stefan@webrtc.org3d7da882014-07-08 13:59:46 +000055 expected_bitrate_bps_(0),
56 start_bitrate_bps_(0),
57 rtx_media_ssrcs_(rtx_media_ssrcs),
58 total_sent_(0),
59 padding_sent_(0),
60 rtx_media_sent_(0),
61 total_packets_sent_(0),
62 padding_packets_sent_(0),
63 rtx_media_packets_sent_(0),
64 test_start_ms_(clock_->TimeInMilliseconds()),
65 ramp_up_finished_ms_(0) {
66 // 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();
72 feedback_transport_.Enable();
73 config.outgoing_transport = &feedback_transport_;
74 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
75 rtp_rtcp_->SetREMBStatus(true);
76 rtp_rtcp_->SetRTCPStatus(kRtcpNonCompound);
Erik Språng6b8d3552015-09-24 15:06:57 +020077 packet_router_.reset(new PacketRouter());
78 packet_router_->AddRtpModule(rtp_rtcp_.get());
stefan@webrtc.org3d7da882014-07-08 13:59:46 +000079 rtp_parser_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
80 kAbsSendTimeExtensionId);
81 rtp_parser_->RegisterRtpHeaderExtension(kRtpExtensionTransmissionTimeOffset,
82 kTransmissionTimeOffsetExtensionId);
Erik Språng6b8d3552015-09-24 15:06:57 +020083 rtp_parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
84 kTransportSequenceNumberExtensionId);
Shao Changbine62202f2015-04-21 20:24:50 +080085 payload_registry_->SetRtxPayloadType(RampUpTest::kSendRtxPayloadType,
86 RampUpTest::kFakeSendPayloadType);
stefan@webrtc.org3d7da882014-07-08 13:59:46 +000087}
88
Erik Språng6b8d3552015-09-24 15:06:57 +020089StreamObserver::~StreamObserver() {
90 packet_router_->RemoveRtpModule(rtp_rtcp_.get());
91}
92
stefan@webrtc.org3d7da882014-07-08 13:59:46 +000093void StreamObserver::set_expected_bitrate_bps(
94 unsigned int expected_bitrate_bps) {
Peter Boströmf2f82832015-05-01 13:00:41 +020095 rtc::CritScope lock(&crit_);
stefan@webrtc.org3d7da882014-07-08 13:59:46 +000096 expected_bitrate_bps_ = expected_bitrate_bps;
97}
98
99void StreamObserver::set_start_bitrate_bps(unsigned int start_bitrate_bps) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200100 rtc::CritScope lock(&crit_);
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000101 start_bitrate_bps_ = start_bitrate_bps;
102}
103
104void StreamObserver::OnReceiveBitrateChanged(
105 const std::vector<unsigned int>& ssrcs, unsigned int bitrate) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200106 rtc::CritScope lock(&crit_);
henrikg91d6ede2015-09-17 00:24:34 -0700107 RTC_DCHECK_GT(expected_bitrate_bps_, 0u);
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000108 if (start_bitrate_bps_ != 0) {
109 // For tests with an explicitly set start bitrate, verify the first
110 // bitrate estimate is close to the start bitrate and lower than the
111 // test target bitrate. This is to verify a call respects the configured
112 // start bitrate, but due to the BWE implementation we can't guarantee the
113 // first estimate really is as high as the start bitrate.
114 EXPECT_GT(bitrate, 0.9 * start_bitrate_bps_);
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000115 start_bitrate_bps_ = 0;
116 }
117 if (bitrate >= expected_bitrate_bps_) {
118 ramp_up_finished_ms_ = clock_->TimeInMilliseconds();
119 // Just trigger if there was any rtx padding packet.
120 if (rtx_media_ssrcs_.empty() || rtx_media_sent_ > 0) {
121 TriggerTestDone();
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000122 }
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000123 }
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +0000124 rtp_rtcp_->SetREMBData(bitrate, ssrcs);
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000125 rtp_rtcp_->Process();
126}
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000127
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000128bool StreamObserver::SendRtp(const uint8_t* packet, size_t length) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200129 rtc::CritScope lock(&crit_);
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000130 RTPHeader header;
pbos@webrtc.orgb951eb12014-11-25 11:13:28 +0000131 EXPECT_TRUE(rtp_parser_->Parse(packet, length, &header));
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000132 receive_stats_->IncomingPacket(header, length, false);
andrew@webrtc.org8f27fcc2015-01-09 20:22:46 +0000133 payload_registry_->SetIncomingPayloadType(header);
henrikg91d6ede2015-09-17 00:24:34 -0700134 RTC_DCHECK(remote_bitrate_estimator_ != nullptr);
Stefan Holmer11324b92015-07-09 17:27:48 +0200135 remote_bitrate_estimator_->IncomingPacket(
136 clock_->TimeInMilliseconds(), length - header.headerLength, header, true);
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000137 if (remote_bitrate_estimator_->TimeUntilNextProcess() <= 0) {
138 remote_bitrate_estimator_->Process();
stefancaa498a2015-07-14 09:14:51 -0700139 rtp_rtcp_->Process();
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000140 }
141 total_sent_ += length;
142 padding_sent_ += header.paddingLength;
143 ++total_packets_sent_;
144 if (header.paddingLength > 0)
145 ++padding_packets_sent_;
pbosbd2522a2015-07-01 05:35:53 -0700146 // Handle RTX retransmission, but only for non-padding-only packets.
147 if (rtx_media_ssrcs_.find(header.ssrc) != rtx_media_ssrcs_.end() &&
148 header.headerLength + header.paddingLength != length) {
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000149 rtx_media_sent_ += length - header.headerLength - header.paddingLength;
150 if (header.paddingLength == 0)
151 ++rtx_media_packets_sent_;
152 uint8_t restored_packet[kMaxPacketSize];
153 uint8_t* restored_packet_ptr = restored_packet;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000154 size_t restored_length = length;
Shao Changbine62202f2015-04-21 20:24:50 +0800155 EXPECT_TRUE(payload_registry_->RestoreOriginalPacket(
156 &restored_packet_ptr, packet, &restored_length,
157 rtx_media_ssrcs_[header.ssrc], header));
pbosbd2522a2015-07-01 05:35:53 -0700158 EXPECT_TRUE(
159 rtp_parser_->Parse(restored_packet_ptr, restored_length, &header));
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000160 } else {
161 rtp_rtcp_->SetRemoteSSRC(header.ssrc);
162 }
163 return true;
164}
165
166bool StreamObserver::SendRtcp(const uint8_t* packet, size_t length) {
167 return true;
168}
169
pbos@webrtc.org32452b22014-10-22 12:15:24 +0000170EventTypeWrapper StreamObserver::Wait() {
171 return test_done_->Wait(test::CallTest::kLongTimeoutMs);
172}
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000173
Erik Språng468e62a2015-07-06 10:50:47 +0200174void StreamObserver::SetRemoteBitrateEstimator(RemoteBitrateEstimator* rbe) {
175 remote_bitrate_estimator_.reset(rbe);
176}
177
Erik Språng6b8d3552015-09-24 15:06:57 +0200178PacketRouter* StreamObserver::GetPacketRouter() {
179 return packet_router_.get();
180}
181
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000182void StreamObserver::ReportResult(const std::string& measurement,
183 size_t value,
184 const std::string& units) {
185 webrtc::test::PrintResult(
186 measurement, "",
187 ::testing::UnitTest::GetInstance()->current_test_info()->name(),
188 value, units, false);
189}
190
191void StreamObserver::TriggerTestDone() EXCLUSIVE_LOCKS_REQUIRED(crit_) {
192 ReportResult("ramp-up-total-sent", total_sent_, "bytes");
193 ReportResult("ramp-up-padding-sent", padding_sent_, "bytes");
194 ReportResult("ramp-up-rtx-media-sent", rtx_media_sent_, "bytes");
195 ReportResult("ramp-up-total-packets-sent", total_packets_sent_, "packets");
196 ReportResult("ramp-up-padding-packets-sent",
197 padding_packets_sent_,
198 "packets");
199 ReportResult("ramp-up-rtx-packets-sent",
200 rtx_media_packets_sent_,
201 "packets");
202 ReportResult("ramp-up-time",
203 ramp_up_finished_ms_ - test_start_ms_,
204 "milliseconds");
205 test_done_->Set();
206}
207
208LowRateStreamObserver::LowRateStreamObserver(
209 newapi::Transport* feedback_transport,
210 Clock* clock,
211 size_t number_of_streams,
212 bool rtx_used)
213 : clock_(clock),
214 number_of_streams_(number_of_streams),
215 rtx_used_(rtx_used),
216 test_done_(EventWrapper::Create()),
217 rtp_parser_(RtpHeaderParser::Create()),
218 feedback_transport_(feedback_transport),
219 receive_stats_(ReceiveStatistics::Create(clock)),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000220 send_stream_(nullptr),
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000221 test_state_(kFirstRampup),
222 state_start_ms_(clock_->TimeInMilliseconds()),
223 interval_start_ms_(state_start_ms_),
224 last_remb_bps_(0),
225 sent_bytes_(0),
226 total_overuse_bytes_(0),
227 suspended_in_stats_(false) {
228 RtpRtcp::Configuration config;
229 config.receive_statistics = receive_stats_.get();
230 feedback_transport_.Enable();
231 config.outgoing_transport = &feedback_transport_;
232 rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(config));
233 rtp_rtcp_->SetREMBStatus(true);
234 rtp_rtcp_->SetRTCPStatus(kRtcpNonCompound);
stefan@webrtc.org88172562014-12-19 18:00:21 +0000235 rtp_parser_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
236 kAbsSendTimeExtensionId);
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000237 const uint32_t kRemoteBitrateEstimatorMinBitrateBps = 10000;
Erik Språng468e62a2015-07-06 10:50:47 +0200238 remote_bitrate_estimator_.reset(new RemoteBitrateEstimatorAbsSendTime(
239 this, clock, kRemoteBitrateEstimatorMinBitrateBps));
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000240 forward_transport_config_.link_capacity_kbps =
241 kHighBandwidthLimitBps / 1000;
stefan@webrtc.orgb8e9e442014-07-09 11:29:06 +0000242 forward_transport_config_.queue_length_packets = 100; // Something large.
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000243 test::DirectTransport::SetConfig(forward_transport_config_);
244 test::DirectTransport::SetReceiver(this);
245}
246
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000247void LowRateStreamObserver::SetSendStream(VideoSendStream* send_stream) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200248 rtc::CritScope lock(&crit_);
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000249 send_stream_ = send_stream;
250}
251
252void LowRateStreamObserver::OnReceiveBitrateChanged(
253 const std::vector<unsigned int>& ssrcs,
254 unsigned int bitrate) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200255 rtc::CritScope lock(&crit_);
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +0000256 rtp_rtcp_->SetREMBData(bitrate, ssrcs);
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000257 rtp_rtcp_->Process();
258 last_remb_bps_ = bitrate;
259}
260
261bool LowRateStreamObserver::SendRtp(const uint8_t* data, size_t length) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200262 rtc::CritScope lock(&crit_);
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000263 sent_bytes_ += length;
264 int64_t now_ms = clock_->TimeInMilliseconds();
265 if (now_ms > interval_start_ms_ + 1000) { // Let at least 1 second pass.
266 // Verify that the send rate was about right.
267 unsigned int average_rate_bps = static_cast<unsigned int>(sent_bytes_) *
268 8 * 1000 / (now_ms - interval_start_ms_);
269 // TODO(holmer): Why is this failing?
270 // EXPECT_LT(average_rate_bps, last_remb_bps_ * 1.1);
271 if (average_rate_bps > last_remb_bps_ * 1.1) {
272 total_overuse_bytes_ +=
273 sent_bytes_ -
274 last_remb_bps_ / 8 * (now_ms - interval_start_ms_) / 1000;
mflodman@webrtc.orgeb16b812014-06-16 08:57:39 +0000275 }
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000276 EvolveTestState(average_rate_bps);
277 interval_start_ms_ = now_ms;
278 sent_bytes_ = 0;
279 }
280 return test::DirectTransport::SendRtp(data, length);
281}
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000282
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000283PacketReceiver::DeliveryStatus LowRateStreamObserver::DeliverPacket(
stefan68786d22015-09-08 05:36:15 -0700284 MediaType media_type,
285 const uint8_t* packet,
286 size_t length,
287 const PacketTime& packet_time) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200288 rtc::CritScope lock(&crit_);
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000289 RTPHeader header;
pbos@webrtc.orgb951eb12014-11-25 11:13:28 +0000290 EXPECT_TRUE(rtp_parser_->Parse(packet, length, &header));
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000291 receive_stats_->IncomingPacket(header, length, false);
Stefan Holmer11324b92015-07-09 17:27:48 +0200292 remote_bitrate_estimator_->IncomingPacket(
293 clock_->TimeInMilliseconds(), length - header.headerLength, header, true);
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000294 if (remote_bitrate_estimator_->TimeUntilNextProcess() <= 0) {
295 remote_bitrate_estimator_->Process();
296 }
297 suspended_in_stats_ = send_stream_->GetStats().suspended;
298 return DELIVERY_OK;
299}
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000300
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000301bool LowRateStreamObserver::SendRtcp(const uint8_t* packet, size_t length) {
302 return true;
303}
andresp@webrtc.orgc1480792014-03-20 03:23:55 +0000304
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000305std::string LowRateStreamObserver::GetModifierString() {
306 std::string str("_");
307 char temp_str[5];
308 sprintf(temp_str, "%i",
309 static_cast<int>(number_of_streams_));
310 str += std::string(temp_str);
311 str += "stream";
312 str += (number_of_streams_ > 1 ? "s" : "");
313 str += "_";
314 str += (rtx_used_ ? "" : "no");
315 str += "rtx";
316 return str;
317}
andresp@webrtc.orgc1480792014-03-20 03:23:55 +0000318
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000319void LowRateStreamObserver::EvolveTestState(unsigned int bitrate_bps) {
320 int64_t now = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +0200321 rtc::CritScope lock(&crit_);
henrikg91d6ede2015-09-17 00:24:34 -0700322 RTC_DCHECK(send_stream_ != nullptr);
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000323 switch (test_state_) {
324 case kFirstRampup: {
325 EXPECT_FALSE(suspended_in_stats_);
326 if (bitrate_bps > kExpectedHighBitrateBps) {
327 // The first ramp-up has reached the target bitrate. Change the
328 // channel limit, and move to the next test state.
329 forward_transport_config_.link_capacity_kbps =
330 kLowBandwidthLimitBps / 1000;
331 test::DirectTransport::SetConfig(forward_transport_config_);
332 test_state_ = kLowRate;
333 webrtc::test::PrintResult("ramp_up_down_up",
334 GetModifierString(),
335 "first_rampup",
336 now - state_start_ms_,
337 "ms",
338 false);
339 state_start_ms_ = now;
340 interval_start_ms_ = now;
341 sent_bytes_ = 0;
andresp@webrtc.orgc1480792014-03-20 03:23:55 +0000342 }
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000343 break;
pbos@webrtc.orgf577ae92014-03-19 08:43:57 +0000344 }
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000345 case kLowRate: {
346 if (bitrate_bps < kExpectedLowBitrateBps && suspended_in_stats_) {
347 // The ramp-down was successful. Change the channel limit back to a
348 // high value, and move to the next test state.
349 forward_transport_config_.link_capacity_kbps =
350 kHighBandwidthLimitBps / 1000;
351 test::DirectTransport::SetConfig(forward_transport_config_);
352 test_state_ = kSecondRampup;
353 webrtc::test::PrintResult("ramp_up_down_up",
354 GetModifierString(),
355 "rampdown",
356 now - state_start_ms_,
357 "ms",
358 false);
359 state_start_ms_ = now;
360 interval_start_ms_ = now;
361 sent_bytes_ = 0;
362 }
363 break;
364 }
365 case kSecondRampup: {
366 if (bitrate_bps > kExpectedHighBitrateBps && !suspended_in_stats_) {
367 webrtc::test::PrintResult("ramp_up_down_up",
368 GetModifierString(),
369 "second_rampup",
370 now - state_start_ms_,
371 "ms",
372 false);
373 webrtc::test::PrintResult("ramp_up_down_up",
374 GetModifierString(),
375 "total_overuse",
376 total_overuse_bytes_,
377 "bytes",
378 false);
379 test_done_->Set();
380 }
381 break;
382 }
383 }
384}
pbos@webrtc.orgf577ae92014-03-19 08:43:57 +0000385
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000386EventTypeWrapper LowRateStreamObserver::Wait() {
387 return test_done_->Wait(test::CallTest::kLongTimeoutMs);
388}
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000389
Erik Språng6b8d3552015-09-24 15:06:57 +0200390class SendBitrateAdapter {
391 public:
392 static const int64_t kPollIntervalMs = 250;
393
394 SendBitrateAdapter(const Call& call,
395 const std::vector<uint32_t>& ssrcs,
396 RemoteBitrateObserver* bitrate_observer)
397 : event_(false, false),
398 call_(call),
399 ssrcs_(ssrcs),
400 bitrate_observer_(bitrate_observer) {
401 RTC_DCHECK(bitrate_observer != nullptr);
402 poller_thread_ = ThreadWrapper::CreateThread(&SendBitrateAdapterThread,
403 this, "SendBitratePoller");
404 bool thread_start_ok = poller_thread_->Start();
405 RTC_DCHECK(thread_start_ok);
406 }
407
408 virtual ~SendBitrateAdapter() {
409 event_.Set();
410 poller_thread_->Stop();
411 }
412
413 private:
414 static bool SendBitrateAdapterThread(void* obj) {
415 return static_cast<SendBitrateAdapter*>(obj)->PollStats();
416 }
417
418 bool PollStats() {
419 Call::Stats stats = call_.GetStats();
420
421 bitrate_observer_->OnReceiveBitrateChanged(ssrcs_,
422 stats.send_bandwidth_bps);
423 return !event_.Wait(kPollIntervalMs);
424 }
425
426 rtc::Event event_;
427 rtc::scoped_ptr<ThreadWrapper> poller_thread_;
428 const Call& call_;
429 const std::vector<uint32_t> ssrcs_;
430 RemoteBitrateObserver* const bitrate_observer_;
431};
432
Shao Changbine62202f2015-04-21 20:24:50 +0800433void RampUpTest::RunRampUpTest(size_t num_streams,
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000434 unsigned int start_bitrate_bps,
Shao Changbine62202f2015-04-21 20:24:50 +0800435 const std::string& extension_type,
436 bool rtx,
437 bool red) {
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000438 std::vector<uint32_t> ssrcs(GenerateSsrcs(num_streams, 100));
439 std::vector<uint32_t> rtx_ssrcs(GenerateSsrcs(num_streams, 200));
440 StreamObserver::SsrcMap rtx_ssrc_map;
441 if (rtx) {
442 for (size_t i = 0; i < ssrcs.size(); ++i)
443 rtx_ssrc_map[rtx_ssrcs[i]] = ssrcs[i];
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000444 }
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000445
Erik Språng468e62a2015-07-06 10:50:47 +0200446 test::DirectTransport receiver_transport;
447 StreamObserver stream_observer(rtx_ssrc_map, &receiver_transport,
448 Clock::GetRealTimeClock());
449
solenberg4fbae2b2015-08-28 04:07:10 -0700450 CreateSendConfig(num_streams, &stream_observer);
451 send_config_.rtp.extensions.clear();
452
Erik Språng6b8d3552015-09-24 15:06:57 +0200453 rtc::scoped_ptr<SendBitrateAdapter> send_bitrate_adapter_;
454
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000455 if (extension_type == RtpExtension::kAbsSendTime) {
Erik Språng468e62a2015-07-06 10:50:47 +0200456 stream_observer.SetRemoteBitrateEstimator(
457 new RemoteBitrateEstimatorAbsSendTime(
458 &stream_observer, Clock::GetRealTimeClock(),
459 kRemoteBitrateEstimatorMinBitrateBps));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000460 send_config_.rtp.extensions.push_back(RtpExtension(
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000461 extension_type.c_str(), kAbsSendTimeExtensionId));
Erik Språng6b8d3552015-09-24 15:06:57 +0200462 } else if (extension_type == RtpExtension::kTransportSequenceNumber) {
463 stream_observer.SetRemoteBitrateEstimator(new RemoteEstimatorProxy(
464 Clock::GetRealTimeClock(), stream_observer.GetPacketRouter()));
465 send_config_.rtp.extensions.push_back(RtpExtension(
466 extension_type.c_str(), kTransportSequenceNumberExtensionId));
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000467 } else {
Erik Språng468e62a2015-07-06 10:50:47 +0200468 stream_observer.SetRemoteBitrateEstimator(
469 new RemoteBitrateEstimatorSingleStream(
470 &stream_observer, Clock::GetRealTimeClock(),
471 kRemoteBitrateEstimatorMinBitrateBps));
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000472 send_config_.rtp.extensions.push_back(RtpExtension(
473 extension_type.c_str(), kTransmissionTimeOffsetExtensionId));
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000474 }
475
solenberg4fbae2b2015-08-28 04:07:10 -0700476 Call::Config call_config;
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000477 if (start_bitrate_bps != 0) {
Stefan Holmere5904162015-03-26 11:11:06 +0100478 call_config.bitrate_config.start_bitrate_bps = start_bitrate_bps;
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000479 stream_observer.set_start_bitrate_bps(start_bitrate_bps);
andresp@webrtc.orga714eaf2014-03-17 15:34:57 +0000480 }
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000481 CreateSenderCall(call_config);
482
483 receiver_transport.SetReceiver(sender_call_->Receiver());
484
485 if (num_streams == 1) {
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000486 encoder_config_.streams[0].target_bitrate_bps = 2000000;
487 encoder_config_.streams[0].max_bitrate_bps = 2000000;
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000488 }
489
490 send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
491 send_config_.rtp.ssrcs = ssrcs;
492 if (rtx) {
493 send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
494 send_config_.rtp.rtx.ssrcs = rtx_ssrcs;
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000495 }
Shao Changbine62202f2015-04-21 20:24:50 +0800496 if (red) {
497 send_config_.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
498 send_config_.rtp.fec.red_payload_type = kRedPayloadType;
499 }
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000500
501 if (num_streams == 1) {
502 // For single stream rampup until 1mbps
503 stream_observer.set_expected_bitrate_bps(kSingleStreamTargetBps);
504 } else {
505 // For multi stream rampup until all streams are being sent. That means
506 // enough birate to send all the target streams plus the min bitrate of
507 // the last one.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000508 int expected_bitrate_bps = encoder_config_.streams.back().min_bitrate_bps;
509 for (size_t i = 0; i < encoder_config_.streams.size() - 1; ++i) {
510 expected_bitrate_bps += encoder_config_.streams[i].target_bitrate_bps;
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000511 }
512 stream_observer.set_expected_bitrate_bps(expected_bitrate_bps);
513 }
514
515 CreateStreams();
516 CreateFrameGeneratorCapturer();
517
Erik Språng6b8d3552015-09-24 15:06:57 +0200518 if (extension_type == RtpExtension::kTransportSequenceNumber) {
519 send_bitrate_adapter_.reset(
520 new SendBitrateAdapter(*sender_call_.get(), ssrcs, &stream_observer));
521 }
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000522 Start();
523
524 EXPECT_EQ(kEventSignaled, stream_observer.Wait());
525
Erik Språng6b8d3552015-09-24 15:06:57 +0200526 // Destroy the SendBitrateAdapter (if any) to stop the poller thread in it,
527 // otherwise we might get a data race with the destruction of the call.
528 send_bitrate_adapter_.reset();
529
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000530 Stop();
531 DestroyStreams();
532}
533
Shao Changbine62202f2015-04-21 20:24:50 +0800534void RampUpTest::RunRampUpDownUpTest(size_t number_of_streams,
535 bool rtx,
536 bool red) {
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000537 test::DirectTransport receiver_transport;
538 LowRateStreamObserver stream_observer(
539 &receiver_transport, Clock::GetRealTimeClock(), number_of_streams, rtx);
540
solenberg4fbae2b2015-08-28 04:07:10 -0700541 Call::Config call_config;
Stefan Holmer11324b92015-07-09 17:27:48 +0200542 call_config.bitrate_config.start_bitrate_bps = 60000;
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000543 CreateSenderCall(call_config);
544 receiver_transport.SetReceiver(sender_call_->Receiver());
545
solenberg4fbae2b2015-08-28 04:07:10 -0700546 CreateSendConfig(number_of_streams, &stream_observer);
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000547
548 send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
549 send_config_.rtp.extensions.push_back(RtpExtension(
stefan@webrtc.org88172562014-12-19 18:00:21 +0000550 RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000551 send_config_.suspend_below_min_bitrate = true;
Stefan Holmer11324b92015-07-09 17:27:48 +0200552
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000553 if (rtx) {
554 send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
555 send_config_.rtp.rtx.ssrcs = GenerateSsrcs(number_of_streams, 200);
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000556 }
Shao Changbine62202f2015-04-21 20:24:50 +0800557 if (red) {
558 send_config_.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
559 send_config_.rtp.fec.red_payload_type = kRedPayloadType;
560 }
stefan@webrtc.org3d7da882014-07-08 13:59:46 +0000561
562 CreateStreams();
563 stream_observer.SetSendStream(send_stream_);
564
565 CreateFrameGeneratorCapturer();
566
567 Start();
568
569 EXPECT_EQ(kEventSignaled, stream_observer.Wait());
570
571 Stop();
572 DestroyStreams();
573}
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000574
stefan@webrtc.orgcb254aa2014-06-12 15:12:25 +0000575TEST_F(RampUpTest, SingleStream) {
Shao Changbine62202f2015-04-21 20:24:50 +0800576 RunRampUpTest(1, 0, RtpExtension::kTOffset, false, false);
andresp@webrtc.orgc1480792014-03-20 03:23:55 +0000577}
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000578
stefan@webrtc.orgcb254aa2014-06-12 15:12:25 +0000579TEST_F(RampUpTest, Simulcast) {
Shao Changbine62202f2015-04-21 20:24:50 +0800580 RunRampUpTest(3, 0, RtpExtension::kTOffset, false, false);
andresp@webrtc.orgc1480792014-03-20 03:23:55 +0000581}
582
stefan@webrtc.orgcb254aa2014-06-12 15:12:25 +0000583TEST_F(RampUpTest, SimulcastWithRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +0800584 RunRampUpTest(3, 0, RtpExtension::kTOffset, true, false);
585}
586
587TEST_F(RampUpTest, SimulcastByRedWithRtx) {
588 RunRampUpTest(3, 0, RtpExtension::kTOffset, true, true);
mflodman@webrtc.orgeb16b812014-06-16 08:57:39 +0000589}
590
591TEST_F(RampUpTest, SingleStreamWithHighStartBitrate) {
Shao Changbine62202f2015-04-21 20:24:50 +0800592 RunRampUpTest(1, 0.9 * kSingleStreamTargetBps, RtpExtension::kTOffset, false,
593 false);
andresp@webrtc.orgc1480792014-03-20 03:23:55 +0000594}
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000595
Shao Changbine62202f2015-04-21 20:24:50 +0800596TEST_F(RampUpTest, UpDownUpOneStream) {
597 RunRampUpDownUpTest(1, false, false);
598}
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000599
Shao Changbine62202f2015-04-21 20:24:50 +0800600TEST_F(RampUpTest, UpDownUpThreeStreams) {
601 RunRampUpDownUpTest(3, false, false);
602}
henrik.lundin@webrtc.org998cb8f2014-03-06 09:12:00 +0000603
Shao Changbine62202f2015-04-21 20:24:50 +0800604TEST_F(RampUpTest, UpDownUpOneStreamRtx) {
605 RunRampUpDownUpTest(1, true, false);
606}
henrik.lundin@webrtc.org998cb8f2014-03-06 09:12:00 +0000607
Shao Changbine62202f2015-04-21 20:24:50 +0800608TEST_F(RampUpTest, UpDownUpThreeStreamsRtx) {
609 RunRampUpDownUpTest(3, true, false);
610}
611
612TEST_F(RampUpTest, UpDownUpOneStreamByRedRtx) {
613 RunRampUpDownUpTest(1, true, true);
614}
615
616TEST_F(RampUpTest, UpDownUpThreeStreamsByRedRtx) {
617 RunRampUpDownUpTest(3, true, true);
618}
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000619
pbos@webrtc.org85bd53e2014-12-10 10:36:20 +0000620TEST_F(RampUpTest, AbsSendTimeSingleStream) {
Shao Changbine62202f2015-04-21 20:24:50 +0800621 RunRampUpTest(1, 0, RtpExtension::kAbsSendTime, false, false);
pbos@webrtc.org85bd53e2014-12-10 10:36:20 +0000622}
623
624TEST_F(RampUpTest, AbsSendTimeSimulcast) {
Shao Changbine62202f2015-04-21 20:24:50 +0800625 RunRampUpTest(3, 0, RtpExtension::kAbsSendTime, false, false);
pbos@webrtc.org85bd53e2014-12-10 10:36:20 +0000626}
627
628TEST_F(RampUpTest, AbsSendTimeSimulcastWithRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +0800629 RunRampUpTest(3, 0, RtpExtension::kAbsSendTime, true, false);
630}
631
632TEST_F(RampUpTest, AbsSendTimeSimulcastByRedWithRtx) {
633 RunRampUpTest(3, 0, RtpExtension::kAbsSendTime, true, true);
pbos@webrtc.org85bd53e2014-12-10 10:36:20 +0000634}
635
636TEST_F(RampUpTest, AbsSendTimeSingleStreamWithHighStartBitrate) {
Shao Changbine62202f2015-04-21 20:24:50 +0800637 RunRampUpTest(1, 0.9 * kSingleStreamTargetBps, RtpExtension::kAbsSendTime,
638 false, false);
pbos@webrtc.org85bd53e2014-12-10 10:36:20 +0000639}
Erik Språng6b8d3552015-09-24 15:06:57 +0200640
641TEST_F(RampUpTest, TransportSequenceNumberSingleStream) {
642 RunRampUpTest(1, 0, RtpExtension::kTransportSequenceNumber, false, false);
643}
644
645TEST_F(RampUpTest, TransportSequenceNumberSimulcast) {
646 RunRampUpTest(3, 0, RtpExtension::kTransportSequenceNumber, false, false);
647}
648
649TEST_F(RampUpTest, TransportSequenceNumberSimulcastWithRtx) {
650 RunRampUpTest(3, 0, RtpExtension::kTransportSequenceNumber, true, false);
651}
652
653TEST_F(RampUpTest, TransportSequenceNumberSimulcastByRedWithRtx) {
654 RunRampUpTest(3, 0, RtpExtension::kTransportSequenceNumber, true, true);
655}
656
657TEST_F(RampUpTest, TransportSequenceNumberSingleStreamWithHighStartBitrate) {
658 RunRampUpTest(1, 0.9 * kSingleStreamTargetBps,
659 RtpExtension::kTransportSequenceNumber, false, false);
660}
pbos@webrtc.org744fbc72013-09-10 09:26:25 +0000661} // namespace webrtc