| 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 |