1 /*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include <limits>
12 #include <vector>
13
14 #include "api/rtp_parameters.h"
15 #include "api/video/video_frame.h"
16 #include "api/video/video_sink_interface.h"
17 #include "api/video/video_source_interface.h"
18 #include "api/video_codecs/video_encoder_config.h"
19 #include "call/video_receive_stream.h"
20 #include "call/video_send_stream.h"
21 #include "rtc_base/checks.h"
22 #include "rtc_base/event.h"
23 #include "test/call_test.h"
24 #include "test/field_trial.h"
25 #include "test/frame_generator_capturer.h"
26 #include "test/gtest.h"
27
28 namespace webrtc {
29 namespace {
30 constexpr int kWidth = 1280;
31 constexpr int kHeight = 720;
32 constexpr int kFps = 28;
33 } // namespace
34
35 // Minimal normal usage at start, then 60s overuse.
36 class CpuOveruseTest : public test::CallTest {
37 protected:
CpuOveruseTest()38 CpuOveruseTest()
39 : field_trials_("WebRTC-ForceSimulatedOveruseIntervalMs/1-60000-60000/") {
40 }
41
42 void RunTestAndCheckForAdaptation(
43 const DegradationPreference& degradation_preference,
44 bool expect_adaptation);
45
46 test::ScopedFieldTrials field_trials_;
47 };
48
RunTestAndCheckForAdaptation(const DegradationPreference & degradation_preference,bool expect_adaptation)49 void CpuOveruseTest::RunTestAndCheckForAdaptation(
50 const DegradationPreference& degradation_preference,
51 bool expect_adaptation) {
52 class OveruseObserver
53 : public test::SendTest,
54 public test::FrameGeneratorCapturer::SinkWantsObserver {
55 public:
56 OveruseObserver(const DegradationPreference& degradation_preference,
57 bool expect_adaptation)
58 : SendTest(expect_adaptation ? kLongTimeoutMs : kDefaultTimeoutMs),
59 degradation_preference_(degradation_preference),
60 expect_adaptation_(expect_adaptation) {}
61
62 private:
63 void OnFrameGeneratorCapturerCreated(
64 test::FrameGeneratorCapturer* frame_generator_capturer) override {
65 frame_generator_capturer->SetSinkWantsObserver(this);
66 // Set initial resolution.
67 frame_generator_capturer->ChangeResolution(kWidth, kHeight);
68 }
69
70 // Called when FrameGeneratorCapturer::AddOrUpdateSink is called.
71 void OnSinkWantsChanged(rtc::VideoSinkInterface<VideoFrame>* sink,
72 const rtc::VideoSinkWants& wants) override {
73 if (wants.max_pixel_count == std::numeric_limits<int>::max() &&
74 wants.max_framerate_fps == kFps) {
75 // Max configured framerate is initially set.
76 return;
77 }
78 switch (degradation_preference_) {
79 case DegradationPreference::MAINTAIN_FRAMERATE:
80 EXPECT_LT(wants.max_pixel_count, kWidth * kHeight);
81 observation_complete_.Set();
82 break;
83 case DegradationPreference::MAINTAIN_RESOLUTION:
84 EXPECT_LT(wants.max_framerate_fps, kFps);
85 observation_complete_.Set();
86 break;
87 case DegradationPreference::BALANCED:
88 if (wants.max_pixel_count == std::numeric_limits<int>::max() &&
89 wants.max_framerate_fps == std::numeric_limits<int>::max()) {
90 // |adapt_counters_| map in VideoStreamEncoder is reset when
91 // balanced mode is set.
92 break;
93 }
94 EXPECT_TRUE(wants.max_pixel_count < kWidth * kHeight ||
95 wants.max_framerate_fps < kFps);
96 observation_complete_.Set();
97 break;
98 default:
99 RTC_NOTREACHED();
100 }
101 }
102
103 void ModifyVideoConfigs(
104 VideoSendStream::Config* send_config,
105 std::vector<VideoReceiveStream::Config>* receive_configs,
106 VideoEncoderConfig* encoder_config) override {
107 EXPECT_FALSE(encoder_config->simulcast_layers.empty());
108 encoder_config->simulcast_layers[0].max_framerate = kFps;
109 }
110
111 void ModifyVideoDegradationPreference(
112 DegradationPreference* degradation_preference) override {
113 *degradation_preference = degradation_preference_;
114 }
115
116 void PerformTest() override {
117 EXPECT_EQ(expect_adaptation_, Wait())
118 << "Timed out while waiting for a scale down.";
119 }
120
121 const DegradationPreference degradation_preference_;
122 const bool expect_adaptation_;
123 } test(degradation_preference, expect_adaptation);
124
125 RunBaseTest(&test);
126 }
127
TEST_F(CpuOveruseTest,AdaptsDownInResolutionOnOveruse)128 TEST_F(CpuOveruseTest, AdaptsDownInResolutionOnOveruse) {
129 RunTestAndCheckForAdaptation(DegradationPreference::MAINTAIN_FRAMERATE, true);
130 }
131
TEST_F(CpuOveruseTest,AdaptsDownInFpsOnOveruse)132 TEST_F(CpuOveruseTest, AdaptsDownInFpsOnOveruse) {
133 RunTestAndCheckForAdaptation(DegradationPreference::MAINTAIN_RESOLUTION,
134 true);
135 }
136
TEST_F(CpuOveruseTest,AdaptsDownInResolutionOrFpsOnOveruse)137 TEST_F(CpuOveruseTest, AdaptsDownInResolutionOrFpsOnOveruse) {
138 RunTestAndCheckForAdaptation(DegradationPreference::BALANCED, true);
139 }
140
TEST_F(CpuOveruseTest,NoAdaptDownOnOveruse)141 TEST_F(CpuOveruseTest, NoAdaptDownOnOveruse) {
142 RunTestAndCheckForAdaptation(DegradationPreference::DISABLED, false);
143 }
144 } // namespace webrtc
145