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 using ScaleReason = ScalingObserverInterface::ScaleReason; |
| 27 |
25 namespace { | 28 namespace { |
26 const size_t kMaxPayloadLength = 1440; | 29 const size_t kMaxPayloadLength = 1440; |
27 const int kTargetBitrateBps = 100000; | 30 const int kTargetBitrateBps = 100000; |
28 | 31 |
29 class TestBuffer : public webrtc::I420Buffer { | 32 class TestBuffer : public webrtc::I420Buffer { |
30 public: | 33 public: |
31 TestBuffer(rtc::Event* event, int width, int height) | 34 TestBuffer(rtc::Event* event, int width, int height) |
32 : I420Buffer(width, height), event_(event) {} | 35 : I420Buffer(width, height), event_(event) {} |
33 | 36 |
34 private: | 37 private: |
35 friend class rtc::RefCountedObject<TestBuffer>; | 38 friend class rtc::RefCountedObject<TestBuffer>; |
36 ~TestBuffer() override { | 39 ~TestBuffer() override { |
37 if (event_) | 40 if (event_) |
38 event_->Set(); | 41 event_->Set(); |
39 } | 42 } |
40 rtc::Event* const event_; | 43 rtc::Event* const event_; |
41 }; | 44 }; |
42 | 45 |
43 class ViEEncoderUnderTest : public ViEEncoder { | 46 class ViEEncoderUnderTest : public ViEEncoder { |
44 public: | 47 public: |
45 ViEEncoderUnderTest( | 48 ViEEncoderUnderTest(SendStatisticsProxy* stats_proxy, |
46 SendStatisticsProxy* stats_proxy, | 49 const VideoSendStream::Config::EncoderSettings& settings) |
47 const webrtc::VideoSendStream::Config::EncoderSettings& settings) | |
48 : ViEEncoder(1 /* number_of_cores */, | 50 : ViEEncoder(1 /* number_of_cores */, |
49 stats_proxy, | 51 stats_proxy, |
50 settings, | 52 settings, |
51 nullptr /* pre_encode_callback */, | 53 nullptr /* pre_encode_callback */, |
52 nullptr /* encoder_timing */) {} | 54 nullptr /* encoder_timing */) {} |
53 | 55 |
54 void TriggerCpuOveruse() { | 56 void PostTaskAndWait(bool down, ScaleReason reason) { |
55 rtc::Event event(false, false); | 57 rtc::Event event(false, false); |
56 encoder_queue()->PostTask([this, &event] { | 58 encoder_queue()->PostTask([this, &event, reason, down] { |
57 OveruseDetected(); | 59 down ? ScaleDown(reason) : ScaleUp(reason); |
58 event.Set(); | 60 event.Set(); |
59 }); | 61 }); |
60 event.Wait(rtc::Event::kForever); | 62 RTC_DCHECK(event.Wait(5000)); |
61 } | 63 } |
62 | 64 |
63 void TriggerCpuNormalUsage() { | 65 void TriggerCpuOveruse() { PostTaskAndWait(true, ScaleReason::kCpu); } |
64 rtc::Event event(false, false); | 66 |
65 encoder_queue()->PostTask([this, &event] { | 67 void TriggerCpuNormalUsage() { PostTaskAndWait(false, ScaleReason::kCpu); } |
66 NormalUsage(); | 68 |
67 event.Set(); | 69 void TriggerQualityLow() { PostTaskAndWait(true, ScaleReason::kQuality); } |
68 }); | 70 |
69 event.Wait(rtc::Event::kForever); | 71 void TriggerQualityHigh() { PostTaskAndWait(false, ScaleReason::kQuality); } |
70 } | |
71 }; | 72 }; |
72 | 73 |
73 class VideoStreamFactory | 74 class VideoStreamFactory |
74 : public VideoEncoderConfig::VideoStreamFactoryInterface { | 75 : public VideoEncoderConfig::VideoStreamFactoryInterface { |
75 public: | 76 public: |
76 explicit VideoStreamFactory(size_t num_temporal_layers) | 77 explicit VideoStreamFactory(size_t num_temporal_layers) |
77 : num_temporal_layers_(num_temporal_layers) { | 78 : num_temporal_layers_(num_temporal_layers) { |
78 EXPECT_GT(num_temporal_layers, 0u); | 79 EXPECT_GT(num_temporal_layers, 0u); |
79 } | 80 } |
80 | 81 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 VideoCodec codec_config() { | 177 VideoCodec codec_config() { |
177 rtc::CritScope lock(&crit_); | 178 rtc::CritScope lock(&crit_); |
178 return config_; | 179 return config_; |
179 } | 180 } |
180 | 181 |
181 void BlockNextEncode() { | 182 void BlockNextEncode() { |
182 rtc::CritScope lock(&crit_); | 183 rtc::CritScope lock(&crit_); |
183 block_next_encode_ = true; | 184 block_next_encode_ = true; |
184 } | 185 } |
185 | 186 |
| 187 VideoEncoder::ScalingSettings GetScalingSettings() const override { |
| 188 return VideoEncoder::ScalingSettings(true, 1, 2); |
| 189 } |
| 190 |
186 void ContinueEncode() { continue_encode_event_.Set(); } | 191 void ContinueEncode() { continue_encode_event_.Set(); } |
187 | 192 |
188 void CheckLastTimeStampsMatch(int64_t ntp_time_ms, | 193 void CheckLastTimeStampsMatch(int64_t ntp_time_ms, |
189 uint32_t timestamp) const { | 194 uint32_t timestamp) const { |
190 rtc::CritScope lock(&crit_); | 195 rtc::CritScope lock(&crit_); |
191 EXPECT_EQ(timestamp_, timestamp); | 196 EXPECT_EQ(timestamp_, timestamp); |
192 EXPECT_EQ(ntp_time_ms_, ntp_time_ms); | 197 EXPECT_EQ(ntp_time_ms_, ntp_time_ms); |
193 } | 198 } |
194 | 199 |
195 private: | 200 private: |
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
542 | 547 |
543 EXPECT_LT(video_source_.sink_wants().max_pixel_count.value_or( | 548 EXPECT_LT(video_source_.sink_wants().max_pixel_count.value_or( |
544 std::numeric_limits<int>::max()), | 549 std::numeric_limits<int>::max()), |
545 frame_width * frame_height); | 550 frame_width * frame_height); |
546 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up); | 551 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up); |
547 | 552 |
548 frame_width /= 2; | 553 frame_width /= 2; |
549 frame_height /= 2; | 554 frame_height /= 2; |
550 } | 555 } |
551 | 556 |
552 // Trigger CPU overuse a one more time. This should not trigger request for | 557 // Trigger CPU overuse one more time. This should not trigger a request for |
553 // lower resolution. | 558 // lower resolution. |
554 rtc::VideoSinkWants current_wants = video_source_.sink_wants(); | 559 rtc::VideoSinkWants current_wants = video_source_.sink_wants(); |
555 video_source_.IncomingCapturedFrame(CreateFrame( | 560 video_source_.IncomingCapturedFrame(CreateFrame( |
556 ViEEncoder::kMaxCpuDowngrades + 1, frame_width, frame_height)); | 561 ViEEncoder::kMaxCpuDowngrades + 1, frame_width, frame_height)); |
557 sink_.WaitForEncodedFrame(ViEEncoder::kMaxCpuDowngrades + 1); | 562 sink_.WaitForEncodedFrame(ViEEncoder::kMaxCpuDowngrades + 1); |
558 vie_encoder_->TriggerCpuOveruse(); | 563 vie_encoder_->TriggerCpuOveruse(); |
559 EXPECT_EQ(video_source_.sink_wants().max_pixel_count, | 564 EXPECT_EQ(video_source_.sink_wants().max_pixel_count, |
560 current_wants.max_pixel_count); | 565 current_wants.max_pixel_count); |
561 EXPECT_EQ(video_source_.sink_wants().max_pixel_count_step_up, | 566 EXPECT_EQ(video_source_.sink_wants().max_pixel_count_step_up, |
562 current_wants.max_pixel_count_step_up); | 567 current_wants.max_pixel_count_step_up); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
646 CreateFrame(3, frame_width, frame_height)); | 651 CreateFrame(3, frame_width, frame_height)); |
647 sink_.WaitForEncodedFrame(3); | 652 sink_.WaitForEncodedFrame(3); |
648 | 653 |
649 stats = stats_proxy_->GetStats(); | 654 stats = stats_proxy_->GetStats(); |
650 EXPECT_FALSE(stats.cpu_limited_resolution); | 655 EXPECT_FALSE(stats.cpu_limited_resolution); |
651 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes); | 656 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes); |
652 | 657 |
653 vie_encoder_->Stop(); | 658 vie_encoder_->Stop(); |
654 } | 659 } |
655 | 660 |
| 661 TEST_F(ViEEncoderTest, SwitchingSourceKeepsCpuAdaptation) { |
| 662 const int kTargetBitrateBps = 100000; |
| 663 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
| 664 |
| 665 int frame_width = 1280; |
| 666 int frame_height = 720; |
| 667 video_source_.IncomingCapturedFrame( |
| 668 CreateFrame(1, frame_width, frame_height)); |
| 669 sink_.WaitForEncodedFrame(1); |
| 670 |
| 671 VideoSendStream::Stats stats = stats_proxy_->GetStats(); |
| 672 EXPECT_FALSE(stats.cpu_limited_resolution); |
| 673 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes); |
| 674 |
| 675 vie_encoder_->TriggerCpuOveruse(); |
| 676 |
| 677 video_source_.IncomingCapturedFrame( |
| 678 CreateFrame(2, frame_width, frame_height)); |
| 679 sink_.WaitForEncodedFrame(2); |
| 680 stats = stats_proxy_->GetStats(); |
| 681 EXPECT_TRUE(stats.cpu_limited_resolution); |
| 682 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes); |
| 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(3, frame_width, frame_height)); |
| 691 sink_.WaitForEncodedFrame(3); |
| 692 stats = stats_proxy_->GetStats(); |
| 693 EXPECT_TRUE(stats.cpu_limited_resolution); |
| 694 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes); |
| 695 |
| 696 // Set adaptation disabled. |
| 697 vie_encoder_->SetSource( |
| 698 &new_video_source, |
| 699 VideoSendStream::DegradationPreference::kMaintainResolution); |
| 700 |
| 701 new_video_source.IncomingCapturedFrame( |
| 702 CreateFrame(4, frame_width, frame_height)); |
| 703 sink_.WaitForEncodedFrame(4); |
| 704 stats = stats_proxy_->GetStats(); |
| 705 EXPECT_FALSE(stats.cpu_limited_resolution); |
| 706 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes); |
| 707 |
| 708 // Set adaptation back to enabled. |
| 709 vie_encoder_->SetSource(&new_video_source, |
| 710 VideoSendStream::DegradationPreference::kBalanced); |
| 711 |
| 712 new_video_source.IncomingCapturedFrame( |
| 713 CreateFrame(5, frame_width, frame_height)); |
| 714 sink_.WaitForEncodedFrame(5); |
| 715 stats = stats_proxy_->GetStats(); |
| 716 EXPECT_TRUE(stats.cpu_limited_resolution); |
| 717 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes); |
| 718 |
| 719 vie_encoder_->TriggerCpuNormalUsage(); |
| 720 |
| 721 new_video_source.IncomingCapturedFrame( |
| 722 CreateFrame(6, frame_width, frame_height)); |
| 723 sink_.WaitForEncodedFrame(6); |
| 724 stats = stats_proxy_->GetStats(); |
| 725 EXPECT_FALSE(stats.cpu_limited_resolution); |
| 726 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes); |
| 727 |
| 728 vie_encoder_->Stop(); |
| 729 } |
| 730 |
| 731 TEST_F(ViEEncoderTest, SwitchingSourceKeepsQualityAdaptation) { |
| 732 const int kTargetBitrateBps = 100000; |
| 733 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
| 734 |
| 735 int frame_width = 1280; |
| 736 int frame_height = 720; |
| 737 video_source_.IncomingCapturedFrame( |
| 738 CreateFrame(1, frame_width, frame_height)); |
| 739 sink_.WaitForEncodedFrame(1); |
| 740 |
| 741 VideoSendStream::Stats stats = stats_proxy_->GetStats(); |
| 742 EXPECT_FALSE(stats.cpu_limited_resolution); |
| 743 EXPECT_FALSE(stats.bw_limited_resolution); |
| 744 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes); |
| 745 |
| 746 // Set new source with adaptation still enabled. |
| 747 test::FrameForwarder new_video_source; |
| 748 vie_encoder_->SetSource(&new_video_source, |
| 749 VideoSendStream::DegradationPreference::kBalanced); |
| 750 |
| 751 new_video_source.IncomingCapturedFrame( |
| 752 CreateFrame(2, frame_width, frame_height)); |
| 753 sink_.WaitForEncodedFrame(2); |
| 754 stats = stats_proxy_->GetStats(); |
| 755 EXPECT_FALSE(stats.cpu_limited_resolution); |
| 756 EXPECT_FALSE(stats.bw_limited_resolution); |
| 757 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes); |
| 758 |
| 759 vie_encoder_->TriggerQualityLow(); |
| 760 |
| 761 new_video_source.IncomingCapturedFrame( |
| 762 CreateFrame(3, frame_width, frame_height)); |
| 763 sink_.WaitForEncodedFrame(3); |
| 764 stats = stats_proxy_->GetStats(); |
| 765 EXPECT_FALSE(stats.cpu_limited_resolution); |
| 766 EXPECT_TRUE(stats.bw_limited_resolution); |
| 767 |
| 768 vie_encoder_->SetSource(&new_video_source, |
| 769 VideoSendStream::DegradationPreference::kBalanced); |
| 770 |
| 771 new_video_source.IncomingCapturedFrame( |
| 772 CreateFrame(4, frame_width, frame_height)); |
| 773 sink_.WaitForEncodedFrame(4); |
| 774 stats = stats_proxy_->GetStats(); |
| 775 EXPECT_FALSE(stats.cpu_limited_resolution); |
| 776 EXPECT_TRUE(stats.bw_limited_resolution); |
| 777 |
| 778 // Set adaptation disabled. |
| 779 vie_encoder_->SetSource( |
| 780 &new_video_source, |
| 781 VideoSendStream::DegradationPreference::kMaintainResolution); |
| 782 |
| 783 new_video_source.IncomingCapturedFrame( |
| 784 CreateFrame(5, frame_width, frame_height)); |
| 785 sink_.WaitForEncodedFrame(5); |
| 786 stats = stats_proxy_->GetStats(); |
| 787 EXPECT_FALSE(stats.cpu_limited_resolution); |
| 788 EXPECT_FALSE(stats.bw_limited_resolution); |
| 789 |
| 790 vie_encoder_->Stop(); |
| 791 } |
| 792 |
656 TEST_F(ViEEncoderTest, StatsTracksAdaptationStatsWhenSwitchingSource) { | 793 TEST_F(ViEEncoderTest, StatsTracksAdaptationStatsWhenSwitchingSource) { |
657 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); | 794 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
658 | 795 |
659 // Trigger CPU overuse. | 796 // Trigger CPU overuse. |
660 vie_encoder_->TriggerCpuOveruse(); | 797 vie_encoder_->TriggerCpuOveruse(); |
661 int frame_width = 1280; | 798 int frame_width = 1280; |
662 int frame_height = 720; | 799 int frame_height = 720; |
663 | 800 |
664 video_source_.IncomingCapturedFrame( | 801 video_source_.IncomingCapturedFrame( |
665 CreateFrame(1, frame_width, frame_height)); | 802 CreateFrame(1, frame_width, frame_height)); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
720 video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720)); | 857 video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720)); |
721 sink_.WaitForEncodedFrame(1); | 858 sink_.WaitForEncodedFrame(1); |
722 | 859 |
723 VideoSendStream::Stats stats = stats_proxy_->GetStats(); | 860 VideoSendStream::Stats stats = stats_proxy_->GetStats(); |
724 EXPECT_EQ(video_encoder_config_.max_bitrate_bps, | 861 EXPECT_EQ(video_encoder_config_.max_bitrate_bps, |
725 stats.preferred_media_bitrate_bps); | 862 stats.preferred_media_bitrate_bps); |
726 | 863 |
727 vie_encoder_->Stop(); | 864 vie_encoder_->Stop(); |
728 } | 865 } |
729 | 866 |
| 867 TEST_F(ViEEncoderTest, ScalingUpAndDownDoesNothingWithMaintainResolution) { |
| 868 const int kTargetBitrateBps = 100000; |
| 869 int frame_width = 1280; |
| 870 int frame_height = 720; |
| 871 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
| 872 |
| 873 // Expect no scaling to begin with |
| 874 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count); |
| 875 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up); |
| 876 |
| 877 // Trigger scale down |
| 878 vie_encoder_->TriggerQualityLow(); |
| 879 video_source_.IncomingCapturedFrame( |
| 880 CreateFrame(1, frame_width, frame_height)); |
| 881 sink_.WaitForEncodedFrame(1); |
| 882 |
| 883 // Expect a scale down. |
| 884 EXPECT_TRUE(video_source_.sink_wants().max_pixel_count); |
| 885 EXPECT_LT(*video_source_.sink_wants().max_pixel_count, |
| 886 frame_width * frame_height); |
| 887 |
| 888 // Set adaptation disabled. |
| 889 test::FrameForwarder new_video_source; |
| 890 vie_encoder_->SetSource( |
| 891 &new_video_source, |
| 892 VideoSendStream::DegradationPreference::kMaintainResolution); |
| 893 |
| 894 // Trigger scale down |
| 895 vie_encoder_->TriggerQualityLow(); |
| 896 new_video_source.IncomingCapturedFrame( |
| 897 CreateFrame(2, frame_width, frame_height)); |
| 898 sink_.WaitForEncodedFrame(2); |
| 899 |
| 900 // Expect no scaling |
| 901 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count); |
| 902 |
| 903 // Trigger scale up |
| 904 vie_encoder_->TriggerQualityHigh(); |
| 905 new_video_source.IncomingCapturedFrame( |
| 906 CreateFrame(3, frame_width, frame_height)); |
| 907 sink_.WaitForEncodedFrame(3); |
| 908 |
| 909 // Expect nothing to change, still no scaling |
| 910 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count); |
| 911 |
| 912 vie_encoder_->Stop(); |
| 913 } |
| 914 |
730 TEST_F(ViEEncoderTest, UMACpuLimitedResolutionInPercent) { | 915 TEST_F(ViEEncoderTest, UMACpuLimitedResolutionInPercent) { |
731 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); | 916 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
732 | 917 |
733 int frame_width = 640; | 918 int frame_width = 640; |
734 int frame_height = 360; | 919 int frame_height = 360; |
735 | 920 |
736 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) { | 921 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) { |
737 video_source_.IncomingCapturedFrame( | 922 video_source_.IncomingCapturedFrame( |
738 CreateFrame(i, frame_width, frame_height)); | 923 CreateFrame(i, frame_width, frame_height)); |
739 sink_.WaitForEncodedFrame(i); | 924 sink_.WaitForEncodedFrame(i); |
(...skipping 11 matching lines...) Expand all Loading... |
751 vie_encoder_->Stop(); | 936 vie_encoder_->Stop(); |
752 | 937 |
753 stats_proxy_.reset(); | 938 stats_proxy_.reset(); |
754 EXPECT_EQ(1, | 939 EXPECT_EQ(1, |
755 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent")); | 940 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent")); |
756 EXPECT_EQ( | 941 EXPECT_EQ( |
757 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50)); | 942 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50)); |
758 } | 943 } |
759 | 944 |
760 } // namespace webrtc | 945 } // namespace webrtc |
OLD | NEW |