| 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 "base/bind_helpers.h" | 7 #include "base/bind_helpers.h" |
| 8 #include "base/debug/debugger.h" | 8 #include "base/debug/debugger.h" |
| 9 #include "base/run_loop.h" | 9 #include "base/run_loop.h" |
| 10 #include "base/test/test_timeouts.h" | 10 #include "base/test/test_timeouts.h" |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 // CopyFromCompositingSurfaceToVideoFrame(), and which allows the video-frame | 156 // CopyFromCompositingSurfaceToVideoFrame(), and which allows the video-frame |
| 157 // readback path to be switched on and off. The behavior is controlled by a | 157 // readback path to be switched on and off. The behavior is controlled by a |
| 158 // CaptureTestSourceController. | 158 // CaptureTestSourceController. |
| 159 class CaptureTestView : public TestRenderWidgetHostView { | 159 class CaptureTestView : public TestRenderWidgetHostView { |
| 160 public: | 160 public: |
| 161 explicit CaptureTestView(RenderWidgetHostImpl* rwh, | 161 explicit CaptureTestView(RenderWidgetHostImpl* rwh, |
| 162 CaptureTestSourceController* controller) | 162 CaptureTestSourceController* controller) |
| 163 : TestRenderWidgetHostView(rwh), | 163 : TestRenderWidgetHostView(rwh), |
| 164 controller_(controller) {} | 164 controller_(controller) {} |
| 165 | 165 |
| 166 virtual ~CaptureTestView() {} | 166 ~CaptureTestView() override {} |
| 167 | 167 |
| 168 // TestRenderWidgetHostView overrides. | 168 // TestRenderWidgetHostView overrides. |
| 169 virtual gfx::Rect GetViewBounds() const override { | 169 gfx::Rect GetViewBounds() const override { |
| 170 return gfx::Rect(100, 100, 100 + kTestWidth, 100 + kTestHeight); | 170 return gfx::Rect(100, 100, 100 + kTestWidth, 100 + kTestHeight); |
| 171 } | 171 } |
| 172 | 172 |
| 173 virtual bool CanCopyToVideoFrame() const override { | 173 bool CanCopyToVideoFrame() const override { |
| 174 return controller_->CanCopyToVideoFrame(); | 174 return controller_->CanCopyToVideoFrame(); |
| 175 } | 175 } |
| 176 | 176 |
| 177 virtual void CopyFromCompositingSurfaceToVideoFrame( | 177 void CopyFromCompositingSurfaceToVideoFrame( |
| 178 const gfx::Rect& src_subrect, | 178 const gfx::Rect& src_subrect, |
| 179 const scoped_refptr<media::VideoFrame>& target, | 179 const scoped_refptr<media::VideoFrame>& target, |
| 180 const base::Callback<void(bool)>& callback) override { | 180 const base::Callback<void(bool)>& callback) override { |
| 181 SkColor c = ConvertRgbToYuv(controller_->GetSolidColor()); | 181 SkColor c = ConvertRgbToYuv(controller_->GetSolidColor()); |
| 182 media::FillYUV( | 182 media::FillYUV( |
| 183 target.get(), SkColorGetR(c), SkColorGetG(c), SkColorGetB(c)); | 183 target.get(), SkColorGetR(c), SkColorGetG(c), SkColorGetB(c)); |
| 184 callback.Run(true); | 184 callback.Run(true); |
| 185 controller_->SignalCopy(); | 185 controller_->SignalCopy(); |
| 186 } | 186 } |
| 187 | 187 |
| 188 virtual void BeginFrameSubscription( | 188 void BeginFrameSubscription( |
| 189 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) override { | 189 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) override { |
| 190 subscriber_.reset(subscriber.release()); | 190 subscriber_.reset(subscriber.release()); |
| 191 } | 191 } |
| 192 | 192 |
| 193 virtual void EndFrameSubscription() override { | 193 void EndFrameSubscription() override { subscriber_.reset(); } |
| 194 subscriber_.reset(); | |
| 195 } | |
| 196 | 194 |
| 197 // Simulate a compositor paint event for our subscriber. | 195 // Simulate a compositor paint event for our subscriber. |
| 198 void SimulateUpdate() { | 196 void SimulateUpdate() { |
| 199 const base::TimeTicks present_time = base::TimeTicks::Now(); | 197 const base::TimeTicks present_time = base::TimeTicks::Now(); |
| 200 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback; | 198 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback; |
| 201 scoped_refptr<media::VideoFrame> target; | 199 scoped_refptr<media::VideoFrame> target; |
| 202 if (subscriber_ && subscriber_->ShouldCaptureFrame( | 200 if (subscriber_ && subscriber_->ShouldCaptureFrame( |
| 203 gfx::Rect(), present_time, &target, &callback)) { | 201 gfx::Rect(), present_time, &target, &callback)) { |
| 204 SkColor c = ConvertRgbToYuv(controller_->GetSolidColor()); | 202 SkColor c = ConvertRgbToYuv(controller_->GetSolidColor()); |
| 205 media::FillYUV( | 203 media::FillYUV( |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 main_frame_routing_id, swapped_out), | 239 main_frame_routing_id, swapped_out), |
| 242 controller_(controller) { | 240 controller_(controller) { |
| 243 // Override the default view installed by TestRenderViewHost; we need | 241 // Override the default view installed by TestRenderViewHost; we need |
| 244 // our special subclass which has mocked-out tab capture support. | 242 // our special subclass which has mocked-out tab capture support. |
| 245 RenderWidgetHostView* old_view = GetView(); | 243 RenderWidgetHostView* old_view = GetView(); |
| 246 SetView(new CaptureTestView(this, controller)); | 244 SetView(new CaptureTestView(this, controller)); |
| 247 delete old_view; | 245 delete old_view; |
| 248 } | 246 } |
| 249 | 247 |
| 250 // TestRenderViewHost overrides. | 248 // TestRenderViewHost overrides. |
| 251 virtual void CopyFromBackingStore( | 249 void CopyFromBackingStore( |
| 252 const gfx::Rect& src_rect, | 250 const gfx::Rect& src_rect, |
| 253 const gfx::Size& accelerated_dst_size, | 251 const gfx::Size& accelerated_dst_size, |
| 254 const base::Callback<void(bool, const SkBitmap&)>& callback, | 252 const base::Callback<void(bool, const SkBitmap&)>& callback, |
| 255 const SkColorType color_type) override { | 253 const SkColorType color_type) override { |
| 256 gfx::Size size = controller_->GetCopyResultSize(); | 254 gfx::Size size = controller_->GetCopyResultSize(); |
| 257 SkColor color = controller_->GetSolidColor(); | 255 SkColor color = controller_->GetSolidColor(); |
| 258 | 256 |
| 259 // Although it's not necessary, use a PlatformBitmap here (instead of a | 257 // Although it's not necessary, use a PlatformBitmap here (instead of a |
| 260 // regular SkBitmap) to exercise possible threading issues. | 258 // regular SkBitmap) to exercise possible threading issues. |
| 261 skia::PlatformBitmap output; | 259 skia::PlatformBitmap output; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 279 #pragma warning(pop) | 277 #pragma warning(pop) |
| 280 #endif | 278 #endif |
| 281 | 279 |
| 282 class CaptureTestRenderViewHostFactory : public RenderViewHostFactory { | 280 class CaptureTestRenderViewHostFactory : public RenderViewHostFactory { |
| 283 public: | 281 public: |
| 284 explicit CaptureTestRenderViewHostFactory( | 282 explicit CaptureTestRenderViewHostFactory( |
| 285 CaptureTestSourceController* controller) : controller_(controller) { | 283 CaptureTestSourceController* controller) : controller_(controller) { |
| 286 RegisterFactory(this); | 284 RegisterFactory(this); |
| 287 } | 285 } |
| 288 | 286 |
| 289 virtual ~CaptureTestRenderViewHostFactory() { | 287 ~CaptureTestRenderViewHostFactory() override { UnregisterFactory(); } |
| 290 UnregisterFactory(); | |
| 291 } | |
| 292 | 288 |
| 293 // RenderViewHostFactory implementation. | 289 // RenderViewHostFactory implementation. |
| 294 virtual RenderViewHost* CreateRenderViewHost( | 290 RenderViewHost* CreateRenderViewHost( |
| 295 SiteInstance* instance, | 291 SiteInstance* instance, |
| 296 RenderViewHostDelegate* delegate, | 292 RenderViewHostDelegate* delegate, |
| 297 RenderWidgetHostDelegate* widget_delegate, | 293 RenderWidgetHostDelegate* widget_delegate, |
| 298 int routing_id, | 294 int routing_id, |
| 299 int main_frame_routing_id, | 295 int main_frame_routing_id, |
| 300 bool swapped_out) override { | 296 bool swapped_out) override { |
| 301 return new CaptureTestRenderViewHost(instance, delegate, widget_delegate, | 297 return new CaptureTestRenderViewHost(instance, delegate, widget_delegate, |
| 302 routing_id, main_frame_routing_id, | 298 routing_id, main_frame_routing_id, |
| 303 swapped_out, controller_); | 299 swapped_out, controller_); |
| 304 } | 300 } |
| 305 private: | 301 private: |
| 306 CaptureTestSourceController* controller_; | 302 CaptureTestSourceController* controller_; |
| 307 | 303 |
| 308 DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTestRenderViewHostFactory); | 304 DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTestRenderViewHostFactory); |
| 309 }; | 305 }; |
| 310 | 306 |
| 311 // A stub consumer of captured video frames, which checks the output of | 307 // A stub consumer of captured video frames, which checks the output of |
| 312 // WebContentsVideoCaptureDevice. | 308 // WebContentsVideoCaptureDevice. |
| 313 class StubClient : public media::VideoCaptureDevice::Client { | 309 class StubClient : public media::VideoCaptureDevice::Client { |
| 314 public: | 310 public: |
| 315 StubClient(const base::Callback<void(SkColor)>& color_callback, | 311 StubClient(const base::Callback<void(SkColor)>& color_callback, |
| 316 const base::Closure& error_callback) | 312 const base::Closure& error_callback) |
| 317 : color_callback_(color_callback), | 313 : color_callback_(color_callback), |
| 318 error_callback_(error_callback) { | 314 error_callback_(error_callback) { |
| 319 buffer_pool_ = new VideoCaptureBufferPool(2); | 315 buffer_pool_ = new VideoCaptureBufferPool(2); |
| 320 } | 316 } |
| 321 virtual ~StubClient() {} | 317 ~StubClient() override {} |
| 322 | 318 |
| 323 virtual scoped_refptr<media::VideoCaptureDevice::Client::Buffer> | 319 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> ReserveOutputBuffer( |
| 324 ReserveOutputBuffer(media::VideoFrame::Format format, | 320 media::VideoFrame::Format format, |
| 325 const gfx::Size& dimensions) override { | 321 const gfx::Size& dimensions) override { |
| 326 CHECK_EQ(format, media::VideoFrame::I420); | 322 CHECK_EQ(format, media::VideoFrame::I420); |
| 327 const size_t frame_bytes = | 323 const size_t frame_bytes = |
| 328 media::VideoFrame::AllocationSize(media::VideoFrame::I420, dimensions); | 324 media::VideoFrame::AllocationSize(media::VideoFrame::I420, dimensions); |
| 329 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; // Ignored. | 325 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; // Ignored. |
| 330 int buffer_id = | 326 int buffer_id = |
| 331 buffer_pool_->ReserveForProducer(frame_bytes, &buffer_id_to_drop); | 327 buffer_pool_->ReserveForProducer(frame_bytes, &buffer_id_to_drop); |
| 332 if (buffer_id == VideoCaptureBufferPool::kInvalidId) | 328 if (buffer_id == VideoCaptureBufferPool::kInvalidId) |
| 333 return NULL; | 329 return NULL; |
| 334 void* data; | 330 void* data; |
| 335 size_t size; | 331 size_t size; |
| 336 buffer_pool_->GetBufferInfo(buffer_id, &data, &size); | 332 buffer_pool_->GetBufferInfo(buffer_id, &data, &size); |
| 337 return scoped_refptr<media::VideoCaptureDevice::Client::Buffer>( | 333 return scoped_refptr<media::VideoCaptureDevice::Client::Buffer>( |
| 338 new PoolBuffer(buffer_pool_, buffer_id, data, size)); | 334 new PoolBuffer(buffer_pool_, buffer_id, data, size)); |
| 339 } | 335 } |
| 340 | 336 |
| 341 virtual void OnIncomingCapturedData( | 337 void OnIncomingCapturedData(const uint8* data, |
| 342 const uint8* data, | 338 int length, |
| 343 int length, | 339 const media::VideoCaptureFormat& frame_format, |
| 344 const media::VideoCaptureFormat& frame_format, | 340 int rotation, |
| 345 int rotation, | 341 base::TimeTicks timestamp) override { |
| 346 base::TimeTicks timestamp) override { | |
| 347 FAIL(); | 342 FAIL(); |
| 348 } | 343 } |
| 349 | 344 |
| 350 virtual void OnIncomingCapturedVideoFrame( | 345 void OnIncomingCapturedVideoFrame( |
| 351 const scoped_refptr<Buffer>& buffer, | 346 const scoped_refptr<Buffer>& buffer, |
| 352 const media::VideoCaptureFormat& buffer_format, | 347 const media::VideoCaptureFormat& buffer_format, |
| 353 const scoped_refptr<media::VideoFrame>& frame, | 348 const scoped_refptr<media::VideoFrame>& frame, |
| 354 base::TimeTicks timestamp) override { | 349 base::TimeTicks timestamp) override { |
| 355 EXPECT_EQ(gfx::Size(kTestWidth, kTestHeight), buffer_format.frame_size); | 350 EXPECT_EQ(gfx::Size(kTestWidth, kTestHeight), buffer_format.frame_size); |
| 356 EXPECT_EQ(media::PIXEL_FORMAT_I420, buffer_format.pixel_format); | 351 EXPECT_EQ(media::PIXEL_FORMAT_I420, buffer_format.pixel_format); |
| 357 EXPECT_EQ(media::VideoFrame::I420, frame->format()); | 352 EXPECT_EQ(media::VideoFrame::I420, frame->format()); |
| 358 uint8 yuv[3]; | 353 uint8 yuv[3]; |
| 359 for (int plane = 0; plane < 3; ++plane) | 354 for (int plane = 0; plane < 3; ++plane) |
| 360 yuv[plane] = frame->data(plane)[0]; | 355 yuv[plane] = frame->data(plane)[0]; |
| 361 // TODO(nick): We just look at the first pixel presently, because if | 356 // TODO(nick): We just look at the first pixel presently, because if |
| 362 // the analysis is too slow, the backlog of frames will grow without bound | 357 // the analysis is too slow, the backlog of frames will grow without bound |
| 363 // and trouble erupts. http://crbug.com/174519 | 358 // and trouble erupts. http://crbug.com/174519 |
| 364 color_callback_.Run((SkColorSetRGB(yuv[0], yuv[1], yuv[2]))); | 359 color_callback_.Run((SkColorSetRGB(yuv[0], yuv[1], yuv[2]))); |
| 365 } | 360 } |
| 366 | 361 |
| 367 virtual void OnError(const std::string& reason) override { | 362 void OnError(const std::string& reason) override { error_callback_.Run(); } |
| 368 error_callback_.Run(); | |
| 369 } | |
| 370 | 363 |
| 371 private: | 364 private: |
| 372 class PoolBuffer : public media::VideoCaptureDevice::Client::Buffer { | 365 class PoolBuffer : public media::VideoCaptureDevice::Client::Buffer { |
| 373 public: | 366 public: |
| 374 PoolBuffer(const scoped_refptr<VideoCaptureBufferPool>& pool, | 367 PoolBuffer(const scoped_refptr<VideoCaptureBufferPool>& pool, |
| 375 int buffer_id, | 368 int buffer_id, |
| 376 void* data, | 369 void* data, |
| 377 size_t size) | 370 size_t size) |
| 378 : Buffer(buffer_id, data, size), pool_(pool) {} | 371 : Buffer(buffer_id, data, size), pool_(pool) {} |
| 379 | 372 |
| 380 private: | 373 private: |
| 381 virtual ~PoolBuffer() { pool_->RelinquishProducerReservation(id()); } | 374 ~PoolBuffer() override { pool_->RelinquishProducerReservation(id()); } |
| 382 const scoped_refptr<VideoCaptureBufferPool> pool_; | 375 const scoped_refptr<VideoCaptureBufferPool> pool_; |
| 383 }; | 376 }; |
| 384 | 377 |
| 385 scoped_refptr<VideoCaptureBufferPool> buffer_pool_; | 378 scoped_refptr<VideoCaptureBufferPool> buffer_pool_; |
| 386 base::Callback<void(SkColor)> color_callback_; | 379 base::Callback<void(SkColor)> color_callback_; |
| 387 base::Closure error_callback_; | 380 base::Closure error_callback_; |
| 388 | 381 |
| 389 DISALLOW_COPY_AND_ASSIGN(StubClient); | 382 DISALLOW_COPY_AND_ASSIGN(StubClient); |
| 390 }; | 383 }; |
| 391 | 384 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 DISALLOW_COPY_AND_ASSIGN(StubClientObserver); | 462 DISALLOW_COPY_AND_ASSIGN(StubClientObserver); |
| 470 }; | 463 }; |
| 471 | 464 |
| 472 // A dummy implementation of gfx::Screen, since WebContentsVideoCaptureDevice | 465 // A dummy implementation of gfx::Screen, since WebContentsVideoCaptureDevice |
| 473 // needs access to a gfx::Display's device scale factor. | 466 // needs access to a gfx::Display's device scale factor. |
| 474 class FakeScreen : public gfx::Screen { | 467 class FakeScreen : public gfx::Screen { |
| 475 public: | 468 public: |
| 476 FakeScreen() : the_one_display_(0x1337, gfx::Rect(0, 0, 2560, 1440)) { | 469 FakeScreen() : the_one_display_(0x1337, gfx::Rect(0, 0, 2560, 1440)) { |
| 477 the_one_display_.set_device_scale_factor(kTestDeviceScaleFactor); | 470 the_one_display_.set_device_scale_factor(kTestDeviceScaleFactor); |
| 478 } | 471 } |
| 479 virtual ~FakeScreen() {} | 472 ~FakeScreen() override {} |
| 480 | 473 |
| 481 // gfx::Screen implementation (only what's needed for testing). | 474 // gfx::Screen implementation (only what's needed for testing). |
| 482 virtual bool IsDIPEnabled() override { return true; } | 475 bool IsDIPEnabled() override { return true; } |
| 483 virtual gfx::Point GetCursorScreenPoint() override { return gfx::Point(); } | 476 gfx::Point GetCursorScreenPoint() override { return gfx::Point(); } |
| 484 virtual gfx::NativeWindow GetWindowUnderCursor() override { return NULL; } | 477 gfx::NativeWindow GetWindowUnderCursor() override { return NULL; } |
| 485 virtual gfx::NativeWindow GetWindowAtScreenPoint( | 478 gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point) override { |
| 486 const gfx::Point& point) override { return NULL; } | 479 return NULL; |
| 487 virtual int GetNumDisplays() const override { return 1; } | 480 } |
| 488 virtual std::vector<gfx::Display> GetAllDisplays() const override { | 481 int GetNumDisplays() const override { return 1; } |
| 482 std::vector<gfx::Display> GetAllDisplays() const override { |
| 489 return std::vector<gfx::Display>(1, the_one_display_); | 483 return std::vector<gfx::Display>(1, the_one_display_); |
| 490 } | 484 } |
| 491 virtual gfx::Display GetDisplayNearestWindow( | 485 gfx::Display GetDisplayNearestWindow(gfx::NativeView view) const override { |
| 492 gfx::NativeView view) const override { | |
| 493 return the_one_display_; | 486 return the_one_display_; |
| 494 } | 487 } |
| 495 virtual gfx::Display GetDisplayNearestPoint( | 488 gfx::Display GetDisplayNearestPoint(const gfx::Point& point) const override { |
| 496 const gfx::Point& point) const override { | |
| 497 return the_one_display_; | 489 return the_one_display_; |
| 498 } | 490 } |
| 499 virtual gfx::Display GetDisplayMatching( | 491 gfx::Display GetDisplayMatching(const gfx::Rect& match_rect) const override { |
| 500 const gfx::Rect& match_rect) const override { | |
| 501 return the_one_display_; | 492 return the_one_display_; |
| 502 } | 493 } |
| 503 virtual gfx::Display GetPrimaryDisplay() const override { | 494 gfx::Display GetPrimaryDisplay() const override { return the_one_display_; } |
| 504 return the_one_display_; | 495 void AddObserver(gfx::DisplayObserver* observer) override {} |
| 505 } | 496 void RemoveObserver(gfx::DisplayObserver* observer) override {} |
| 506 virtual void AddObserver(gfx::DisplayObserver* observer) override {} | |
| 507 virtual void RemoveObserver(gfx::DisplayObserver* observer) override {} | |
| 508 | 497 |
| 509 private: | 498 private: |
| 510 gfx::Display the_one_display_; | 499 gfx::Display the_one_display_; |
| 511 | 500 |
| 512 DISALLOW_COPY_AND_ASSIGN(FakeScreen); | 501 DISALLOW_COPY_AND_ASSIGN(FakeScreen); |
| 513 }; | 502 }; |
| 514 | 503 |
| 515 // Test harness that sets up a minimal environment with necessary stubs. | 504 // Test harness that sets up a minimal environment with necessary stubs. |
| 516 class WebContentsVideoCaptureDeviceTest : public testing::Test { | 505 class WebContentsVideoCaptureDeviceTest : public testing::Test { |
| 517 public: | 506 public: |
| (...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 855 source()->SetSolidColor(SK_ColorGREEN); | 844 source()->SetSolidColor(SK_ColorGREEN); |
| 856 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorGREEN)); | 845 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorGREEN)); |
| 857 source()->SetSolidColor(SK_ColorRED); | 846 source()->SetSolidColor(SK_ColorRED); |
| 858 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED)); | 847 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED)); |
| 859 | 848 |
| 860 device()->StopAndDeAllocate(); | 849 device()->StopAndDeAllocate(); |
| 861 } | 850 } |
| 862 | 851 |
| 863 } // namespace | 852 } // namespace |
| 864 } // namespace content | 853 } // namespace content |
| OLD | NEW |