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