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

Side by Side Diff: media/capture/video_capture_oracle_unittest.cc

Issue 1199593005: Automatic resolution throttling for screen capture pipeline. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@resolution_chooser_ITEM13
Patch Set: Move all end_t assignments out of for-loop init. Created 5 years, 5 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
« no previous file with comments | « media/capture/video_capture_oracle.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/capture/video_capture_oracle.h" 5 #include "media/capture/video_capture_oracle.h"
6 6
7 #include "base/strings/stringprintf.h" 7 #include "base/strings/stringprintf.h"
8 #include "testing/gtest/include/gtest/gtest.h" 8 #include "testing/gtest/include/gtest/gtest.h"
9 9
10 namespace media { 10 namespace media {
11 11
12 namespace { 12 namespace {
13 13
14 base::TimeTicks InitialTestTimeTicks() { 14 base::TimeTicks InitialTestTimeTicks() {
15 return base::TimeTicks() + base::TimeDelta::FromSeconds(1); 15 return base::TimeTicks() + base::TimeDelta::FromSeconds(1);
16 } 16 }
17 17
18 base::TimeDelta Get30HzPeriod() {
19 return base::TimeDelta::FromSeconds(1) / 30;
20 }
21
22 gfx::Size Get720pSize() {
23 return gfx::Size(1280, 720);
24 }
25
18 } // namespace 26 } // namespace
19 27
20 // Tests that VideoCaptureOracle filters out events whose timestamps are 28 // Tests that VideoCaptureOracle filters out events whose timestamps are
21 // decreasing. 29 // decreasing.
22 TEST(VideoCaptureOracleTest, EnforcesEventTimeMonotonicity) { 30 TEST(VideoCaptureOracleTest, EnforcesEventTimeMonotonicity) {
23 const base::TimeDelta min_capture_period = 31 const gfx::Rect damage_rect(Get720pSize());
24 base::TimeDelta::FromSeconds(1) / 30; 32 const base::TimeDelta event_increment = Get30HzPeriod() * 2;
25 const gfx::Rect damage_rect(0, 0, 1280, 720);
26 const base::TimeDelta event_increment = min_capture_period * 2;
27 33
28 VideoCaptureOracle oracle(min_capture_period); 34 VideoCaptureOracle oracle(Get30HzPeriod(),
35 Get720pSize(),
36 media::RESOLUTION_POLICY_FIXED_RESOLUTION,
37 false);
29 38
30 base::TimeTicks t = InitialTestTimeTicks(); 39 base::TimeTicks t = InitialTestTimeTicks();
31 for (int i = 0; i < 10; ++i) { 40 for (int i = 0; i < 10; ++i) {
32 t += event_increment; 41 t += event_increment;
33 ASSERT_TRUE(oracle.ObserveEventAndDecideCapture( 42 ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
34 VideoCaptureOracle::kCompositorUpdate, 43 VideoCaptureOracle::kCompositorUpdate,
35 damage_rect, t)); 44 damage_rect, t));
36 } 45 }
37 46
38 base::TimeTicks furthest_event_time = t; 47 base::TimeTicks furthest_event_time = t;
(...skipping 10 matching lines...) Expand all
49 ASSERT_TRUE(oracle.ObserveEventAndDecideCapture( 58 ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
50 VideoCaptureOracle::kCompositorUpdate, 59 VideoCaptureOracle::kCompositorUpdate,
51 damage_rect, t)); 60 damage_rect, t));
52 } 61 }
53 } 62 }
54 63
55 // Tests that VideoCaptureOracle is enforcing the requirement that 64 // Tests that VideoCaptureOracle is enforcing the requirement that
56 // successfully captured frames are delivered in order. Otherwise, downstream 65 // successfully captured frames are delivered in order. Otherwise, downstream
57 // consumers could be tripped-up by out-of-order frames or frame timestamps. 66 // consumers could be tripped-up by out-of-order frames or frame timestamps.
58 TEST(VideoCaptureOracleTest, EnforcesFramesDeliveredInOrder) { 67 TEST(VideoCaptureOracleTest, EnforcesFramesDeliveredInOrder) {
59 const base::TimeDelta min_capture_period = 68 const gfx::Rect damage_rect(Get720pSize());
60 base::TimeDelta::FromSeconds(1) / 30; 69 const base::TimeDelta event_increment = Get30HzPeriod() * 2;
61 const gfx::Rect damage_rect(0, 0, 1280, 720);
62 const base::TimeDelta event_increment = min_capture_period * 2;
63 70
64 VideoCaptureOracle oracle(min_capture_period); 71 VideoCaptureOracle oracle(Get30HzPeriod(),
72 Get720pSize(),
73 media::RESOLUTION_POLICY_FIXED_RESOLUTION,
74 false);
65 75
66 // Most basic scenario: Frames delivered one at a time, with no additional 76 // Most basic scenario: Frames delivered one at a time, with no additional
67 // captures in-between deliveries. 77 // captures in-between deliveries.
68 base::TimeTicks t = InitialTestTimeTicks(); 78 base::TimeTicks t = InitialTestTimeTicks();
69 int last_frame_number; 79 int last_frame_number;
70 base::TimeTicks ignored; 80 base::TimeTicks ignored;
71 for (int i = 0; i < 10; ++i) { 81 for (int i = 0; i < 10; ++i) {
72 t += event_increment; 82 t += event_increment;
73 ASSERT_TRUE(oracle.ObserveEventAndDecideCapture( 83 ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
74 VideoCaptureOracle::kCompositorUpdate, 84 VideoCaptureOracle::kCompositorUpdate,
75 damage_rect, t)); 85 damage_rect, t));
76 last_frame_number = oracle.RecordCapture(); 86 last_frame_number = oracle.RecordCapture(0.0);
77 ASSERT_TRUE(oracle.CompleteCapture(last_frame_number, true, &ignored)); 87 ASSERT_TRUE(oracle.CompleteCapture(last_frame_number, true, &ignored));
78 } 88 }
79 89
80 // Basic pipelined scenario: More than one frame in-flight at delivery points. 90 // Basic pipelined scenario: More than one frame in-flight at delivery points.
81 for (int i = 0; i < 50; ++i) { 91 for (int i = 0; i < 50; ++i) {
82 const int num_in_flight = 1 + i % 3; 92 const int num_in_flight = 1 + i % 3;
83 for (int j = 0; j < num_in_flight; ++j) { 93 for (int j = 0; j < num_in_flight; ++j) {
84 t += event_increment; 94 t += event_increment;
85 ASSERT_TRUE(oracle.ObserveEventAndDecideCapture( 95 ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
86 VideoCaptureOracle::kCompositorUpdate, 96 VideoCaptureOracle::kCompositorUpdate,
87 damage_rect, t)); 97 damage_rect, t));
88 last_frame_number = oracle.RecordCapture(); 98 last_frame_number = oracle.RecordCapture(0.0);
89 } 99 }
90 for (int j = num_in_flight - 1; j >= 0; --j) { 100 for (int j = num_in_flight - 1; j >= 0; --j) {
91 ASSERT_TRUE( 101 ASSERT_TRUE(
92 oracle.CompleteCapture(last_frame_number - j, true, &ignored)); 102 oracle.CompleteCapture(last_frame_number - j, true, &ignored));
93 } 103 }
94 } 104 }
95 105
96 // Pipelined scenario with successful out-of-order delivery attempts 106 // Pipelined scenario with successful out-of-order delivery attempts
97 // rejected. 107 // rejected.
98 for (int i = 0; i < 50; ++i) { 108 for (int i = 0; i < 50; ++i) {
99 const int num_in_flight = 1 + i % 3; 109 const int num_in_flight = 1 + i % 3;
100 for (int j = 0; j < num_in_flight; ++j) { 110 for (int j = 0; j < num_in_flight; ++j) {
101 t += event_increment; 111 t += event_increment;
102 ASSERT_TRUE(oracle.ObserveEventAndDecideCapture( 112 ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
103 VideoCaptureOracle::kCompositorUpdate, 113 VideoCaptureOracle::kCompositorUpdate,
104 damage_rect, t)); 114 damage_rect, t));
105 last_frame_number = oracle.RecordCapture(); 115 last_frame_number = oracle.RecordCapture(0.0);
106 } 116 }
107 ASSERT_TRUE(oracle.CompleteCapture(last_frame_number, true, &ignored)); 117 ASSERT_TRUE(oracle.CompleteCapture(last_frame_number, true, &ignored));
108 for (int j = 1; j < num_in_flight; ++j) { 118 for (int j = 1; j < num_in_flight; ++j) {
109 ASSERT_FALSE( 119 ASSERT_FALSE(
110 oracle.CompleteCapture(last_frame_number - j, true, &ignored)); 120 oracle.CompleteCapture(last_frame_number - j, true, &ignored));
111 } 121 }
112 } 122 }
113 123
114 // Pipelined scenario with successful delivery attempts accepted after an 124 // Pipelined scenario with successful delivery attempts accepted after an
115 // unsuccessful out of order delivery attempt. 125 // unsuccessful out of order delivery attempt.
116 for (int i = 0; i < 50; ++i) { 126 for (int i = 0; i < 50; ++i) {
117 const int num_in_flight = 1 + i % 3; 127 const int num_in_flight = 1 + i % 3;
118 for (int j = 0; j < num_in_flight; ++j) { 128 for (int j = 0; j < num_in_flight; ++j) {
119 t += event_increment; 129 t += event_increment;
120 ASSERT_TRUE(oracle.ObserveEventAndDecideCapture( 130 ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
121 VideoCaptureOracle::kCompositorUpdate, 131 VideoCaptureOracle::kCompositorUpdate,
122 damage_rect, t)); 132 damage_rect, t));
123 last_frame_number = oracle.RecordCapture(); 133 last_frame_number = oracle.RecordCapture(0.0);
124 } 134 }
125 // Report the last frame as an out of order failure. 135 // Report the last frame as an out of order failure.
126 ASSERT_FALSE(oracle.CompleteCapture(last_frame_number, false, &ignored)); 136 ASSERT_FALSE(oracle.CompleteCapture(last_frame_number, false, &ignored));
127 for (int j = 1; j < num_in_flight - 1; ++j) { 137 for (int j = 1; j < num_in_flight - 1; ++j) {
128 ASSERT_TRUE( 138 ASSERT_TRUE(
129 oracle.CompleteCapture(last_frame_number - j, true, &ignored)); 139 oracle.CompleteCapture(last_frame_number - j, true, &ignored));
130 } 140 }
131 141
132 } 142 }
133 } 143 }
134 144
135 // Tests that VideoCaptureOracle transitions between using its two samplers in a 145 // Tests that VideoCaptureOracle transitions between using its two samplers in a
136 // way that does not introduce severe jank, pauses, etc. 146 // way that does not introduce severe jank, pauses, etc.
137 TEST(VideoCaptureOracleTest, TransitionsSmoothlyBetweenSamplers) { 147 TEST(VideoCaptureOracleTest, TransitionsSmoothlyBetweenSamplers) {
138 const base::TimeDelta min_capture_period = 148 const gfx::Rect animation_damage_rect(Get720pSize());
139 base::TimeDelta::FromSeconds(1) / 30; 149 const base::TimeDelta event_increment = Get30HzPeriod() * 2;
140 const gfx::Rect animation_damage_rect(0, 0, 1280, 720);
141 const base::TimeDelta event_increment = min_capture_period * 2;
142 150
143 VideoCaptureOracle oracle(min_capture_period); 151 VideoCaptureOracle oracle(Get30HzPeriod(),
152 Get720pSize(),
153 media::RESOLUTION_POLICY_FIXED_RESOLUTION,
154 false);
144 155
145 // Run sequences of animation events and non-animation events through the 156 // Run sequences of animation events and non-animation events through the
146 // oracle. As the oracle transitions between each sampler, make sure the 157 // oracle. As the oracle transitions between each sampler, make sure the
147 // frame timestamps won't trip-up downstream consumers. 158 // frame timestamps won't trip-up downstream consumers.
148 base::TimeTicks t = InitialTestTimeTicks(); 159 base::TimeTicks t = InitialTestTimeTicks();
149 base::TimeTicks last_frame_timestamp; 160 base::TimeTicks last_frame_timestamp;
150 for (int i = 0; i < 1000; ++i) { 161 for (int i = 0; i < 1000; ++i) {
151 t += event_increment; 162 t += event_increment;
152 163
153 // For every 100 events, provide 50 that will cause the 164 // For every 100 events, provide 50 that will cause the
(...skipping 12 matching lines...) Expand all
166 provide_animated_content_event ? animation_damage_rect : gfx::Rect(), 177 provide_animated_content_event ? animation_damage_rect : gfx::Rect(),
167 t); 178 t);
168 if (require_oracle_says_sample) 179 if (require_oracle_says_sample)
169 ASSERT_TRUE(oracle_says_sample); 180 ASSERT_TRUE(oracle_says_sample);
170 if (!oracle_says_sample) { 181 if (!oracle_says_sample) {
171 ASSERT_EQ(base::TimeDelta(), oracle.estimated_frame_duration()); 182 ASSERT_EQ(base::TimeDelta(), oracle.estimated_frame_duration());
172 continue; 183 continue;
173 } 184 }
174 ASSERT_LT(base::TimeDelta(), oracle.estimated_frame_duration()); 185 ASSERT_LT(base::TimeDelta(), oracle.estimated_frame_duration());
175 186
176 const int frame_number = oracle.RecordCapture(); 187 const int frame_number = oracle.RecordCapture(0.0);
177 188
178 base::TimeTicks frame_timestamp; 189 base::TimeTicks frame_timestamp;
179 ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &frame_timestamp)); 190 ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &frame_timestamp));
180 ASSERT_FALSE(frame_timestamp.is_null()); 191 ASSERT_FALSE(frame_timestamp.is_null());
181 if (!last_frame_timestamp.is_null()) { 192 if (!last_frame_timestamp.is_null()) {
182 const base::TimeDelta delta = frame_timestamp - last_frame_timestamp; 193 const base::TimeDelta delta = frame_timestamp - last_frame_timestamp;
183 EXPECT_LE(event_increment.InMicroseconds(), delta.InMicroseconds()); 194 EXPECT_LE(event_increment.InMicroseconds(), delta.InMicroseconds());
184 // Right after the AnimatedContentSampler lock-out transition, there were 195 // Right after the AnimatedContentSampler lock-out transition, there were
185 // a few frames dropped, so allow a gap in the timestamps. Otherwise, the 196 // a few frames dropped, so allow a gap in the timestamps. Otherwise, the
186 // delta between frame timestamps should never be more than 2X the 197 // delta between frame timestamps should never be more than 2X the
187 // |event_increment|. 198 // |event_increment|.
188 const base::TimeDelta max_acceptable_delta = (i % 100) == 78 ? 199 const base::TimeDelta max_acceptable_delta = (i % 100) == 78 ?
189 event_increment * 5 : event_increment * 2; 200 event_increment * 5 : event_increment * 2;
190 EXPECT_GE(max_acceptable_delta.InMicroseconds(), delta.InMicroseconds()); 201 EXPECT_GE(max_acceptable_delta.InMicroseconds(), delta.InMicroseconds());
191 } 202 }
192 last_frame_timestamp = frame_timestamp; 203 last_frame_timestamp = frame_timestamp;
193 } 204 }
194 } 205 }
195 206
196 // Tests that VideoCaptureOracle prevents timer polling from initiating 207 // Tests that VideoCaptureOracle prevents timer polling from initiating
197 // simultaneous captures. 208 // simultaneous captures.
198 TEST(VideoCaptureOracleTest, SamplesOnlyOneOverdueFrameAtATime) { 209 TEST(VideoCaptureOracleTest, SamplesOnlyOneOverdueFrameAtATime) {
199 const base::TimeDelta min_capture_period =
200 base::TimeDelta::FromSeconds(1) / 30;
201 const base::TimeDelta vsync_interval = 210 const base::TimeDelta vsync_interval =
202 base::TimeDelta::FromSeconds(1) / 60; 211 base::TimeDelta::FromSeconds(1) / 60;
203 const base::TimeDelta timer_interval = base::TimeDelta::FromMilliseconds( 212 const base::TimeDelta timer_interval = base::TimeDelta::FromMilliseconds(
204 VideoCaptureOracle::kMinTimerPollPeriodMillis); 213 VideoCaptureOracle::kMinTimerPollPeriodMillis);
205 214
206 VideoCaptureOracle oracle(min_capture_period); 215 VideoCaptureOracle oracle(Get30HzPeriod(),
216 Get720pSize(),
217 media::RESOLUTION_POLICY_FIXED_RESOLUTION,
218 false);
207 219
208 // Have the oracle observe some compositor events. Simulate that each capture 220 // Have the oracle observe some compositor events. Simulate that each capture
209 // completes successfully. 221 // completes successfully.
210 base::TimeTicks t = InitialTestTimeTicks(); 222 base::TimeTicks t = InitialTestTimeTicks();
211 base::TimeTicks ignored; 223 base::TimeTicks ignored;
212 bool did_complete_a_capture = false; 224 bool did_complete_a_capture = false;
213 for (int i = 0; i < 10; ++i) { 225 for (int i = 0; i < 10; ++i) {
214 t += vsync_interval; 226 t += vsync_interval;
215 if (oracle.ObserveEventAndDecideCapture( 227 if (oracle.ObserveEventAndDecideCapture(
216 VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t)) { 228 VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t)) {
217 ASSERT_TRUE( 229 ASSERT_TRUE(
218 oracle.CompleteCapture(oracle.RecordCapture(), true, &ignored)); 230 oracle.CompleteCapture(oracle.RecordCapture(0.0), true, &ignored));
219 did_complete_a_capture = true; 231 did_complete_a_capture = true;
220 } 232 }
221 } 233 }
222 ASSERT_TRUE(did_complete_a_capture); 234 ASSERT_TRUE(did_complete_a_capture);
223 235
224 // Start one more compositor-based capture, but do not notify of completion 236 // Start one more compositor-based capture, but do not notify of completion
225 // yet. 237 // yet.
226 for (int i = 0; i <= 10; ++i) { 238 for (int i = 0; i <= 10; ++i) {
227 ASSERT_GT(10, i) << "BUG: Seems like it'll never happen!"; 239 ASSERT_GT(10, i) << "BUG: Seems like it'll never happen!";
228 t += vsync_interval; 240 t += vsync_interval;
229 if (oracle.ObserveEventAndDecideCapture( 241 if (oracle.ObserveEventAndDecideCapture(
230 VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t)) { 242 VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t)) {
231 break; 243 break;
232 } 244 }
233 } 245 }
234 int frame_number = oracle.RecordCapture(); 246 int frame_number = oracle.RecordCapture(0.0);
235 247
236 // Stop providing the compositor events and start providing timer polling 248 // Stop providing the compositor events and start providing timer polling
237 // events. No overdue samplings should be recommended because of the 249 // events. No overdue samplings should be recommended because of the
238 // not-yet-complete compositor-based capture. 250 // not-yet-complete compositor-based capture.
239 for (int i = 0; i < 10; ++i) { 251 for (int i = 0; i < 10; ++i) {
240 t += timer_interval; 252 t += timer_interval;
241 ASSERT_FALSE(oracle.ObserveEventAndDecideCapture( 253 ASSERT_FALSE(oracle.ObserveEventAndDecideCapture(
242 VideoCaptureOracle::kTimerPoll, gfx::Rect(), t)); 254 VideoCaptureOracle::kTimerPoll, gfx::Rect(), t));
243 } 255 }
244 256
245 // Now, complete the oustanding compositor-based capture and continue 257 // Now, complete the oustanding compositor-based capture and continue
246 // providing timer polling events. The oracle should start recommending 258 // providing timer polling events. The oracle should start recommending
247 // sampling again. 259 // sampling again.
248 ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored)); 260 ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
249 did_complete_a_capture = false; 261 did_complete_a_capture = false;
250 for (int i = 0; i < 10; ++i) { 262 for (int i = 0; i < 10; ++i) {
251 t += timer_interval; 263 t += timer_interval;
252 if (oracle.ObserveEventAndDecideCapture( 264 if (oracle.ObserveEventAndDecideCapture(
253 VideoCaptureOracle::kTimerPoll, gfx::Rect(), t)) { 265 VideoCaptureOracle::kTimerPoll, gfx::Rect(), t)) {
254 ASSERT_TRUE( 266 ASSERT_TRUE(
255 oracle.CompleteCapture(oracle.RecordCapture(), true, &ignored)); 267 oracle.CompleteCapture(oracle.RecordCapture(0.0), true, &ignored));
256 did_complete_a_capture = true; 268 did_complete_a_capture = true;
257 } 269 }
258 } 270 }
259 ASSERT_TRUE(did_complete_a_capture); 271 ASSERT_TRUE(did_complete_a_capture);
260 272
261 // Start one more timer-based capture, but do not notify of completion yet. 273 // Start one more timer-based capture, but do not notify of completion yet.
262 for (int i = 0; i <= 10; ++i) { 274 for (int i = 0; i <= 10; ++i) {
263 ASSERT_GT(10, i) << "BUG: Seems like it'll never happen!"; 275 ASSERT_GT(10, i) << "BUG: Seems like it'll never happen!";
264 t += timer_interval; 276 t += timer_interval;
265 if (oracle.ObserveEventAndDecideCapture( 277 if (oracle.ObserveEventAndDecideCapture(
266 VideoCaptureOracle::kTimerPoll, gfx::Rect(), t)) { 278 VideoCaptureOracle::kTimerPoll, gfx::Rect(), t)) {
267 break; 279 break;
268 } 280 }
269 } 281 }
270 frame_number = oracle.RecordCapture(); 282 frame_number = oracle.RecordCapture(0.0);
271 283
272 // Confirm that the oracle does not recommend sampling until the outstanding 284 // Confirm that the oracle does not recommend sampling until the outstanding
273 // timer-based capture completes. 285 // timer-based capture completes.
274 for (int i = 0; i < 10; ++i) { 286 for (int i = 0; i < 10; ++i) {
275 t += timer_interval; 287 t += timer_interval;
276 ASSERT_FALSE(oracle.ObserveEventAndDecideCapture( 288 ASSERT_FALSE(oracle.ObserveEventAndDecideCapture(
277 VideoCaptureOracle::kTimerPoll, gfx::Rect(), t)); 289 VideoCaptureOracle::kTimerPoll, gfx::Rect(), t));
278 } 290 }
279 ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored)); 291 ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
280 for (int i = 0; i <= 10; ++i) { 292 for (int i = 0; i <= 10; ++i) {
281 ASSERT_GT(10, i) << "BUG: Seems like it'll never happen!"; 293 ASSERT_GT(10, i) << "BUG: Seems like it'll never happen!";
282 t += timer_interval; 294 t += timer_interval;
283 if (oracle.ObserveEventAndDecideCapture( 295 if (oracle.ObserveEventAndDecideCapture(
284 VideoCaptureOracle::kTimerPoll, gfx::Rect(), t)) { 296 VideoCaptureOracle::kTimerPoll, gfx::Rect(), t)) {
285 break; 297 break;
286 } 298 }
287 } 299 }
288 } 300 }
289 301
302 // Tests that VideoCaptureOracle does not rapidly change proposed capture sizes,
303 // to allow both the source content and the rest of the end-to-end system to
304 // stabilize.
305 TEST(VideoCaptureOracleTest, DoesNotRapidlyChangeCaptureSize) {
306 VideoCaptureOracle oracle(Get30HzPeriod(),
307 Get720pSize(),
308 media::RESOLUTION_POLICY_ANY_WITHIN_LIMIT,
309 true);
310
311 // Run 30 seconds of frame captures without any source size changes.
312 base::TimeTicks t = InitialTestTimeTicks();
313 const base::TimeDelta event_increment = Get30HzPeriod() * 2;
314 base::TimeTicks end_t = t + base::TimeDelta::FromSeconds(30);
315 for (; t < end_t; t += event_increment) {
316 ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
317 VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t));
318 ASSERT_EQ(Get720pSize(), oracle.capture_size());
319 base::TimeTicks ignored;
320 ASSERT_TRUE(oracle.CompleteCapture(
321 oracle.RecordCapture(0.0), true, &ignored));
322 }
323
324 // Now run 30 seconds of frame captures with lots of random source size
325 // changes. Check that there was no more than one size change per second.
326 gfx::Size source_size = oracle.capture_size();
327 base::TimeTicks time_of_last_size_change = InitialTestTimeTicks();
328 gfx::Size last_capture_size = oracle.capture_size();
329 end_t = t + base::TimeDelta::FromSeconds(30);
330 for (; t < end_t; t += event_increment) {
331 // Change the source size every frame to a random non-empty size.
332 const gfx::Size last_source_size = source_size;
333 source_size.SetSize(
334 ((last_source_size.width() * 11 + 12345) % 1280) + 1,
335 ((last_source_size.height() * 11 + 12345) % 720) + 1);
336 ASSERT_NE(last_source_size, source_size);
337 oracle.SetSourceSize(source_size);
338
339 ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
340 VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t));
341
342 if (oracle.capture_size() != last_capture_size) {
343 ASSERT_GE(t - time_of_last_size_change, base::TimeDelta::FromSeconds(1));
344 time_of_last_size_change = t;
345 last_capture_size = oracle.capture_size();
346 }
347
348 base::TimeTicks ignored;
349 ASSERT_TRUE(oracle.CompleteCapture(
350 oracle.RecordCapture(0.0), true, &ignored));
351 }
352 }
353
354 namespace {
355
356 // Tests that VideoCaptureOracle can auto-throttle by stepping the capture size
357 // up or down. When |is_content_animating| is false, there is more
358 // aggressiveness expected in the timing of stepping upwards. If
359 // |with_consumer_feedback| is false, only buffer pool utilization varies and no
360 // consumer feedback is provided. If |with_consumer_feedback| is true, the
361 // buffer pool utilization is held constant at 25%, and the consumer utilization
362 // feedback varies.
363 void RunAutoThrottleTest(bool is_content_animating,
364 bool with_consumer_feedback) {
365 SCOPED_TRACE(::testing::Message() << "RunAutoThrottleTest("
366 << "(is_content_animating=" << is_content_animating
367 << ", with_consumer_feedback=" << with_consumer_feedback << ")");
368
369 VideoCaptureOracle oracle(Get30HzPeriod(),
370 Get720pSize(),
371 media::RESOLUTION_POLICY_ANY_WITHIN_LIMIT,
372 true);
373
374 // Run 10 seconds of frame captures with 90% utilization expect no capture
375 // size changes.
376 base::TimeTicks t = InitialTestTimeTicks();
377 base::TimeTicks time_of_last_size_change = t;
378 const base::TimeDelta event_increment = Get30HzPeriod() * 2;
379 base::TimeTicks end_t = t + base::TimeDelta::FromSeconds(10);
380 for (; t < end_t; t += event_increment) {
381 ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
382 VideoCaptureOracle::kCompositorUpdate,
383 is_content_animating ? gfx::Rect(Get720pSize()) : gfx::Rect(),
384 t));
385 ASSERT_EQ(Get720pSize(), oracle.capture_size());
386 const double utilization = 0.9;
387 const int frame_number =
388 oracle.RecordCapture(with_consumer_feedback ? 0.25 : utilization);
389 base::TimeTicks ignored;
390 ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
391 if (with_consumer_feedback)
392 oracle.RecordConsumerFeedback(frame_number, utilization);
393 }
394
395 // Cause two downward steppings in resolution. First, indicate overload
396 // until the resolution steps down. Then, indicate a 90% utilization and
397 // expect the resolution to remain constant. Repeat.
398 for (int i = 0; i < 2; ++i) {
399 const gfx::Size starting_size = oracle.capture_size();
400 SCOPED_TRACE(::testing::Message()
401 << "Stepping down from " << starting_size.ToString()
402 << ", i=" << i);
403
404 gfx::Size stepped_down_size;
405 end_t = t + base::TimeDelta::FromSeconds(10);
406 for (; t < end_t; t += event_increment) {
407 ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
408 VideoCaptureOracle::kCompositorUpdate,
409 is_content_animating ? gfx::Rect(Get720pSize()) : gfx::Rect(),
410 t));
411
412 if (stepped_down_size.IsEmpty()) {
413 if (oracle.capture_size() != starting_size) {
414 time_of_last_size_change = t;
415 stepped_down_size = oracle.capture_size();
416 ASSERT_GT(starting_size.width(), stepped_down_size.width());
417 ASSERT_GT(starting_size.height(), stepped_down_size.height());
418 }
419 } else {
420 ASSERT_EQ(stepped_down_size, oracle.capture_size());
421 }
422
423 const double utilization = stepped_down_size.IsEmpty() ? 1.5 : 0.9;
424 const int frame_number =
425 oracle.RecordCapture(with_consumer_feedback ? 0.25 : utilization);
426 base::TimeTicks ignored;
427 ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
428 if (with_consumer_feedback)
429 oracle.RecordConsumerFeedback(frame_number, utilization);
430 }
431 }
432
433 // Now, cause two upward steppings in resolution. First, indicate
434 // under-utilization until the resolution steps up. Then, indicate a 90%
435 // utilization and expect the resolution to remain constant. Repeat.
436 for (int i = 0; i < 2; ++i) {
437 const gfx::Size starting_size = oracle.capture_size();
438 SCOPED_TRACE(::testing::Message()
439 << "Stepping up from " << starting_size.ToString()
440 << ", i=" << i);
441
442 gfx::Size stepped_up_size;
443 end_t = t + base::TimeDelta::FromSeconds(is_content_animating ? 90 : 10);
444 for (; t < end_t; t += event_increment) {
445 ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
446 VideoCaptureOracle::kCompositorUpdate,
447 is_content_animating ? gfx::Rect(Get720pSize()) : gfx::Rect(),
448 t));
449
450 if (stepped_up_size.IsEmpty()) {
451 if (oracle.capture_size() != starting_size) {
452 // When content is animating, a much longer amount of time must pass
453 // before the capture size will step up.
454 ASSERT_LT(
455 base::TimeDelta::FromSeconds(is_content_animating ? 15 : 1),
456 t - time_of_last_size_change);
457 time_of_last_size_change = t;
458 stepped_up_size = oracle.capture_size();
459 ASSERT_LT(starting_size.width(), stepped_up_size.width());
460 ASSERT_LT(starting_size.height(), stepped_up_size.height());
461 }
462 } else {
463 ASSERT_EQ(stepped_up_size, oracle.capture_size());
464 }
465
466 const double utilization = stepped_up_size.IsEmpty() ? 0.0 : 0.9;
467 const int frame_number =
468 oracle.RecordCapture(with_consumer_feedback ? 0.25 : utilization);
469 base::TimeTicks ignored;
470 ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
471 if (with_consumer_feedback)
472 oracle.RecordConsumerFeedback(frame_number, utilization);
473 }
474 }
475 }
476
477 } // namespace
478
479 // Tests that VideoCaptureOracle can auto-throttle by stepping the capture size
480 // up or down, using utilization feedback signals from either the buffer pool or
481 // the consumer, and with slightly different behavior depending on whether
482 // content is animating.
483 TEST(VideoCaptureOracleTest, AutoThrottlesBasedOnUtilizationFeedback) {
484 RunAutoThrottleTest(false, false);
485 RunAutoThrottleTest(false, true);
486 RunAutoThrottleTest(true, false);
487 RunAutoThrottleTest(true, true);
488 }
489
490 // Tests that VideoCaptureOracle does not change the capture size if
491 // auto-throttling is enabled when using a fixed resolution policy.
492 TEST(VideoCaptureOracleTest, DoesNotAutoThrottleWhenResolutionIsFixed) {
493 VideoCaptureOracle oracle(Get30HzPeriod(),
494 Get720pSize(),
495 media::RESOLUTION_POLICY_FIXED_RESOLUTION,
496 true);
497
498 // Run 10 seconds of frame captures with 90% utilization expect no capture
499 // size changes.
500 base::TimeTicks t = InitialTestTimeTicks();
501 const base::TimeDelta event_increment = Get30HzPeriod() * 2;
502 base::TimeTicks end_t = t + base::TimeDelta::FromSeconds(10);
503 for (; t < end_t; t += event_increment) {
504 ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
505 VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t));
506 ASSERT_EQ(Get720pSize(), oracle.capture_size());
507 base::TimeTicks ignored;
508 ASSERT_TRUE(
509 oracle.CompleteCapture(oracle.RecordCapture(0.9), true, &ignored));
510 }
511
512 // Now run 10 seconds with overload indicated. Still, expect no capture size
513 // changes.
514 end_t = t + base::TimeDelta::FromSeconds(10);
515 for (; t < end_t; t += event_increment) {
516 ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
517 VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t));
518 ASSERT_EQ(Get720pSize(), oracle.capture_size());
519 base::TimeTicks ignored;
520 ASSERT_TRUE(
521 oracle.CompleteCapture(oracle.RecordCapture(2.0), true, &ignored));
522 }
523 }
524
290 } // namespace media 525 } // namespace media
OLDNEW
« no previous file with comments | « media/capture/video_capture_oracle.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698