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 |