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