| 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 |
| 11 #include <algorithm> | 11 #include <algorithm> |
| 12 #include <limits> | 12 #include <limits> |
| 13 #include <memory> | 13 #include <memory> |
| 14 #include <sstream> | |
| 15 #include <string> | 14 #include <string> |
| 16 | 15 |
| 17 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 18 | 17 |
| 19 #include "webrtc/base/checks.h" | 18 #include "webrtc/base/checks.h" |
| 20 #include "webrtc/base/constructormagic.h" | 19 #include "webrtc/base/constructormagic.h" |
| 21 #include "webrtc/base/thread_annotations.h" | 20 #include "webrtc/base/thread_annotations.h" |
| 22 #include "webrtc/call.h" | 21 #include "webrtc/call.h" |
| 23 #include "webrtc/call/transport_adapter.h" | 22 #include "webrtc/call/transport_adapter.h" |
| 24 #include "webrtc/config.h" | 23 #include "webrtc/config.h" |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 { | 92 { |
| 94 rtc::CritScope lock(&crit_); | 93 rtc::CritScope lock(&crit_); |
| 95 if (receive_stream_) | 94 if (receive_stream_) |
| 96 stats = receive_stream_->GetStats(); | 95 stats = receive_stream_->GetStats(); |
| 97 } | 96 } |
| 98 if (stats.sync_offset_ms == std::numeric_limits<int>::max()) | 97 if (stats.sync_offset_ms == std::numeric_limits<int>::max()) |
| 99 return; | 98 return; |
| 100 | 99 |
| 101 int64_t now_ms = clock_->TimeInMilliseconds(); | 100 int64_t now_ms = clock_->TimeInMilliseconds(); |
| 102 | 101 |
| 103 std::stringstream ss; | 102 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_; | 103 int64_t time_since_creation = now_ms - creation_time_ms_; |
| 112 // During the first couple of seconds audio and video can falsely be | 104 // 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. | 105 // estimated as being synchronized. We don't want to trigger on those. |
| 114 if (time_since_creation < kStartupTimeMs) | 106 if (time_since_creation < kStartupTimeMs) |
| 115 return; | 107 return; |
| 116 if (std::abs(stats.sync_offset_ms) < kInSyncThresholdMs) { | 108 if (std::abs(stats.sync_offset_ms) < kInSyncThresholdMs) { |
| 117 if (first_time_in_sync_ == -1) { | 109 if (first_time_in_sync_ == -1) { |
| 118 first_time_in_sync_ = now_ms; | 110 first_time_in_sync_ = now_ms; |
| 119 webrtc::test::PrintResult("sync_convergence_time", | 111 webrtc::test::PrintResult("sync_convergence_time", |
| 120 "", | 112 "", |
| 121 "synchronization", | 113 "synchronization", |
| 122 time_since_creation, | 114 time_since_creation, |
| 123 "ms", | 115 "ms", |
| 124 false); | 116 false); |
| 125 } | 117 } |
| 126 if (time_since_creation > kMinRunTimeMs) | 118 if (time_since_creation > kMinRunTimeMs) |
| 127 observation_complete_.Set(); | 119 observation_complete_.Set(); |
| 128 } | 120 } |
| 129 } | 121 } |
| 130 | 122 |
| 131 void set_receive_stream(VideoReceiveStream* receive_stream) { | 123 void set_receive_stream(VideoReceiveStream* receive_stream) { |
| 132 rtc::CritScope lock(&crit_); | 124 rtc::CritScope lock(&crit_); |
| 133 receive_stream_ = receive_stream; | 125 receive_stream_ = receive_stream; |
| 134 } | 126 } |
| 135 | 127 |
| 128 void PrintResults() { |
| 129 test::PrintResultList("stream_offset", "", "synchronization", |
| 130 test::ValuesToString(sync_offset_ms_list_), "ms", |
| 131 false); |
| 132 } |
| 133 |
| 136 private: | 134 private: |
| 137 Clock* const clock_; | 135 Clock* const clock_; |
| 138 const int64_t creation_time_ms_; | 136 const int64_t creation_time_ms_; |
| 139 int64_t first_time_in_sync_; | 137 int64_t first_time_in_sync_; |
| 140 rtc::CriticalSection crit_; | 138 rtc::CriticalSection crit_; |
| 141 VideoReceiveStream* receive_stream_ GUARDED_BY(crit_); | 139 VideoReceiveStream* receive_stream_ GUARDED_BY(crit_); |
| 140 std::vector<int> sync_offset_ms_list_; |
| 142 }; | 141 }; |
| 143 | 142 |
| 144 void CallPerfTest::TestAudioVideoSync(FecMode fec, | 143 void CallPerfTest::TestAudioVideoSync(FecMode fec, |
| 145 CreateOrder create_first, | 144 CreateOrder create_first, |
| 146 float video_ntp_speed, | 145 float video_ntp_speed, |
| 147 float video_rtp_speed, | 146 float video_rtp_speed, |
| 148 float audio_rtp_speed) { | 147 float audio_rtp_speed) { |
| 149 const char* kSyncGroup = "av_sync"; | 148 const char* kSyncGroup = "av_sync"; |
| 150 const uint32_t kAudioSendSsrc = 1234; | 149 const uint32_t kAudioSendSsrc = 1234; |
| 151 const uint32_t kAudioRecvSsrc = 5678; | 150 const uint32_t kAudioRecvSsrc = 5678; |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 293 | 292 |
| 294 voe_base->DeleteChannel(send_channel_id); | 293 voe_base->DeleteChannel(send_channel_id); |
| 295 voe_base->DeleteChannel(recv_channel_id); | 294 voe_base->DeleteChannel(recv_channel_id); |
| 296 voe_base->Release(); | 295 voe_base->Release(); |
| 297 voe_codec->Release(); | 296 voe_codec->Release(); |
| 298 | 297 |
| 299 DestroyCalls(); | 298 DestroyCalls(); |
| 300 | 299 |
| 301 VoiceEngine::Delete(voice_engine); | 300 VoiceEngine::Delete(voice_engine); |
| 302 | 301 |
| 302 observer.PrintResults(); |
| 303 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AVSyncOffsetInMs")); | 303 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AVSyncOffsetInMs")); |
| 304 } | 304 } |
| 305 | 305 |
| 306 TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSyncWithVideoNtpDrift) { | 306 TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSyncWithVideoNtpDrift) { |
| 307 TestAudioVideoSync(FecMode::kOff, CreateOrder::kAudioFirst, | 307 TestAudioVideoSync(FecMode::kOff, CreateOrder::kAudioFirst, |
| 308 DriftingClock::PercentsFaster(10.0f), | 308 DriftingClock::PercentsFaster(10.0f), |
| 309 DriftingClock::kNoDrift, DriftingClock::kNoDrift); | 309 DriftingClock::kNoDrift, DriftingClock::kNoDrift); |
| 310 } | 310 } |
| 311 | 311 |
| 312 TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSyncWithAudioFasterThanVideoDrift) { | 312 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()); | 380 EXPECT_TRUE(iter != capture_time_list_.end()); |
| 381 | 381 |
| 382 // The real capture time has been wrapped to uint32_t before converted | 382 // 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 | 383 // 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. | 384 // capture time to a uint32_t 90k timestamp also for comparing. |
| 385 uint32_t estimated_capture_timestamp = | 385 uint32_t estimated_capture_timestamp = |
| 386 90 * static_cast<uint32_t>(video_frame.ntp_time_ms()); | 386 90 * static_cast<uint32_t>(video_frame.ntp_time_ms()); |
| 387 uint32_t real_capture_timestamp = iter->second; | 387 uint32_t real_capture_timestamp = iter->second; |
| 388 int time_offset_ms = real_capture_timestamp - estimated_capture_timestamp; | 388 int time_offset_ms = real_capture_timestamp - estimated_capture_timestamp; |
| 389 time_offset_ms = time_offset_ms / 90; | 389 time_offset_ms = time_offset_ms / 90; |
| 390 std::stringstream ss; | 390 time_offset_ms_list_.push_back(time_offset_ms); |
| 391 ss << time_offset_ms; | |
| 392 | 391 |
| 393 webrtc::test::PrintResult( | |
| 394 "capture_ntp_time", "", "real - estimated", ss.str(), "ms", true); | |
| 395 EXPECT_TRUE(std::abs(time_offset_ms) < threshold_ms_); | 392 EXPECT_TRUE(std::abs(time_offset_ms) < threshold_ms_); |
| 396 } | 393 } |
| 397 | 394 |
| 398 Action OnSendRtp(const uint8_t* packet, size_t length) override { | 395 Action OnSendRtp(const uint8_t* packet, size_t length) override { |
| 399 rtc::CritScope lock(&crit_); | 396 rtc::CritScope lock(&crit_); |
| 400 RTPHeader header; | 397 RTPHeader header; |
| 401 EXPECT_TRUE(parser_->Parse(packet, length, &header)); | 398 EXPECT_TRUE(parser_->Parse(packet, length, &header)); |
| 402 | 399 |
| 403 if (!rtp_start_timestamp_set_) { | 400 if (!rtp_start_timestamp_set_) { |
| 404 // Calculate the rtp timestamp offset in order to calculate the real | 401 // Calculate the rtp timestamp offset in order to calculate the real |
| (...skipping 22 matching lines...) Expand all Loading... |
| 427 VideoEncoderConfig* encoder_config) override { | 424 VideoEncoderConfig* encoder_config) override { |
| 428 (*receive_configs)[0].renderer = this; | 425 (*receive_configs)[0].renderer = this; |
| 429 // Enable the receiver side rtt calculation. | 426 // Enable the receiver side rtt calculation. |
| 430 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true; | 427 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true; |
| 431 } | 428 } |
| 432 | 429 |
| 433 void PerformTest() override { | 430 void PerformTest() override { |
| 434 EXPECT_TRUE(Wait()) << "Timed out while waiting for " | 431 EXPECT_TRUE(Wait()) << "Timed out while waiting for " |
| 435 "estimated capture NTP time to be " | 432 "estimated capture NTP time to be " |
| 436 "within bounds."; | 433 "within bounds."; |
| 434 test::PrintResultList("capture_ntp_time", "", "real - estimated", |
| 435 test::ValuesToString(time_offset_ms_list_), "ms", |
| 436 true); |
| 437 } | 437 } |
| 438 | 438 |
| 439 rtc::CriticalSection crit_; | 439 rtc::CriticalSection crit_; |
| 440 const FakeNetworkPipe::Config net_config_; | 440 const FakeNetworkPipe::Config net_config_; |
| 441 Clock* const clock_; | 441 Clock* const clock_; |
| 442 int threshold_ms_; | 442 int threshold_ms_; |
| 443 int start_time_ms_; | 443 int start_time_ms_; |
| 444 int run_time_ms_; | 444 int run_time_ms_; |
| 445 int64_t creation_time_ms_; | 445 int64_t creation_time_ms_; |
| 446 test::FrameGeneratorCapturer* capturer_; | 446 test::FrameGeneratorCapturer* capturer_; |
| 447 bool rtp_start_timestamp_set_; | 447 bool rtp_start_timestamp_set_; |
| 448 uint32_t rtp_start_timestamp_; | 448 uint32_t rtp_start_timestamp_; |
| 449 typedef std::map<uint32_t, uint32_t> FrameCaptureTimeList; | 449 typedef std::map<uint32_t, uint32_t> FrameCaptureTimeList; |
| 450 FrameCaptureTimeList capture_time_list_ GUARDED_BY(&crit_); | 450 FrameCaptureTimeList capture_time_list_ GUARDED_BY(&crit_); |
| 451 std::vector<int> time_offset_ms_list_; |
| 451 } test(net_config, threshold_ms, start_time_ms, run_time_ms); | 452 } test(net_config, threshold_ms, start_time_ms, run_time_ms); |
| 452 | 453 |
| 453 RunBaseTest(&test); | 454 RunBaseTest(&test); |
| 454 } | 455 } |
| 455 | 456 |
| 456 TEST_F(CallPerfTest, CaptureNtpTimeWithNetworkDelay) { | 457 TEST_F(CallPerfTest, CaptureNtpTimeWithNetworkDelay) { |
| 457 FakeNetworkPipe::Config net_config; | 458 FakeNetworkPipe::Config net_config; |
| 458 net_config.queue_delay_ms = 100; | 459 net_config.queue_delay_ms = 100; |
| 459 // TODO(wu): lower the threshold as the calculation/estimatation becomes more | 460 // TODO(wu): lower the threshold as the calculation/estimatation becomes more |
| 460 // accurate. | 461 // accurate. |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 536 | 537 |
| 537 private: | 538 private: |
| 538 // TODO(holmer): Run this with a timer instead of once per packet. | 539 // TODO(holmer): Run this with a timer instead of once per packet. |
| 539 Action OnSendRtp(const uint8_t* packet, size_t length) override { | 540 Action OnSendRtp(const uint8_t* packet, size_t length) override { |
| 540 VideoSendStream::Stats stats = send_stream_->GetStats(); | 541 VideoSendStream::Stats stats = send_stream_->GetStats(); |
| 541 if (stats.substreams.size() > 0) { | 542 if (stats.substreams.size() > 0) { |
| 542 RTC_DCHECK_EQ(1u, stats.substreams.size()); | 543 RTC_DCHECK_EQ(1u, stats.substreams.size()); |
| 543 int bitrate_kbps = | 544 int bitrate_kbps = |
| 544 stats.substreams.begin()->second.total_bitrate_bps / 1000; | 545 stats.substreams.begin()->second.total_bitrate_bps / 1000; |
| 545 if (bitrate_kbps > 0) { | 546 if (bitrate_kbps > 0) { |
| 546 test::PrintResult( | 547 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_) { | 548 if (pad_to_min_bitrate_) { |
| 555 if (bitrate_kbps > kMinAcceptableTransmitBitrate && | 549 if (bitrate_kbps > kMinAcceptableTransmitBitrate && |
| 556 bitrate_kbps < kMaxAcceptableTransmitBitrate) { | 550 bitrate_kbps < kMaxAcceptableTransmitBitrate) { |
| 557 ++num_bitrate_observations_in_range_; | 551 ++num_bitrate_observations_in_range_; |
| 558 } | 552 } |
| 559 } else { | 553 } else { |
| 560 // Expect bitrate stats to roughly match the max encode bitrate. | 554 // Expect bitrate stats to roughly match the max encode bitrate. |
| 561 if (bitrate_kbps > (kMaxEncodeBitrateKbps - | 555 if (bitrate_kbps > (kMaxEncodeBitrateKbps - |
| 562 kAcceptableBitrateErrorMargin / 2) && | 556 kAcceptableBitrateErrorMargin / 2) && |
| 563 bitrate_kbps < (kMaxEncodeBitrateKbps + | 557 bitrate_kbps < (kMaxEncodeBitrateKbps + |
| (...skipping 21 matching lines...) Expand all Loading... |
| 585 VideoEncoderConfig* encoder_config) override { | 579 VideoEncoderConfig* encoder_config) override { |
| 586 if (pad_to_min_bitrate_) { | 580 if (pad_to_min_bitrate_) { |
| 587 encoder_config->min_transmit_bitrate_bps = kMinTransmitBitrateBps; | 581 encoder_config->min_transmit_bitrate_bps = kMinTransmitBitrateBps; |
| 588 } else { | 582 } else { |
| 589 RTC_DCHECK_EQ(0, encoder_config->min_transmit_bitrate_bps); | 583 RTC_DCHECK_EQ(0, encoder_config->min_transmit_bitrate_bps); |
| 590 } | 584 } |
| 591 } | 585 } |
| 592 | 586 |
| 593 void PerformTest() override { | 587 void PerformTest() override { |
| 594 EXPECT_TRUE(Wait()) << "Timeout while waiting for send-bitrate stats."; | 588 EXPECT_TRUE(Wait()) << "Timeout while waiting for send-bitrate stats."; |
| 589 test::PrintResultList( |
| 590 "bitrate_stats_", |
| 591 (pad_to_min_bitrate_ ? "min_transmit_bitrate" |
| 592 : "without_min_transmit_bitrate"), |
| 593 "bitrate_kbps", test::ValuesToString(bitrate_kbps_list), "kbps", |
| 594 false); |
| 595 } | 595 } |
| 596 | 596 |
| 597 VideoSendStream* send_stream_; | 597 VideoSendStream* send_stream_; |
| 598 const bool pad_to_min_bitrate_; | 598 const bool pad_to_min_bitrate_; |
| 599 int num_bitrate_observations_in_range_; | 599 int num_bitrate_observations_in_range_; |
| 600 std::vector<size_t> bitrate_kbps_list; |
| 600 } test(pad_to_min_bitrate); | 601 } test(pad_to_min_bitrate); |
| 601 | 602 |
| 602 fake_encoder_.SetMaxBitrate(kMaxEncodeBitrateKbps); | 603 fake_encoder_.SetMaxBitrate(kMaxEncodeBitrateKbps); |
| 603 RunBaseTest(&test); | 604 RunBaseTest(&test); |
| 604 } | 605 } |
| 605 | 606 |
| 606 TEST_F(CallPerfTest, PadsToMinTransmitBitrate) { TestMinTransmitBitrate(true); } | 607 TEST_F(CallPerfTest, PadsToMinTransmitBitrate) { TestMinTransmitBitrate(true); } |
| 607 | 608 |
| 608 TEST_F(CallPerfTest, NoPadWithoutMinTransmitBitrate) { | 609 TEST_F(CallPerfTest, NoPadWithoutMinTransmitBitrate) { |
| 609 TestMinTransmitBitrate(false); | 610 TestMinTransmitBitrate(false); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 693 int encoder_inits_; | 694 int encoder_inits_; |
| 694 uint32_t last_set_bitrate_; | 695 uint32_t last_set_bitrate_; |
| 695 VideoSendStream* send_stream_; | 696 VideoSendStream* send_stream_; |
| 696 VideoEncoderConfig encoder_config_; | 697 VideoEncoderConfig encoder_config_; |
| 697 } test; | 698 } test; |
| 698 | 699 |
| 699 RunBaseTest(&test); | 700 RunBaseTest(&test); |
| 700 } | 701 } |
| 701 | 702 |
| 702 } // namespace webrtc | 703 } // namespace webrtc |
| OLD | NEW |