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/base/event.h" | 13 #include "webrtc/base/event.h" |
14 #include "webrtc/system_wrappers/include/clock.h" | 14 #include "webrtc/system_wrappers/include/clock.h" |
15 #include "webrtc/test/gmock.h" | 15 #include "webrtc/test/gmock.h" |
16 #include "webrtc/test/gtest.h" | 16 #include "webrtc/test/gtest.h" |
17 #include "webrtc/video/overuse_frame_detector.h" | 17 #include "webrtc/video/overuse_frame_detector.h" |
18 #include "webrtc/video_frame.h" | 18 #include "webrtc/video_frame.h" |
| 19 #include "webrtc/modules/video_coding/utility/quality_scaler.h" |
19 | 20 |
20 namespace webrtc { | 21 namespace webrtc { |
21 | 22 |
22 using ::testing::Invoke; | 23 using ::testing::Invoke; |
23 | 24 |
24 namespace { | 25 namespace { |
25 const int kWidth = 640; | 26 const int kWidth = 640; |
26 const int kHeight = 480; | 27 const int kHeight = 480; |
27 const int kFrameInterval33ms = 33; | 28 const int kFrameInterval33ms = 33; |
28 const int kProcessIntervalMs = 5000; | 29 const int kProcessIntervalMs = 5000; |
29 const int kProcessTime5ms = 5; | 30 const int kProcessTime5ms = 5; |
30 } // namespace | 31 } // namespace |
31 | 32 |
32 class MockCpuOveruseObserver : public CpuOveruseObserver { | 33 class MockCpuOveruseObserver : public ScalingInterface { |
33 public: | 34 public: |
34 MockCpuOveruseObserver() {} | 35 MockCpuOveruseObserver() {} |
35 virtual ~MockCpuOveruseObserver() {} | 36 virtual ~MockCpuOveruseObserver() {} |
36 | 37 |
37 MOCK_METHOD0(OveruseDetected, void()); | 38 MOCK_METHOD0(ScaleUp, void()); |
38 MOCK_METHOD0(NormalUsage, void()); | 39 MOCK_METHOD0(ScaleDown, void()); |
39 }; | 40 }; |
40 | 41 |
41 class CpuOveruseObserverImpl : public CpuOveruseObserver { | 42 class CpuOveruseObserverImpl : public ScalingInterface { |
42 public: | 43 public: |
43 CpuOveruseObserverImpl() : | 44 CpuOveruseObserverImpl() : |
44 overuse_(0), | 45 overuse_(0), |
45 normaluse_(0) {} | 46 normaluse_(0) {} |
46 virtual ~CpuOveruseObserverImpl() {} | 47 virtual ~CpuOveruseObserverImpl() {} |
47 | 48 |
48 void OveruseDetected() { ++overuse_; } | 49 void ScaleDown() { ++overuse_; } |
49 void NormalUsage() { ++normaluse_; } | 50 void ScaleUp() { ++normaluse_; } |
50 | 51 |
51 int overuse_; | 52 int overuse_; |
52 int normaluse_; | 53 int normaluse_; |
53 }; | 54 }; |
54 | 55 |
55 class OveruseFrameDetectorUnderTest : public OveruseFrameDetector { | 56 class OveruseFrameDetectorUnderTest : public OveruseFrameDetector { |
56 public: | 57 public: |
57 OveruseFrameDetectorUnderTest(Clock* clock, | 58 OveruseFrameDetectorUnderTest(Clock* clock, |
58 const CpuOveruseOptions& options, | 59 const CpuOveruseOptions& options, |
59 CpuOveruseObserver* overuse_observer, | 60 ScalingInterface* overuse_observer, |
60 EncodedFrameObserver* encoder_timing, | 61 EncodedFrameObserver* encoder_timing, |
61 CpuOveruseMetricsObserver* metrics_observer) | 62 CpuOveruseMetricsObserver* metrics_observer) |
62 : OveruseFrameDetector(clock, | 63 : OveruseFrameDetector(clock, |
63 options, | 64 options, |
64 overuse_observer, | 65 overuse_observer, |
65 encoder_timing, | 66 encoder_timing, |
66 metrics_observer) {} | 67 metrics_observer) {} |
67 ~OveruseFrameDetectorUnderTest() {} | 68 ~OveruseFrameDetectorUnderTest() {} |
68 | 69 |
69 using OveruseFrameDetector::CheckForOveruse; | 70 using OveruseFrameDetector::CheckForOveruse; |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 std::unique_ptr<MockCpuOveruseObserver> observer_; | 146 std::unique_ptr<MockCpuOveruseObserver> observer_; |
146 std::unique_ptr<OveruseFrameDetectorUnderTest> overuse_detector_; | 147 std::unique_ptr<OveruseFrameDetectorUnderTest> overuse_detector_; |
147 CpuOveruseMetrics metrics_; | 148 CpuOveruseMetrics metrics_; |
148 }; | 149 }; |
149 | 150 |
150 | 151 |
151 // UsagePercent() > high_encode_usage_threshold_percent => overuse. | 152 // UsagePercent() > high_encode_usage_threshold_percent => overuse. |
152 // UsagePercent() < low_encode_usage_threshold_percent => underuse. | 153 // UsagePercent() < low_encode_usage_threshold_percent => underuse. |
153 TEST_F(OveruseFrameDetectorTest, TriggerOveruse) { | 154 TEST_F(OveruseFrameDetectorTest, TriggerOveruse) { |
154 // usage > high => overuse | 155 // usage > high => overuse |
155 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1); | 156 EXPECT_CALL(*(observer_.get()), ScaleDown()).Times(1); |
156 TriggerOveruse(options_.high_threshold_consecutive_count); | 157 TriggerOveruse(options_.high_threshold_consecutive_count); |
157 } | 158 } |
158 | 159 |
159 TEST_F(OveruseFrameDetectorTest, OveruseAndRecover) { | 160 TEST_F(OveruseFrameDetectorTest, OveruseAndRecover) { |
160 // usage > high => overuse | 161 // usage > high => overuse |
161 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1); | 162 EXPECT_CALL(*(observer_.get()), ScaleDown()).Times(1); |
162 TriggerOveruse(options_.high_threshold_consecutive_count); | 163 TriggerOveruse(options_.high_threshold_consecutive_count); |
163 // usage < low => underuse | 164 // usage < low => underuse |
164 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(testing::AtLeast(1)); | 165 EXPECT_CALL(*(observer_.get()), ScaleUp()).Times(testing::AtLeast(1)); |
165 TriggerUnderuse(); | 166 TriggerUnderuse(); |
166 } | 167 } |
167 | 168 |
168 TEST_F(OveruseFrameDetectorTest, OveruseAndRecoverWithNoObserver) { | 169 TEST_F(OveruseFrameDetectorTest, OveruseAndRecoverWithNoObserver) { |
169 overuse_detector_.reset(new OveruseFrameDetectorUnderTest( | 170 overuse_detector_.reset(new OveruseFrameDetectorUnderTest( |
170 clock_.get(), options_, nullptr, nullptr, this)); | 171 clock_.get(), options_, nullptr, nullptr, this)); |
171 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(0); | 172 EXPECT_CALL(*(observer_.get()), ScaleDown()).Times(0); |
172 TriggerOveruse(options_.high_threshold_consecutive_count); | 173 TriggerOveruse(options_.high_threshold_consecutive_count); |
173 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(0); | 174 EXPECT_CALL(*(observer_.get()), ScaleUp()).Times(0); |
174 TriggerUnderuse(); | 175 TriggerUnderuse(); |
175 } | 176 } |
176 | 177 |
177 TEST_F(OveruseFrameDetectorTest, DoubleOveruseAndRecover) { | 178 TEST_F(OveruseFrameDetectorTest, DoubleOveruseAndRecover) { |
178 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(2); | 179 EXPECT_CALL(*(observer_.get()), ScaleDown()).Times(2); |
179 TriggerOveruse(options_.high_threshold_consecutive_count); | 180 TriggerOveruse(options_.high_threshold_consecutive_count); |
180 TriggerOveruse(options_.high_threshold_consecutive_count); | 181 TriggerOveruse(options_.high_threshold_consecutive_count); |
181 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(testing::AtLeast(1)); | 182 EXPECT_CALL(*(observer_.get()), ScaleUp()).Times(testing::AtLeast(1)); |
182 TriggerUnderuse(); | 183 TriggerUnderuse(); |
183 } | 184 } |
184 | 185 |
185 TEST_F(OveruseFrameDetectorTest, TriggerUnderuseWithMinProcessCount) { | 186 TEST_F(OveruseFrameDetectorTest, TriggerUnderuseWithMinProcessCount) { |
186 options_.min_process_count = 1; | 187 options_.min_process_count = 1; |
187 CpuOveruseObserverImpl overuse_observer; | 188 CpuOveruseObserverImpl overuse_observer; |
188 overuse_detector_.reset(new OveruseFrameDetectorUnderTest( | 189 overuse_detector_.reset(new OveruseFrameDetectorUnderTest( |
189 clock_.get(), options_, &overuse_observer, nullptr, this)); | 190 clock_.get(), options_, &overuse_observer, nullptr, this)); |
190 InsertAndSendFramesWithInterval( | 191 InsertAndSendFramesWithInterval( |
191 1200, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); | 192 1200, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); |
192 overuse_detector_->CheckForOveruse(); | 193 overuse_detector_->CheckForOveruse(); |
193 EXPECT_EQ(0, overuse_observer.normaluse_); | 194 EXPECT_EQ(0, overuse_observer.normaluse_); |
194 clock_->AdvanceTimeMilliseconds(kProcessIntervalMs); | 195 clock_->AdvanceTimeMilliseconds(kProcessIntervalMs); |
195 overuse_detector_->CheckForOveruse(); | 196 overuse_detector_->CheckForOveruse(); |
196 EXPECT_EQ(1, overuse_observer.normaluse_); | 197 EXPECT_EQ(1, overuse_observer.normaluse_); |
197 } | 198 } |
198 | 199 |
199 TEST_F(OveruseFrameDetectorTest, ConstantOveruseGivesNoNormalUsage) { | 200 TEST_F(OveruseFrameDetectorTest, ConstantOveruseGivesNoNormalUsage) { |
200 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(0); | 201 EXPECT_CALL(*(observer_.get()), ScaleUp()).Times(0); |
201 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(64); | 202 EXPECT_CALL(*(observer_.get()), ScaleDown()).Times(64); |
202 for (size_t i = 0; i < 64; ++i) { | 203 for (size_t i = 0; i < 64; ++i) { |
203 TriggerOveruse(options_.high_threshold_consecutive_count); | 204 TriggerOveruse(options_.high_threshold_consecutive_count); |
204 } | 205 } |
205 } | 206 } |
206 | 207 |
207 TEST_F(OveruseFrameDetectorTest, ConsecutiveCountTriggersOveruse) { | 208 TEST_F(OveruseFrameDetectorTest, ConsecutiveCountTriggersOveruse) { |
208 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1); | 209 EXPECT_CALL(*(observer_.get()), ScaleDown()).Times(1); |
209 options_.high_threshold_consecutive_count = 2; | 210 options_.high_threshold_consecutive_count = 2; |
210 ReinitializeOveruseDetector(); | 211 ReinitializeOveruseDetector(); |
211 TriggerOveruse(2); | 212 TriggerOveruse(2); |
212 } | 213 } |
213 | 214 |
214 TEST_F(OveruseFrameDetectorTest, IncorrectConsecutiveCountTriggersNoOveruse) { | 215 TEST_F(OveruseFrameDetectorTest, IncorrectConsecutiveCountTriggersNoOveruse) { |
215 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(0); | 216 EXPECT_CALL(*(observer_.get()), ScaleDown()).Times(0); |
216 options_.high_threshold_consecutive_count = 2; | 217 options_.high_threshold_consecutive_count = 2; |
217 ReinitializeOveruseDetector(); | 218 ReinitializeOveruseDetector(); |
218 TriggerOveruse(1); | 219 TriggerOveruse(1); |
219 } | 220 } |
220 | 221 |
221 TEST_F(OveruseFrameDetectorTest, ProcessingUsage) { | 222 TEST_F(OveruseFrameDetectorTest, ProcessingUsage) { |
222 InsertAndSendFramesWithInterval( | 223 InsertAndSendFramesWithInterval( |
223 1000, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); | 224 1000, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); |
224 EXPECT_EQ(kProcessTime5ms * 100 / kFrameInterval33ms, UsagePercent()); | 225 EXPECT_EQ(kProcessTime5ms * 100 / kFrameInterval33ms, UsagePercent()); |
225 } | 226 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 1, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); | 272 1, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); |
272 EXPECT_NE(InitialUsage(), UsagePercent()); | 273 EXPECT_NE(InitialUsage(), UsagePercent()); |
273 } | 274 } |
274 | 275 |
275 TEST_F(OveruseFrameDetectorTest, InitialProcessingUsage) { | 276 TEST_F(OveruseFrameDetectorTest, InitialProcessingUsage) { |
276 ForceUpdate(kWidth, kHeight); | 277 ForceUpdate(kWidth, kHeight); |
277 EXPECT_EQ(InitialUsage(), UsagePercent()); | 278 EXPECT_EQ(InitialUsage(), UsagePercent()); |
278 } | 279 } |
279 | 280 |
280 TEST_F(OveruseFrameDetectorTest, MeasuresMultipleConcurrentSamples) { | 281 TEST_F(OveruseFrameDetectorTest, MeasuresMultipleConcurrentSamples) { |
281 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(testing::AtLeast(1)); | 282 EXPECT_CALL(*(observer_.get()), ScaleDown()).Times(testing::AtLeast(1)); |
282 static const int kIntervalMs = 33; | 283 static const int kIntervalMs = 33; |
283 static const size_t kNumFramesEncodingDelay = 3; | 284 static const size_t kNumFramesEncodingDelay = 3; |
284 VideoFrame frame; | 285 VideoFrame frame; |
285 frame.CreateEmptyFrame(kWidth, kHeight, kWidth, kWidth / 2, kWidth / 2); | 286 frame.CreateEmptyFrame(kWidth, kHeight, kWidth, kWidth / 2, kWidth / 2); |
286 for (size_t i = 0; i < 1000; ++i) { | 287 for (size_t i = 0; i < 1000; ++i) { |
287 // Unique timestamps. | 288 // Unique timestamps. |
288 frame.set_timestamp(static_cast<uint32_t>(i)); | 289 frame.set_timestamp(static_cast<uint32_t>(i)); |
289 overuse_detector_->FrameCaptured(frame, clock_->TimeInMilliseconds()); | 290 overuse_detector_->FrameCaptured(frame, clock_->TimeInMilliseconds()); |
290 clock_->AdvanceTimeMilliseconds(kIntervalMs); | 291 clock_->AdvanceTimeMilliseconds(kIntervalMs); |
291 if (i > kNumFramesEncodingDelay) { | 292 if (i > kNumFramesEncodingDelay) { |
292 overuse_detector_->FrameSent( | 293 overuse_detector_->FrameSent( |
293 static_cast<uint32_t>(i - kNumFramesEncodingDelay), | 294 static_cast<uint32_t>(i - kNumFramesEncodingDelay), |
294 clock_->TimeInMilliseconds()); | 295 clock_->TimeInMilliseconds()); |
295 } | 296 } |
296 overuse_detector_->CheckForOveruse(); | 297 overuse_detector_->CheckForOveruse(); |
297 } | 298 } |
298 } | 299 } |
299 | 300 |
300 TEST_F(OveruseFrameDetectorTest, UpdatesExistingSamples) { | 301 TEST_F(OveruseFrameDetectorTest, UpdatesExistingSamples) { |
301 // >85% encoding time should trigger overuse. | 302 // >85% encoding time should trigger overuse. |
302 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(testing::AtLeast(1)); | 303 EXPECT_CALL(*(observer_.get()), ScaleDown()).Times(testing::AtLeast(1)); |
303 static const int kIntervalMs = 33; | 304 static const int kIntervalMs = 33; |
304 static const int kDelayMs = 30; | 305 static const int kDelayMs = 30; |
305 VideoFrame frame; | 306 VideoFrame frame; |
306 frame.CreateEmptyFrame(kWidth, kHeight, kWidth, kWidth / 2, kWidth / 2); | 307 frame.CreateEmptyFrame(kWidth, kHeight, kWidth, kWidth / 2, kWidth / 2); |
307 uint32_t timestamp = 0; | 308 uint32_t timestamp = 0; |
308 for (size_t i = 0; i < 1000; ++i) { | 309 for (size_t i = 0; i < 1000; ++i) { |
309 frame.set_timestamp(timestamp); | 310 frame.set_timestamp(timestamp); |
310 overuse_detector_->FrameCaptured(frame, clock_->TimeInMilliseconds()); | 311 overuse_detector_->FrameCaptured(frame, clock_->TimeInMilliseconds()); |
311 // Encode and send first parts almost instantly. | 312 // Encode and send first parts almost instantly. |
312 clock_->AdvanceTimeMilliseconds(1); | 313 clock_->AdvanceTimeMilliseconds(1); |
(...skipping 12 matching lines...) Expand all Loading... |
325 | 326 |
326 rtc::Event event(false, false); | 327 rtc::Event event(false, false); |
327 queue.PostTask([this, &event] { | 328 queue.PostTask([this, &event] { |
328 overuse_detector_->StartCheckForOveruse(); | 329 overuse_detector_->StartCheckForOveruse(); |
329 event.Set(); | 330 event.Set(); |
330 }); | 331 }); |
331 event.Wait(rtc::Event::kForever); | 332 event.Wait(rtc::Event::kForever); |
332 | 333 |
333 // Expect NormalUsage(). When called, stop the |overuse_detector_| and then | 334 // Expect NormalUsage(). When called, stop the |overuse_detector_| and then |
334 // set |event| to end the test. | 335 // set |event| to end the test. |
335 EXPECT_CALL(*(observer_.get()), NormalUsage()) | 336 EXPECT_CALL(*(observer_.get()), ScaleUp()).WillOnce(Invoke([this, &event] { |
336 .WillOnce(Invoke([this, &event] { | 337 overuse_detector_->StopCheckForOveruse(); |
337 overuse_detector_->StopCheckForOveruse(); | 338 event.Set(); |
338 event.Set(); | 339 })); |
339 })); | |
340 | 340 |
341 queue.PostTask([this, &event] { | 341 queue.PostTask([this, &event] { |
342 const int kDelayMs1 = 5; | 342 const int kDelayMs1 = 5; |
343 const int kDelayMs2 = 6; | 343 const int kDelayMs2 = 6; |
344 InsertAndSendFramesWithInterval(1300, kFrameInterval33ms, kWidth, kHeight, | 344 InsertAndSendFramesWithInterval(1300, kFrameInterval33ms, kWidth, kHeight, |
345 kDelayMs1); | 345 kDelayMs1); |
346 InsertAndSendFramesWithInterval(1, kFrameInterval33ms, kWidth, kHeight, | 346 InsertAndSendFramesWithInterval(1, kFrameInterval33ms, kWidth, kHeight, |
347 kDelayMs2); | 347 kDelayMs2); |
348 }); | 348 }); |
349 | 349 |
350 EXPECT_TRUE(event.Wait(10000)); | 350 EXPECT_TRUE(event.Wait(10000)); |
351 } | 351 } |
352 | 352 |
353 } // namespace webrtc | 353 } // namespace webrtc |
OLD | NEW |