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 <algorithm> 11#include <sstream> 12#include <string> 13 14#include "testing/gtest/include/gtest/gtest.h" 15 16#include "webrtc/base/checks.h" 17#include "webrtc/base/scoped_ptr.h" 18#include "webrtc/base/thread_annotations.h" 19#include "webrtc/call.h" 20#include "webrtc/call/transport_adapter.h" 21#include "webrtc/common.h" 22#include "webrtc/config.h" 23#include "webrtc/modules/audio_coding/include/audio_coding_module.h" 24#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" 25#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" 26#include "webrtc/system_wrappers/include/critical_section_wrapper.h" 27#include "webrtc/system_wrappers/include/rtp_to_ntp.h" 28#include "webrtc/test/call_test.h" 29#include "webrtc/test/direct_transport.h" 30#include "webrtc/test/encoder_settings.h" 31#include "webrtc/test/fake_audio_device.h" 32#include "webrtc/test/fake_decoder.h" 33#include "webrtc/test/fake_encoder.h" 34#include "webrtc/test/frame_generator.h" 35#include "webrtc/test/frame_generator_capturer.h" 36#include "webrtc/test/rtp_rtcp_observer.h" 37#include "webrtc/test/testsupport/fileutils.h" 38#include "webrtc/test/testsupport/perf_test.h" 39#include "webrtc/voice_engine/include/voe_base.h" 40#include "webrtc/voice_engine/include/voe_codec.h" 41#include "webrtc/voice_engine/include/voe_network.h" 42#include "webrtc/voice_engine/include/voe_rtp_rtcp.h" 43#include "webrtc/voice_engine/include/voe_video_sync.h" 44 45namespace webrtc { 46 47class CallPerfTest : public test::CallTest { 48 protected: 49 void TestAudioVideoSync(bool fec, bool create_audio_first); 50 51 void TestCpuOveruse(LoadObserver::Load tested_load, int encode_delay_ms); 52 53 void TestMinTransmitBitrate(bool pad_to_min_bitrate); 54 55 void TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config, 56 int threshold_ms, 57 int start_time_ms, 58 int run_time_ms); 59}; 60 61class SyncRtcpObserver : public test::RtpRtcpObserver { 62 public: 63 SyncRtcpObserver() : test::RtpRtcpObserver(CallPerfTest::kLongTimeoutMs) {} 64 65 Action OnSendRtcp(const uint8_t* packet, size_t length) override { 66 RTCPUtility::RTCPParserV2 parser(packet, length, true); 67 EXPECT_TRUE(parser.IsValid()); 68 69 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin(); 70 packet_type != RTCPUtility::RTCPPacketTypes::kInvalid; 71 packet_type = parser.Iterate()) { 72 if (packet_type == RTCPUtility::RTCPPacketTypes::kSr) { 73 const RTCPUtility::RTCPPacket& packet = parser.Packet(); 74 RtcpMeasurement ntp_rtp_pair( 75 packet.SR.NTPMostSignificant, 76 packet.SR.NTPLeastSignificant, 77 packet.SR.RTPTimestamp); 78 StoreNtpRtpPair(ntp_rtp_pair); 79 } 80 } 81 return SEND_PACKET; 82 } 83 84 int64_t RtpTimestampToNtp(uint32_t timestamp) const { 85 rtc::CritScope lock(&crit_); 86 int64_t timestamp_in_ms = -1; 87 if (ntp_rtp_pairs_.size() == 2) { 88 // TODO(stefan): We can't EXPECT_TRUE on this call due to a bug in the 89 // RTCP sender where it sends RTCP SR before any RTP packets, which leads 90 // to a bogus NTP/RTP mapping. 91 RtpToNtpMs(timestamp, ntp_rtp_pairs_, ×tamp_in_ms); 92 return timestamp_in_ms; 93 } 94 return -1; 95 } 96 97 private: 98 void StoreNtpRtpPair(RtcpMeasurement ntp_rtp_pair) { 99 rtc::CritScope lock(&crit_); 100 for (RtcpList::iterator it = ntp_rtp_pairs_.begin(); 101 it != ntp_rtp_pairs_.end(); 102 ++it) { 103 if (ntp_rtp_pair.ntp_secs == it->ntp_secs && 104 ntp_rtp_pair.ntp_frac == it->ntp_frac) { 105 // This RTCP has already been added to the list. 106 return; 107 } 108 } 109 // We need two RTCP SR reports to map between RTP and NTP. More than two 110 // will not improve the mapping. 111 if (ntp_rtp_pairs_.size() == 2) { 112 ntp_rtp_pairs_.pop_back(); 113 } 114 ntp_rtp_pairs_.push_front(ntp_rtp_pair); 115 } 116 117 mutable rtc::CriticalSection crit_; 118 RtcpList ntp_rtp_pairs_ GUARDED_BY(crit_); 119}; 120 121class VideoRtcpAndSyncObserver : public SyncRtcpObserver, public VideoRenderer { 122 static const int kInSyncThresholdMs = 50; 123 static const int kStartupTimeMs = 2000; 124 static const int kMinRunTimeMs = 30000; 125 126 public: 127 VideoRtcpAndSyncObserver(Clock* clock, 128 int voe_channel, 129 VoEVideoSync* voe_sync, 130 SyncRtcpObserver* audio_observer) 131 : clock_(clock), 132 voe_channel_(voe_channel), 133 voe_sync_(voe_sync), 134 audio_observer_(audio_observer), 135 creation_time_ms_(clock_->TimeInMilliseconds()), 136 first_time_in_sync_(-1) {} 137 138 void RenderFrame(const VideoFrame& video_frame, 139 int time_to_render_ms) override { 140 int64_t now_ms = clock_->TimeInMilliseconds(); 141 uint32_t playout_timestamp = 0; 142 if (voe_sync_->GetPlayoutTimestamp(voe_channel_, playout_timestamp) != 0) 143 return; 144 int64_t latest_audio_ntp = 145 audio_observer_->RtpTimestampToNtp(playout_timestamp); 146 int64_t latest_video_ntp = RtpTimestampToNtp(video_frame.timestamp()); 147 if (latest_audio_ntp < 0 || latest_video_ntp < 0) 148 return; 149 int time_until_render_ms = 150 std::max(0, static_cast<int>(video_frame.render_time_ms() - now_ms)); 151 latest_video_ntp += time_until_render_ms; 152 int64_t stream_offset = latest_audio_ntp - latest_video_ntp; 153 std::stringstream ss; 154 ss << stream_offset; 155 webrtc::test::PrintResult("stream_offset", 156 "", 157 "synchronization", 158 ss.str(), 159 "ms", 160 false); 161 int64_t time_since_creation = now_ms - creation_time_ms_; 162 // During the first couple of seconds audio and video can falsely be 163 // estimated as being synchronized. We don't want to trigger on those. 164 if (time_since_creation < kStartupTimeMs) 165 return; 166 if (std::abs(latest_audio_ntp - latest_video_ntp) < kInSyncThresholdMs) { 167 if (first_time_in_sync_ == -1) { 168 first_time_in_sync_ = now_ms; 169 webrtc::test::PrintResult("sync_convergence_time", 170 "", 171 "synchronization", 172 time_since_creation, 173 "ms", 174 false); 175 } 176 if (time_since_creation > kMinRunTimeMs) 177 observation_complete_.Set(); 178 } 179 } 180 181 bool IsTextureSupported() const override { return false; } 182 183 private: 184 Clock* const clock_; 185 const int voe_channel_; 186 VoEVideoSync* const voe_sync_; 187 SyncRtcpObserver* const audio_observer_; 188 const int64_t creation_time_ms_; 189 int64_t first_time_in_sync_; 190}; 191 192void CallPerfTest::TestAudioVideoSync(bool fec, bool create_audio_first) { 193 const char* kSyncGroup = "av_sync"; 194 const uint32_t kAudioSendSsrc = 1234; 195 const uint32_t kAudioRecvSsrc = 5678; 196 class AudioPacketReceiver : public PacketReceiver { 197 public: 198 AudioPacketReceiver(int channel, VoENetwork* voe_network) 199 : channel_(channel), 200 voe_network_(voe_network), 201 parser_(RtpHeaderParser::Create()) {} 202 DeliveryStatus DeliverPacket(MediaType media_type, 203 const uint8_t* packet, 204 size_t length, 205 const PacketTime& packet_time) override { 206 EXPECT_TRUE(media_type == MediaType::ANY || 207 media_type == MediaType::AUDIO); 208 int ret; 209 if (parser_->IsRtcp(packet, length)) { 210 ret = voe_network_->ReceivedRTCPPacket(channel_, packet, length); 211 } else { 212 ret = voe_network_->ReceivedRTPPacket(channel_, packet, length, 213 PacketTime()); 214 } 215 return ret == 0 ? DELIVERY_OK : DELIVERY_PACKET_ERROR; 216 } 217 218 private: 219 int channel_; 220 VoENetwork* voe_network_; 221 rtc::scoped_ptr<RtpHeaderParser> parser_; 222 }; 223 224 VoiceEngine* voice_engine = VoiceEngine::Create(); 225 VoEBase* voe_base = VoEBase::GetInterface(voice_engine); 226 VoECodec* voe_codec = VoECodec::GetInterface(voice_engine); 227 VoENetwork* voe_network = VoENetwork::GetInterface(voice_engine); 228 VoEVideoSync* voe_sync = VoEVideoSync::GetInterface(voice_engine); 229 const std::string audio_filename = 230 test::ResourcePath("voice_engine/audio_long16", "pcm"); 231 ASSERT_STRNE("", audio_filename.c_str()); 232 test::FakeAudioDevice fake_audio_device(Clock::GetRealTimeClock(), 233 audio_filename); 234 EXPECT_EQ(0, voe_base->Init(&fake_audio_device, nullptr)); 235 Config voe_config; 236 voe_config.Set<VoicePacing>(new VoicePacing(true)); 237 int send_channel_id = voe_base->CreateChannel(voe_config); 238 int recv_channel_id = voe_base->CreateChannel(); 239 240 SyncRtcpObserver audio_observer; 241 242 AudioState::Config send_audio_state_config; 243 send_audio_state_config.voice_engine = voice_engine; 244 Call::Config sender_config; 245 sender_config.audio_state = AudioState::Create(send_audio_state_config); 246 Call::Config receiver_config; 247 receiver_config.audio_state = sender_config.audio_state; 248 CreateCalls(sender_config, receiver_config); 249 250 AudioPacketReceiver voe_send_packet_receiver(send_channel_id, voe_network); 251 AudioPacketReceiver voe_recv_packet_receiver(recv_channel_id, voe_network); 252 253 FakeNetworkPipe::Config net_config; 254 net_config.queue_delay_ms = 500; 255 net_config.loss_percent = 5; 256 test::PacketTransport audio_send_transport( 257 nullptr, &audio_observer, test::PacketTransport::kSender, net_config); 258 audio_send_transport.SetReceiver(&voe_recv_packet_receiver); 259 test::PacketTransport audio_receive_transport( 260 nullptr, &audio_observer, test::PacketTransport::kReceiver, net_config); 261 audio_receive_transport.SetReceiver(&voe_send_packet_receiver); 262 263 internal::TransportAdapter send_transport_adapter(&audio_send_transport); 264 send_transport_adapter.Enable(); 265 EXPECT_EQ(0, voe_network->RegisterExternalTransport(send_channel_id, 266 send_transport_adapter)); 267 268 internal::TransportAdapter recv_transport_adapter(&audio_receive_transport); 269 recv_transport_adapter.Enable(); 270 EXPECT_EQ(0, voe_network->RegisterExternalTransport(recv_channel_id, 271 recv_transport_adapter)); 272 273 VideoRtcpAndSyncObserver observer(Clock::GetRealTimeClock(), recv_channel_id, 274 voe_sync, &audio_observer); 275 276 test::PacketTransport sync_send_transport(sender_call_.get(), &observer, 277 test::PacketTransport::kSender, 278 FakeNetworkPipe::Config()); 279 sync_send_transport.SetReceiver(receiver_call_->Receiver()); 280 test::PacketTransport sync_receive_transport(receiver_call_.get(), &observer, 281 test::PacketTransport::kReceiver, 282 FakeNetworkPipe::Config()); 283 sync_receive_transport.SetReceiver(sender_call_->Receiver()); 284 285 test::FakeDecoder fake_decoder; 286 287 CreateSendConfig(1, 0, &sync_send_transport); 288 CreateMatchingReceiveConfigs(&sync_receive_transport); 289 290 AudioSendStream::Config audio_send_config(&audio_send_transport); 291 audio_send_config.voe_channel_id = send_channel_id; 292 audio_send_config.rtp.ssrc = kAudioSendSsrc; 293 AudioSendStream* audio_send_stream = 294 sender_call_->CreateAudioSendStream(audio_send_config); 295 296 CodecInst isac = {103, "ISAC", 16000, 480, 1, 32000}; 297 EXPECT_EQ(0, voe_codec->SetSendCodec(send_channel_id, isac)); 298 299 video_send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs; 300 if (fec) { 301 video_send_config_.rtp.fec.red_payload_type = kRedPayloadType; 302 video_send_config_.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType; 303 video_receive_configs_[0].rtp.fec.red_payload_type = kRedPayloadType; 304 video_receive_configs_[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType; 305 } 306 video_receive_configs_[0].rtp.nack.rtp_history_ms = 1000; 307 video_receive_configs_[0].renderer = &observer; 308 video_receive_configs_[0].sync_group = kSyncGroup; 309 310 AudioReceiveStream::Config audio_recv_config; 311 audio_recv_config.rtp.remote_ssrc = kAudioSendSsrc; 312 audio_recv_config.rtp.local_ssrc = kAudioRecvSsrc; 313 audio_recv_config.voe_channel_id = recv_channel_id; 314 audio_recv_config.sync_group = kSyncGroup; 315 316 AudioReceiveStream* audio_receive_stream; 317 318 if (create_audio_first) { 319 audio_receive_stream = 320 receiver_call_->CreateAudioReceiveStream(audio_recv_config); 321 CreateVideoStreams(); 322 } else { 323 CreateVideoStreams(); 324 audio_receive_stream = 325 receiver_call_->CreateAudioReceiveStream(audio_recv_config); 326 } 327 328 CreateFrameGeneratorCapturer(); 329 330 Start(); 331 332 fake_audio_device.Start(); 333 EXPECT_EQ(0, voe_base->StartPlayout(recv_channel_id)); 334 EXPECT_EQ(0, voe_base->StartReceive(recv_channel_id)); 335 EXPECT_EQ(0, voe_base->StartSend(send_channel_id)); 336 337 EXPECT_TRUE(observer.Wait()) 338 << "Timed out while waiting for audio and video to be synchronized."; 339 340 EXPECT_EQ(0, voe_base->StopSend(send_channel_id)); 341 EXPECT_EQ(0, voe_base->StopReceive(recv_channel_id)); 342 EXPECT_EQ(0, voe_base->StopPlayout(recv_channel_id)); 343 fake_audio_device.Stop(); 344 345 Stop(); 346 sync_send_transport.StopSending(); 347 sync_receive_transport.StopSending(); 348 audio_send_transport.StopSending(); 349 audio_receive_transport.StopSending(); 350 351 DestroyStreams(); 352 353 sender_call_->DestroyAudioSendStream(audio_send_stream); 354 receiver_call_->DestroyAudioReceiveStream(audio_receive_stream); 355 356 voe_base->DeleteChannel(send_channel_id); 357 voe_base->DeleteChannel(recv_channel_id); 358 voe_base->Release(); 359 voe_codec->Release(); 360 voe_network->Release(); 361 voe_sync->Release(); 362 363 DestroyCalls(); 364 365 VoiceEngine::Delete(voice_engine); 366} 367 368TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSyncWithAudioCreatedFirst) { 369 TestAudioVideoSync(false, true); 370} 371 372TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSyncWithVideoCreatedFirst) { 373 TestAudioVideoSync(false, false); 374} 375 376TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSyncWithFec) { 377 TestAudioVideoSync(true, false); 378} 379 380void CallPerfTest::TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config, 381 int threshold_ms, 382 int start_time_ms, 383 int run_time_ms) { 384 class CaptureNtpTimeObserver : public test::EndToEndTest, 385 public VideoRenderer { 386 public: 387 CaptureNtpTimeObserver(const FakeNetworkPipe::Config& net_config, 388 int threshold_ms, 389 int start_time_ms, 390 int run_time_ms) 391 : EndToEndTest(kLongTimeoutMs), 392 net_config_(net_config), 393 clock_(Clock::GetRealTimeClock()), 394 threshold_ms_(threshold_ms), 395 start_time_ms_(start_time_ms), 396 run_time_ms_(run_time_ms), 397 creation_time_ms_(clock_->TimeInMilliseconds()), 398 capturer_(nullptr), 399 rtp_start_timestamp_set_(false), 400 rtp_start_timestamp_(0) {} 401 402 private: 403 test::PacketTransport* CreateSendTransport(Call* sender_call) override { 404 return new test::PacketTransport( 405 sender_call, this, test::PacketTransport::kSender, net_config_); 406 } 407 408 test::PacketTransport* CreateReceiveTransport() override { 409 return new test::PacketTransport( 410 nullptr, this, test::PacketTransport::kReceiver, net_config_); 411 } 412 413 void RenderFrame(const VideoFrame& video_frame, 414 int time_to_render_ms) override { 415 rtc::CritScope lock(&crit_); 416 if (video_frame.ntp_time_ms() <= 0) { 417 // Haven't got enough RTCP SR in order to calculate the capture ntp 418 // time. 419 return; 420 } 421 422 int64_t now_ms = clock_->TimeInMilliseconds(); 423 int64_t time_since_creation = now_ms - creation_time_ms_; 424 if (time_since_creation < start_time_ms_) { 425 // Wait for |start_time_ms_| before start measuring. 426 return; 427 } 428 429 if (time_since_creation > run_time_ms_) { 430 observation_complete_.Set(); 431 } 432 433 FrameCaptureTimeList::iterator iter = 434 capture_time_list_.find(video_frame.timestamp()); 435 EXPECT_TRUE(iter != capture_time_list_.end()); 436 437 // The real capture time has been wrapped to uint32_t before converted 438 // to rtp timestamp in the sender side. So here we convert the estimated 439 // capture time to a uint32_t 90k timestamp also for comparing. 440 uint32_t estimated_capture_timestamp = 441 90 * static_cast<uint32_t>(video_frame.ntp_time_ms()); 442 uint32_t real_capture_timestamp = iter->second; 443 int time_offset_ms = real_capture_timestamp - estimated_capture_timestamp; 444 time_offset_ms = time_offset_ms / 90; 445 std::stringstream ss; 446 ss << time_offset_ms; 447 448 webrtc::test::PrintResult( 449 "capture_ntp_time", "", "real - estimated", ss.str(), "ms", true); 450 EXPECT_TRUE(std::abs(time_offset_ms) < threshold_ms_); 451 } 452 453 bool IsTextureSupported() const override { return false; } 454 455 virtual Action OnSendRtp(const uint8_t* packet, size_t length) { 456 rtc::CritScope lock(&crit_); 457 RTPHeader header; 458 EXPECT_TRUE(parser_->Parse(packet, length, &header)); 459 460 if (!rtp_start_timestamp_set_) { 461 // Calculate the rtp timestamp offset in order to calculate the real 462 // capture time. 463 uint32_t first_capture_timestamp = 464 90 * static_cast<uint32_t>(capturer_->first_frame_capture_time()); 465 rtp_start_timestamp_ = header.timestamp - first_capture_timestamp; 466 rtp_start_timestamp_set_ = true; 467 } 468 469 uint32_t capture_timestamp = header.timestamp - rtp_start_timestamp_; 470 capture_time_list_.insert( 471 capture_time_list_.end(), 472 std::make_pair(header.timestamp, capture_timestamp)); 473 return SEND_PACKET; 474 } 475 476 void OnFrameGeneratorCapturerCreated( 477 test::FrameGeneratorCapturer* frame_generator_capturer) override { 478 capturer_ = frame_generator_capturer; 479 } 480 481 void ModifyVideoConfigs( 482 VideoSendStream::Config* send_config, 483 std::vector<VideoReceiveStream::Config>* receive_configs, 484 VideoEncoderConfig* encoder_config) override { 485 (*receive_configs)[0].renderer = this; 486 // Enable the receiver side rtt calculation. 487 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true; 488 } 489 490 void PerformTest() override { 491 EXPECT_TRUE(Wait()) << "Timed out while waiting for " 492 "estimated capture NTP time to be " 493 "within bounds."; 494 } 495 496 rtc::CriticalSection crit_; 497 const FakeNetworkPipe::Config net_config_; 498 Clock* const clock_; 499 int threshold_ms_; 500 int start_time_ms_; 501 int run_time_ms_; 502 int64_t creation_time_ms_; 503 test::FrameGeneratorCapturer* capturer_; 504 bool rtp_start_timestamp_set_; 505 uint32_t rtp_start_timestamp_; 506 typedef std::map<uint32_t, uint32_t> FrameCaptureTimeList; 507 FrameCaptureTimeList capture_time_list_ GUARDED_BY(&crit_); 508 } test(net_config, threshold_ms, start_time_ms, run_time_ms); 509 510 RunBaseTest(&test); 511} 512 513TEST_F(CallPerfTest, CaptureNtpTimeWithNetworkDelay) { 514 FakeNetworkPipe::Config net_config; 515 net_config.queue_delay_ms = 100; 516 // TODO(wu): lower the threshold as the calculation/estimatation becomes more 517 // accurate. 518 const int kThresholdMs = 100; 519 const int kStartTimeMs = 10000; 520 const int kRunTimeMs = 20000; 521 TestCaptureNtpTime(net_config, kThresholdMs, kStartTimeMs, kRunTimeMs); 522} 523 524TEST_F(CallPerfTest, CaptureNtpTimeWithNetworkJitter) { 525 FakeNetworkPipe::Config net_config; 526 net_config.queue_delay_ms = 100; 527 net_config.delay_standard_deviation_ms = 10; 528 // TODO(wu): lower the threshold as the calculation/estimatation becomes more 529 // accurate. 530 const int kThresholdMs = 100; 531 const int kStartTimeMs = 10000; 532 const int kRunTimeMs = 20000; 533 TestCaptureNtpTime(net_config, kThresholdMs, kStartTimeMs, kRunTimeMs); 534} 535 536void CallPerfTest::TestCpuOveruse(LoadObserver::Load tested_load, 537 int encode_delay_ms) { 538 class LoadObserver : public test::SendTest, public webrtc::LoadObserver { 539 public: 540 LoadObserver(LoadObserver::Load tested_load, int encode_delay_ms) 541 : SendTest(kLongTimeoutMs), 542 tested_load_(tested_load), 543 encoder_(Clock::GetRealTimeClock(), encode_delay_ms) {} 544 545 void OnLoadUpdate(Load load) override { 546 if (load == tested_load_) 547 observation_complete_.Set(); 548 } 549 550 void ModifyVideoConfigs( 551 VideoSendStream::Config* send_config, 552 std::vector<VideoReceiveStream::Config>* receive_configs, 553 VideoEncoderConfig* encoder_config) override { 554 send_config->overuse_callback = this; 555 send_config->encoder_settings.encoder = &encoder_; 556 } 557 558 void PerformTest() override { 559 EXPECT_TRUE(Wait()) << "Timed out before receiving an overuse callback."; 560 } 561 562 LoadObserver::Load tested_load_; 563 test::DelayedEncoder encoder_; 564 } test(tested_load, encode_delay_ms); 565 566 RunBaseTest(&test); 567} 568 569TEST_F(CallPerfTest, ReceivesCpuUnderuse) { 570 const int kEncodeDelayMs = 2; 571 TestCpuOveruse(LoadObserver::kUnderuse, kEncodeDelayMs); 572} 573 574TEST_F(CallPerfTest, ReceivesCpuOveruse) { 575 const int kEncodeDelayMs = 35; 576 TestCpuOveruse(LoadObserver::kOveruse, kEncodeDelayMs); 577} 578 579void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) { 580 static const int kMaxEncodeBitrateKbps = 30; 581 static const int kMinTransmitBitrateBps = 150000; 582 static const int kMinAcceptableTransmitBitrate = 130; 583 static const int kMaxAcceptableTransmitBitrate = 170; 584 static const int kNumBitrateObservationsInRange = 100; 585 static const int kAcceptableBitrateErrorMargin = 15; // +- 7 586 class BitrateObserver : public test::EndToEndTest { 587 public: 588 explicit BitrateObserver(bool using_min_transmit_bitrate) 589 : EndToEndTest(kLongTimeoutMs), 590 send_stream_(nullptr), 591 pad_to_min_bitrate_(using_min_transmit_bitrate), 592 num_bitrate_observations_in_range_(0) {} 593 594 private: 595 // TODO(holmer): Run this with a timer instead of once per packet. 596 Action OnSendRtp(const uint8_t* packet, size_t length) override { 597 VideoSendStream::Stats stats = send_stream_->GetStats(); 598 if (stats.substreams.size() > 0) { 599 RTC_DCHECK_EQ(1u, stats.substreams.size()); 600 int bitrate_kbps = 601 stats.substreams.begin()->second.total_bitrate_bps / 1000; 602 if (bitrate_kbps > 0) { 603 test::PrintResult( 604 "bitrate_stats_", 605 (pad_to_min_bitrate_ ? "min_transmit_bitrate" 606 : "without_min_transmit_bitrate"), 607 "bitrate_kbps", 608 static_cast<size_t>(bitrate_kbps), 609 "kbps", 610 false); 611 if (pad_to_min_bitrate_) { 612 if (bitrate_kbps > kMinAcceptableTransmitBitrate && 613 bitrate_kbps < kMaxAcceptableTransmitBitrate) { 614 ++num_bitrate_observations_in_range_; 615 } 616 } else { 617 // Expect bitrate stats to roughly match the max encode bitrate. 618 if (bitrate_kbps > (kMaxEncodeBitrateKbps - 619 kAcceptableBitrateErrorMargin / 2) && 620 bitrate_kbps < (kMaxEncodeBitrateKbps + 621 kAcceptableBitrateErrorMargin / 2)) { 622 ++num_bitrate_observations_in_range_; 623 } 624 } 625 if (num_bitrate_observations_in_range_ == 626 kNumBitrateObservationsInRange) 627 observation_complete_.Set(); 628 } 629 } 630 return SEND_PACKET; 631 } 632 633 void OnVideoStreamsCreated( 634 VideoSendStream* send_stream, 635 const std::vector<VideoReceiveStream*>& receive_streams) override { 636 send_stream_ = send_stream; 637 } 638 639 void ModifyVideoConfigs( 640 VideoSendStream::Config* send_config, 641 std::vector<VideoReceiveStream::Config>* receive_configs, 642 VideoEncoderConfig* encoder_config) override { 643 if (pad_to_min_bitrate_) { 644 encoder_config->min_transmit_bitrate_bps = kMinTransmitBitrateBps; 645 } else { 646 RTC_DCHECK_EQ(0, encoder_config->min_transmit_bitrate_bps); 647 } 648 } 649 650 void PerformTest() override { 651 EXPECT_TRUE(Wait()) << "Timeout while waiting for send-bitrate stats."; 652 } 653 654 VideoSendStream* send_stream_; 655 const bool pad_to_min_bitrate_; 656 int num_bitrate_observations_in_range_; 657 } test(pad_to_min_bitrate); 658 659 fake_encoder_.SetMaxBitrate(kMaxEncodeBitrateKbps); 660 RunBaseTest(&test); 661} 662 663TEST_F(CallPerfTest, PadsToMinTransmitBitrate) { TestMinTransmitBitrate(true); } 664 665TEST_F(CallPerfTest, NoPadWithoutMinTransmitBitrate) { 666 TestMinTransmitBitrate(false); 667} 668 669TEST_F(CallPerfTest, KeepsHighBitrateWhenReconfiguringSender) { 670 static const uint32_t kInitialBitrateKbps = 400; 671 static const uint32_t kReconfigureThresholdKbps = 600; 672 static const uint32_t kPermittedReconfiguredBitrateDiffKbps = 100; 673 674 class BitrateObserver : public test::EndToEndTest, public test::FakeEncoder { 675 public: 676 BitrateObserver() 677 : EndToEndTest(kDefaultTimeoutMs), 678 FakeEncoder(Clock::GetRealTimeClock()), 679 time_to_reconfigure_(false, false), 680 encoder_inits_(0), 681 last_set_bitrate_(0), 682 send_stream_(nullptr) {} 683 684 int32_t InitEncode(const VideoCodec* config, 685 int32_t number_of_cores, 686 size_t max_payload_size) override { 687 if (encoder_inits_ == 0) { 688 EXPECT_EQ(kInitialBitrateKbps, config->startBitrate) 689 << "Encoder not initialized at expected bitrate."; 690 } 691 ++encoder_inits_; 692 if (encoder_inits_ == 2) { 693 EXPECT_GE(last_set_bitrate_, kReconfigureThresholdKbps); 694 EXPECT_NEAR(config->startBitrate, 695 last_set_bitrate_, 696 kPermittedReconfiguredBitrateDiffKbps) 697 << "Encoder reconfigured with bitrate too far away from last set."; 698 observation_complete_.Set(); 699 } 700 return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size); 701 } 702 703 int32_t SetRates(uint32_t new_target_bitrate_kbps, 704 uint32_t framerate) override { 705 last_set_bitrate_ = new_target_bitrate_kbps; 706 if (encoder_inits_ == 1 && 707 new_target_bitrate_kbps > kReconfigureThresholdKbps) { 708 time_to_reconfigure_.Set(); 709 } 710 return FakeEncoder::SetRates(new_target_bitrate_kbps, framerate); 711 } 712 713 Call::Config GetSenderCallConfig() override { 714 Call::Config config = EndToEndTest::GetSenderCallConfig(); 715 config.bitrate_config.start_bitrate_bps = kInitialBitrateKbps * 1000; 716 return config; 717 } 718 719 void ModifyVideoConfigs( 720 VideoSendStream::Config* send_config, 721 std::vector<VideoReceiveStream::Config>* receive_configs, 722 VideoEncoderConfig* encoder_config) override { 723 send_config->encoder_settings.encoder = this; 724 encoder_config->streams[0].min_bitrate_bps = 50000; 725 encoder_config->streams[0].target_bitrate_bps = 726 encoder_config->streams[0].max_bitrate_bps = 2000000; 727 728 encoder_config_ = *encoder_config; 729 } 730 731 void OnVideoStreamsCreated( 732 VideoSendStream* send_stream, 733 const std::vector<VideoReceiveStream*>& receive_streams) override { 734 send_stream_ = send_stream; 735 } 736 737 void PerformTest() override { 738 ASSERT_TRUE(time_to_reconfigure_.Wait(kDefaultTimeoutMs)) 739 << "Timed out before receiving an initial high bitrate."; 740 encoder_config_.streams[0].width *= 2; 741 encoder_config_.streams[0].height *= 2; 742 EXPECT_TRUE(send_stream_->ReconfigureVideoEncoder(encoder_config_)); 743 EXPECT_TRUE(Wait()) 744 << "Timed out while waiting for a couple of high bitrate estimates " 745 "after reconfiguring the send stream."; 746 } 747 748 private: 749 rtc::Event time_to_reconfigure_; 750 int encoder_inits_; 751 uint32_t last_set_bitrate_; 752 VideoSendStream* send_stream_; 753 VideoEncoderConfig encoder_config_; 754 } test; 755 756 RunBaseTest(&test); 757} 758 759} // namespace webrtc 760