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 <memory> | 11 #include <memory> |
12 | 12 |
13 #include "webrtc/video/overuse_frame_detector.h" | 13 #include "webrtc/video/overuse_frame_detector.h" |
14 | 14 |
15 #include "testing/gmock/include/gmock/gmock.h" | 15 #include "testing/gmock/include/gmock/gmock.h" |
16 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
17 | 17 |
18 #include "webrtc/base/event.h" | |
18 #include "webrtc/system_wrappers/include/clock.h" | 19 #include "webrtc/system_wrappers/include/clock.h" |
19 #include "webrtc/video_frame.h" | 20 #include "webrtc/video_frame.h" |
20 | 21 |
21 namespace webrtc { | 22 namespace webrtc { |
23 | |
24 using ::testing::Invoke; | |
25 | |
22 namespace { | 26 namespace { |
23 const int kWidth = 640; | 27 const int kWidth = 640; |
24 const int kHeight = 480; | 28 const int kHeight = 480; |
25 const int kFrameInterval33ms = 33; | 29 const int kFrameInterval33ms = 33; |
26 const int kProcessIntervalMs = 5000; | 30 const int kProcessIntervalMs = 5000; |
27 const int kProcessTime5ms = 5; | 31 const int kProcessTime5ms = 5; |
28 } // namespace | 32 } // namespace |
29 | 33 |
30 class MockCpuOveruseObserver : public CpuOveruseObserver { | 34 class MockCpuOveruseObserver : public CpuOveruseObserver { |
31 public: | 35 public: |
(...skipping 11 matching lines...) Expand all Loading... | |
43 normaluse_(0) {} | 47 normaluse_(0) {} |
44 virtual ~CpuOveruseObserverImpl() {} | 48 virtual ~CpuOveruseObserverImpl() {} |
45 | 49 |
46 void OveruseDetected() { ++overuse_; } | 50 void OveruseDetected() { ++overuse_; } |
47 void NormalUsage() { ++normaluse_; } | 51 void NormalUsage() { ++normaluse_; } |
48 | 52 |
49 int overuse_; | 53 int overuse_; |
50 int normaluse_; | 54 int normaluse_; |
51 }; | 55 }; |
52 | 56 |
57 class OveruseFrameDetectorUnderTest : public OveruseFrameDetector { | |
58 public: | |
59 OveruseFrameDetectorUnderTest(Clock* clock, | |
60 const CpuOveruseOptions& options, | |
61 CpuOveruseObserver* overuse_observer, | |
62 EncodedFrameObserver* encoder_timing, | |
63 CpuOveruseMetricsObserver* metrics_observer) | |
64 : OveruseFrameDetector(clock, | |
65 options, | |
66 overuse_observer, | |
67 encoder_timing, | |
68 metrics_observer) {} | |
69 ~OveruseFrameDetectorUnderTest() {} | |
70 | |
71 using OveruseFrameDetector::CheckForOveruse; | |
72 }; | |
73 | |
53 class OveruseFrameDetectorTest : public ::testing::Test, | 74 class OveruseFrameDetectorTest : public ::testing::Test, |
54 public CpuOveruseMetricsObserver { | 75 public CpuOveruseMetricsObserver { |
55 protected: | 76 protected: |
56 void SetUp() override { | 77 void SetUp() override { |
57 clock_.reset(new SimulatedClock(1234)); | 78 clock_.reset(new SimulatedClock(1234)); |
58 observer_.reset(new MockCpuOveruseObserver()); | 79 observer_.reset(new MockCpuOveruseObserver()); |
59 options_.min_process_count = 0; | 80 options_.min_process_count = 0; |
60 ReinitializeOveruseDetector(); | 81 ReinitializeOveruseDetector(); |
61 } | 82 } |
62 | 83 |
63 void ReinitializeOveruseDetector() { | 84 void ReinitializeOveruseDetector() { |
64 overuse_detector_.reset(new OveruseFrameDetector( | 85 overuse_detector_.reset(new OveruseFrameDetectorUnderTest( |
65 clock_.get(), options_, observer_.get(), nullptr, this)); | 86 clock_.get(), options_, observer_.get(), nullptr, this)); |
66 } | 87 } |
67 | 88 |
68 void OnEncodedFrameTimeMeasured(int encode_time_ms, | 89 void OnEncodedFrameTimeMeasured(int encode_time_ms, |
69 const CpuOveruseMetrics& metrics) override { | 90 const CpuOveruseMetrics& metrics) override { |
70 metrics_ = metrics; | 91 metrics_ = metrics; |
71 } | 92 } |
72 | 93 |
73 int InitialUsage() { | 94 int InitialUsage() { |
74 return ((options_.low_encode_usage_threshold_percent + | 95 return ((options_.low_encode_usage_threshold_percent + |
75 options_.high_encode_usage_threshold_percent) / 2.0f) + 0.5; | 96 options_.high_encode_usage_threshold_percent) / 2.0f) + 0.5; |
76 } | 97 } |
77 | 98 |
78 void InsertAndSendFramesWithInterval(int num_frames, | 99 void InsertAndSendFramesWithInterval(int num_frames, |
79 int interval_ms, | 100 int interval_ms, |
80 int width, | 101 int width, |
81 int height, | 102 int height, |
82 int delay_ms) { | 103 int delay_ms) { |
83 VideoFrame frame; | 104 VideoFrame frame; |
84 frame.CreateEmptyFrame(width, height, width, width / 2, width / 2); | 105 frame.CreateEmptyFrame(width, height, width, width / 2, width / 2); |
85 uint32_t timestamp = 0; | 106 uint32_t timestamp = 0; |
86 while (num_frames-- > 0) { | 107 while (num_frames-- > 0) { |
87 frame.set_timestamp(timestamp); | 108 frame.set_timestamp(timestamp); |
88 overuse_detector_->FrameCaptured(frame); | 109 overuse_detector_->FrameCaptured(frame, clock_->TimeInMilliseconds()); |
89 clock_->AdvanceTimeMilliseconds(delay_ms); | 110 clock_->AdvanceTimeMilliseconds(delay_ms); |
90 overuse_detector_->FrameSent(timestamp); | 111 overuse_detector_->FrameSent(timestamp, clock_->TimeInMilliseconds()); |
91 clock_->AdvanceTimeMilliseconds(interval_ms - delay_ms); | 112 clock_->AdvanceTimeMilliseconds(interval_ms - delay_ms); |
92 timestamp += interval_ms * 90; | 113 timestamp += interval_ms * 90; |
93 } | 114 } |
94 } | 115 } |
95 | 116 |
96 void ForceUpdate(int width, int height) { | 117 void ForceUpdate(int width, int height) { |
97 // Insert one frame, wait a second and then put in another to force update | 118 // Insert one frame, wait a second and then put in another to force update |
98 // the usage. From the tests where these are used, adding another sample | 119 // the usage. From the tests where these are used, adding another sample |
99 // doesn't affect the expected outcome (this is mainly to check initial | 120 // doesn't affect the expected outcome (this is mainly to check initial |
100 // values and whether the overuse detector has been reset or not). | 121 // values and whether the overuse detector has been reset or not). |
101 InsertAndSendFramesWithInterval(2, 1000, width, height, kFrameInterval33ms); | 122 InsertAndSendFramesWithInterval(2, 1000, width, height, kFrameInterval33ms); |
102 } | 123 } |
103 void TriggerOveruse(int num_times) { | 124 void TriggerOveruse(int num_times) { |
104 const int kDelayMs = 32; | 125 const int kDelayMs = 32; |
105 for (int i = 0; i < num_times; ++i) { | 126 for (int i = 0; i < num_times; ++i) { |
106 InsertAndSendFramesWithInterval( | 127 InsertAndSendFramesWithInterval( |
107 1000, kFrameInterval33ms, kWidth, kHeight, kDelayMs); | 128 1000, kFrameInterval33ms, kWidth, kHeight, kDelayMs); |
108 overuse_detector_->Process(); | 129 overuse_detector_->CheckForOveruse(); |
109 } | 130 } |
110 } | 131 } |
111 | 132 |
112 void TriggerUnderuse() { | 133 void TriggerUnderuse() { |
113 const int kDelayMs1 = 5; | 134 const int kDelayMs1 = 5; |
114 const int kDelayMs2 = 6; | 135 const int kDelayMs2 = 6; |
115 InsertAndSendFramesWithInterval( | 136 InsertAndSendFramesWithInterval( |
116 1300, kFrameInterval33ms, kWidth, kHeight, kDelayMs1); | 137 1300, kFrameInterval33ms, kWidth, kHeight, kDelayMs1); |
117 InsertAndSendFramesWithInterval( | 138 InsertAndSendFramesWithInterval( |
118 1, kFrameInterval33ms, kWidth, kHeight, kDelayMs2); | 139 1, kFrameInterval33ms, kWidth, kHeight, kDelayMs2); |
119 overuse_detector_->Process(); | 140 overuse_detector_->CheckForOveruse(); |
120 } | 141 } |
121 | 142 |
122 int UsagePercent() { return metrics_.encode_usage_percent; } | 143 int UsagePercent() { return metrics_.encode_usage_percent; } |
123 | 144 |
124 CpuOveruseOptions options_; | 145 CpuOveruseOptions options_; |
125 std::unique_ptr<SimulatedClock> clock_; | 146 std::unique_ptr<SimulatedClock> clock_; |
126 std::unique_ptr<MockCpuOveruseObserver> observer_; | 147 std::unique_ptr<MockCpuOveruseObserver> observer_; |
127 std::unique_ptr<OveruseFrameDetector> overuse_detector_; | 148 std::unique_ptr<OveruseFrameDetectorUnderTest> overuse_detector_; |
128 CpuOveruseMetrics metrics_; | 149 CpuOveruseMetrics metrics_; |
129 }; | 150 }; |
130 | 151 |
131 | 152 |
132 // UsagePercent() > high_encode_usage_threshold_percent => overuse. | 153 // UsagePercent() > high_encode_usage_threshold_percent => overuse. |
133 // UsagePercent() < low_encode_usage_threshold_percent => underuse. | 154 // UsagePercent() < low_encode_usage_threshold_percent => underuse. |
134 TEST_F(OveruseFrameDetectorTest, TriggerOveruse) { | 155 TEST_F(OveruseFrameDetectorTest, TriggerOveruse) { |
135 // usage > high => overuse | 156 // usage > high => overuse |
136 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1); | 157 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1); |
137 TriggerOveruse(options_.high_threshold_consecutive_count); | 158 TriggerOveruse(options_.high_threshold_consecutive_count); |
138 } | 159 } |
139 | 160 |
140 TEST_F(OveruseFrameDetectorTest, OveruseAndRecover) { | 161 TEST_F(OveruseFrameDetectorTest, OveruseAndRecover) { |
141 // usage > high => overuse | 162 // usage > high => overuse |
142 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1); | 163 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1); |
143 TriggerOveruse(options_.high_threshold_consecutive_count); | 164 TriggerOveruse(options_.high_threshold_consecutive_count); |
144 // usage < low => underuse | 165 // usage < low => underuse |
145 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(testing::AtLeast(1)); | 166 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(testing::AtLeast(1)); |
146 TriggerUnderuse(); | 167 TriggerUnderuse(); |
147 } | 168 } |
148 | 169 |
149 TEST_F(OveruseFrameDetectorTest, OveruseAndRecoverWithNoObserver) { | 170 TEST_F(OveruseFrameDetectorTest, OveruseAndRecoverWithNoObserver) { |
150 overuse_detector_.reset( | 171 overuse_detector_.reset(new OveruseFrameDetectorUnderTest( |
151 new OveruseFrameDetector(clock_.get(), options_, nullptr, nullptr, this)); | 172 clock_.get(), options_, nullptr, nullptr, this)); |
152 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(0); | 173 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(0); |
153 TriggerOveruse(options_.high_threshold_consecutive_count); | 174 TriggerOveruse(options_.high_threshold_consecutive_count); |
154 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(0); | 175 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(0); |
155 TriggerUnderuse(); | 176 TriggerUnderuse(); |
156 } | 177 } |
157 | 178 |
158 TEST_F(OveruseFrameDetectorTest, DoubleOveruseAndRecover) { | 179 TEST_F(OveruseFrameDetectorTest, DoubleOveruseAndRecover) { |
159 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(2); | 180 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(2); |
160 TriggerOveruse(options_.high_threshold_consecutive_count); | 181 TriggerOveruse(options_.high_threshold_consecutive_count); |
161 TriggerOveruse(options_.high_threshold_consecutive_count); | 182 TriggerOveruse(options_.high_threshold_consecutive_count); |
162 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(testing::AtLeast(1)); | 183 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(testing::AtLeast(1)); |
163 TriggerUnderuse(); | 184 TriggerUnderuse(); |
164 } | 185 } |
165 | 186 |
166 TEST_F(OveruseFrameDetectorTest, TriggerUnderuseWithMinProcessCount) { | 187 TEST_F(OveruseFrameDetectorTest, TriggerUnderuseWithMinProcessCount) { |
167 options_.min_process_count = 1; | 188 options_.min_process_count = 1; |
168 CpuOveruseObserverImpl overuse_observer; | 189 CpuOveruseObserverImpl overuse_observer; |
169 overuse_detector_.reset(new OveruseFrameDetector( | 190 overuse_detector_.reset(new OveruseFrameDetectorUnderTest( |
170 clock_.get(), options_, &overuse_observer, nullptr, this)); | 191 clock_.get(), options_, &overuse_observer, nullptr, this)); |
171 InsertAndSendFramesWithInterval( | 192 InsertAndSendFramesWithInterval( |
172 1200, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); | 193 1200, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); |
173 overuse_detector_->Process(); | 194 overuse_detector_->CheckForOveruse(); |
174 EXPECT_EQ(0, overuse_observer.normaluse_); | 195 EXPECT_EQ(0, overuse_observer.normaluse_); |
175 clock_->AdvanceTimeMilliseconds(kProcessIntervalMs); | 196 clock_->AdvanceTimeMilliseconds(kProcessIntervalMs); |
176 overuse_detector_->Process(); | 197 overuse_detector_->CheckForOveruse(); |
177 EXPECT_EQ(1, overuse_observer.normaluse_); | 198 EXPECT_EQ(1, overuse_observer.normaluse_); |
178 } | 199 } |
179 | 200 |
180 TEST_F(OveruseFrameDetectorTest, ConstantOveruseGivesNoNormalUsage) { | 201 TEST_F(OveruseFrameDetectorTest, ConstantOveruseGivesNoNormalUsage) { |
181 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(0); | 202 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(0); |
182 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(64); | 203 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(64); |
183 for (size_t i = 0; i < 64; ++i) { | 204 for (size_t i = 0; i < 64; ++i) { |
184 TriggerOveruse(options_.high_threshold_consecutive_count); | 205 TriggerOveruse(options_.high_threshold_consecutive_count); |
185 } | 206 } |
186 } | 207 } |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
260 | 281 |
261 TEST_F(OveruseFrameDetectorTest, MeasuresMultipleConcurrentSamples) { | 282 TEST_F(OveruseFrameDetectorTest, MeasuresMultipleConcurrentSamples) { |
262 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(testing::AtLeast(1)); | 283 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(testing::AtLeast(1)); |
263 static const int kIntervalMs = 33; | 284 static const int kIntervalMs = 33; |
264 static const size_t kNumFramesEncodingDelay = 3; | 285 static const size_t kNumFramesEncodingDelay = 3; |
265 VideoFrame frame; | 286 VideoFrame frame; |
266 frame.CreateEmptyFrame(kWidth, kHeight, kWidth, kWidth / 2, kWidth / 2); | 287 frame.CreateEmptyFrame(kWidth, kHeight, kWidth, kWidth / 2, kWidth / 2); |
267 for (size_t i = 0; i < 1000; ++i) { | 288 for (size_t i = 0; i < 1000; ++i) { |
268 // Unique timestamps. | 289 // Unique timestamps. |
269 frame.set_timestamp(static_cast<uint32_t>(i)); | 290 frame.set_timestamp(static_cast<uint32_t>(i)); |
270 overuse_detector_->FrameCaptured(frame); | 291 overuse_detector_->FrameCaptured(frame, clock_->TimeInMilliseconds()); |
271 clock_->AdvanceTimeMilliseconds(kIntervalMs); | 292 clock_->AdvanceTimeMilliseconds(kIntervalMs); |
272 if (i > kNumFramesEncodingDelay) { | 293 if (i > kNumFramesEncodingDelay) { |
273 overuse_detector_->FrameSent( | 294 overuse_detector_->FrameSent( |
274 static_cast<uint32_t>(i - kNumFramesEncodingDelay)); | 295 static_cast<uint32_t>(i - kNumFramesEncodingDelay), |
296 clock_->TimeInMilliseconds()); | |
275 } | 297 } |
276 overuse_detector_->Process(); | 298 overuse_detector_->CheckForOveruse(); |
277 } | 299 } |
278 } | 300 } |
279 | 301 |
280 TEST_F(OveruseFrameDetectorTest, UpdatesExistingSamples) { | 302 TEST_F(OveruseFrameDetectorTest, UpdatesExistingSamples) { |
281 // >85% encoding time should trigger overuse. | 303 // >85% encoding time should trigger overuse. |
282 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(testing::AtLeast(1)); | 304 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(testing::AtLeast(1)); |
283 static const int kIntervalMs = 33; | 305 static const int kIntervalMs = 33; |
284 static const int kDelayMs = 30; | 306 static const int kDelayMs = 30; |
285 VideoFrame frame; | 307 VideoFrame frame; |
286 frame.CreateEmptyFrame(kWidth, kHeight, kWidth, kWidth / 2, kWidth / 2); | 308 frame.CreateEmptyFrame(kWidth, kHeight, kWidth, kWidth / 2, kWidth / 2); |
287 uint32_t timestamp = 0; | 309 uint32_t timestamp = 0; |
288 for (size_t i = 0; i < 1000; ++i) { | 310 for (size_t i = 0; i < 1000; ++i) { |
289 frame.set_timestamp(timestamp); | 311 frame.set_timestamp(timestamp); |
290 overuse_detector_->FrameCaptured(frame); | 312 overuse_detector_->FrameCaptured(frame, clock_->TimeInMilliseconds()); |
291 // Encode and send first parts almost instantly. | 313 // Encode and send first parts almost instantly. |
292 clock_->AdvanceTimeMilliseconds(1); | 314 clock_->AdvanceTimeMilliseconds(1); |
293 overuse_detector_->FrameSent(timestamp); | 315 overuse_detector_->FrameSent(timestamp, clock_->TimeInMilliseconds()); |
294 // Encode heavier part, resulting in >85% usage total. | 316 // Encode heavier part, resulting in >85% usage total. |
295 clock_->AdvanceTimeMilliseconds(kDelayMs - 1); | 317 clock_->AdvanceTimeMilliseconds(kDelayMs - 1); |
296 overuse_detector_->FrameSent(timestamp); | 318 overuse_detector_->FrameSent(timestamp, clock_->TimeInMilliseconds()); |
297 clock_->AdvanceTimeMilliseconds(kIntervalMs - kDelayMs); | 319 clock_->AdvanceTimeMilliseconds(kIntervalMs - kDelayMs); |
298 timestamp += kIntervalMs * 90; | 320 timestamp += kIntervalMs * 90; |
299 overuse_detector_->Process(); | 321 overuse_detector_->CheckForOveruse(); |
300 } | 322 } |
301 } | 323 } |
302 | 324 |
325 TEST_F(OveruseFrameDetectorTest, RunOnTqNormalUsage) { | |
326 rtc::TaskQueue queue("OveruseFrameDetectorTestQueu"); | |
åsapersson
2016/08/24 08:59:05
Queue
perkj_webrtc
2016/09/01 10:03:30
Done.
| |
327 | |
328 rtc::Event event(false, false); | |
329 queue.PostTask([this, &event] { | |
330 overuse_detector_->StartCheckForOveruse(); | |
331 event.Set(); | |
332 }); | |
333 event.Wait(rtc::Event::kForever); | |
334 | |
335 // Expect NormalUsage(). When called, stop the |overuse_detector_| and then | |
336 // set |event| to end the test. | |
337 EXPECT_CALL(*(observer_.get()), NormalUsage()) | |
338 .WillOnce(Invoke([this, &event] { | |
339 overuse_detector_->StopCheckForOveruse(); | |
340 event.Set(); | |
341 })); | |
342 | |
343 queue.PostTask([this, &event] { | |
344 const int kDelayMs1 = 5; | |
345 const int kDelayMs2 = 6; | |
346 InsertAndSendFramesWithInterval(1300, kFrameInterval33ms, kWidth, kHeight, | |
347 kDelayMs1); | |
348 InsertAndSendFramesWithInterval(1, kFrameInterval33ms, kWidth, kHeight, | |
349 kDelayMs2); | |
350 }); | |
351 | |
352 EXPECT_TRUE(event.Wait(10000)); | |
353 } | |
354 | |
303 } // namespace webrtc | 355 } // namespace webrtc |
OLD | NEW |