OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2016 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 <limits> | 11 #include <limits> |
12 #include <utility> | 12 #include <utility> |
13 | 13 |
14 #include "webrtc/base/logging.h" | 14 #include "webrtc/base/logging.h" |
15 #include "webrtc/system_wrappers/include/metrics_default.h" | 15 #include "webrtc/system_wrappers/include/metrics_default.h" |
16 #include "webrtc/test/encoder_settings.h" | 16 #include "webrtc/test/encoder_settings.h" |
17 #include "webrtc/test/fake_encoder.h" | 17 #include "webrtc/test/fake_encoder.h" |
18 #include "webrtc/test/frame_generator.h" | 18 #include "webrtc/test/frame_generator.h" |
19 #include "webrtc/test/gtest.h" | 19 #include "webrtc/test/gtest.h" |
20 #include "webrtc/video/send_statistics_proxy.h" | 20 #include "webrtc/video/send_statistics_proxy.h" |
21 #include "webrtc/video/vie_encoder.h" | 21 #include "webrtc/video/vie_encoder.h" |
22 | 22 |
23 namespace webrtc { | 23 namespace webrtc { |
24 | 24 |
25 using DegredationPreference = VideoSendStream::DegradationPreference; | |
26 | |
25 namespace { | 27 namespace { |
28 // Copied from vie_encoder.cc. Must be kept in sync. | |
29 static const int kMaxCpuDowngrades = 2; | |
perkj_webrtc
2016/11/14 07:21:16
Why not keep this in ViEEncoder then? You can eve
kthelgason
2016/11/14 14:36:45
For some reason I did this because I had seen it d
| |
30 | |
26 class TestBuffer : public webrtc::I420Buffer { | 31 class TestBuffer : public webrtc::I420Buffer { |
27 public: | 32 public: |
28 TestBuffer(rtc::Event* event, int width, int height) | 33 TestBuffer(rtc::Event* event, int width, int height) |
29 : I420Buffer(width, height), event_(event) {} | 34 : I420Buffer(width, height), event_(event) {} |
30 | 35 |
31 private: | 36 private: |
32 friend class rtc::RefCountedObject<TestBuffer>; | 37 friend class rtc::RefCountedObject<TestBuffer>; |
33 ~TestBuffer() override { | 38 ~TestBuffer() override { |
34 if (event_) | 39 if (event_) |
35 event_->Set(); | 40 event_->Set(); |
36 } | 41 } |
37 rtc::Event* const event_; | 42 rtc::Event* const event_; |
38 }; | 43 }; |
39 | 44 |
40 class ViEEncoderUnderTest : public ViEEncoder { | 45 class ViEEncoderUnderTest : public ViEEncoder { |
41 public: | 46 public: |
42 ViEEncoderUnderTest( | 47 using ScalingObserverInterface::ScaleReason; |
43 SendStatisticsProxy* stats_proxy, | 48 ViEEncoderUnderTest(SendStatisticsProxy* stats_proxy, |
44 const webrtc::VideoSendStream::Config::EncoderSettings& settings) | 49 const VideoSendStream::Config::EncoderSettings& settings) |
45 : ViEEncoder(1 /* number_of_cores */, | 50 : ViEEncoder(1 /* number_of_cores */, |
46 stats_proxy, | 51 stats_proxy, |
47 settings, | 52 settings, |
48 nullptr /* pre_encode_callback */, | 53 nullptr /* pre_encode_callback */, |
49 nullptr /* encoder_timing */) {} | 54 nullptr /* encoder_timing */) {} |
50 | 55 |
51 void TriggerCpuOveruse() { | 56 void PostTaskAndWait(bool down, ScaleReason reason) { |
52 rtc::Event event(false, false); | 57 rtc::Event event(false, false); |
53 encoder_queue()->PostTask([this, &event] { | 58 encoder_queue()->PostTask([this, &event, reason, down] { |
54 OveruseDetected(); | 59 down ? ScaleDown(reason) : ScaleUp(reason); |
55 event.Set(); | 60 event.Set(); |
56 }); | 61 }); |
57 event.Wait(rtc::Event::kForever); | 62 RTC_DCHECK(event.Wait(5000)); |
58 } | 63 } |
59 | 64 |
60 void TriggerCpuNormalUsage() { | 65 void TriggerCpuOveruse() { PostTaskAndWait(true, kCpu); } |
61 rtc::Event event(false, false); | 66 |
62 encoder_queue()->PostTask([this, &event] { | 67 void TriggerCpuNormalUsage() { PostTaskAndWait(false, kCpu); } |
63 NormalUsage(); | 68 |
64 event.Set(); | 69 void TriggerQualityLow() { PostTaskAndWait(true, kQuality); } |
65 }); | 70 |
66 event.Wait(rtc::Event::kForever); | 71 void TriggerQualityHigh() { PostTaskAndWait(false, kQuality); } |
67 } | |
68 }; | 72 }; |
69 | 73 |
70 } // namespace | 74 } // namespace |
71 | 75 |
72 class ViEEncoderTest : public ::testing::Test { | 76 class ViEEncoderTest : public ::testing::Test { |
73 public: | 77 public: |
74 static const int kDefaultTimeoutMs = 30 * 1000; | 78 static const int kDefaultTimeoutMs = 30 * 1000; |
75 | 79 |
76 ViEEncoderTest() | 80 ViEEncoderTest() |
77 : video_send_config_(VideoSendStream::Config(nullptr)), | 81 : video_send_config_(VideoSendStream::Config(nullptr)), |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
127 VideoCodec codec_config() { | 131 VideoCodec codec_config() { |
128 rtc::CritScope lock(&crit_); | 132 rtc::CritScope lock(&crit_); |
129 return config_; | 133 return config_; |
130 } | 134 } |
131 | 135 |
132 void BlockNextEncode() { | 136 void BlockNextEncode() { |
133 rtc::CritScope lock(&crit_); | 137 rtc::CritScope lock(&crit_); |
134 block_next_encode_ = true; | 138 block_next_encode_ = true; |
135 } | 139 } |
136 | 140 |
141 QualityScaler::Settings GetQPThresholds() const override { | |
142 return QualityScaler::Settings(true, 1, 2); | |
143 } | |
144 | |
137 void ContinueEncode() { continue_encode_event_.Set(); } | 145 void ContinueEncode() { continue_encode_event_.Set(); } |
138 | 146 |
139 void CheckLastTimeStampsMatch(int64_t ntp_time_ms, | 147 void CheckLastTimeStampsMatch(int64_t ntp_time_ms, |
140 uint32_t timestamp) const { | 148 uint32_t timestamp) const { |
141 rtc::CritScope lock(&crit_); | 149 rtc::CritScope lock(&crit_); |
142 EXPECT_EQ(timestamp_, timestamp); | 150 EXPECT_EQ(timestamp_, timestamp); |
143 EXPECT_EQ(ntp_time_ms_, ntp_time_ms); | 151 EXPECT_EQ(ntp_time_ms_, ntp_time_ms); |
144 } | 152 } |
145 | 153 |
146 private: | 154 private: |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
404 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); | 412 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
405 | 413 |
406 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count); | 414 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count); |
407 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up); | 415 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up); |
408 | 416 |
409 int frame_width = 1280; | 417 int frame_width = 1280; |
410 int frame_height = 720; | 418 int frame_height = 720; |
411 | 419 |
412 // Trigger CPU overuse kMaxCpuDowngrades times. Every time, ViEEncoder should | 420 // Trigger CPU overuse kMaxCpuDowngrades times. Every time, ViEEncoder should |
413 // request lower resolution. | 421 // request lower resolution. |
414 for (int i = 1; i <= ViEEncoder::kMaxCpuDowngrades; ++i) { | 422 for (int i = 1; i <= kMaxCpuDowngrades; ++i) { |
415 video_source_.IncomingCapturedFrame( | 423 video_source_.IncomingCapturedFrame( |
416 CreateFrame(i, frame_width, frame_height)); | 424 CreateFrame(i, frame_width, frame_height)); |
417 sink_.WaitForEncodedFrame(i); | 425 sink_.WaitForEncodedFrame(i); |
418 | 426 |
419 vie_encoder_->TriggerCpuOveruse(); | 427 vie_encoder_->TriggerCpuOveruse(); |
420 | 428 |
421 EXPECT_LT(video_source_.sink_wants().max_pixel_count.value_or( | 429 EXPECT_LT(video_source_.sink_wants().max_pixel_count.value_or( |
422 std::numeric_limits<int>::max()), | 430 std::numeric_limits<int>::max()), |
423 frame_width * frame_height); | 431 frame_width * frame_height); |
424 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up); | 432 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up); |
425 | 433 |
426 frame_width /= 2; | 434 frame_width /= 2; |
427 frame_height /= 2; | 435 frame_height /= 2; |
428 } | 436 } |
429 | 437 |
430 // Trigger CPU overuse a one more time. This should not trigger request for | 438 // Trigger CPU overuse one more time. This should not trigger a request for |
431 // lower resolution. | 439 // lower resolution. |
432 rtc::VideoSinkWants current_wants = video_source_.sink_wants(); | 440 rtc::VideoSinkWants current_wants = video_source_.sink_wants(); |
433 video_source_.IncomingCapturedFrame(CreateFrame( | 441 video_source_.IncomingCapturedFrame( |
434 ViEEncoder::kMaxCpuDowngrades + 1, frame_width, frame_height)); | 442 CreateFrame(kMaxCpuDowngrades + 1, frame_width, frame_height)); |
435 sink_.WaitForEncodedFrame(ViEEncoder::kMaxCpuDowngrades + 1); | 443 sink_.WaitForEncodedFrame(kMaxCpuDowngrades + 1); |
436 vie_encoder_->TriggerCpuOveruse(); | 444 vie_encoder_->TriggerCpuOveruse(); |
437 EXPECT_EQ(video_source_.sink_wants().max_pixel_count, | 445 EXPECT_EQ(video_source_.sink_wants().max_pixel_count, |
438 current_wants.max_pixel_count); | 446 current_wants.max_pixel_count); |
439 EXPECT_EQ(video_source_.sink_wants().max_pixel_count_step_up, | 447 EXPECT_EQ(video_source_.sink_wants().max_pixel_count_step_up, |
440 current_wants.max_pixel_count_step_up); | 448 current_wants.max_pixel_count_step_up); |
441 | 449 |
442 // Trigger CPU normal use. | 450 // Trigger CPU normal use. |
443 vie_encoder_->TriggerCpuNormalUsage(); | 451 vie_encoder_->TriggerCpuNormalUsage(); |
444 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count); | 452 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count); |
445 EXPECT_EQ(video_source_.sink_wants().max_pixel_count_step_up.value_or(0), | 453 EXPECT_EQ(video_source_.sink_wants().max_pixel_count_step_up.value_or(0), |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
526 CreateFrame(3, frame_width, frame_height)); | 534 CreateFrame(3, frame_width, frame_height)); |
527 sink_.WaitForEncodedFrame(3); | 535 sink_.WaitForEncodedFrame(3); |
528 | 536 |
529 stats = stats_proxy_->GetStats(); | 537 stats = stats_proxy_->GetStats(); |
530 EXPECT_FALSE(stats.cpu_limited_resolution); | 538 EXPECT_FALSE(stats.cpu_limited_resolution); |
531 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes); | 539 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes); |
532 | 540 |
533 vie_encoder_->Stop(); | 541 vie_encoder_->Stop(); |
534 } | 542 } |
535 | 543 |
544 TEST_F(ViEEncoderTest, SwitchingSourceKeepsAdaptation) { | |
perkj_webrtc
2016/11/14 07:21:16
This looks like the same test as StatsTracksAdapta
kthelgason
2016/11/14 14:36:45
Ah, that's a rebase artifact. The test got duplica
| |
545 const int kTargetBitrateBps = 100000; | |
546 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); | |
547 | |
548 int frame_width = 1280; | |
549 int frame_height = 720; | |
550 video_source_.IncomingCapturedFrame( | |
551 CreateFrame(1, frame_width, frame_height)); | |
552 sink_.WaitForEncodedFrame(1); | |
553 | |
554 VideoSendStream::Stats stats = stats_proxy_->GetStats(); | |
555 EXPECT_FALSE(stats.cpu_limited_resolution); | |
556 EXPECT_FALSE(stats.bw_limited_resolution); | |
557 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes); | |
558 | |
559 // Set new source with adaptation still enabled. | |
560 test::FrameForwarder new_video_source; | |
561 vie_encoder_->SetSource(&new_video_source, | |
562 VideoSendStream::DegradationPreference::kBalanced); | |
563 | |
564 new_video_source.IncomingCapturedFrame( | |
565 CreateFrame(2, frame_width, frame_height)); | |
566 sink_.WaitForEncodedFrame(2); | |
567 stats = stats_proxy_->GetStats(); | |
568 EXPECT_FALSE(stats.cpu_limited_resolution); | |
569 EXPECT_FALSE(stats.bw_limited_resolution); | |
570 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes); | |
571 | |
572 vie_encoder_->TriggerQualityLow(); | |
573 | |
574 new_video_source.IncomingCapturedFrame( | |
575 CreateFrame(3, frame_width, frame_height)); | |
576 sink_.WaitForEncodedFrame(3); | |
577 stats = stats_proxy_->GetStats(); | |
578 EXPECT_FALSE(stats.cpu_limited_resolution); | |
579 EXPECT_TRUE(stats.bw_limited_resolution); | |
580 | |
581 vie_encoder_->SetSource(&new_video_source, | |
582 VideoSendStream::DegradationPreference::kBalanced); | |
583 | |
584 new_video_source.IncomingCapturedFrame( | |
585 CreateFrame(4, frame_width, frame_height)); | |
586 sink_.WaitForEncodedFrame(4); | |
587 stats = stats_proxy_->GetStats(); | |
588 EXPECT_FALSE(stats.cpu_limited_resolution); | |
589 EXPECT_TRUE(stats.bw_limited_resolution); | |
590 | |
591 // Set adaptation disabled. | |
592 vie_encoder_->SetSource( | |
593 &new_video_source, | |
594 VideoSendStream::DegradationPreference::kMaintainResolution); | |
595 | |
596 new_video_source.IncomingCapturedFrame( | |
597 CreateFrame(5, frame_width, frame_height)); | |
598 sink_.WaitForEncodedFrame(5); | |
599 stats = stats_proxy_->GetStats(); | |
600 EXPECT_FALSE(stats.cpu_limited_resolution); | |
601 EXPECT_FALSE(stats.bw_limited_resolution); | |
602 | |
603 vie_encoder_->Stop(); | |
604 } | |
605 | |
536 TEST_F(ViEEncoderTest, StatsTracksAdaptationStatsWhenSwitchingSource) { | 606 TEST_F(ViEEncoderTest, StatsTracksAdaptationStatsWhenSwitchingSource) { |
537 const int kTargetBitrateBps = 100000; | 607 const int kTargetBitrateBps = 100000; |
538 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); | 608 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
539 | 609 |
540 // Trigger CPU overuse. | 610 // Trigger CPU overuse. |
541 vie_encoder_->TriggerCpuOveruse(); | 611 vie_encoder_->TriggerCpuOveruse(); |
542 int frame_width = 1280; | 612 int frame_width = 1280; |
543 int frame_height = 720; | 613 int frame_height = 720; |
544 | 614 |
545 video_source_.IncomingCapturedFrame( | 615 video_source_.IncomingCapturedFrame( |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
588 video_source_.IncomingCapturedFrame( | 658 video_source_.IncomingCapturedFrame( |
589 CreateFrame(5, frame_width, frame_height)); | 659 CreateFrame(5, frame_width, frame_height)); |
590 sink_.WaitForEncodedFrame(5); | 660 sink_.WaitForEncodedFrame(5); |
591 stats = stats_proxy_->GetStats(); | 661 stats = stats_proxy_->GetStats(); |
592 EXPECT_FALSE(stats.cpu_limited_resolution); | 662 EXPECT_FALSE(stats.cpu_limited_resolution); |
593 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes); | 663 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes); |
594 | 664 |
595 vie_encoder_->Stop(); | 665 vie_encoder_->Stop(); |
596 } | 666 } |
597 | 667 |
668 TEST_F(ViEEncoderTest, StatsTracksQualityAdaptationStatsWhenSwitchingSource) { | |
669 const int kTargetBitrateBps = 100000; | |
670 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); | |
671 | |
672 // Trigger CPU overuse. | |
673 vie_encoder_->TriggerQualityLow(); | |
674 int frame_width = 1280; | |
675 int frame_height = 720; | |
676 | |
677 video_source_.IncomingCapturedFrame( | |
678 CreateFrame(1, frame_width, frame_height)); | |
679 sink_.WaitForEncodedFrame(1); | |
680 | |
681 VideoSendStream::Stats stats = stats_proxy_->GetStats(); | |
682 EXPECT_TRUE(stats.bw_limited_resolution); | |
683 | |
684 // Set new source with adaptation still enabled. | |
685 test::FrameForwarder new_video_source; | |
686 vie_encoder_->SetSource(&new_video_source, | |
687 VideoSendStream::DegradationPreference::kBalanced); | |
688 | |
689 new_video_source.IncomingCapturedFrame( | |
690 CreateFrame(2, frame_width, frame_height)); | |
691 sink_.WaitForEncodedFrame(2); | |
692 stats = stats_proxy_->GetStats(); | |
693 EXPECT_TRUE(stats.bw_limited_resolution); | |
694 | |
695 // Set adaptation disabled. | |
696 vie_encoder_->SetSource( | |
697 &new_video_source, | |
698 VideoSendStream::DegradationPreference::kMaintainResolution); | |
699 | |
700 new_video_source.IncomingCapturedFrame( | |
701 CreateFrame(3, frame_width, frame_height)); | |
702 sink_.WaitForEncodedFrame(3); | |
703 stats = stats_proxy_->GetStats(); | |
704 EXPECT_FALSE(stats.bw_limited_resolution); | |
705 | |
706 // Switch back the source with adaptation enabled. | |
707 vie_encoder_->SetSource(&video_source_, | |
708 VideoSendStream::DegradationPreference::kBalanced); | |
709 video_source_.IncomingCapturedFrame( | |
710 CreateFrame(4, frame_width, frame_height)); | |
711 sink_.WaitForEncodedFrame(4); | |
712 stats = stats_proxy_->GetStats(); | |
713 EXPECT_TRUE(stats.bw_limited_resolution); | |
714 | |
715 // Trigger CPU normal usage. | |
716 vie_encoder_->TriggerQualityHigh(); | |
717 video_source_.IncomingCapturedFrame( | |
718 CreateFrame(5, frame_width, frame_height)); | |
719 sink_.WaitForEncodedFrame(5); | |
720 stats = stats_proxy_->GetStats(); | |
721 EXPECT_FALSE(stats.bw_limited_resolution); | |
722 | |
723 vie_encoder_->Stop(); | |
724 } | |
725 | |
598 TEST_F(ViEEncoderTest, UMACpuLimitedResolutionInPercent) { | 726 TEST_F(ViEEncoderTest, UMACpuLimitedResolutionInPercent) { |
599 const int kTargetBitrateBps = 100000; | 727 const int kTargetBitrateBps = 100000; |
600 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); | 728 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
601 | 729 |
602 int frame_width = 640; | 730 int frame_width = 640; |
603 int frame_height = 360; | 731 int frame_height = 360; |
604 | 732 |
605 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) { | 733 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) { |
606 video_source_.IncomingCapturedFrame( | 734 video_source_.IncomingCapturedFrame( |
607 CreateFrame(i, frame_width, frame_height)); | 735 CreateFrame(i, frame_width, frame_height)); |
(...skipping 12 matching lines...) Expand all Loading... | |
620 vie_encoder_->Stop(); | 748 vie_encoder_->Stop(); |
621 | 749 |
622 stats_proxy_.reset(); | 750 stats_proxy_.reset(); |
623 EXPECT_EQ(1, | 751 EXPECT_EQ(1, |
624 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent")); | 752 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent")); |
625 EXPECT_EQ( | 753 EXPECT_EQ( |
626 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50)); | 754 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50)); |
627 } | 755 } |
628 | 756 |
629 } // namespace webrtc | 757 } // namespace webrtc |
OLD | NEW |