OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "content/browser/media/capture/web_contents_video_capture_device.h" | 5 #include "content/browser/media/capture/web_contents_video_capture_device.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <utility> | 10 #include <utility> |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 #include "ui/base/layout.h" | 45 #include "ui/base/layout.h" |
46 #include "ui/display/display.h" | 46 #include "ui/display/display.h" |
47 #include "ui/display/screen.h" | 47 #include "ui/display/screen.h" |
48 #include "ui/display/test/test_screen.h" | 48 #include "ui/display/test/test_screen.h" |
49 #include "ui/gfx/geometry/dip_util.h" | 49 #include "ui/gfx/geometry/dip_util.h" |
50 #include "ui/gfx/geometry/size_conversions.h" | 50 #include "ui/gfx/geometry/size_conversions.h" |
51 | 51 |
52 namespace content { | 52 namespace content { |
53 namespace { | 53 namespace { |
54 | 54 |
55 const int kTestWidth = 320; | 55 constexpr int kTestWidth = 320; |
56 const int kTestHeight = 240; | 56 constexpr int kTestHeight = 240; |
57 const int kTestFramesPerSecond = 20; | 57 constexpr int kTestFramesPerSecond = 20; |
58 const float kTestDeviceScaleFactor = 2.0f; | 58 constexpr float kTestDeviceScaleFactor = 2.0f; |
59 const SkColor kNothingYet = 0xdeadbeef; | 59 constexpr SkColor kDrawColorNotSet = 0xcafe1950; |
60 const SkColor kNotInterested = ~kNothingYet; | 60 constexpr SkColor kWaitColorNotSet = ~kDrawColorNotSet; |
| 61 constexpr SkColor kNothingYet = 0xdeadbeef; |
| 62 constexpr SkColor kNotInterested = ~kNothingYet; |
61 | 63 |
62 void DeadlineExceeded(base::Closure quit_closure) { | 64 void DeadlineExceeded(base::Closure quit_closure) { |
63 if (!base::debug::BeingDebugged()) { | 65 if (!base::debug::BeingDebugged()) { |
64 if (!quit_closure.is_null()) | 66 if (!quit_closure.is_null()) |
65 quit_closure.Run(); | 67 quit_closure.Run(); |
66 FAIL() << "Deadline exceeded while waiting, quitting"; | 68 FAIL() << "Deadline exceeded while waiting, quitting"; |
67 } else { | 69 } else { |
68 LOG(WARNING) << "Deadline exceeded; test would fail if debugger weren't " | 70 LOG(WARNING) << "Deadline exceeded; test would fail if debugger weren't " |
69 << "attached."; | 71 << "attached."; |
70 } | 72 } |
71 } | 73 } |
72 | 74 |
73 void RunCurrentLoopWithDeadline() { | 75 void RunCurrentLoopWithDeadline() { |
74 base::Timer deadline(false, false); | 76 base::Timer deadline(false, false); |
75 deadline.Start( | 77 deadline.Start( |
76 FROM_HERE, TestTimeouts::action_max_timeout(), | 78 FROM_HERE, TestTimeouts::action_max_timeout(), |
77 base::Bind(&DeadlineExceeded, | 79 base::Bind(&DeadlineExceeded, |
78 base::MessageLoop::current()->QuitWhenIdleClosure())); | 80 base::MessageLoop::current()->QuitWhenIdleClosure())); |
79 base::RunLoop().Run(); | 81 base::RunLoop().Run(); |
80 deadline.Stop(); | 82 deadline.Stop(); |
81 } | 83 } |
82 | 84 |
83 SkColor ConvertRgbToYuv(SkColor rgb) { | 85 SkColor ConvertRgbToYuv(SkColor rgb) { |
84 uint8_t yuv[3]; | 86 uint8_t yuv[3]; |
85 media::ConvertRGB32ToYUV(reinterpret_cast<uint8_t*>(&rgb), yuv, yuv + 1, | 87 media::ConvertRGB32ToYUV(reinterpret_cast<uint8_t*>(&rgb), yuv, yuv + 1, |
86 yuv + 2, 1, 1, 1, 1, 1); | 88 yuv + 2, 1, 1, 1, 1, 1); |
87 return SkColorSetRGB(yuv[0], yuv[1], yuv[2]); | 89 return SkColorSetRGB(yuv[0], yuv[1], yuv[2]); |
88 } | 90 } |
89 | 91 |
90 // Thread-safe class that controls the source pattern to be captured by the | 92 media::VideoCaptureParams DefaultCaptureParams() { |
91 // system under test. The lifetime of this class is greater than the lifetime | 93 media::VideoCaptureParams capture_params; |
92 // of all objects that reference it, so it does not need to be reference | 94 capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight); |
93 // counted. | 95 capture_params.requested_format.frame_rate = kTestFramesPerSecond; |
94 class CaptureTestSourceController { | 96 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; |
95 public: | 97 return capture_params; |
96 CaptureTestSourceController() | 98 } |
97 : color_(SK_ColorMAGENTA), | |
98 copy_result_size_(kTestWidth, kTestHeight), | |
99 can_copy_to_video_frame_(true) {} | |
100 | 99 |
101 void SetSolidColor(SkColor color) { | 100 // A stub implementation which fills solid-colors into VideoFrames in calls to |
102 base::AutoLock guard(lock_); | 101 // CopyFromCompositingSurfaceToVideoFrame(). The colors are changed by tests |
103 color_ = color; | 102 // in-between draw events to confirm that the right frames have the right |
104 } | 103 // content and in the right sequence. |
105 | |
106 SkColor GetSolidColor() { | |
107 base::AutoLock guard(lock_); | |
108 return color_; | |
109 } | |
110 | |
111 void SetCopyResultSize(int width, int height) { | |
112 base::AutoLock guard(lock_); | |
113 copy_result_size_ = gfx::Size(width, height); | |
114 } | |
115 | |
116 gfx::Size GetCopyResultSize() { | |
117 base::AutoLock guard(lock_); | |
118 return copy_result_size_; | |
119 } | |
120 | |
121 void SignalCopy() { | |
122 // TODO(nick): This actually should always be happening on the UI thread. | |
123 base::AutoLock guard(lock_); | |
124 if (!copy_done_.is_null()) { | |
125 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, copy_done_); | |
126 copy_done_.Reset(); | |
127 } | |
128 } | |
129 | |
130 void SetCanCopyToVideoFrame(bool value) { | |
131 base::AutoLock guard(lock_); | |
132 can_copy_to_video_frame_ = value; | |
133 } | |
134 | |
135 bool CanCopyToVideoFrame() { | |
136 base::AutoLock guard(lock_); | |
137 return can_copy_to_video_frame_; | |
138 } | |
139 | |
140 void WaitForNextCopy() { | |
141 { | |
142 base::AutoLock guard(lock_); | |
143 copy_done_ = base::MessageLoop::current()->QuitWhenIdleClosure(); | |
144 } | |
145 | |
146 RunCurrentLoopWithDeadline(); | |
147 } | |
148 | |
149 private: | |
150 base::Lock lock_; // Guards changes to all members. | |
151 SkColor color_; | |
152 gfx::Size copy_result_size_; | |
153 bool can_copy_to_video_frame_; | |
154 base::Closure copy_done_; | |
155 | |
156 DISALLOW_COPY_AND_ASSIGN(CaptureTestSourceController); | |
157 }; | |
158 | |
159 // A stub implementation which returns solid-color bitmaps in calls to | |
160 // CopyFromCompositingSurfaceToVideoFrame(), and which allows the video-frame | |
161 // readback path to be switched on and off. The behavior is controlled by a | |
162 // CaptureTestSourceController. | |
163 class CaptureTestView : public TestRenderWidgetHostView { | 104 class CaptureTestView : public TestRenderWidgetHostView { |
164 public: | 105 public: |
165 CaptureTestView(RenderWidgetHostImpl* rwh, | 106 explicit CaptureTestView(RenderWidgetHostImpl* rwh) |
166 CaptureTestSourceController* controller) | |
167 : TestRenderWidgetHostView(rwh), | 107 : TestRenderWidgetHostView(rwh), |
168 controller_(controller), | 108 fake_bounds_(100, 100, 100 + kTestWidth, 100 + kTestHeight), |
169 fake_bounds_(100, 100, 100 + kTestWidth, 100 + kTestHeight) {} | 109 yuv_color_(kDrawColorNotSet) {} |
170 | 110 |
171 ~CaptureTestView() override {} | 111 ~CaptureTestView() override {} |
172 | 112 |
173 // TestRenderWidgetHostView overrides. | 113 // TestRenderWidgetHostView overrides. |
174 gfx::Rect GetViewBounds() const override { | 114 gfx::Rect GetViewBounds() const override { |
175 return fake_bounds_; | 115 return fake_bounds_; |
176 } | 116 } |
177 | 117 |
178 void SetSize(const gfx::Size& size) override { | 118 void SetSize(const gfx::Size& size) override { |
179 SetBounds(gfx::Rect(fake_bounds_.origin(), size)); | 119 SetBounds(gfx::Rect(fake_bounds_.origin(), size)); |
180 } | 120 } |
181 | 121 |
182 void SetBounds(const gfx::Rect& rect) override { | 122 void SetBounds(const gfx::Rect& rect) override { |
183 fake_bounds_ = rect; | 123 fake_bounds_ = rect; |
184 } | 124 } |
185 | 125 |
186 bool CanCopyToVideoFrame() const override { | 126 bool CanCopyToVideoFrame() const override { return true; } |
187 return controller_->CanCopyToVideoFrame(); | |
188 } | |
189 | 127 |
190 void CopyFromCompositingSurfaceToVideoFrame( | 128 void CopyFromCompositingSurfaceToVideoFrame( |
191 const gfx::Rect& src_subrect, | 129 const gfx::Rect& src_subrect, |
192 const scoped_refptr<media::VideoFrame>& target, | 130 const scoped_refptr<media::VideoFrame>& target, |
193 const base::Callback<void(const gfx::Rect&, bool)>& callback) override { | 131 const base::Callback<void(const gfx::Rect&, bool)>& callback) override { |
194 SkColor c = ConvertRgbToYuv(controller_->GetSolidColor()); | 132 media::FillYUV(target.get(), SkColorGetR(yuv_color_), |
195 media::FillYUV( | 133 SkColorGetG(yuv_color_), SkColorGetB(yuv_color_)); |
196 target.get(), SkColorGetR(c), SkColorGetG(c), SkColorGetB(c)); | 134 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
197 callback.Run(gfx::Rect(), true); | 135 base::Bind(callback, gfx::Rect(), true)); |
198 controller_->SignalCopy(); | |
199 } | 136 } |
200 | 137 |
201 void BeginFrameSubscription( | 138 void BeginFrameSubscription( |
202 std::unique_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) | 139 std::unique_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) |
203 override { | 140 override { |
204 subscriber_.reset(subscriber.release()); | 141 subscriber_ = std::move(subscriber); |
205 } | 142 } |
206 | 143 |
207 void EndFrameSubscription() override { subscriber_.reset(); } | 144 void EndFrameSubscription() override { subscriber_.reset(); } |
208 | 145 |
| 146 void SetSolidColor(SkColor rgb_color) { |
| 147 yuv_color_ = ConvertRgbToYuv(rgb_color); |
| 148 } |
| 149 |
209 // Simulate a compositor paint event for our subscriber. | 150 // Simulate a compositor paint event for our subscriber. |
210 void SimulateUpdate() { | 151 void SimulateUpdate() { |
211 const base::TimeTicks present_time = base::TimeTicks::Now(); | 152 const base::TimeTicks present_time = base::TimeTicks::Now(); |
212 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback; | 153 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback; |
213 scoped_refptr<media::VideoFrame> target; | 154 scoped_refptr<media::VideoFrame> target; |
214 if (subscriber_ && subscriber_->ShouldCaptureFrame( | 155 if (subscriber_ && subscriber_->ShouldCaptureFrame( |
215 gfx::Rect(), present_time, &target, &callback)) { | 156 gfx::Rect(), present_time, &target, &callback)) { |
216 SkColor c = ConvertRgbToYuv(controller_->GetSolidColor()); | 157 CopyFromCompositingSurfaceToVideoFrame( |
217 media::FillYUV( | 158 gfx::Rect(), target, base::Bind(callback, present_time)); |
218 target.get(), SkColorGetR(c), SkColorGetG(c), SkColorGetB(c)); | |
219 BrowserThread::PostTask( | |
220 BrowserThread::UI, FROM_HERE, | |
221 base::Bind(callback, present_time, gfx::Rect(), true)); | |
222 controller_->SignalCopy(); | |
223 } | 159 } |
224 } | 160 } |
225 | 161 |
226 private: | 162 private: |
227 std::unique_ptr<RenderWidgetHostViewFrameSubscriber> subscriber_; | 163 std::unique_ptr<RenderWidgetHostViewFrameSubscriber> subscriber_; |
228 CaptureTestSourceController* const controller_; | |
229 gfx::Rect fake_bounds_; | 164 gfx::Rect fake_bounds_; |
| 165 SkColor yuv_color_; |
230 | 166 |
231 DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTestView); | 167 DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTestView); |
232 }; | 168 }; |
233 | 169 |
234 // A stub implementation which returns solid-color bitmaps in calls to | |
235 // CopyFromBackingStore(). The behavior is controlled by a | |
236 // CaptureTestSourceController. | |
237 class CaptureTestRenderWidgetHost : public RenderWidgetHostImpl { | |
238 public: | |
239 CaptureTestRenderWidgetHost(RenderWidgetHostDelegate* delegate, | |
240 RenderProcessHost* process, | |
241 int32_t routing_id, | |
242 CaptureTestSourceController* controller) | |
243 : RenderWidgetHostImpl(delegate, process, routing_id, false /* hidden */), | |
244 controller_(controller) {} | |
245 | |
246 // RenderWidgetHostImpl overrides. | |
247 void CopyFromBackingStore(const gfx::Rect& src_rect, | |
248 const gfx::Size& accelerated_dst_size, | |
249 const ReadbackRequestCallback& callback, | |
250 const SkColorType color_type) override { | |
251 gfx::Size size = controller_->GetCopyResultSize(); | |
252 SkColor color = controller_->GetSolidColor(); | |
253 | |
254 SkBitmap output; | |
255 EXPECT_TRUE(output.tryAllocN32Pixels(size.width(), size.height())); | |
256 { | |
257 SkAutoLockPixels locker(output); | |
258 output.eraseColor(color); | |
259 } | |
260 callback.Run(output, content::READBACK_SUCCESS); | |
261 controller_->SignalCopy(); | |
262 } | |
263 | |
264 private: | |
265 CaptureTestSourceController* controller_; | |
266 | |
267 DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTestRenderWidgetHost); | |
268 }; | |
269 | |
270 class CaptureTestRenderViewHost : public TestRenderViewHost { | 170 class CaptureTestRenderViewHost : public TestRenderViewHost { |
271 public: | 171 public: |
272 CaptureTestRenderViewHost(SiteInstance* instance, | 172 CaptureTestRenderViewHost(SiteInstance* instance, |
273 RenderViewHostDelegate* delegate, | 173 RenderViewHostDelegate* delegate, |
274 RenderWidgetHostDelegate* widget_delegate, | 174 RenderWidgetHostDelegate* widget_delegate, |
275 int32_t routing_id, | 175 int32_t routing_id, |
276 int32_t main_frame_routing_id, | 176 int32_t main_frame_routing_id, |
277 bool swapped_out, | 177 bool swapped_out) |
278 CaptureTestSourceController* controller) | |
279 : TestRenderViewHost(instance, | 178 : TestRenderViewHost(instance, |
280 base::MakeUnique<CaptureTestRenderWidgetHost>( | 179 base::MakeUnique<RenderWidgetHostImpl>( |
281 widget_delegate, | 180 widget_delegate, |
282 instance->GetProcess(), | 181 instance->GetProcess(), |
283 routing_id, | 182 routing_id, |
284 controller), | 183 false /* This means: "Is not hidden." */), |
285 delegate, | 184 delegate, |
286 main_frame_routing_id, | 185 main_frame_routing_id, |
287 swapped_out) { | 186 swapped_out) { |
288 // Override the default view installed by TestRenderViewHost; we need | 187 // Override the default view installed by TestRenderViewHost; we need |
289 // our special subclass which has mocked-out tab capture support. | 188 // our special subclass which has mocked-out tab capture support. |
290 RenderWidgetHostView* old_view = GetWidget()->GetView(); | 189 RenderWidgetHostView* old_view = GetWidget()->GetView(); |
291 GetWidget()->SetView(new CaptureTestView(GetWidget(), controller)); | 190 GetWidget()->SetView(new CaptureTestView(GetWidget())); |
292 delete old_view; | 191 delete old_view; |
293 } | 192 } |
294 | 193 |
295 private: | 194 private: |
296 DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTestRenderViewHost); | 195 DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTestRenderViewHost); |
297 }; | 196 }; |
298 | 197 |
299 class CaptureTestRenderViewHostFactory : public RenderViewHostFactory { | 198 class CaptureTestRenderViewHostFactory : public RenderViewHostFactory { |
300 public: | 199 public: |
301 explicit CaptureTestRenderViewHostFactory( | 200 CaptureTestRenderViewHostFactory() { RegisterFactory(this); } |
302 CaptureTestSourceController* controller) : controller_(controller) { | |
303 RegisterFactory(this); | |
304 } | |
305 | 201 |
306 ~CaptureTestRenderViewHostFactory() override { UnregisterFactory(); } | 202 ~CaptureTestRenderViewHostFactory() override { UnregisterFactory(); } |
307 | 203 |
308 // RenderViewHostFactory implementation. | 204 // RenderViewHostFactory implementation. |
309 RenderViewHost* CreateRenderViewHost( | 205 RenderViewHost* CreateRenderViewHost( |
310 SiteInstance* instance, | 206 SiteInstance* instance, |
311 RenderViewHostDelegate* delegate, | 207 RenderViewHostDelegate* delegate, |
312 RenderWidgetHostDelegate* widget_delegate, | 208 RenderWidgetHostDelegate* widget_delegate, |
313 int32_t routing_id, | 209 int32_t routing_id, |
314 int32_t main_frame_routing_id, | 210 int32_t main_frame_routing_id, |
315 bool swapped_out) override { | 211 bool swapped_out) override { |
316 return new CaptureTestRenderViewHost(instance, delegate, widget_delegate, | 212 return new CaptureTestRenderViewHost(instance, delegate, widget_delegate, |
317 routing_id, main_frame_routing_id, | 213 routing_id, main_frame_routing_id, |
318 swapped_out, controller_); | 214 swapped_out); |
319 } | 215 } |
320 | 216 |
321 private: | 217 private: |
322 CaptureTestSourceController* controller_; | 218 DISALLOW_COPY_AND_ASSIGN(CaptureTestRenderViewHostFactory); |
323 | |
324 DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTestRenderViewHostFactory); | |
325 }; | 219 }; |
326 | 220 |
327 // A stub consumer of captured video frames, which checks the output of | 221 // A stub consumer of captured video frames, which checks the output of |
328 // WebContentsVideoCaptureDevice. | 222 // WebContentsVideoCaptureDevice. |
329 class StubClient : public media::VideoCaptureDevice::Client { | 223 class StubClient : public media::VideoCaptureDevice::Client { |
330 public: | 224 public: |
331 StubClient( | 225 StubClient( |
332 const base::Callback<void(SkColor, const gfx::Size&)>& report_callback, | 226 const base::Callback<void(SkColor, const gfx::Size&)>& report_callback, |
333 const base::Closure& error_callback) | 227 const base::Closure& error_callback) |
334 : report_callback_(report_callback), | 228 : report_callback_(report_callback), |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
475 base::Callback<void(SkColor, const gfx::Size&)> report_callback_; | 369 base::Callback<void(SkColor, const gfx::Size&)> report_callback_; |
476 base::Closure error_callback_; | 370 base::Closure error_callback_; |
477 | 371 |
478 DISALLOW_COPY_AND_ASSIGN(StubClient); | 372 DISALLOW_COPY_AND_ASSIGN(StubClient); |
479 }; | 373 }; |
480 | 374 |
481 class StubClientObserver { | 375 class StubClientObserver { |
482 public: | 376 public: |
483 StubClientObserver() | 377 StubClientObserver() |
484 : error_encountered_(false), | 378 : error_encountered_(false), |
485 wait_color_yuv_(0xcafe1950), | 379 wait_color_yuv_(kWaitColorNotSet), |
486 expecting_frames_(true) { | 380 expecting_frames_(true) { |
487 client_.reset(new StubClient( | 381 client_.reset(new StubClient( |
488 base::Bind(&StubClientObserver::DidDeliverFrame, | 382 base::Bind(&StubClientObserver::DidDeliverFrame, |
489 base::Unretained(this)), | 383 base::Unretained(this)), |
490 base::Bind(&StubClientObserver::OnError, base::Unretained(this)))); | 384 base::Bind(&StubClientObserver::OnError, base::Unretained(this)))); |
491 } | 385 } |
492 | 386 |
493 virtual ~StubClientObserver() {} | 387 virtual ~StubClientObserver() {} |
494 | 388 |
495 std::unique_ptr<media::VideoCaptureDevice::Client> PassClient() { | 389 std::unique_ptr<media::VideoCaptureDevice::Client> PassClient() { |
496 return std::move(client_); | 390 return std::move(client_); |
497 } | 391 } |
498 | 392 |
499 void SetIsExpectingFrames(bool expecting_frames) { | 393 void SetIsExpectingFrames(bool expecting_frames) { |
500 base::AutoLock guard(lock_); | |
501 expecting_frames_ = expecting_frames; | 394 expecting_frames_ = expecting_frames; |
502 } | 395 } |
503 | 396 |
504 void QuitIfConditionsMet(SkColor color, const gfx::Size& size) { | 397 void QuitIfConditionsMet(SkColor color, const gfx::Size& size) { |
505 base::AutoLock guard(lock_); | |
506 EXPECT_TRUE(expecting_frames_); | 398 EXPECT_TRUE(expecting_frames_); |
507 if (error_encountered_ || wait_color_yuv_ == kNotInterested || | 399 if (error_encountered_ || wait_color_yuv_ == kNotInterested || |
508 wait_color_yuv_ == color) { | 400 wait_color_yuv_ == color) { |
509 last_frame_color_yuv_ = color; | 401 last_frame_color_yuv_ = color; |
510 last_frame_size_ = size; | 402 last_frame_size_ = size; |
511 base::MessageLoop::current()->QuitWhenIdle(); | 403 base::MessageLoop::current()->QuitWhenIdle(); |
512 } | 404 } |
513 } | 405 } |
514 | 406 |
515 // Run the current loop until the next frame is delivered. Returns the YUV | 407 // Run the current loop until the next frame is delivered. Returns the YUV |
516 // color and frame size. | 408 // color and frame size. |
517 std::pair<SkColor, gfx::Size> WaitForNextFrame() { | 409 std::pair<SkColor, gfx::Size> WaitForNextFrame() { |
518 { | 410 wait_color_yuv_ = kNotInterested; |
519 base::AutoLock guard(lock_); | 411 error_encountered_ = false; |
520 wait_color_yuv_ = kNotInterested; | 412 |
521 error_encountered_ = false; | |
522 } | |
523 RunCurrentLoopWithDeadline(); | 413 RunCurrentLoopWithDeadline(); |
524 { | 414 |
525 base::AutoLock guard(lock_); | 415 CHECK(!error_encountered_); |
526 CHECK(!error_encountered_); | 416 return std::make_pair(last_frame_color_yuv_, last_frame_size_); |
527 return std::make_pair(last_frame_color_yuv_, last_frame_size_); | |
528 } | |
529 } | 417 } |
530 | 418 |
531 // Run the current loop until a frame is delivered with the |expected_color|. | 419 // Run the current loop until a frame is delivered with the |expected_color|. |
532 void WaitForNextColor(SkColor expected_color) { | 420 void WaitForNextColor(SkColor expected_color) { |
533 { | 421 wait_color_yuv_ = ConvertRgbToYuv(expected_color); |
534 base::AutoLock guard(lock_); | 422 error_encountered_ = false; |
535 wait_color_yuv_ = ConvertRgbToYuv(expected_color); | 423 |
536 error_encountered_ = false; | |
537 } | |
538 RunCurrentLoopWithDeadline(); | 424 RunCurrentLoopWithDeadline(); |
539 { | 425 |
540 base::AutoLock guard(lock_); | 426 ASSERT_FALSE(error_encountered_); |
541 ASSERT_FALSE(error_encountered_); | |
542 } | |
543 } | 427 } |
544 | 428 |
| 429 // Run the current loop until an error is encountered. |
545 void WaitForError() { | 430 void WaitForError() { |
546 { | 431 wait_color_yuv_ = kNotInterested; |
547 base::AutoLock guard(lock_); | 432 error_encountered_ = false; |
548 wait_color_yuv_ = kNotInterested; | 433 |
549 error_encountered_ = false; | |
550 } | |
551 RunCurrentLoopWithDeadline(); | 434 RunCurrentLoopWithDeadline(); |
552 { | 435 |
553 base::AutoLock guard(lock_); | 436 ASSERT_TRUE(error_encountered_); |
554 ASSERT_TRUE(error_encountered_); | |
555 } | |
556 } | 437 } |
557 | 438 |
558 bool HasError() { | 439 bool HasError() { |
559 base::AutoLock guard(lock_); | |
560 return error_encountered_; | 440 return error_encountered_; |
561 } | 441 } |
562 | 442 |
563 void OnError() { | 443 void OnError() { |
564 { | 444 error_encountered_ = true; |
565 base::AutoLock guard(lock_); | |
566 error_encountered_ = true; | |
567 } | |
568 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( | 445 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( |
569 &StubClientObserver::QuitIfConditionsMet, | 446 &StubClientObserver::QuitIfConditionsMet, |
570 base::Unretained(this), | 447 base::Unretained(this), |
571 kNothingYet, | 448 kNothingYet, |
572 gfx::Size())); | 449 gfx::Size())); |
573 } | 450 } |
574 | 451 |
575 void DidDeliverFrame(SkColor color, const gfx::Size& size) { | 452 void DidDeliverFrame(SkColor color, const gfx::Size& size) { |
576 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( | 453 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( |
577 &StubClientObserver::QuitIfConditionsMet, | 454 &StubClientObserver::QuitIfConditionsMet, |
578 base::Unretained(this), | 455 base::Unretained(this), |
579 color, | 456 color, |
580 size)); | 457 size)); |
581 } | 458 } |
582 | 459 |
583 private: | 460 private: |
584 base::Lock lock_; | |
585 bool error_encountered_; | 461 bool error_encountered_; |
586 SkColor wait_color_yuv_; | 462 SkColor wait_color_yuv_; |
587 SkColor last_frame_color_yuv_; | 463 SkColor last_frame_color_yuv_; |
588 gfx::Size last_frame_size_; | 464 gfx::Size last_frame_size_; |
589 std::unique_ptr<StubClient> client_; | 465 std::unique_ptr<StubClient> client_; |
590 bool expecting_frames_; | 466 bool expecting_frames_; |
591 | 467 |
592 DISALLOW_COPY_AND_ASSIGN(StubClientObserver); | 468 DISALLOW_COPY_AND_ASSIGN(StubClientObserver); |
593 }; | 469 }; |
594 | 470 |
595 // crbug.com/159234 | |
596 #if defined(OS_ANDROID) | |
597 #define MAYBE_WebContentsVideoCaptureDeviceTest \ | |
598 DISABLED_WebContentsVideoCaptureDeviceTest | |
599 #else | |
600 #define MAYBE_WebContentsVideoCaptureDeviceTest \ | |
601 WebContentsVideoCaptureDeviceTest | |
602 #endif // defined(OS_ANDROID) | |
603 | |
604 // Test harness that sets up a minimal environment with necessary stubs. | 471 // Test harness that sets up a minimal environment with necessary stubs. |
605 class MAYBE_WebContentsVideoCaptureDeviceTest : public testing::Test { | 472 class WebContentsVideoCaptureDeviceTest : public testing::Test { |
606 public: | 473 public: |
607 // This is public because C++ method pointer scoping rules are silly and make | 474 // This is public because C++ method pointer scoping rules are silly and make |
608 // this hard to use with Bind(). | 475 // this hard to use with Bind(). |
609 void ResetWebContents() { | 476 void ResetWebContents() { |
610 web_contents_.reset(); | 477 web_contents_.reset(); |
611 } | 478 } |
612 | 479 |
613 protected: | 480 protected: |
614 void SetUp() override { | 481 void SetUp() override { |
615 const display::Display test_display = test_screen_.GetPrimaryDisplay(); | 482 const display::Display test_display = test_screen_.GetPrimaryDisplay(); |
616 display::Display display(test_display); | 483 display::Display display(test_display); |
617 display.set_id(0x1337); | 484 display.set_id(0x1337); |
618 display.set_bounds(gfx::Rect(0, 0, 2560, 1440)); | 485 display.set_bounds(gfx::Rect(0, 0, 2560, 1440)); |
619 display.set_device_scale_factor(kTestDeviceScaleFactor); | 486 display.set_device_scale_factor(kTestDeviceScaleFactor); |
620 test_screen_.display_list().RemoveDisplay(test_display.id()); | 487 test_screen_.display_list().RemoveDisplay(test_display.id()); |
621 test_screen_.display_list().AddDisplay(display, | 488 test_screen_.display_list().AddDisplay(display, |
622 display::DisplayList::Type::PRIMARY); | 489 display::DisplayList::Type::PRIMARY); |
623 display::Screen::SetScreenInstance(&test_screen_); | 490 display::Screen::SetScreenInstance(&test_screen_); |
624 ASSERT_EQ(&test_screen_, display::Screen::GetScreen()); | 491 ASSERT_EQ(&test_screen_, display::Screen::GetScreen()); |
625 | 492 |
626 // TODO(nick): Sadness and woe! Much "mock-the-world" boilerplate could be | 493 // TODO(nick): Sadness and woe! Much "mock-the-world" boilerplate could be |
627 // eliminated here, if only we could use RenderViewHostTestHarness. The | 494 // eliminated here, if only we could use RenderViewHostTestHarness. The |
628 // catch is that we need our TestRenderViewHost to support a | 495 // catch is that we need to inject our CaptureTestView:: |
629 // CopyFromBackingStore operation that we control. To accomplish that, | 496 // CopyFromCompositingSurfaceToVideoFrame() mock. To accomplish that, |
630 // either RenderViewHostTestHarness would have to support installing a | 497 // either RenderViewHostTestHarness would have to support installing a |
631 // custom RenderViewHostFactory, or else we implant some kind of delegated | 498 // custom RenderViewHostFactory, or else we implant some kind of delegated |
632 // CopyFromBackingStore functionality into TestRenderViewHost itself. | 499 // CopyFromCompositingSurfaceToVideoFrame functionality into |
| 500 // TestRenderViewHostView itself. |
633 | 501 |
634 render_process_host_factory_.reset(new MockRenderProcessHostFactory()); | 502 render_process_host_factory_.reset(new MockRenderProcessHostFactory()); |
635 // Create our (self-registering) RVH factory, so that when we create a | 503 // Create our (self-registering) RVH factory, so that when we create a |
636 // WebContents, it in turn creates CaptureTestRenderViewHosts. | 504 // WebContents, it in turn creates CaptureTestRenderViewHosts. |
637 render_view_host_factory_.reset( | 505 render_view_host_factory_.reset(new CaptureTestRenderViewHostFactory()); |
638 new CaptureTestRenderViewHostFactory(&controller_)); | |
639 render_frame_host_factory_.reset(new TestRenderFrameHostFactory()); | 506 render_frame_host_factory_.reset(new TestRenderFrameHostFactory()); |
640 | 507 |
641 browser_context_.reset(new TestBrowserContext()); | 508 browser_context_.reset(new TestBrowserContext()); |
642 | 509 |
643 scoped_refptr<SiteInstance> site_instance = | 510 scoped_refptr<SiteInstance> site_instance = |
644 SiteInstance::Create(browser_context_.get()); | 511 SiteInstance::Create(browser_context_.get()); |
645 SiteInstanceImpl::set_render_process_host_factory( | 512 SiteInstanceImpl::set_render_process_host_factory( |
646 render_process_host_factory_.get()); | 513 render_process_host_factory_.get()); |
647 web_contents_.reset( | 514 web_contents_.reset( |
648 TestWebContents::Create(browser_context_.get(), site_instance.get())); | 515 TestWebContents::Create(browser_context_.get(), site_instance.get())); |
649 RenderFrameHost* const main_frame = web_contents_->GetMainFrame(); | 516 RenderFrameHost* const main_frame = web_contents_->GetMainFrame(); |
650 device_ = WebContentsVideoCaptureDevice::Create(base::StringPrintf( | 517 device_ = WebContentsVideoCaptureDevice::Create(base::StringPrintf( |
651 "web-contents-media-stream://%d:%d", main_frame->GetProcess()->GetID(), | 518 "web-contents-media-stream://%d:%d", main_frame->GetProcess()->GetID(), |
652 main_frame->GetRoutingID())); | 519 main_frame->GetRoutingID())); |
653 | 520 |
654 base::RunLoop().RunUntilIdle(); | 521 base::RunLoop().RunUntilIdle(); |
655 } | 522 } |
656 | 523 |
657 void TearDown() override { | 524 void TearDown() override { |
658 // Tear down in opposite order of set-up. | 525 // Tear down in opposite order of set-up. |
659 | 526 |
660 // The device is destroyed asynchronously, and will notify the | |
661 // CaptureTestSourceController when it finishes destruction. | |
662 // Trigger this, and wait. | |
663 if (device_) { | 527 if (device_) { |
664 device_->StopAndDeAllocate(); | 528 device_->StopAndDeAllocate(); |
665 device_.reset(); | 529 device_.reset(); |
666 } | 530 } |
667 | 531 |
668 base::RunLoop().RunUntilIdle(); | 532 base::RunLoop().RunUntilIdle(); |
669 | 533 |
670 // Destroy the browser objects. | 534 // Destroy the browser objects. |
671 web_contents_.reset(); | 535 web_contents_.reset(); |
672 browser_context_.reset(); | 536 browser_context_.reset(); |
673 | 537 |
674 base::RunLoop().RunUntilIdle(); | 538 base::RunLoop().RunUntilIdle(); |
675 | 539 |
676 SiteInstanceImpl::set_render_process_host_factory(NULL); | 540 SiteInstanceImpl::set_render_process_host_factory(NULL); |
677 render_frame_host_factory_.reset(); | 541 render_frame_host_factory_.reset(); |
678 render_view_host_factory_.reset(); | 542 render_view_host_factory_.reset(); |
679 render_process_host_factory_.reset(); | 543 render_process_host_factory_.reset(); |
680 | 544 |
681 display::Screen::SetScreenInstance(nullptr); | 545 display::Screen::SetScreenInstance(nullptr); |
682 } | 546 } |
683 | 547 |
684 // Accessors. | 548 // Accessors. |
685 CaptureTestSourceController* source() { return &controller_; } | |
686 WebContents* web_contents() const { return web_contents_.get(); } | 549 WebContents* web_contents() const { return web_contents_.get(); } |
| 550 CaptureTestView* test_view() const { |
| 551 return static_cast<CaptureTestView*>( |
| 552 web_contents_->GetRenderViewHost()->GetWidget()->GetView()); |
| 553 } |
687 media::VideoCaptureDevice* device() { return device_.get(); } | 554 media::VideoCaptureDevice* device() { return device_.get(); } |
688 | 555 |
689 // Returns the device scale factor of the capture target's native view. This | 556 // Returns the device scale factor of the capture target's native view. |
690 // is necessary because, architecturally, the TestScreen implementation is | |
691 // ignored on Mac platforms (when determining the device scale factor for a | |
692 // particular window). | |
693 float GetDeviceScaleFactor() const { | 557 float GetDeviceScaleFactor() const { |
694 RenderWidgetHostView* const view = | 558 RenderWidgetHostView* const view = |
695 web_contents_->GetRenderViewHost()->GetWidget()->GetView(); | 559 web_contents_->GetRenderViewHost()->GetWidget()->GetView(); |
696 CHECK(view); | 560 CHECK(view); |
697 return ui::GetScaleFactorForNativeView(view->GetNativeView()); | 561 return ui::GetScaleFactorForNativeView(view->GetNativeView()); |
698 } | 562 } |
699 | 563 |
700 void SimulateDrawEvent() { | 564 void SimulateDrawEvent() { |
701 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 565 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
702 | 566 |
703 // Force at least one frame period's worth of time to pass. Otherwise, | 567 // Force at least one frame period's worth of time to pass. Otherwise, |
704 // internal logic may decide not to capture a frame because the draw events | 568 // internal logic may decide not to capture a frame because the draw events |
705 // are more frequent that kTestFramesPerSecond. | 569 // are more frequent that kTestFramesPerSecond. |
706 // | 570 // |
707 // TODO(miu): Instead of physically waiting, we should inject simulated | 571 // TODO(miu): Instead of physically waiting, we should inject simulated |
708 // clocks for testing. | 572 // clocks for testing. |
709 base::RunLoop run_loop; | 573 base::RunLoop run_loop; |
710 BrowserThread::PostDelayedTask( | 574 BrowserThread::PostDelayedTask( |
711 BrowserThread::UI, FROM_HERE, | 575 BrowserThread::UI, FROM_HERE, |
712 run_loop.QuitClosure(), | 576 run_loop.QuitClosure(), |
713 base::TimeDelta::FromMicroseconds( | 577 base::TimeDelta::FromMicroseconds( |
714 base::Time::kMicrosecondsPerSecond / kTestFramesPerSecond)); | 578 base::Time::kMicrosecondsPerSecond / kTestFramesPerSecond)); |
715 run_loop.Run(); | 579 run_loop.Run(); |
716 | 580 |
717 // Schedule the update to occur when the test runs the event loop (and not | 581 // Schedule the update to occur when the test runs the event loop (and not |
718 // before expectations have been set). | 582 // before expectations have been set). |
719 CaptureTestView* test_view = static_cast<CaptureTestView*>( | 583 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
720 web_contents_->GetRenderViewHost()->GetWidget()->GetView()); | 584 base::Bind(&CaptureTestView::SimulateUpdate, |
721 BrowserThread::PostTask( | 585 base::Unretained(test_view()))); |
722 BrowserThread::UI, FROM_HERE, | |
723 base::Bind(&CaptureTestView::SimulateUpdate, | |
724 base::Unretained(test_view))); | |
725 } | 586 } |
726 | 587 |
727 void SimulateSourceSizeChange(const gfx::Size& size) { | 588 void SimulateSourceSizeChange(const gfx::Size& size) { |
728 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 589 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
729 CaptureTestView* test_view = static_cast<CaptureTestView*>( | 590 auto* const view = test_view(); |
730 web_contents_->GetRenderViewHost()->GetWidget()->GetView()); | 591 view->SetSize(size); |
731 test_view->SetSize(size); | |
732 // Normally, RenderWidgetHostImpl would notify WebContentsImpl that the size | 592 // Normally, RenderWidgetHostImpl would notify WebContentsImpl that the size |
733 // has changed. However, in this test setup where there is no render | 593 // has changed. However, in this test setup, where there is no render |
734 // process, we must notify WebContentsImpl directly. | 594 // process, we must notify WebContentsImpl directly. |
735 WebContentsImpl* const as_web_contents_impl = | 595 WebContentsImpl* const as_web_contents_impl = |
736 static_cast<WebContentsImpl*>(web_contents_.get()); | 596 static_cast<WebContentsImpl*>(web_contents_.get()); |
737 RenderWidgetHostDelegate* const as_rwh_delegate = | 597 RenderWidgetHostDelegate* const as_rwh_delegate = |
738 static_cast<RenderWidgetHostDelegate*>(as_web_contents_impl); | 598 static_cast<RenderWidgetHostDelegate*>(as_web_contents_impl); |
739 as_rwh_delegate->RenderWidgetWasResized( | 599 as_rwh_delegate->RenderWidgetWasResized( |
740 as_web_contents_impl->GetMainFrame()->GetRenderWidgetHost(), true); | 600 as_web_contents_impl->GetMainFrame()->GetRenderWidgetHost(), true); |
741 } | 601 } |
742 | 602 |
743 // Repeatedly schedules draw events and scans for frames until the output from | 603 // Repeatedly schedules draw events and scans for frames until the output from |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
781 | 641 |
782 void DestroyVideoCaptureDevice() { device_.reset(); } | 642 void DestroyVideoCaptureDevice() { device_.reset(); } |
783 | 643 |
784 StubClientObserver* client_observer() { | 644 StubClientObserver* client_observer() { |
785 return &client_observer_; | 645 return &client_observer_; |
786 } | 646 } |
787 | 647 |
788 private: | 648 private: |
789 display::test::TestScreen test_screen_; | 649 display::test::TestScreen test_screen_; |
790 | 650 |
| 651 TestBrowserThreadBundle thread_bundle_; |
| 652 |
791 StubClientObserver client_observer_; | 653 StubClientObserver client_observer_; |
792 | 654 |
793 // The controller controls which pixel patterns to produce. | |
794 CaptureTestSourceController controller_; | |
795 | |
796 // Self-registering RenderProcessHostFactory. | 655 // Self-registering RenderProcessHostFactory. |
797 std::unique_ptr<MockRenderProcessHostFactory> render_process_host_factory_; | 656 std::unique_ptr<MockRenderProcessHostFactory> render_process_host_factory_; |
798 | 657 |
799 // Creates capture-capable RenderViewHosts whose pixel content production is | 658 // Creates capture-capable RenderViewHosts. |
800 // under the control of |controller_|. | |
801 std::unique_ptr<CaptureTestRenderViewHostFactory> render_view_host_factory_; | 659 std::unique_ptr<CaptureTestRenderViewHostFactory> render_view_host_factory_; |
802 | 660 |
803 // Self-registering RenderFrameHostFactory. | 661 // Self-registering RenderFrameHostFactory. |
804 std::unique_ptr<TestRenderFrameHostFactory> render_frame_host_factory_; | 662 std::unique_ptr<TestRenderFrameHostFactory> render_frame_host_factory_; |
805 | 663 |
806 // A mocked-out browser and tab. | 664 // A mocked-out browser and tab. |
807 std::unique_ptr<TestBrowserContext> browser_context_; | 665 std::unique_ptr<TestBrowserContext> browser_context_; |
808 std::unique_ptr<WebContents> web_contents_; | 666 std::unique_ptr<WebContents> web_contents_; |
809 | 667 |
810 // Finally, the WebContentsVideoCaptureDevice under test. | 668 // Finally, the WebContentsVideoCaptureDevice under test. |
811 std::unique_ptr<media::VideoCaptureDevice> device_; | 669 std::unique_ptr<media::VideoCaptureDevice> device_; |
812 | |
813 TestBrowserThreadBundle thread_bundle_; | |
814 }; | 670 }; |
815 | 671 |
816 TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest, | 672 // In real-world use cases, there can exist a race condition between starting |
817 InvalidInitialWebContentsError) { | 673 // capture on a WebContents and having the WebContents be destroyed in the |
818 // Before the installs itself on the UI thread up to start capturing, we'll | 674 // meantime. This tests that WebContentsVideoCaptureDevice errors-out |
819 // delete the web contents. This should trigger an error which can happen in | 675 // gracefully. |
820 // practice; we should be able to recover gracefully. | 676 TEST_F(WebContentsVideoCaptureDeviceTest, |
| 677 SafelyStartsUpAfterWebContentsHasGone) { |
821 ResetWebContents(); | 678 ResetWebContents(); |
822 | 679 device()->AllocateAndStart(DefaultCaptureParams(), |
823 media::VideoCaptureParams capture_params; | 680 client_observer()->PassClient()); |
824 capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight); | |
825 capture_params.requested_format.frame_rate = kTestFramesPerSecond; | |
826 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; | |
827 device()->AllocateAndStart(capture_params, client_observer()->PassClient()); | |
828 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForError()); | 681 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForError()); |
829 device()->StopAndDeAllocate(); | 682 device()->StopAndDeAllocate(); |
830 } | 683 } |
831 | 684 |
832 TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest, WebContentsDestroyed) { | 685 // Tests that WebContentsVideoCaptureDevice starts, captures a frame, and then |
833 const float device_scale_factor = GetDeviceScaleFactor(); | 686 // gracefully errors-out if the WebContents is destroyed before the device is |
834 const gfx::Size capture_preferred_size( | 687 // stopped. |
835 static_cast<int>(kTestWidth / device_scale_factor), | 688 TEST_F(WebContentsVideoCaptureDeviceTest, |
836 static_cast<int>(kTestHeight / device_scale_factor)); | 689 RunsThenErrorsOutWhenWebContentsIsDestroyed) { |
837 ASSERT_NE(capture_preferred_size, web_contents()->GetPreferredSize()); | |
838 | |
839 // We'll simulate the tab being closed after the capture pipeline is up and | 690 // We'll simulate the tab being closed after the capture pipeline is up and |
840 // running. | 691 // running. |
841 media::VideoCaptureParams capture_params; | 692 device()->AllocateAndStart(DefaultCaptureParams(), |
842 capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight); | 693 client_observer()->PassClient()); |
843 capture_params.requested_format.frame_rate = kTestFramesPerSecond; | |
844 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; | |
845 device()->AllocateAndStart(capture_params, client_observer()->PassClient()); | |
846 | 694 |
847 // Do one capture to prove the tab is initially open and being captured | 695 // Do one capture to prove the tab is initially open and being captured |
848 // normally. | 696 // normally. |
849 source()->SetSolidColor(SK_ColorRED); | 697 test_view()->SetSolidColor(SK_ColorRED); |
850 SimulateDrawEvent(); | 698 SimulateDrawEvent(); |
851 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED)); | 699 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED)); |
852 | 700 |
853 base::RunLoop().RunUntilIdle(); | 701 base::RunLoop().RunUntilIdle(); |
854 | 702 |
855 // Check that the preferred size of the WebContents matches the one provided | |
856 // by WebContentsVideoCaptureDevice. | |
857 EXPECT_EQ(capture_preferred_size, web_contents()->GetPreferredSize()); | |
858 | |
859 // Post a task to close the tab. We should see an error reported to the | 703 // Post a task to close the tab. We should see an error reported to the |
860 // consumer. | 704 // consumer. |
861 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 705 BrowserThread::PostTask( |
862 base::Bind(&MAYBE_WebContentsVideoCaptureDeviceTest::ResetWebContents, | 706 BrowserThread::UI, FROM_HERE, |
| 707 base::Bind(&WebContentsVideoCaptureDeviceTest::ResetWebContents, |
863 base::Unretained(this))); | 708 base::Unretained(this))); |
864 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForError()); | 709 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForError()); |
865 device()->StopAndDeAllocate(); | 710 device()->StopAndDeAllocate(); |
866 } | 711 } |
867 | 712 |
868 TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest, | 713 // Sanity-check that starting/stopping the WebContentsVideoCaptureDevice, but |
| 714 // without first returning to the event loop in-between, will behave rationally. |
| 715 TEST_F(WebContentsVideoCaptureDeviceTest, |
869 StopDeviceBeforeCaptureMachineCreation) { | 716 StopDeviceBeforeCaptureMachineCreation) { |
870 media::VideoCaptureParams capture_params; | 717 device()->AllocateAndStart(DefaultCaptureParams(), |
871 capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight); | 718 client_observer()->PassClient()); |
872 capture_params.requested_format.frame_rate = kTestFramesPerSecond; | |
873 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; | |
874 device()->AllocateAndStart(capture_params, client_observer()->PassClient()); | |
875 | 719 |
876 // Make a point of not running the UI messageloop here. | 720 // Make a point of not running the UI messageloop here. |
877 device()->StopAndDeAllocate(); | 721 device()->StopAndDeAllocate(); |
878 DestroyVideoCaptureDevice(); | 722 DestroyVideoCaptureDevice(); |
879 | 723 |
880 // Currently, there should be CreateCaptureMachineOnUIThread() and | 724 // Currently, there should be CreateCaptureMachineOnUIThread() and |
881 // DestroyCaptureMachineOnUIThread() tasks pending on the current (UI) message | 725 // DestroyCaptureMachineOnUIThread() tasks pending on the current (UI) message |
882 // loop. These should both succeed without crashing, and the machine should | 726 // loop. These should both succeed without crashing, and the machine should |
883 // wind up in the idle state. | 727 // wind up in the idle state. |
884 base::RunLoop().RunUntilIdle(); | 728 base::RunLoop().RunUntilIdle(); |
885 } | 729 } |
886 | 730 |
887 TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest, StopWithRendererWorkToDo) { | 731 // Tests that frames are delivered to different clients across restarts of the |
888 // Set up the test to use RGB captures into SkBitmaps instead of YUV captures | 732 // same instance. |
889 // into VideoFrames. | 733 TEST_F(WebContentsVideoCaptureDeviceTest, |
890 source()->SetCanCopyToVideoFrame(false); | 734 DeliversToCorrectClientAcrossRestarts) { |
891 media::VideoCaptureParams capture_params; | 735 // While the device is up-and-running, expect frame captures. |
892 capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight); | 736 client_observer()->SetIsExpectingFrames(true); |
893 capture_params.requested_format.frame_rate = kTestFramesPerSecond; | 737 device()->AllocateAndStart(DefaultCaptureParams(), |
894 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; | 738 client_observer()->PassClient()); |
895 device()->AllocateAndStart(capture_params, client_observer()->PassClient()); | 739 base::RunLoop().RunUntilIdle(); |
| 740 test_view()->SetSolidColor(SK_ColorRED); |
| 741 SimulateDrawEvent(); |
| 742 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED)); |
| 743 SimulateDrawEvent(); |
| 744 test_view()->SetSolidColor(SK_ColorGREEN); |
| 745 SimulateDrawEvent(); |
| 746 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorGREEN)); |
| 747 SimulateDrawEvent(); |
| 748 device()->StopAndDeAllocate(); |
896 | 749 |
897 base::RunLoop().RunUntilIdle(); | 750 base::RunLoop().RunUntilIdle(); |
898 | 751 |
899 for (int i = 0; i < 3; ++i) | 752 // Now that the device is stopped, expect frames are no longer captured. |
900 SimulateDrawEvent(); | 753 client_observer()->SetIsExpectingFrames(false); |
901 | |
902 ASSERT_FALSE(client_observer()->HasError()); | |
903 device()->StopAndDeAllocate(); | |
904 ASSERT_FALSE(client_observer()->HasError()); | |
905 base::RunLoop().RunUntilIdle(); | |
906 ASSERT_FALSE(client_observer()->HasError()); | |
907 } | |
908 | |
909 TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest, DeviceRestart) { | |
910 media::VideoCaptureParams capture_params; | |
911 capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight); | |
912 capture_params.requested_format.frame_rate = kTestFramesPerSecond; | |
913 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; | |
914 device()->AllocateAndStart(capture_params, client_observer()->PassClient()); | |
915 base::RunLoop().RunUntilIdle(); | |
916 source()->SetSolidColor(SK_ColorRED); | |
917 SimulateDrawEvent(); | |
918 SimulateDrawEvent(); | |
919 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED)); | |
920 SimulateDrawEvent(); | |
921 SimulateDrawEvent(); | |
922 source()->SetSolidColor(SK_ColorGREEN); | |
923 SimulateDrawEvent(); | |
924 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorGREEN)); | |
925 device()->StopAndDeAllocate(); | |
926 | |
927 // Device is stopped, but content can still be animating. | |
928 SimulateDrawEvent(); | 754 SimulateDrawEvent(); |
929 SimulateDrawEvent(); | 755 SimulateDrawEvent(); |
930 base::RunLoop().RunUntilIdle(); | 756 base::RunLoop().RunUntilIdle(); |
931 | 757 |
| 758 // Re-start the device with a different client. Only the second client should |
| 759 // expect to see any frame captures. |
932 StubClientObserver observer2; | 760 StubClientObserver observer2; |
933 device()->AllocateAndStart(capture_params, observer2.PassClient()); | 761 observer2.SetIsExpectingFrames(true); |
934 source()->SetSolidColor(SK_ColorBLUE); | 762 device()->AllocateAndStart(DefaultCaptureParams(), observer2.PassClient()); |
| 763 test_view()->SetSolidColor(SK_ColorBLUE); |
935 SimulateDrawEvent(); | 764 SimulateDrawEvent(); |
936 ASSERT_NO_FATAL_FAILURE(observer2.WaitForNextColor(SK_ColorBLUE)); | 765 ASSERT_NO_FATAL_FAILURE(observer2.WaitForNextColor(SK_ColorBLUE)); |
937 source()->SetSolidColor(SK_ColorYELLOW); | 766 test_view()->SetSolidColor(SK_ColorYELLOW); |
938 SimulateDrawEvent(); | 767 SimulateDrawEvent(); |
939 ASSERT_NO_FATAL_FAILURE(observer2.WaitForNextColor(SK_ColorYELLOW)); | 768 ASSERT_NO_FATAL_FAILURE(observer2.WaitForNextColor(SK_ColorYELLOW)); |
940 device()->StopAndDeAllocate(); | 769 device()->StopAndDeAllocate(); |
941 } | 770 } |
942 | 771 |
943 // The "happy case" test. No scaling is needed, so we should be able to change | 772 // The "happy case" test. No scaling is needed, so we should be able to change |
944 // the picture emitted from the source and expect to see each delivered to the | 773 // the picture emitted from the source and expect to see each delivered to the |
945 // consumer. The test will alternate between the RGB/SkBitmap and YUV/VideoFrame | 774 // consumer. The test will alternate between the RGB/SkBitmap and YUV/VideoFrame |
946 // capture paths. | 775 // capture paths. |
947 TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest, GoesThroughAllTheMotions) { | 776 TEST_F(WebContentsVideoCaptureDeviceTest, GoesThroughAllTheMotions) { |
948 media::VideoCaptureParams capture_params; | 777 device()->AllocateAndStart(DefaultCaptureParams(), |
949 capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight); | 778 client_observer()->PassClient()); |
950 capture_params.requested_format.frame_rate = kTestFramesPerSecond; | |
951 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; | |
952 device()->AllocateAndStart(capture_params, client_observer()->PassClient()); | |
953 | 779 |
954 for (int i = 0; i < 4; i++) { | 780 for (int i = 0; i < 3; i++) { |
955 const char* name = NULL; | 781 SCOPED_TRACE(base::StringPrintf("Iteration #%d", i)); |
956 if (i % 2) { | |
957 source()->SetCanCopyToVideoFrame(false); | |
958 name = "SkBitmap"; | |
959 } else { | |
960 source()->SetCanCopyToVideoFrame(true); | |
961 name = "VideoFrame"; | |
962 } | |
963 | 782 |
964 SCOPED_TRACE(base::StringPrintf("Using %s path, iteration #%d", name, i)); | 783 test_view()->SetSolidColor(SK_ColorRED); |
965 | 784 for (int j = 0; j <= i; j++) |
966 source()->SetSolidColor(SK_ColorRED); | 785 SimulateDrawEvent(); |
967 SimulateDrawEvent(); | |
968 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED)); | 786 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED)); |
969 | 787 |
970 source()->SetSolidColor(SK_ColorGREEN); | 788 test_view()->SetSolidColor(SK_ColorGREEN); |
971 SimulateDrawEvent(); | 789 for (int j = 0; j <= i; j++) |
| 790 SimulateDrawEvent(); |
972 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorGREEN)); | 791 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorGREEN)); |
973 | 792 |
974 source()->SetSolidColor(SK_ColorBLUE); | 793 test_view()->SetSolidColor(SK_ColorBLUE); |
975 SimulateDrawEvent(); | 794 for (int j = 0; j <= i; j++) |
| 795 SimulateDrawEvent(); |
976 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorBLUE)); | 796 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorBLUE)); |
977 | 797 |
978 source()->SetSolidColor(SK_ColorBLACK); | 798 test_view()->SetSolidColor(SK_ColorBLACK); |
979 SimulateDrawEvent(); | 799 for (int j = 0; j <= i; j++) |
| 800 SimulateDrawEvent(); |
980 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorBLACK)); | 801 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorBLACK)); |
981 } | 802 } |
982 device()->StopAndDeAllocate(); | |
983 } | |
984 | |
985 TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest, BadFramesGoodFrames) { | |
986 media::VideoCaptureParams capture_params; | |
987 capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight); | |
988 capture_params.requested_format.frame_rate = kTestFramesPerSecond; | |
989 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; | |
990 // 1x1 is too small to process; we intend for this to result in an error. | |
991 source()->SetCopyResultSize(1, 1); | |
992 source()->SetSolidColor(SK_ColorRED); | |
993 device()->AllocateAndStart(capture_params, client_observer()->PassClient()); | |
994 | |
995 // These frames ought to be dropped during the Render stage. Let | |
996 // several captures to happen. | |
997 for (int i = 0; i < 3; ++i) { | |
998 SimulateDrawEvent(); | |
999 ASSERT_NO_FATAL_FAILURE(source()->WaitForNextCopy()); | |
1000 } | |
1001 | |
1002 // Now push some good frames through; they should be processed normally. | |
1003 source()->SetCopyResultSize(kTestWidth, kTestHeight); | |
1004 source()->SetSolidColor(SK_ColorGREEN); | |
1005 SimulateDrawEvent(); | |
1006 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorGREEN)); | |
1007 source()->SetSolidColor(SK_ColorRED); | |
1008 SimulateDrawEvent(); | |
1009 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED)); | |
1010 | 803 |
1011 device()->StopAndDeAllocate(); | 804 device()->StopAndDeAllocate(); |
1012 } | 805 } |
1013 | 806 |
1014 // Tests that, when configured with the FIXED_ASPECT_RATIO resolution change | 807 // Tests that, when configured with the FIXED_ASPECT_RATIO resolution change |
1015 // policy, the source size changes result in video frames of possibly varying | 808 // policy, the source size changes result in video frames of possibly varying |
1016 // resolutions, but all with the same aspect ratio. | 809 // resolutions, but all with the same aspect ratio. |
1017 TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest, | 810 TEST_F(WebContentsVideoCaptureDeviceTest, VariableResolution_FixedAspectRatio) { |
1018 VariableResolution_FixedAspectRatio) { | 811 auto capture_params = DefaultCaptureParams(); |
1019 media::VideoCaptureParams capture_params; | |
1020 capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight); | |
1021 capture_params.requested_format.frame_rate = kTestFramesPerSecond; | |
1022 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; | |
1023 capture_params.resolution_change_policy = | 812 capture_params.resolution_change_policy = |
1024 media::RESOLUTION_POLICY_FIXED_ASPECT_RATIO; | 813 media::RESOLUTION_POLICY_FIXED_ASPECT_RATIO; |
1025 | |
1026 device()->AllocateAndStart(capture_params, client_observer()->PassClient()); | 814 device()->AllocateAndStart(capture_params, client_observer()->PassClient()); |
1027 | 815 |
1028 // Source size equals maximum size. Expect delivered frames to be | 816 // Source size equals maximum size. Expect delivered frames to be |
1029 // kTestWidth by kTestHeight. | 817 // kTestWidth by kTestHeight. |
1030 source()->SetSolidColor(SK_ColorRED); | 818 test_view()->SetSolidColor(SK_ColorRED); |
1031 const float device_scale_factor = GetDeviceScaleFactor(); | 819 const float device_scale_factor = GetDeviceScaleFactor(); |
1032 SimulateSourceSizeChange(gfx::ConvertSizeToDIP( | 820 SimulateSourceSizeChange(gfx::ConvertSizeToDIP( |
1033 device_scale_factor, gfx::Size(kTestWidth, kTestHeight))); | 821 device_scale_factor, gfx::Size(kTestWidth, kTestHeight))); |
1034 SimulateDrawsUntilNewFrameSizeArrives( | 822 SimulateDrawsUntilNewFrameSizeArrives( |
1035 SK_ColorRED, gfx::Size(kTestWidth, kTestHeight)); | 823 SK_ColorRED, gfx::Size(kTestWidth, kTestHeight)); |
1036 | 824 |
1037 // Source size is half in both dimensions. Expect delivered frames to be of | 825 // Source size is half in both dimensions. Expect delivered frames to be of |
1038 // the same aspect ratio as kTestWidth by kTestHeight, but larger than the | 826 // the same aspect ratio as kTestWidth by kTestHeight, but larger than the |
1039 // half size because the minimum height is 180 lines. | 827 // half size because the minimum height is 180 lines. |
1040 source()->SetSolidColor(SK_ColorGREEN); | 828 test_view()->SetSolidColor(SK_ColorGREEN); |
1041 SimulateSourceSizeChange(gfx::ConvertSizeToDIP( | 829 SimulateSourceSizeChange(gfx::ConvertSizeToDIP( |
1042 device_scale_factor, gfx::Size(kTestWidth / 2, kTestHeight / 2))); | 830 device_scale_factor, gfx::Size(kTestWidth / 2, kTestHeight / 2))); |
1043 SimulateDrawsUntilNewFrameSizeArrives( | 831 SimulateDrawsUntilNewFrameSizeArrives( |
1044 SK_ColorGREEN, gfx::Size(180 * kTestWidth / kTestHeight, 180)); | 832 SK_ColorGREEN, gfx::Size(180 * kTestWidth / kTestHeight, 180)); |
1045 | 833 |
1046 // Source size changes aspect ratio. Expect delivered frames to be padded | 834 // Source size changes aspect ratio. Expect delivered frames to be padded |
1047 // in the horizontal dimension to preserve aspect ratio. | 835 // in the horizontal dimension to preserve aspect ratio. |
1048 source()->SetSolidColor(SK_ColorBLUE); | 836 test_view()->SetSolidColor(SK_ColorBLUE); |
1049 SimulateSourceSizeChange(gfx::ConvertSizeToDIP( | 837 SimulateSourceSizeChange(gfx::ConvertSizeToDIP( |
1050 device_scale_factor, gfx::Size(kTestWidth / 2, kTestHeight))); | 838 device_scale_factor, gfx::Size(kTestWidth / 2, kTestHeight))); |
1051 SimulateDrawsUntilNewFrameSizeArrives( | 839 SimulateDrawsUntilNewFrameSizeArrives( |
1052 SK_ColorBLUE, gfx::Size(kTestWidth, kTestHeight)); | 840 SK_ColorBLUE, gfx::Size(kTestWidth, kTestHeight)); |
1053 | 841 |
1054 // Source size changes aspect ratio again. Expect delivered frames to be | 842 // Source size changes aspect ratio again. Expect delivered frames to be |
1055 // padded in the vertical dimension to preserve aspect ratio. | 843 // padded in the vertical dimension to preserve aspect ratio. |
1056 source()->SetSolidColor(SK_ColorBLACK); | 844 test_view()->SetSolidColor(SK_ColorBLACK); |
1057 SimulateSourceSizeChange(gfx::ConvertSizeToDIP( | 845 SimulateSourceSizeChange(gfx::ConvertSizeToDIP( |
1058 device_scale_factor, gfx::Size(kTestWidth, kTestHeight / 2))); | 846 device_scale_factor, gfx::Size(kTestWidth, kTestHeight / 2))); |
1059 SimulateDrawsUntilNewFrameSizeArrives( | 847 SimulateDrawsUntilNewFrameSizeArrives( |
1060 SK_ColorBLACK, gfx::Size(kTestWidth, kTestHeight)); | 848 SK_ColorBLACK, gfx::Size(kTestWidth, kTestHeight)); |
1061 | 849 |
1062 device()->StopAndDeAllocate(); | 850 device()->StopAndDeAllocate(); |
1063 } | 851 } |
1064 | 852 |
1065 // Tests that, when configured with the ANY_WITHIN_LIMIT resolution change | 853 // Tests that, when configured with the ANY_WITHIN_LIMIT resolution change |
1066 // policy, the source size changes result in video frames of possibly varying | 854 // policy, the source size changes result in video frames of possibly varying |
1067 // resolutions. | 855 // resolutions. |
1068 TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest, | 856 TEST_F(WebContentsVideoCaptureDeviceTest, VariableResolution_AnyWithinLimits) { |
1069 VariableResolution_AnyWithinLimits) { | 857 auto capture_params = DefaultCaptureParams(); |
1070 media::VideoCaptureParams capture_params; | |
1071 capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight); | |
1072 capture_params.requested_format.frame_rate = kTestFramesPerSecond; | |
1073 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; | |
1074 capture_params.resolution_change_policy = | 858 capture_params.resolution_change_policy = |
1075 media::RESOLUTION_POLICY_ANY_WITHIN_LIMIT; | 859 media::RESOLUTION_POLICY_ANY_WITHIN_LIMIT; |
1076 | |
1077 device()->AllocateAndStart(capture_params, client_observer()->PassClient()); | 860 device()->AllocateAndStart(capture_params, client_observer()->PassClient()); |
1078 | 861 |
1079 // Source size equals maximum size. Expect delivered frames to be | 862 // Source size equals maximum size. Expect delivered frames to be |
1080 // kTestWidth by kTestHeight. | 863 // kTestWidth by kTestHeight. |
1081 source()->SetSolidColor(SK_ColorRED); | 864 test_view()->SetSolidColor(SK_ColorRED); |
1082 const float device_scale_factor = GetDeviceScaleFactor(); | 865 const float device_scale_factor = GetDeviceScaleFactor(); |
1083 SimulateSourceSizeChange(gfx::ConvertSizeToDIP( | 866 SimulateSourceSizeChange(gfx::ConvertSizeToDIP( |
1084 device_scale_factor, gfx::Size(kTestWidth, kTestHeight))); | 867 device_scale_factor, gfx::Size(kTestWidth, kTestHeight))); |
1085 SimulateDrawsUntilNewFrameSizeArrives( | 868 SimulateDrawsUntilNewFrameSizeArrives( |
1086 SK_ColorRED, gfx::Size(kTestWidth, kTestHeight)); | 869 SK_ColorRED, gfx::Size(kTestWidth, kTestHeight)); |
1087 | 870 |
1088 // Source size is half in both dimensions. Expect delivered frames to also | 871 // Source size is half in both dimensions. Expect delivered frames to also |
1089 // be half in both dimensions. | 872 // be half in both dimensions. |
1090 source()->SetSolidColor(SK_ColorGREEN); | 873 test_view()->SetSolidColor(SK_ColorGREEN); |
1091 SimulateSourceSizeChange(gfx::ConvertSizeToDIP( | 874 SimulateSourceSizeChange(gfx::ConvertSizeToDIP( |
1092 device_scale_factor, gfx::Size(kTestWidth / 2, kTestHeight / 2))); | 875 device_scale_factor, gfx::Size(kTestWidth / 2, kTestHeight / 2))); |
1093 SimulateDrawsUntilNewFrameSizeArrives( | 876 SimulateDrawsUntilNewFrameSizeArrives( |
1094 SK_ColorGREEN, gfx::Size(kTestWidth / 2, kTestHeight / 2)); | 877 SK_ColorGREEN, gfx::Size(kTestWidth / 2, kTestHeight / 2)); |
1095 | 878 |
1096 // Source size changes to something arbitrary. Since the source size is | 879 // Source size changes to something arbitrary. Since the source size is |
1097 // less than the maximum size, expect delivered frames to be the same size | 880 // less than the maximum size, expect delivered frames to be the same size |
1098 // as the source size. | 881 // as the source size. |
1099 source()->SetSolidColor(SK_ColorBLUE); | 882 test_view()->SetSolidColor(SK_ColorBLUE); |
1100 gfx::Size arbitrary_source_size(kTestWidth / 2 + 42, kTestHeight - 10); | 883 gfx::Size arbitrary_source_size(kTestWidth / 2 + 42, kTestHeight - 10); |
1101 SimulateSourceSizeChange(gfx::ConvertSizeToDIP(device_scale_factor, | 884 SimulateSourceSizeChange(gfx::ConvertSizeToDIP(device_scale_factor, |
1102 arbitrary_source_size)); | 885 arbitrary_source_size)); |
1103 SimulateDrawsUntilNewFrameSizeArrives(SK_ColorBLUE, arbitrary_source_size); | 886 SimulateDrawsUntilNewFrameSizeArrives(SK_ColorBLUE, arbitrary_source_size); |
1104 | 887 |
1105 // Source size changes to something arbitrary that exceeds the maximum frame | 888 // Source size changes to something arbitrary that exceeds the maximum frame |
1106 // size. Since the source size exceeds the maximum size, expect delivered | 889 // size. Since the source size exceeds the maximum size, expect delivered |
1107 // frames to be downscaled. | 890 // frames to be downscaled. |
1108 source()->SetSolidColor(SK_ColorBLACK); | 891 test_view()->SetSolidColor(SK_ColorBLACK); |
1109 arbitrary_source_size = gfx::Size(kTestWidth * 2, kTestHeight / 2); | 892 arbitrary_source_size = gfx::Size(kTestWidth * 2, kTestHeight / 2); |
1110 SimulateSourceSizeChange(gfx::ConvertSizeToDIP(device_scale_factor, | 893 SimulateSourceSizeChange(gfx::ConvertSizeToDIP(device_scale_factor, |
1111 arbitrary_source_size)); | 894 arbitrary_source_size)); |
1112 SimulateDrawsUntilNewFrameSizeArrives( | 895 SimulateDrawsUntilNewFrameSizeArrives( |
1113 SK_ColorBLACK, gfx::Size(kTestWidth, | 896 SK_ColorBLACK, gfx::Size(kTestWidth, |
1114 kTestWidth * arbitrary_source_size.height() / | 897 kTestWidth * arbitrary_source_size.height() / |
1115 arbitrary_source_size.width())); | 898 arbitrary_source_size.width())); |
1116 | 899 |
1117 device()->StopAndDeAllocate(); | 900 device()->StopAndDeAllocate(); |
1118 } | 901 } |
1119 | 902 |
1120 TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest, | 903 TEST_F(WebContentsVideoCaptureDeviceTest, |
1121 ComputesStandardResolutionsForPreferredSize) { | 904 ComputesStandardResolutionsForPreferredSize) { |
1122 // Helper function to run the same testing procedure for multiple combinations | 905 // Helper function to run the same testing procedure for multiple combinations |
1123 // of |policy|, |standard_size| and |oddball_size|. | 906 // of |policy|, |standard_size| and |oddball_size|. |
1124 const auto RunTestForPreferredSize = | 907 const auto RunTestForPreferredSize = |
1125 [=](media::ResolutionChangePolicy policy, | 908 [=](media::ResolutionChangePolicy policy, |
1126 const gfx::Size& oddball_size, | 909 const gfx::Size& oddball_size, |
1127 const gfx::Size& standard_size) { | 910 const gfx::Size& standard_size) { |
1128 SCOPED_TRACE(::testing::Message() | 911 SCOPED_TRACE(::testing::Message() |
1129 << "policy=" << policy | 912 << "policy=" << policy |
1130 << ", oddball_size=" << oddball_size.ToString() | 913 << ", oddball_size=" << oddball_size.ToString() |
1131 << ", standard_size=" << standard_size.ToString()); | 914 << ", standard_size=" << standard_size.ToString()); |
1132 | 915 |
1133 // Compute the expected preferred size. For the fixed-resolution use case, | 916 // Compute the expected preferred size. For the fixed-resolution use case, |
1134 // the |oddball_size| is always the expected size; whereas for the | 917 // the |oddball_size| is always the expected size; whereas for the |
1135 // variable-resolution cases, the |standard_size| is the expected size. | 918 // variable-resolution cases, the |standard_size| is the expected size. |
1136 // Also, adjust to account for the device scale factor. | 919 // Also, adjust to account for the device scale factor. |
1137 gfx::Size capture_preferred_size = gfx::ScaleToFlooredSize( | 920 gfx::Size capture_preferred_size = gfx::ScaleToFlooredSize( |
1138 policy == media::RESOLUTION_POLICY_FIXED_RESOLUTION ? oddball_size | 921 policy == media::RESOLUTION_POLICY_FIXED_RESOLUTION ? oddball_size |
1139 : standard_size, | 922 : standard_size, |
1140 1.0f / GetDeviceScaleFactor()); | 923 1.0f / GetDeviceScaleFactor()); |
1141 ASSERT_NE(capture_preferred_size, web_contents()->GetPreferredSize()); | 924 ASSERT_NE(capture_preferred_size, web_contents()->GetPreferredSize()); |
1142 | 925 |
1143 // Start the WebContentsVideoCaptureDevice. | 926 // Start the WebContentsVideoCaptureDevice. |
1144 media::VideoCaptureParams capture_params; | 927 auto capture_params = DefaultCaptureParams(); |
1145 capture_params.requested_format.frame_size = oddball_size; | 928 capture_params.requested_format.frame_size = oddball_size; |
1146 capture_params.requested_format.frame_rate = kTestFramesPerSecond; | |
1147 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; | |
1148 capture_params.resolution_change_policy = policy; | 929 capture_params.resolution_change_policy = policy; |
1149 StubClientObserver unused_observer; | 930 StubClientObserver unused_observer; |
1150 device()->AllocateAndStart(capture_params, unused_observer.PassClient()); | 931 device()->AllocateAndStart(capture_params, unused_observer.PassClient()); |
1151 base::RunLoop().RunUntilIdle(); | 932 base::RunLoop().RunUntilIdle(); |
1152 | 933 |
1153 // Check that the preferred size of the WebContents matches the one provided | 934 // Check that the preferred size of the WebContents matches the one provided |
1154 // by WebContentsVideoCaptureDevice. | 935 // by WebContentsVideoCaptureDevice. |
1155 EXPECT_EQ(capture_preferred_size, web_contents()->GetPreferredSize()); | 936 EXPECT_EQ(capture_preferred_size, web_contents()->GetPreferredSize()); |
1156 | 937 |
1157 // Stop the WebContentsVideoCaptureDevice. | 938 // Stop the WebContentsVideoCaptureDevice. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1205 RunTestForPreferredSize( | 986 RunTestForPreferredSize( |
1206 policies[i], gfx::Size(1000, 1000), gfx::Size(1000, 1000)); | 987 policies[i], gfx::Size(1000, 1000), gfx::Size(1000, 1000)); |
1207 RunTestForPreferredSize( | 988 RunTestForPreferredSize( |
1208 policies[i], gfx::Size(1600, 1000), gfx::Size(1600, 1000)); | 989 policies[i], gfx::Size(1600, 1000), gfx::Size(1600, 1000)); |
1209 RunTestForPreferredSize( | 990 RunTestForPreferredSize( |
1210 policies[i], gfx::Size(837, 999), gfx::Size(837, 999)); | 991 policies[i], gfx::Size(837, 999), gfx::Size(837, 999)); |
1211 } | 992 } |
1212 } | 993 } |
1213 | 994 |
1214 // Tests the Suspend/Resume() functionality. | 995 // Tests the Suspend/Resume() functionality. |
1215 TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest, SuspendsAndResumes) { | 996 TEST_F(WebContentsVideoCaptureDeviceTest, SuspendsAndResumes) { |
1216 media::VideoCaptureParams capture_params; | 997 device()->AllocateAndStart(DefaultCaptureParams(), |
1217 capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight); | 998 client_observer()->PassClient()); |
1218 capture_params.requested_format.frame_rate = kTestFramesPerSecond; | |
1219 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; | |
1220 device()->AllocateAndStart(capture_params, client_observer()->PassClient()); | |
1221 | 999 |
1222 for (int i = 0; i < 3; ++i) { | 1000 for (int i = 0; i < 3; ++i) { |
1223 // Draw a RED frame and wait for a normal frame capture to occur. | 1001 // Draw a RED frame and wait for a normal frame capture to occur. |
1224 source()->SetSolidColor(SK_ColorRED); | 1002 test_view()->SetSolidColor(SK_ColorRED); |
1225 SimulateDrawEvent(); | 1003 SimulateDrawEvent(); |
1226 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED)); | 1004 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED)); |
1227 | 1005 |
1228 // Suspend capture and then draw a GREEN frame. No frame capture should | 1006 // Suspend capture and then draw a GREEN frame. No frame capture should |
1229 // occur. | 1007 // occur. |
1230 device()->MaybeSuspend(); | 1008 device()->MaybeSuspend(); |
1231 base::RunLoop().RunUntilIdle(); | 1009 base::RunLoop().RunUntilIdle(); |
1232 client_observer()->SetIsExpectingFrames(false); | 1010 client_observer()->SetIsExpectingFrames(false); |
1233 source()->SetSolidColor(SK_ColorGREEN); | 1011 test_view()->SetSolidColor(SK_ColorGREEN); |
1234 SimulateDrawEvent(); | 1012 SimulateDrawEvent(); |
1235 base::RunLoop().RunUntilIdle(); | 1013 base::RunLoop().RunUntilIdle(); |
1236 | 1014 |
1237 // Resume capture and then draw a BLUE frame and wait for it to be captured. | 1015 // Resume capture and then draw a BLUE frame and wait for it to be captured. |
1238 device()->Resume(); | 1016 device()->Resume(); |
1239 base::RunLoop().RunUntilIdle(); | 1017 base::RunLoop().RunUntilIdle(); |
1240 client_observer()->SetIsExpectingFrames(true); | 1018 client_observer()->SetIsExpectingFrames(true); |
1241 source()->SetSolidColor(SK_ColorBLUE); | 1019 test_view()->SetSolidColor(SK_ColorBLUE); |
1242 SimulateDrawEvent(); | 1020 SimulateDrawEvent(); |
1243 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorBLUE)); | 1021 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorBLUE)); |
1244 } | 1022 } |
1245 | 1023 |
1246 device()->StopAndDeAllocate(); | 1024 device()->StopAndDeAllocate(); |
1247 } | 1025 } |
1248 | 1026 |
1249 // Tests the RequestRefreshFrame() functionality. | 1027 // Tests the RequestRefreshFrame() functionality. |
1250 TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest, ProvidesRefreshFrames) { | 1028 TEST_F(WebContentsVideoCaptureDeviceTest, ProvidesRefreshFrames) { |
1251 media::VideoCaptureParams capture_params; | 1029 device()->AllocateAndStart(DefaultCaptureParams(), |
1252 capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight); | 1030 client_observer()->PassClient()); |
1253 capture_params.requested_format.frame_rate = kTestFramesPerSecond; | |
1254 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; | |
1255 device()->AllocateAndStart(capture_params, client_observer()->PassClient()); | |
1256 | 1031 |
1257 // Request a refresh frame before the first frame has been drawn. This forces | 1032 // Request a refresh frame before the first frame has been drawn. This forces |
1258 // a capture. | 1033 // a capture. |
1259 source()->SetSolidColor(SK_ColorRED); | 1034 test_view()->SetSolidColor(SK_ColorRED); |
1260 SimulateRefreshFrameRequest(); | 1035 SimulateRefreshFrameRequest(); |
1261 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED)); | 1036 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED)); |
1262 | 1037 |
1263 // Now, draw a frame and wait for a normal frame capture to occur. | 1038 // Now, draw a frame and wait for a normal frame capture to occur. |
1264 source()->SetSolidColor(SK_ColorGREEN); | 1039 test_view()->SetSolidColor(SK_ColorGREEN); |
1265 SimulateDrawEvent(); | 1040 SimulateDrawEvent(); |
1266 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorGREEN)); | 1041 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorGREEN)); |
1267 | 1042 |
1268 // Now, make three more refresh frame requests. Although the source has | 1043 // Now, make three more refresh frame requests. Although the source has |
1269 // changed to BLUE, no draw event has occurred. Therefore, expect the refresh | 1044 // changed to BLUE, no draw event has occurred. Therefore, expect the refresh |
1270 // frames to contain the content from the last drawn frame, which is GREEN. | 1045 // frames to contain the content from the last drawn frame, which is GREEN. |
1271 source()->SetSolidColor(SK_ColorBLUE); | 1046 test_view()->SetSolidColor(SK_ColorBLUE); |
1272 for (int i = 0; i < 3; ++i) { | 1047 for (int i = 0; i < 3; ++i) { |
1273 SimulateRefreshFrameRequest(); | 1048 SimulateRefreshFrameRequest(); |
1274 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorGREEN)); | 1049 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorGREEN)); |
1275 } | 1050 } |
1276 | 1051 |
1277 device()->StopAndDeAllocate(); | 1052 device()->StopAndDeAllocate(); |
1278 } | 1053 } |
1279 | 1054 |
1280 } // namespace | 1055 } // namespace |
1281 } // namespace content | 1056 } // namespace content |
OLD | NEW |