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

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

Issue 1162863003: Move ContentVideoCaptureDeviceCore from src/content to src/media (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 6 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
(Empty)
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/media/capture/video_capture_oracle.h"
6
7 #include "base/strings/stringprintf.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9
10 namespace content {
11
12 namespace {
13
14 base::TimeTicks InitialTestTimeTicks() {
15 return base::TimeTicks() + base::TimeDelta::FromSeconds(1);
16 }
17
18 } // namespace
19
20 // Tests that VideoCaptureOracle filters out events whose timestamps are
21 // decreasing.
22 TEST(VideoCaptureOracleTest, EnforcesEventTimeMonotonicity) {
23 const base::TimeDelta min_capture_period =
24 base::TimeDelta::FromSeconds(1) / 30;
25 const gfx::Rect damage_rect(0, 0, 1280, 720);
26 const base::TimeDelta event_increment = min_capture_period * 2;
27
28 VideoCaptureOracle oracle(min_capture_period);
29
30 base::TimeTicks t = InitialTestTimeTicks();
31 for (int i = 0; i < 10; ++i) {
32 t += event_increment;
33 ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
34 VideoCaptureOracle::kCompositorUpdate,
35 damage_rect, t));
36 }
37
38 base::TimeTicks furthest_event_time = t;
39 for (int i = 0; i < 10; ++i) {
40 t -= event_increment;
41 ASSERT_FALSE(oracle.ObserveEventAndDecideCapture(
42 VideoCaptureOracle::kCompositorUpdate,
43 damage_rect, t));
44 }
45
46 t = furthest_event_time;
47 for (int i = 0; i < 10; ++i) {
48 t += event_increment;
49 ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
50 VideoCaptureOracle::kCompositorUpdate,
51 damage_rect, t));
52 }
53 }
54
55 // Tests that VideoCaptureOracle is enforcing the requirement that captured
56 // frames are delivered in order. Otherwise, downstream consumers could be
57 // tripped-up by out-of-order frames or frame timestamps.
58 TEST(VideoCaptureOracleTest, EnforcesFramesDeliveredInOrder) {
59 const base::TimeDelta min_capture_period =
60 base::TimeDelta::FromSeconds(1) / 30;
61 const gfx::Rect damage_rect(0, 0, 1280, 720);
62 const base::TimeDelta event_increment = min_capture_period * 2;
63
64 VideoCaptureOracle oracle(min_capture_period);
65
66 // Most basic scenario: Frames delivered one at a time, with no additional
67 // captures in-between deliveries.
68 base::TimeTicks t = InitialTestTimeTicks();
69 int last_frame_number;
70 base::TimeTicks ignored;
71 for (int i = 0; i < 10; ++i) {
72 t += event_increment;
73 ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
74 VideoCaptureOracle::kCompositorUpdate,
75 damage_rect, t));
76 last_frame_number = oracle.RecordCapture();
77 ASSERT_TRUE(oracle.CompleteCapture(last_frame_number, true, &ignored));
78 }
79
80 // Basic pipelined scenario: More than one frame in-flight at delivery points.
81 for (int i = 0; i < 50; ++i) {
82 const int num_in_flight = 1 + i % 3;
83 for (int j = 0; j < num_in_flight; ++j) {
84 t += event_increment;
85 ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
86 VideoCaptureOracle::kCompositorUpdate,
87 damage_rect, t));
88 last_frame_number = oracle.RecordCapture();
89 }
90 for (int j = num_in_flight - 1; j >= 0; --j) {
91 ASSERT_TRUE(
92 oracle.CompleteCapture(last_frame_number - j, true, &ignored));
93 }
94 }
95
96 // Pipelined scenario with out-of-order delivery attempts rejected.
97 for (int i = 0; i < 50; ++i) {
98 const int num_in_flight = 1 + i % 3;
99 for (int j = 0; j < num_in_flight; ++j) {
100 t += event_increment;
101 ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
102 VideoCaptureOracle::kCompositorUpdate,
103 damage_rect, t));
104 last_frame_number = oracle.RecordCapture();
105 }
106 ASSERT_TRUE(oracle.CompleteCapture(last_frame_number, true, &ignored));
107 for (int j = 1; j < num_in_flight; ++j) {
108 ASSERT_FALSE(
109 oracle.CompleteCapture(last_frame_number - j, true, &ignored));
110 }
111 }
112 }
113
114 // Tests that VideoCaptureOracle transitions between using its two samplers in a
115 // way that does not introduce severe jank, pauses, etc.
116 TEST(VideoCaptureOracleTest, TransitionsSmoothlyBetweenSamplers) {
117 const base::TimeDelta min_capture_period =
118 base::TimeDelta::FromSeconds(1) / 30;
119 const gfx::Rect animation_damage_rect(0, 0, 1280, 720);
120 const base::TimeDelta event_increment = min_capture_period * 2;
121
122 VideoCaptureOracle oracle(min_capture_period);
123
124 // Run sequences of animation events and non-animation events through the
125 // oracle. As the oracle transitions between each sampler, make sure the
126 // frame timestamps won't trip-up downstream consumers.
127 base::TimeTicks t = InitialTestTimeTicks();
128 base::TimeTicks last_frame_timestamp;
129 for (int i = 0; i < 1000; ++i) {
130 t += event_increment;
131
132 // For every 100 events, provide 50 that will cause the
133 // AnimatedContentSampler to lock-in, followed by 50 that will cause it to
134 // lock-out (i.e., the oracle will use the SmoothEventSampler instead).
135 const bool provide_animated_content_event =
136 (i % 100) >= 25 && (i % 100) < 75;
137
138 // Only the few events that trigger the lock-out transition should be
139 // dropped, because the AnimatedContentSampler doesn't yet realize the
140 // animation ended. Otherwise, the oracle should always decide to sample
141 // because one of its samplers says to.
142 const bool require_oracle_says_sample = (i % 100) < 75 || (i % 100) >= 78;
143 const bool oracle_says_sample = oracle.ObserveEventAndDecideCapture(
144 VideoCaptureOracle::kCompositorUpdate,
145 provide_animated_content_event ? animation_damage_rect : gfx::Rect(),
146 t);
147 if (require_oracle_says_sample)
148 ASSERT_TRUE(oracle_says_sample);
149 if (!oracle_says_sample) {
150 ASSERT_EQ(base::TimeDelta(), oracle.estimated_frame_duration());
151 continue;
152 }
153 ASSERT_LT(base::TimeDelta(), oracle.estimated_frame_duration());
154
155 const int frame_number = oracle.RecordCapture();
156
157 base::TimeTicks frame_timestamp;
158 ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &frame_timestamp));
159 ASSERT_FALSE(frame_timestamp.is_null());
160 if (!last_frame_timestamp.is_null()) {
161 const base::TimeDelta delta = frame_timestamp - last_frame_timestamp;
162 EXPECT_LE(event_increment.InMicroseconds(), delta.InMicroseconds());
163 // Right after the AnimatedContentSampler lock-out transition, there were
164 // a few frames dropped, so allow a gap in the timestamps. Otherwise, the
165 // delta between frame timestamps should never be more than 2X the
166 // |event_increment|.
167 const base::TimeDelta max_acceptable_delta = (i % 100) == 78 ?
168 event_increment * 5 : event_increment * 2;
169 EXPECT_GE(max_acceptable_delta.InMicroseconds(), delta.InMicroseconds());
170 }
171 last_frame_timestamp = frame_timestamp;
172 }
173 }
174
175 // Tests that VideoCaptureOracle prevents timer polling from initiating
176 // simultaneous captures.
177 TEST(VideoCaptureOracleTest, SamplesOnlyOneOverdueFrameAtATime) {
178 const base::TimeDelta min_capture_period =
179 base::TimeDelta::FromSeconds(1) / 30;
180 const base::TimeDelta vsync_interval =
181 base::TimeDelta::FromSeconds(1) / 60;
182 const base::TimeDelta timer_interval = base::TimeDelta::FromMilliseconds(
183 VideoCaptureOracle::kMinTimerPollPeriodMillis);
184
185 VideoCaptureOracle oracle(min_capture_period);
186
187 // Have the oracle observe some compositor events. Simulate that each capture
188 // completes successfully.
189 base::TimeTicks t = InitialTestTimeTicks();
190 base::TimeTicks ignored;
191 bool did_complete_a_capture = false;
192 for (int i = 0; i < 10; ++i) {
193 t += vsync_interval;
194 if (oracle.ObserveEventAndDecideCapture(
195 VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t)) {
196 ASSERT_TRUE(
197 oracle.CompleteCapture(oracle.RecordCapture(), true, &ignored));
198 did_complete_a_capture = true;
199 }
200 }
201 ASSERT_TRUE(did_complete_a_capture);
202
203 // Start one more compositor-based capture, but do not notify of completion
204 // yet.
205 for (int i = 0; i <= 10; ++i) {
206 ASSERT_GT(10, i) << "BUG: Seems like it'll never happen!";
207 t += vsync_interval;
208 if (oracle.ObserveEventAndDecideCapture(
209 VideoCaptureOracle::kCompositorUpdate, gfx::Rect(), t)) {
210 break;
211 }
212 }
213 int frame_number = oracle.RecordCapture();
214
215 // Stop providing the compositor events and start providing timer polling
216 // events. No overdue samplings should be recommended because of the
217 // not-yet-complete compositor-based capture.
218 for (int i = 0; i < 10; ++i) {
219 t += timer_interval;
220 ASSERT_FALSE(oracle.ObserveEventAndDecideCapture(
221 VideoCaptureOracle::kTimerPoll, gfx::Rect(), t));
222 }
223
224 // Now, complete the oustanding compositor-based capture and continue
225 // providing timer polling events. The oracle should start recommending
226 // sampling again.
227 ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
228 did_complete_a_capture = false;
229 for (int i = 0; i < 10; ++i) {
230 t += timer_interval;
231 if (oracle.ObserveEventAndDecideCapture(
232 VideoCaptureOracle::kTimerPoll, gfx::Rect(), t)) {
233 ASSERT_TRUE(
234 oracle.CompleteCapture(oracle.RecordCapture(), true, &ignored));
235 did_complete_a_capture = true;
236 }
237 }
238 ASSERT_TRUE(did_complete_a_capture);
239
240 // Start one more timer-based capture, but do not notify of completion yet.
241 for (int i = 0; i <= 10; ++i) {
242 ASSERT_GT(10, i) << "BUG: Seems like it'll never happen!";
243 t += timer_interval;
244 if (oracle.ObserveEventAndDecideCapture(
245 VideoCaptureOracle::kTimerPoll, gfx::Rect(), t)) {
246 break;
247 }
248 }
249 frame_number = oracle.RecordCapture();
250
251 // Confirm that the oracle does not recommend sampling until the outstanding
252 // timer-based capture completes.
253 for (int i = 0; i < 10; ++i) {
254 t += timer_interval;
255 ASSERT_FALSE(oracle.ObserveEventAndDecideCapture(
256 VideoCaptureOracle::kTimerPoll, gfx::Rect(), t));
257 }
258 ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
259 for (int i = 0; i <= 10; ++i) {
260 ASSERT_GT(10, i) << "BUG: Seems like it'll never happen!";
261 t += timer_interval;
262 if (oracle.ObserveEventAndDecideCapture(
263 VideoCaptureOracle::kTimerPoll, gfx::Rect(), t)) {
264 break;
265 }
266 }
267 }
268
269 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698