Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 42 #include "webrtc/test/testsupport/perf_test.h" | 42 #include "webrtc/test/testsupport/perf_test.h" |
| 43 #include "webrtc/voice_engine/include/voe_base.h" | 43 #include "webrtc/voice_engine/include/voe_base.h" |
| 44 #include "webrtc/voice_engine/include/voe_codec.h" | 44 #include "webrtc/voice_engine/include/voe_codec.h" |
| 45 #include "webrtc/voice_engine/include/voe_rtp_rtcp.h" | 45 #include "webrtc/voice_engine/include/voe_rtp_rtcp.h" |
| 46 #include "webrtc/voice_engine/include/voe_video_sync.h" | 46 #include "webrtc/voice_engine/include/voe_video_sync.h" |
| 47 | 47 |
| 48 using webrtc::test::DriftingClock; | 48 using webrtc::test::DriftingClock; |
| 49 using webrtc::test::FakeAudioDevice; | 49 using webrtc::test::FakeAudioDevice; |
| 50 | 50 |
| 51 namespace webrtc { | 51 namespace webrtc { |
| 52 namespace { | |
| 53 | |
| 54 // Converts list of values into comma-separated string for PrintResultList. | |
|
pbos-webrtc
2016/06/03 15:10:03
Pref that you move this to webrtc/test/testsupport
danilchap
2016/06/03 15:32:13
Moved to perf_test.h since it is a template functi
| |
| 55 template <typename Container> | |
| 56 std::string ValuesToString(const Container& container) { | |
| 57 if (container.empty()) | |
| 58 return ""; | |
| 59 | |
| 60 std::stringstream ss; | |
| 61 auto it = container.begin(); | |
| 62 while (true) { | |
| 63 ss << *it; | |
| 64 if (++it == container.end()) | |
| 65 return ss.str(); | |
|
pbos-webrtc
2016/06/03 15:10:03
preferring break here, I think some compilers migh
danilchap
2016/06/03 15:32:13
Done.
| |
| 66 ss << ','; | |
| 67 } | |
| 68 } | |
| 69 | |
| 70 } // namespace | |
| 52 | 71 |
| 53 class CallPerfTest : public test::CallTest { | 72 class CallPerfTest : public test::CallTest { |
| 54 protected: | 73 protected: |
| 55 enum class FecMode { | 74 enum class FecMode { |
| 56 kOn, kOff | 75 kOn, kOff |
| 57 }; | 76 }; |
| 58 enum class CreateOrder { | 77 enum class CreateOrder { |
| 59 kAudioFirst, kVideoFirst | 78 kAudioFirst, kVideoFirst |
| 60 }; | 79 }; |
| 61 void TestAudioVideoSync(FecMode fec, | 80 void TestAudioVideoSync(FecMode fec, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 93 { | 112 { |
| 94 rtc::CritScope lock(&crit_); | 113 rtc::CritScope lock(&crit_); |
| 95 if (receive_stream_) | 114 if (receive_stream_) |
| 96 stats = receive_stream_->GetStats(); | 115 stats = receive_stream_->GetStats(); |
| 97 } | 116 } |
| 98 if (stats.sync_offset_ms == std::numeric_limits<int>::max()) | 117 if (stats.sync_offset_ms == std::numeric_limits<int>::max()) |
| 99 return; | 118 return; |
| 100 | 119 |
| 101 int64_t now_ms = clock_->TimeInMilliseconds(); | 120 int64_t now_ms = clock_->TimeInMilliseconds(); |
| 102 | 121 |
| 103 std::stringstream ss; | 122 sync_offset_ms_list_.push_back(stats.sync_offset_ms); |
| 104 ss << stats.sync_offset_ms; | |
| 105 webrtc::test::PrintResult("stream_offset", | |
| 106 "", | |
| 107 "synchronization", | |
| 108 ss.str(), | |
| 109 "ms", | |
| 110 false); | |
| 111 int64_t time_since_creation = now_ms - creation_time_ms_; | 123 int64_t time_since_creation = now_ms - creation_time_ms_; |
| 112 // During the first couple of seconds audio and video can falsely be | 124 // During the first couple of seconds audio and video can falsely be |
| 113 // estimated as being synchronized. We don't want to trigger on those. | 125 // estimated as being synchronized. We don't want to trigger on those. |
| 114 if (time_since_creation < kStartupTimeMs) | 126 if (time_since_creation < kStartupTimeMs) |
| 115 return; | 127 return; |
| 116 if (std::abs(stats.sync_offset_ms) < kInSyncThresholdMs) { | 128 if (std::abs(stats.sync_offset_ms) < kInSyncThresholdMs) { |
| 117 if (first_time_in_sync_ == -1) { | 129 if (first_time_in_sync_ == -1) { |
| 118 first_time_in_sync_ = now_ms; | 130 first_time_in_sync_ = now_ms; |
| 119 webrtc::test::PrintResult("sync_convergence_time", | 131 webrtc::test::PrintResult("sync_convergence_time", |
| 120 "", | 132 "", |
| 121 "synchronization", | 133 "synchronization", |
| 122 time_since_creation, | 134 time_since_creation, |
| 123 "ms", | 135 "ms", |
| 124 false); | 136 false); |
| 125 } | 137 } |
| 126 if (time_since_creation > kMinRunTimeMs) | 138 if (time_since_creation > kMinRunTimeMs) |
| 127 observation_complete_.Set(); | 139 observation_complete_.Set(); |
| 128 } | 140 } |
| 129 } | 141 } |
| 130 | 142 |
| 131 void set_receive_stream(VideoReceiveStream* receive_stream) { | 143 void set_receive_stream(VideoReceiveStream* receive_stream) { |
| 132 rtc::CritScope lock(&crit_); | 144 rtc::CritScope lock(&crit_); |
| 133 receive_stream_ = receive_stream; | 145 receive_stream_ = receive_stream; |
| 134 } | 146 } |
| 135 | 147 |
| 148 void PrintResults() { | |
| 149 test::PrintResultList("stream_offset", "", "synchronization", | |
| 150 ValuesToString(sync_offset_ms_list_), "ms", false); | |
| 151 } | |
| 152 | |
| 136 private: | 153 private: |
| 137 Clock* const clock_; | 154 Clock* const clock_; |
| 138 const int64_t creation_time_ms_; | 155 const int64_t creation_time_ms_; |
| 139 int64_t first_time_in_sync_; | 156 int64_t first_time_in_sync_; |
| 140 rtc::CriticalSection crit_; | 157 rtc::CriticalSection crit_; |
| 141 VideoReceiveStream* receive_stream_ GUARDED_BY(crit_); | 158 VideoReceiveStream* receive_stream_ GUARDED_BY(crit_); |
| 159 std::vector<int> sync_offset_ms_list_; | |
| 142 }; | 160 }; |
| 143 | 161 |
| 144 void CallPerfTest::TestAudioVideoSync(FecMode fec, | 162 void CallPerfTest::TestAudioVideoSync(FecMode fec, |
| 145 CreateOrder create_first, | 163 CreateOrder create_first, |
| 146 float video_ntp_speed, | 164 float video_ntp_speed, |
| 147 float video_rtp_speed, | 165 float video_rtp_speed, |
| 148 float audio_rtp_speed) { | 166 float audio_rtp_speed) { |
| 149 const char* kSyncGroup = "av_sync"; | 167 const char* kSyncGroup = "av_sync"; |
| 150 const uint32_t kAudioSendSsrc = 1234; | 168 const uint32_t kAudioSendSsrc = 1234; |
| 151 const uint32_t kAudioRecvSsrc = 5678; | 169 const uint32_t kAudioRecvSsrc = 5678; |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 293 | 311 |
| 294 voe_base->DeleteChannel(send_channel_id); | 312 voe_base->DeleteChannel(send_channel_id); |
| 295 voe_base->DeleteChannel(recv_channel_id); | 313 voe_base->DeleteChannel(recv_channel_id); |
| 296 voe_base->Release(); | 314 voe_base->Release(); |
| 297 voe_codec->Release(); | 315 voe_codec->Release(); |
| 298 | 316 |
| 299 DestroyCalls(); | 317 DestroyCalls(); |
| 300 | 318 |
| 301 VoiceEngine::Delete(voice_engine); | 319 VoiceEngine::Delete(voice_engine); |
| 302 | 320 |
| 321 observer.PrintResults(); | |
| 303 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AVSyncOffsetInMs")); | 322 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AVSyncOffsetInMs")); |
| 304 } | 323 } |
| 305 | 324 |
| 306 TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSyncWithVideoNtpDrift) { | 325 TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSyncWithVideoNtpDrift) { |
| 307 TestAudioVideoSync(FecMode::kOff, CreateOrder::kAudioFirst, | 326 TestAudioVideoSync(FecMode::kOff, CreateOrder::kAudioFirst, |
| 308 DriftingClock::PercentsFaster(10.0f), | 327 DriftingClock::PercentsFaster(10.0f), |
| 309 DriftingClock::kNoDrift, DriftingClock::kNoDrift); | 328 DriftingClock::kNoDrift, DriftingClock::kNoDrift); |
| 310 } | 329 } |
| 311 | 330 |
| 312 TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSyncWithAudioFasterThanVideoDrift) { | 331 TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSyncWithAudioFasterThanVideoDrift) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 380 EXPECT_TRUE(iter != capture_time_list_.end()); | 399 EXPECT_TRUE(iter != capture_time_list_.end()); |
| 381 | 400 |
| 382 // The real capture time has been wrapped to uint32_t before converted | 401 // The real capture time has been wrapped to uint32_t before converted |
| 383 // to rtp timestamp in the sender side. So here we convert the estimated | 402 // to rtp timestamp in the sender side. So here we convert the estimated |
| 384 // capture time to a uint32_t 90k timestamp also for comparing. | 403 // capture time to a uint32_t 90k timestamp also for comparing. |
| 385 uint32_t estimated_capture_timestamp = | 404 uint32_t estimated_capture_timestamp = |
| 386 90 * static_cast<uint32_t>(video_frame.ntp_time_ms()); | 405 90 * static_cast<uint32_t>(video_frame.ntp_time_ms()); |
| 387 uint32_t real_capture_timestamp = iter->second; | 406 uint32_t real_capture_timestamp = iter->second; |
| 388 int time_offset_ms = real_capture_timestamp - estimated_capture_timestamp; | 407 int time_offset_ms = real_capture_timestamp - estimated_capture_timestamp; |
| 389 time_offset_ms = time_offset_ms / 90; | 408 time_offset_ms = time_offset_ms / 90; |
| 390 std::stringstream ss; | 409 time_offset_list_.push_back(time_offset_ms); |
| 391 ss << time_offset_ms; | |
| 392 | 410 |
| 393 webrtc::test::PrintResult( | |
| 394 "capture_ntp_time", "", "real - estimated", ss.str(), "ms", true); | |
| 395 EXPECT_TRUE(std::abs(time_offset_ms) < threshold_ms_); | 411 EXPECT_TRUE(std::abs(time_offset_ms) < threshold_ms_); |
| 396 } | 412 } |
| 397 | 413 |
| 398 Action OnSendRtp(const uint8_t* packet, size_t length) override { | 414 Action OnSendRtp(const uint8_t* packet, size_t length) override { |
| 399 rtc::CritScope lock(&crit_); | 415 rtc::CritScope lock(&crit_); |
| 400 RTPHeader header; | 416 RTPHeader header; |
| 401 EXPECT_TRUE(parser_->Parse(packet, length, &header)); | 417 EXPECT_TRUE(parser_->Parse(packet, length, &header)); |
| 402 | 418 |
| 403 if (!rtp_start_timestamp_set_) { | 419 if (!rtp_start_timestamp_set_) { |
| 404 // Calculate the rtp timestamp offset in order to calculate the real | 420 // Calculate the rtp timestamp offset in order to calculate the real |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 427 VideoEncoderConfig* encoder_config) override { | 443 VideoEncoderConfig* encoder_config) override { |
| 428 (*receive_configs)[0].renderer = this; | 444 (*receive_configs)[0].renderer = this; |
| 429 // Enable the receiver side rtt calculation. | 445 // Enable the receiver side rtt calculation. |
| 430 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true; | 446 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true; |
| 431 } | 447 } |
| 432 | 448 |
| 433 void PerformTest() override { | 449 void PerformTest() override { |
| 434 EXPECT_TRUE(Wait()) << "Timed out while waiting for " | 450 EXPECT_TRUE(Wait()) << "Timed out while waiting for " |
| 435 "estimated capture NTP time to be " | 451 "estimated capture NTP time to be " |
| 436 "within bounds."; | 452 "within bounds."; |
| 453 test::PrintResultList("capture_ntp_time", "", "real - estimated", | |
| 454 ValuesToString(time_offset_list_), "ms", true); | |
| 437 } | 455 } |
| 438 | 456 |
| 439 rtc::CriticalSection crit_; | 457 rtc::CriticalSection crit_; |
| 440 const FakeNetworkPipe::Config net_config_; | 458 const FakeNetworkPipe::Config net_config_; |
| 441 Clock* const clock_; | 459 Clock* const clock_; |
| 442 int threshold_ms_; | 460 int threshold_ms_; |
| 443 int start_time_ms_; | 461 int start_time_ms_; |
| 444 int run_time_ms_; | 462 int run_time_ms_; |
| 445 int64_t creation_time_ms_; | 463 int64_t creation_time_ms_; |
| 446 test::FrameGeneratorCapturer* capturer_; | 464 test::FrameGeneratorCapturer* capturer_; |
| 447 bool rtp_start_timestamp_set_; | 465 bool rtp_start_timestamp_set_; |
| 448 uint32_t rtp_start_timestamp_; | 466 uint32_t rtp_start_timestamp_; |
| 449 typedef std::map<uint32_t, uint32_t> FrameCaptureTimeList; | 467 typedef std::map<uint32_t, uint32_t> FrameCaptureTimeList; |
| 450 FrameCaptureTimeList capture_time_list_ GUARDED_BY(&crit_); | 468 FrameCaptureTimeList capture_time_list_ GUARDED_BY(&crit_); |
| 469 std::vector<int> time_offset_list_; | |
| 451 } test(net_config, threshold_ms, start_time_ms, run_time_ms); | 470 } test(net_config, threshold_ms, start_time_ms, run_time_ms); |
| 452 | 471 |
| 453 RunBaseTest(&test); | 472 RunBaseTest(&test); |
| 454 } | 473 } |
| 455 | 474 |
| 456 TEST_F(CallPerfTest, CaptureNtpTimeWithNetworkDelay) { | 475 TEST_F(CallPerfTest, CaptureNtpTimeWithNetworkDelay) { |
| 457 FakeNetworkPipe::Config net_config; | 476 FakeNetworkPipe::Config net_config; |
| 458 net_config.queue_delay_ms = 100; | 477 net_config.queue_delay_ms = 100; |
| 459 // TODO(wu): lower the threshold as the calculation/estimatation becomes more | 478 // TODO(wu): lower the threshold as the calculation/estimatation becomes more |
| 460 // accurate. | 479 // accurate. |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 536 | 555 |
| 537 private: | 556 private: |
| 538 // TODO(holmer): Run this with a timer instead of once per packet. | 557 // TODO(holmer): Run this with a timer instead of once per packet. |
| 539 Action OnSendRtp(const uint8_t* packet, size_t length) override { | 558 Action OnSendRtp(const uint8_t* packet, size_t length) override { |
| 540 VideoSendStream::Stats stats = send_stream_->GetStats(); | 559 VideoSendStream::Stats stats = send_stream_->GetStats(); |
| 541 if (stats.substreams.size() > 0) { | 560 if (stats.substreams.size() > 0) { |
| 542 RTC_DCHECK_EQ(1u, stats.substreams.size()); | 561 RTC_DCHECK_EQ(1u, stats.substreams.size()); |
| 543 int bitrate_kbps = | 562 int bitrate_kbps = |
| 544 stats.substreams.begin()->second.total_bitrate_bps / 1000; | 563 stats.substreams.begin()->second.total_bitrate_bps / 1000; |
| 545 if (bitrate_kbps > 0) { | 564 if (bitrate_kbps > 0) { |
| 546 test::PrintResult( | 565 bitrate_kbps_list.push_back(bitrate_kbps); |
| 547 "bitrate_stats_", | |
| 548 (pad_to_min_bitrate_ ? "min_transmit_bitrate" | |
| 549 : "without_min_transmit_bitrate"), | |
| 550 "bitrate_kbps", | |
| 551 static_cast<size_t>(bitrate_kbps), | |
| 552 "kbps", | |
| 553 false); | |
| 554 if (pad_to_min_bitrate_) { | 566 if (pad_to_min_bitrate_) { |
| 555 if (bitrate_kbps > kMinAcceptableTransmitBitrate && | 567 if (bitrate_kbps > kMinAcceptableTransmitBitrate && |
| 556 bitrate_kbps < kMaxAcceptableTransmitBitrate) { | 568 bitrate_kbps < kMaxAcceptableTransmitBitrate) { |
| 557 ++num_bitrate_observations_in_range_; | 569 ++num_bitrate_observations_in_range_; |
| 558 } | 570 } |
| 559 } else { | 571 } else { |
| 560 // Expect bitrate stats to roughly match the max encode bitrate. | 572 // Expect bitrate stats to roughly match the max encode bitrate. |
| 561 if (bitrate_kbps > (kMaxEncodeBitrateKbps - | 573 if (bitrate_kbps > (kMaxEncodeBitrateKbps - |
| 562 kAcceptableBitrateErrorMargin / 2) && | 574 kAcceptableBitrateErrorMargin / 2) && |
| 563 bitrate_kbps < (kMaxEncodeBitrateKbps + | 575 bitrate_kbps < (kMaxEncodeBitrateKbps + |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 585 VideoEncoderConfig* encoder_config) override { | 597 VideoEncoderConfig* encoder_config) override { |
| 586 if (pad_to_min_bitrate_) { | 598 if (pad_to_min_bitrate_) { |
| 587 encoder_config->min_transmit_bitrate_bps = kMinTransmitBitrateBps; | 599 encoder_config->min_transmit_bitrate_bps = kMinTransmitBitrateBps; |
| 588 } else { | 600 } else { |
| 589 RTC_DCHECK_EQ(0, encoder_config->min_transmit_bitrate_bps); | 601 RTC_DCHECK_EQ(0, encoder_config->min_transmit_bitrate_bps); |
| 590 } | 602 } |
| 591 } | 603 } |
| 592 | 604 |
| 593 void PerformTest() override { | 605 void PerformTest() override { |
| 594 EXPECT_TRUE(Wait()) << "Timeout while waiting for send-bitrate stats."; | 606 EXPECT_TRUE(Wait()) << "Timeout while waiting for send-bitrate stats."; |
| 607 test::PrintResultList( | |
| 608 "bitrate_stats_", | |
| 609 (pad_to_min_bitrate_ ? "min_transmit_bitrate" | |
| 610 : "without_min_transmit_bitrate"), | |
| 611 "bitrate_kbps", ValuesToString(bitrate_kbps_list), "kbps", false); | |
| 595 } | 612 } |
| 596 | 613 |
| 597 VideoSendStream* send_stream_; | 614 VideoSendStream* send_stream_; |
| 598 const bool pad_to_min_bitrate_; | 615 const bool pad_to_min_bitrate_; |
| 599 int num_bitrate_observations_in_range_; | 616 int num_bitrate_observations_in_range_; |
| 617 std::vector<size_t> bitrate_kbps_list; | |
| 600 } test(pad_to_min_bitrate); | 618 } test(pad_to_min_bitrate); |
| 601 | 619 |
| 602 fake_encoder_.SetMaxBitrate(kMaxEncodeBitrateKbps); | 620 fake_encoder_.SetMaxBitrate(kMaxEncodeBitrateKbps); |
| 603 RunBaseTest(&test); | 621 RunBaseTest(&test); |
| 604 } | 622 } |
| 605 | 623 |
| 606 TEST_F(CallPerfTest, PadsToMinTransmitBitrate) { TestMinTransmitBitrate(true); } | 624 TEST_F(CallPerfTest, PadsToMinTransmitBitrate) { TestMinTransmitBitrate(true); } |
| 607 | 625 |
| 608 TEST_F(CallPerfTest, NoPadWithoutMinTransmitBitrate) { | 626 TEST_F(CallPerfTest, NoPadWithoutMinTransmitBitrate) { |
| 609 TestMinTransmitBitrate(false); | 627 TestMinTransmitBitrate(false); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 693 int encoder_inits_; | 711 int encoder_inits_; |
| 694 uint32_t last_set_bitrate_; | 712 uint32_t last_set_bitrate_; |
| 695 VideoSendStream* send_stream_; | 713 VideoSendStream* send_stream_; |
| 696 VideoEncoderConfig encoder_config_; | 714 VideoEncoderConfig encoder_config_; |
| 697 } test; | 715 } test; |
| 698 | 716 |
| 699 RunBaseTest(&test); | 717 RunBaseTest(&test); |
| 700 } | 718 } |
| 701 | 719 |
| 702 } // namespace webrtc | 720 } // namespace webrtc |
| OLD | NEW |