Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: webrtc/video/overuse_frame_detector_unittest.cc

Issue 1569853002: Measure encoding time on encode callbacks. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: rebase Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "webrtc/video/overuse_frame_detector.h" 11 #include "webrtc/video/overuse_frame_detector.h"
12 12
13 #include "testing/gmock/include/gmock/gmock.h" 13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h" 14 #include "testing/gtest/include/gtest/gtest.h"
15 15
16 #include "webrtc/base/scoped_ptr.h" 16 #include "webrtc/base/scoped_ptr.h"
17 #include "webrtc/system_wrappers/include/clock.h" 17 #include "webrtc/system_wrappers/include/clock.h"
18 #include "webrtc/video_frame.h"
18 19
19 namespace webrtc { 20 namespace webrtc {
20 namespace { 21 namespace {
21 const int kWidth = 640; 22 const int kWidth = 640;
22 const int kHeight = 480; 23 const int kHeight = 480;
23 const int kFrameInterval33ms = 33; 24 const int kFrameInterval33ms = 33;
24 const int kProcessIntervalMs = 5000; 25 const int kProcessIntervalMs = 5000;
25 const int kProcessTime5ms = 5; 26 const int kProcessTime5ms = 5;
26 } // namespace 27 } // namespace
27 28
(...skipping 24 matching lines...) Expand all
52 public CpuOveruseMetricsObserver { 53 public CpuOveruseMetricsObserver {
53 protected: 54 protected:
54 virtual void SetUp() { 55 virtual void SetUp() {
55 clock_.reset(new SimulatedClock(1234)); 56 clock_.reset(new SimulatedClock(1234));
56 observer_.reset(new MockCpuOveruseObserver()); 57 observer_.reset(new MockCpuOveruseObserver());
57 options_.min_process_count = 0; 58 options_.min_process_count = 0;
58 ReinitializeOveruseDetector(); 59 ReinitializeOveruseDetector();
59 } 60 }
60 61
61 void ReinitializeOveruseDetector() { 62 void ReinitializeOveruseDetector() {
62 overuse_detector_.reset(new OveruseFrameDetector(clock_.get(), options_, 63 overuse_detector_.reset(new OveruseFrameDetector(
63 observer_.get(), this)); 64 clock_.get(), options_, observer_.get(), nullptr, this));
64 } 65 }
65 66
66 void CpuOveruseMetricsUpdated(const CpuOveruseMetrics& metrics) override { 67 void OnEncodedFrameTimeMeasured(int encode_time_ms,
68 const CpuOveruseMetrics& metrics) override {
67 metrics_ = metrics; 69 metrics_ = metrics;
68 } 70 }
69 71
70 int InitialUsage() { 72 int InitialUsage() {
71 return ((options_.low_encode_usage_threshold_percent + 73 return ((options_.low_encode_usage_threshold_percent +
72 options_.high_encode_usage_threshold_percent) / 2.0f) + 0.5; 74 options_.high_encode_usage_threshold_percent) / 2.0f) + 0.5;
73 } 75 }
74 76
75 void InsertAndSendFramesWithInterval( 77 void InsertAndSendFramesWithInterval(int num_frames,
76 int num_frames, int interval_ms, int width, int height, int delay_ms) { 78 int interval_ms,
79 int width,
80 int height,
81 int delay_ms) {
82 VideoFrame frame;
83 frame.CreateEmptyFrame(width, height, width, width / 2, width / 2);
84 uint32_t timestamp = 0;
77 while (num_frames-- > 0) { 85 while (num_frames-- > 0) {
78 int64_t capture_time_ms = clock_->TimeInMilliseconds(); 86 frame.set_timestamp(timestamp);
79 overuse_detector_->FrameCaptured(width, height, capture_time_ms); 87 overuse_detector_->FrameCaptured(frame);
80 clock_->AdvanceTimeMilliseconds(delay_ms); 88 clock_->AdvanceTimeMilliseconds(delay_ms);
81 overuse_detector_->FrameSent(capture_time_ms); 89 overuse_detector_->FrameSent(timestamp);
82 clock_->AdvanceTimeMilliseconds(interval_ms - delay_ms); 90 clock_->AdvanceTimeMilliseconds(interval_ms - delay_ms);
91 timestamp += interval_ms * 90;
83 } 92 }
84 } 93 }
85 94
95 void ForceUpdate(int width, int height) {
96 // Insert one frame, wait a second and then put in another to force update
97 // the usage. From the tests where these are used, adding another sample
98 // doesn't affect the expected outcome (this is mainly to check initial
99 // values and whether the overuse detector has been reset or not).
100 InsertAndSendFramesWithInterval(2, 1000, width, height, kFrameInterval33ms);
101 }
86 void TriggerOveruse(int num_times) { 102 void TriggerOveruse(int num_times) {
87 const int kDelayMs = 32; 103 const int kDelayMs = 32;
88 for (int i = 0; i < num_times; ++i) { 104 for (int i = 0; i < num_times; ++i) {
89 InsertAndSendFramesWithInterval( 105 InsertAndSendFramesWithInterval(
90 1000, kFrameInterval33ms, kWidth, kHeight, kDelayMs); 106 1000, kFrameInterval33ms, kWidth, kHeight, kDelayMs);
91 overuse_detector_->Process(); 107 overuse_detector_->Process();
92 } 108 }
93 } 109 }
94 110
95 void TriggerUnderuse() { 111 void TriggerUnderuse() {
(...skipping 28 matching lines...) Expand all
124 // usage > high => overuse 140 // usage > high => overuse
125 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1); 141 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1);
126 TriggerOveruse(options_.high_threshold_consecutive_count); 142 TriggerOveruse(options_.high_threshold_consecutive_count);
127 // usage < low => underuse 143 // usage < low => underuse
128 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(testing::AtLeast(1)); 144 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(testing::AtLeast(1));
129 TriggerUnderuse(); 145 TriggerUnderuse();
130 } 146 }
131 147
132 TEST_F(OveruseFrameDetectorTest, OveruseAndRecoverWithNoObserver) { 148 TEST_F(OveruseFrameDetectorTest, OveruseAndRecoverWithNoObserver) {
133 overuse_detector_.reset( 149 overuse_detector_.reset(
134 new OveruseFrameDetector(clock_.get(), options_, nullptr, this)); 150 new OveruseFrameDetector(clock_.get(), options_, nullptr, nullptr, this));
135 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(0); 151 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(0);
136 TriggerOveruse(options_.high_threshold_consecutive_count); 152 TriggerOveruse(options_.high_threshold_consecutive_count);
137 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(0); 153 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(0);
138 TriggerUnderuse(); 154 TriggerUnderuse();
139 } 155 }
140 156
141 TEST_F(OveruseFrameDetectorTest, DoubleOveruseAndRecover) { 157 TEST_F(OveruseFrameDetectorTest, DoubleOveruseAndRecover) {
142 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(2); 158 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(2);
143 TriggerOveruse(options_.high_threshold_consecutive_count); 159 TriggerOveruse(options_.high_threshold_consecutive_count);
144 TriggerOveruse(options_.high_threshold_consecutive_count); 160 TriggerOveruse(options_.high_threshold_consecutive_count);
145 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(testing::AtLeast(1)); 161 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(testing::AtLeast(1));
146 TriggerUnderuse(); 162 TriggerUnderuse();
147 } 163 }
148 164
149 TEST_F(OveruseFrameDetectorTest, TriggerUnderuseWithMinProcessCount) { 165 TEST_F(OveruseFrameDetectorTest, TriggerUnderuseWithMinProcessCount) {
150 options_.min_process_count = 1; 166 options_.min_process_count = 1;
151 CpuOveruseObserverImpl overuse_observer; 167 CpuOveruseObserverImpl overuse_observer;
152 overuse_detector_.reset(new OveruseFrameDetector(clock_.get(), options_, 168 overuse_detector_.reset(new OveruseFrameDetector(
153 &overuse_observer, this)); 169 clock_.get(), options_, &overuse_observer, nullptr, this));
154 InsertAndSendFramesWithInterval( 170 InsertAndSendFramesWithInterval(
155 1200, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); 171 1200, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms);
156 overuse_detector_->Process(); 172 overuse_detector_->Process();
157 EXPECT_EQ(0, overuse_observer.normaluse_); 173 EXPECT_EQ(0, overuse_observer.normaluse_);
158 clock_->AdvanceTimeMilliseconds(kProcessIntervalMs); 174 clock_->AdvanceTimeMilliseconds(kProcessIntervalMs);
159 overuse_detector_->Process(); 175 overuse_detector_->Process();
160 EXPECT_EQ(1, overuse_observer.normaluse_); 176 EXPECT_EQ(1, overuse_observer.normaluse_);
161 } 177 }
162 178
163 TEST_F(OveruseFrameDetectorTest, ConstantOveruseGivesNoNormalUsage) { 179 TEST_F(OveruseFrameDetectorTest, ConstantOveruseGivesNoNormalUsage) {
(...skipping 18 matching lines...) Expand all
182 TriggerOveruse(1); 198 TriggerOveruse(1);
183 } 199 }
184 200
185 TEST_F(OveruseFrameDetectorTest, ProcessingUsage) { 201 TEST_F(OveruseFrameDetectorTest, ProcessingUsage) {
186 InsertAndSendFramesWithInterval( 202 InsertAndSendFramesWithInterval(
187 1000, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); 203 1000, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms);
188 EXPECT_EQ(kProcessTime5ms * 100 / kFrameInterval33ms, UsagePercent()); 204 EXPECT_EQ(kProcessTime5ms * 100 / kFrameInterval33ms, UsagePercent());
189 } 205 }
190 206
191 TEST_F(OveruseFrameDetectorTest, ResetAfterResolutionChange) { 207 TEST_F(OveruseFrameDetectorTest, ResetAfterResolutionChange) {
208 ForceUpdate(kWidth, kHeight);
192 EXPECT_EQ(InitialUsage(), UsagePercent()); 209 EXPECT_EQ(InitialUsage(), UsagePercent());
193 InsertAndSendFramesWithInterval( 210 InsertAndSendFramesWithInterval(
194 1000, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); 211 1000, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms);
195 EXPECT_NE(InitialUsage(), UsagePercent()); 212 EXPECT_NE(InitialUsage(), UsagePercent());
196 // Verify reset. 213 // Verify reset (with new width/height).
197 InsertAndSendFramesWithInterval( 214 ForceUpdate(kWidth, kHeight + 1);
198 1, kFrameInterval33ms, kWidth, kHeight + 1, kProcessTime5ms);
199 EXPECT_EQ(InitialUsage(), UsagePercent()); 215 EXPECT_EQ(InitialUsage(), UsagePercent());
200 } 216 }
201 217
202 TEST_F(OveruseFrameDetectorTest, ResetAfterFrameTimeout) { 218 TEST_F(OveruseFrameDetectorTest, ResetAfterFrameTimeout) {
219 ForceUpdate(kWidth, kHeight);
203 EXPECT_EQ(InitialUsage(), UsagePercent()); 220 EXPECT_EQ(InitialUsage(), UsagePercent());
204 InsertAndSendFramesWithInterval( 221 InsertAndSendFramesWithInterval(
205 1000, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); 222 1000, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms);
206 EXPECT_NE(InitialUsage(), UsagePercent()); 223 EXPECT_NE(InitialUsage(), UsagePercent());
207 InsertAndSendFramesWithInterval( 224 InsertAndSendFramesWithInterval(
208 2, options_.frame_timeout_interval_ms, kWidth, kHeight, kProcessTime5ms); 225 2, options_.frame_timeout_interval_ms, kWidth, kHeight, kProcessTime5ms);
209 EXPECT_NE(InitialUsage(), UsagePercent()); 226 EXPECT_NE(InitialUsage(), UsagePercent());
210 // Verify reset. 227 // Verify reset.
211 InsertAndSendFramesWithInterval( 228 InsertAndSendFramesWithInterval(
212 2, options_.frame_timeout_interval_ms + 1, kWidth, kHeight, 229 2, options_.frame_timeout_interval_ms + 1, kWidth, kHeight,
213 kProcessTime5ms); 230 kProcessTime5ms);
231 ForceUpdate(kWidth, kHeight);
214 EXPECT_EQ(InitialUsage(), UsagePercent()); 232 EXPECT_EQ(InitialUsage(), UsagePercent());
215 } 233 }
216 234
217 TEST_F(OveruseFrameDetectorTest, MinFrameSamplesBeforeUpdating) { 235 TEST_F(OveruseFrameDetectorTest, MinFrameSamplesBeforeUpdating) {
218 options_.min_frame_samples = 40; 236 options_.min_frame_samples = 40;
219 ReinitializeOveruseDetector(); 237 ReinitializeOveruseDetector();
220 InsertAndSendFramesWithInterval( 238 InsertAndSendFramesWithInterval(
221 40, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); 239 40, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms);
222 EXPECT_EQ(InitialUsage(), UsagePercent()); 240 EXPECT_EQ(InitialUsage(), UsagePercent());
241 // Pass time far enough to digest all previous samples.
242 clock_->AdvanceTimeMilliseconds(1000);
243 InsertAndSendFramesWithInterval(
244 1, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms);
245 // The last sample has not been processed here.
246 EXPECT_EQ(InitialUsage(), UsagePercent());
247
248 // Pass time far enough to digest all previous samples, 41 in total.
249 clock_->AdvanceTimeMilliseconds(1000);
223 InsertAndSendFramesWithInterval( 250 InsertAndSendFramesWithInterval(
224 1, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms); 251 1, kFrameInterval33ms, kWidth, kHeight, kProcessTime5ms);
225 EXPECT_NE(InitialUsage(), UsagePercent()); 252 EXPECT_NE(InitialUsage(), UsagePercent());
226 } 253 }
227 254
228 TEST_F(OveruseFrameDetectorTest, InitialProcessingUsage) { 255 TEST_F(OveruseFrameDetectorTest, InitialProcessingUsage) {
256 ForceUpdate(kWidth, kHeight);
229 EXPECT_EQ(InitialUsage(), UsagePercent()); 257 EXPECT_EQ(InitialUsage(), UsagePercent());
230 } 258 }
231 259
232 TEST_F(OveruseFrameDetectorTest, FrameDelay_OneFrame) { 260 TEST_F(OveruseFrameDetectorTest, MeasuresMultipleConcurrentSamples) {
233 const int kProcessingTimeMs = 100; 261 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(testing::AtLeast(1));
234 overuse_detector_->FrameCaptured(kWidth, kHeight, 33); 262 static const int kIntervalMs = 33;
235 clock_->AdvanceTimeMilliseconds(kProcessingTimeMs); 263 static const size_t kNumFramesEncodingDelay = 3;
236 EXPECT_EQ(-1, overuse_detector_->LastProcessingTimeMs()); 264 VideoFrame frame;
237 overuse_detector_->FrameSent(33); 265 frame.CreateEmptyFrame(kWidth, kHeight, kWidth, kWidth / 2, kWidth / 2);
238 EXPECT_EQ(kProcessingTimeMs, overuse_detector_->LastProcessingTimeMs()); 266 for (size_t i = 0; i < 1000; ++i) {
239 EXPECT_EQ(0, overuse_detector_->FramesInQueue()); 267 // Unique timestamps.
268 frame.set_timestamp(static_cast<uint32_t>(i));
269 overuse_detector_->FrameCaptured(frame);
270 clock_->AdvanceTimeMilliseconds(kIntervalMs);
271 if (i > kNumFramesEncodingDelay) {
272 overuse_detector_->FrameSent(
273 static_cast<uint32_t>(i - kNumFramesEncodingDelay));
274 }
275 overuse_detector_->Process();
276 }
240 } 277 }
241 278
242 TEST_F(OveruseFrameDetectorTest, FrameDelay_TwoFrames) { 279 TEST_F(OveruseFrameDetectorTest, UpdatesExistingSamples) {
243 const int kProcessingTimeMs1 = 100; 280 // >85% encoding time should trigger overuse.
244 const int kProcessingTimeMs2 = 50; 281 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(testing::AtLeast(1));
245 const int kTimeBetweenFramesMs = 200; 282 static const int kIntervalMs = 33;
246 overuse_detector_->FrameCaptured(kWidth, kHeight, 33); 283 static const int kDelayMs = 30;
247 clock_->AdvanceTimeMilliseconds(kProcessingTimeMs1); 284 VideoFrame frame;
248 overuse_detector_->FrameSent(33); 285 frame.CreateEmptyFrame(kWidth, kHeight, kWidth, kWidth / 2, kWidth / 2);
249 EXPECT_EQ(kProcessingTimeMs1, overuse_detector_->LastProcessingTimeMs()); 286 uint32_t timestamp = 0;
250 clock_->AdvanceTimeMilliseconds(kTimeBetweenFramesMs); 287 for (size_t i = 0; i < 1000; ++i) {
251 overuse_detector_->FrameCaptured(kWidth, kHeight, 66); 288 frame.set_timestamp(timestamp);
252 clock_->AdvanceTimeMilliseconds(kProcessingTimeMs2); 289 overuse_detector_->FrameCaptured(frame);
253 overuse_detector_->FrameSent(66); 290 // Encode and send first parts almost instantly.
254 EXPECT_EQ(kProcessingTimeMs2, overuse_detector_->LastProcessingTimeMs()); 291 clock_->AdvanceTimeMilliseconds(1);
255 } 292 overuse_detector_->FrameSent(timestamp);
256 293 // Encode heavier part, resulting in >85% usage total.
257 TEST_F(OveruseFrameDetectorTest, FrameDelay_MaxQueueSize) { 294 clock_->AdvanceTimeMilliseconds(kDelayMs - 1);
258 const int kMaxQueueSize = 91; 295 overuse_detector_->FrameSent(timestamp);
259 for (int i = 0; i < kMaxQueueSize * 2; ++i) { 296 clock_->AdvanceTimeMilliseconds(kIntervalMs - kDelayMs);
260 overuse_detector_->FrameCaptured(kWidth, kHeight, i); 297 timestamp += kIntervalMs * 90;
298 overuse_detector_->Process();
261 } 299 }
262 EXPECT_EQ(kMaxQueueSize, overuse_detector_->FramesInQueue());
263 }
264
265 TEST_F(OveruseFrameDetectorTest, FrameDelay_NonProcessedFramesRemoved) {
266 const int kProcessingTimeMs = 100;
267 overuse_detector_->FrameCaptured(kWidth, kHeight, 33);
268 clock_->AdvanceTimeMilliseconds(kProcessingTimeMs);
269 overuse_detector_->FrameCaptured(kWidth, kHeight, 35);
270 clock_->AdvanceTimeMilliseconds(kProcessingTimeMs);
271 overuse_detector_->FrameCaptured(kWidth, kHeight, 66);
272 clock_->AdvanceTimeMilliseconds(kProcessingTimeMs);
273 overuse_detector_->FrameCaptured(kWidth, kHeight, 99);
274 clock_->AdvanceTimeMilliseconds(kProcessingTimeMs);
275 EXPECT_EQ(-1, overuse_detector_->LastProcessingTimeMs());
276 EXPECT_EQ(4, overuse_detector_->FramesInQueue());
277 overuse_detector_->FrameSent(66);
278 // Frame 33, 35 removed, 66 processed, 99 not processed.
279 EXPECT_EQ(2 * kProcessingTimeMs, overuse_detector_->LastProcessingTimeMs());
280 EXPECT_EQ(1, overuse_detector_->FramesInQueue());
281 overuse_detector_->FrameSent(99);
282 EXPECT_EQ(kProcessingTimeMs, overuse_detector_->LastProcessingTimeMs());
283 EXPECT_EQ(0, overuse_detector_->FramesInQueue());
284 }
285
286 TEST_F(OveruseFrameDetectorTest, FrameDelay_ResetClearsFrames) {
287 const int kProcessingTimeMs = 100;
288 overuse_detector_->FrameCaptured(kWidth, kHeight, 33);
289 EXPECT_EQ(1, overuse_detector_->FramesInQueue());
290 clock_->AdvanceTimeMilliseconds(kProcessingTimeMs);
291 // Verify reset (resolution changed).
292 overuse_detector_->FrameCaptured(kWidth, kHeight + 1, 66);
293 EXPECT_EQ(1, overuse_detector_->FramesInQueue());
294 clock_->AdvanceTimeMilliseconds(kProcessingTimeMs);
295 overuse_detector_->FrameSent(66);
296 EXPECT_EQ(kProcessingTimeMs, overuse_detector_->LastProcessingTimeMs());
297 EXPECT_EQ(0, overuse_detector_->FramesInQueue());
298 }
299
300 TEST_F(OveruseFrameDetectorTest, FrameDelay_NonMatchingSendFrameIgnored) {
301 const int kProcessingTimeMs = 100;
302 overuse_detector_->FrameCaptured(kWidth, kHeight, 33);
303 clock_->AdvanceTimeMilliseconds(kProcessingTimeMs);
304 overuse_detector_->FrameSent(34);
305 EXPECT_EQ(-1, overuse_detector_->LastProcessingTimeMs());
306 overuse_detector_->FrameSent(33);
307 EXPECT_EQ(kProcessingTimeMs, overuse_detector_->LastProcessingTimeMs());
308 } 300 }
309 301
310 } // namespace webrtc 302 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698