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 // Implementation notes: This needs to work on a variety of hardware | 5 // Implementation notes: This needs to work on a variety of hardware |
6 // configurations where the speed of the CPU and GPU greatly affect overall | 6 // configurations where the speed of the CPU and GPU greatly affect overall |
7 // performance. Spanning several threads, the process of capturing has been | 7 // performance. Spanning several threads, the process of capturing has been |
8 // split up into four conceptual stages: | 8 // split up into four conceptual stages: |
9 // | 9 // |
10 // 1. Reserve Buffer: Before a frame can be captured, a slot in the client's | 10 // 1. Reserve Buffer: Before a frame can be captured, a slot in the client's |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 #include "content/public/browser/render_process_host.h" | 72 #include "content/public/browser/render_process_host.h" |
73 #include "content/public/browser/render_widget_host_view.h" | 73 #include "content/public/browser/render_widget_host_view.h" |
74 #include "content/public/browser/render_widget_host_view_frame_subscriber.h" | 74 #include "content/public/browser/render_widget_host_view_frame_subscriber.h" |
75 #include "content/public/browser/web_contents.h" | 75 #include "content/public/browser/web_contents.h" |
76 #include "media/base/video_capture_types.h" | 76 #include "media/base/video_capture_types.h" |
77 #include "media/base/video_util.h" | 77 #include "media/base/video_util.h" |
78 #include "skia/ext/image_operations.h" | 78 #include "skia/ext/image_operations.h" |
79 #include "third_party/skia/include/core/SkBitmap.h" | 79 #include "third_party/skia/include/core/SkBitmap.h" |
80 #include "third_party/skia/include/core/SkColor.h" | 80 #include "third_party/skia/include/core/SkColor.h" |
81 #include "ui/gfx/display.h" | 81 #include "ui/gfx/display.h" |
82 #include "ui/gfx/geometry/size.h" | |
83 #include "ui/gfx/geometry/size_conversions.h" | 82 #include "ui/gfx/geometry/size_conversions.h" |
84 #include "ui/gfx/screen.h" | 83 #include "ui/gfx/screen.h" |
85 | 84 |
86 namespace content { | 85 namespace content { |
87 | 86 |
88 namespace { | 87 namespace { |
89 | 88 |
90 // Compute a letterbox region, aligned to even coordinates. | |
91 gfx::Rect ComputeYV12LetterboxRegion(const gfx::Rect& visible_rect, | |
92 const gfx::Size& content_size) { | |
93 | |
94 gfx::Rect result = media::ComputeLetterboxRegion(visible_rect, content_size); | |
95 | |
96 result.set_x(MakeEven(result.x())); | |
97 result.set_y(MakeEven(result.y())); | |
98 result.set_width(std::max(kMinFrameWidth, MakeEven(result.width()))); | |
99 result.set_height(std::max(kMinFrameHeight, MakeEven(result.height()))); | |
100 | |
101 return result; | |
102 } | |
103 | |
104 void DeleteOnWorkerThread(scoped_ptr<base::Thread> render_thread, | 89 void DeleteOnWorkerThread(scoped_ptr<base::Thread> render_thread, |
105 const base::Closure& callback) { | 90 const base::Closure& callback) { |
106 render_thread.reset(); | 91 render_thread.reset(); |
107 | 92 |
108 // After thread join call the callback on UI thread. | 93 // After thread join call the callback on UI thread. |
109 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); | 94 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); |
110 } | 95 } |
111 | 96 |
112 // Responsible for logging the effective frame rate. | 97 // Responsible for logging the effective frame rate. |
113 class VideoFrameDeliveryLog { | 98 class VideoFrameDeliveryLog { |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 const SkBitmap& bitmap, | 232 const SkBitmap& bitmap, |
248 ReadbackResponse response); | 233 ReadbackResponse response); |
249 | 234 |
250 // Response callback for RWHVP::CopyFromCompositingSurfaceToVideoFrame(). | 235 // Response callback for RWHVP::CopyFromCompositingSurfaceToVideoFrame(). |
251 void DidCopyFromCompositingSurfaceToVideoFrame( | 236 void DidCopyFromCompositingSurfaceToVideoFrame( |
252 const base::TimeTicks& start_time, | 237 const base::TimeTicks& start_time, |
253 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback& | 238 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback& |
254 deliver_frame_cb, | 239 deliver_frame_cb, |
255 bool success); | 240 bool success); |
256 | 241 |
257 // Remove the old subscription, and start a new one if |rwh| is not NULL. | 242 // Remove the old subscription, and attempt to start a new one if |had_target| |
258 void RenewFrameSubscription(RenderWidgetHost* rwh); | 243 // is true. |
| 244 void RenewFrameSubscription(bool had_target); |
| 245 |
| 246 // Called whenever the render widget is resized. |
| 247 void UpdateCaptureSize(); |
259 | 248 |
260 // Parameters saved in constructor. | 249 // Parameters saved in constructor. |
261 const int initial_render_process_id_; | 250 const int initial_render_process_id_; |
262 const int initial_main_render_frame_id_; | 251 const int initial_main_render_frame_id_; |
263 | 252 |
264 // Tracks events and calls back to RenewFrameSubscription() to maintain | 253 // Tracks events and calls back to RenewFrameSubscription() to maintain |
265 // capture on the correct RenderWidgetHost. | 254 // capture on the correct RenderWidgetHost. |
266 const scoped_refptr<WebContentsTracker> tracker_; | 255 const scoped_refptr<WebContentsTracker> tracker_; |
267 | 256 |
268 // A dedicated worker thread on which SkBitmap->VideoFrame conversion will | 257 // A dedicated worker thread on which SkBitmap->VideoFrame conversion will |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
389 } | 378 } |
390 | 379 |
391 // Sanity-check the output buffer. | 380 // Sanity-check the output buffer. |
392 if (output->format() != media::VideoFrame::I420) { | 381 if (output->format() != media::VideoFrame::I420) { |
393 NOTREACHED(); | 382 NOTREACHED(); |
394 return; | 383 return; |
395 } | 384 } |
396 | 385 |
397 // Calculate the width and height of the content region in the |output|, based | 386 // Calculate the width and height of the content region in the |output|, based |
398 // on the aspect ratio of |input|. | 387 // on the aspect ratio of |input|. |
399 gfx::Rect region_in_frame = ComputeYV12LetterboxRegion( | 388 const gfx::Rect region_in_frame = media::ComputeLetterboxRegion( |
400 output->visible_rect(), gfx::Size(input.width(), input.height())); | 389 output->visible_rect(), gfx::Size(input.width(), input.height())); |
401 | 390 |
402 // Scale the bitmap to the required size, if necessary. | 391 // Scale the bitmap to the required size, if necessary. |
403 SkBitmap scaled_bitmap; | 392 SkBitmap scaled_bitmap; |
404 if (input.width() != region_in_frame.width() || | 393 if (input.width() != region_in_frame.width() || |
405 input.height() != region_in_frame.height()) { | 394 input.height() != region_in_frame.height()) { |
406 | 395 |
407 skia::ImageOperations::ResizeMethod method; | 396 skia::ImageOperations::ResizeMethod method; |
408 if (input.width() < region_in_frame.width() || | 397 if (input.width() < region_in_frame.width() || |
409 input.height() < region_in_frame.height()) { | 398 input.height() < region_in_frame.height()) { |
410 // Avoid box filtering when magnifying, because it's actually | 399 // Avoid box filtering when magnifying, because it's actually |
411 // nearest-neighbor. | 400 // nearest-neighbor. |
412 method = skia::ImageOperations::RESIZE_HAMMING1; | 401 method = skia::ImageOperations::RESIZE_HAMMING1; |
413 } else { | 402 } else { |
414 method = skia::ImageOperations::RESIZE_BOX; | 403 method = skia::ImageOperations::RESIZE_BOX; |
415 } | 404 } |
416 | 405 |
417 TRACE_EVENT_ASYNC_STEP_INTO0("gpu.capture", | 406 TRACE_EVENT_ASYNC_STEP_INTO0("gpu.capture", |
418 "Capture", output.get(), "Scale"); | 407 "Capture", output.get(), "Scale"); |
419 scaled_bitmap = skia::ImageOperations::Resize(input, method, | 408 scaled_bitmap = skia::ImageOperations::Resize(input, method, |
420 region_in_frame.width(), | 409 region_in_frame.width(), |
421 region_in_frame.height()); | 410 region_in_frame.height()); |
422 } else { | 411 } else { |
423 scaled_bitmap = input; | 412 scaled_bitmap = input; |
424 } | 413 } |
425 | 414 |
426 TRACE_EVENT_ASYNC_STEP_INTO0("gpu.capture", "Capture", output.get(), "YUV"); | 415 TRACE_EVENT_ASYNC_STEP_INTO0("gpu.capture", "Capture", output.get(), "YUV"); |
427 { | 416 { |
| 417 // Align to 2x2 pixel boundaries, as required by |
| 418 // media::CopyRGBToVideoFrame(). |
| 419 const gfx::Rect region_in_yv12_frame(region_in_frame.x() & ~1, |
| 420 region_in_frame.y() & ~1, |
| 421 region_in_frame.width() & ~1, |
| 422 region_in_frame.height() & ~1); |
| 423 if (region_in_yv12_frame.IsEmpty()) |
| 424 return; |
| 425 |
428 SkAutoLockPixels scaled_bitmap_locker(scaled_bitmap); | 426 SkAutoLockPixels scaled_bitmap_locker(scaled_bitmap); |
429 | |
430 media::CopyRGBToVideoFrame( | 427 media::CopyRGBToVideoFrame( |
431 reinterpret_cast<uint8*>(scaled_bitmap.getPixels()), | 428 reinterpret_cast<uint8*>(scaled_bitmap.getPixels()), |
432 scaled_bitmap.rowBytes(), | 429 scaled_bitmap.rowBytes(), |
433 region_in_frame, | 430 region_in_yv12_frame, |
434 output.get()); | 431 output.get()); |
435 } | 432 } |
436 | 433 |
437 // The result is now ready. | 434 // The result is now ready. |
438 ignore_result(failure_handler.Release()); | 435 ignore_result(failure_handler.Release()); |
439 done_cb.Run(true); | 436 done_cb.Run(true); |
440 } | 437 } |
441 | 438 |
442 VideoFrameDeliveryLog::VideoFrameDeliveryLog() | 439 VideoFrameDeliveryLog::VideoFrameDeliveryLog() |
443 : last_frame_rate_log_time_(), | 440 : last_frame_rate_log_time_(), |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
494 | 491 |
495 render_thread_.reset(new base::Thread("WebContentsVideo_RenderThread")); | 492 render_thread_.reset(new base::Thread("WebContentsVideo_RenderThread")); |
496 if (!render_thread_->Start()) { | 493 if (!render_thread_->Start()) { |
497 DVLOG(1) << "Failed to spawn render thread."; | 494 DVLOG(1) << "Failed to spawn render thread."; |
498 render_thread_.reset(); | 495 render_thread_.reset(); |
499 return false; | 496 return false; |
500 } | 497 } |
501 | 498 |
502 // Note: Creation of the first WeakPtr in the following statement will cause | 499 // Note: Creation of the first WeakPtr in the following statement will cause |
503 // IsStarted() to return true from now on. | 500 // IsStarted() to return true from now on. |
| 501 tracker_->SetResizeChangeCallback( |
| 502 base::Bind(&WebContentsCaptureMachine::UpdateCaptureSize, |
| 503 weak_ptr_factory_.GetWeakPtr())); |
504 tracker_->Start(initial_render_process_id_, initial_main_render_frame_id_, | 504 tracker_->Start(initial_render_process_id_, initial_main_render_frame_id_, |
505 base::Bind(&WebContentsCaptureMachine::RenewFrameSubscription, | 505 base::Bind(&WebContentsCaptureMachine::RenewFrameSubscription, |
506 weak_ptr_factory_.GetWeakPtr())); | 506 weak_ptr_factory_.GetWeakPtr())); |
507 | 507 |
508 return true; | 508 return true; |
509 } | 509 } |
510 | 510 |
511 void WebContentsCaptureMachine::Stop(const base::Closure& callback) { | 511 void WebContentsCaptureMachine::Stop(const base::Closure& callback) { |
512 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 512 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
513 | 513 |
514 if (!IsStarted()) { | 514 if (!IsStarted()) { |
515 callback.Run(); | 515 callback.Run(); |
516 return; | 516 return; |
517 } | 517 } |
518 | 518 |
519 // The following cancels any outstanding callbacks and causes IsStarted() to | 519 // The following cancels any outstanding callbacks and causes IsStarted() to |
520 // return false from here onward. | 520 // return false from here onward. |
521 weak_ptr_factory_.InvalidateWeakPtrs(); | 521 weak_ptr_factory_.InvalidateWeakPtrs(); |
522 | 522 |
523 // Note: RenewFrameSubscription() must be called before stopping |tracker_| so | 523 // Note: RenewFrameSubscription() must be called before stopping |tracker_| so |
524 // the web_contents() can be notified that the capturing is ending. | 524 // the web_contents() can be notified that the capturing is ending. |
525 RenewFrameSubscription(NULL); | 525 RenewFrameSubscription(false); |
526 tracker_->Stop(); | 526 tracker_->Stop(); |
527 | 527 |
528 // The render thread cannot be stopped on the UI thread, so post a message | 528 // The render thread cannot be stopped on the UI thread, so post a message |
529 // to the thread pool used for blocking operations. | 529 // to the thread pool used for blocking operations. |
530 if (render_thread_.get()) { | 530 if (render_thread_.get()) { |
531 BrowserThread::PostBlockingPoolTask( | 531 BrowserThread::PostBlockingPoolTask( |
532 FROM_HERE, | 532 FROM_HERE, |
533 base::Bind(&DeleteOnWorkerThread, base::Passed(&render_thread_), | 533 base::Bind(&DeleteOnWorkerThread, base::Passed(&render_thread_), |
534 callback)); | 534 callback)); |
535 } | 535 } |
536 } | 536 } |
537 | 537 |
538 void WebContentsCaptureMachine::Capture( | 538 void WebContentsCaptureMachine::Capture( |
539 const base::TimeTicks& start_time, | 539 const base::TimeTicks& start_time, |
540 const scoped_refptr<media::VideoFrame>& target, | 540 const scoped_refptr<media::VideoFrame>& target, |
541 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback& | 541 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback& |
542 deliver_frame_cb) { | 542 deliver_frame_cb) { |
543 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 543 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
544 | 544 |
545 RenderWidgetHost* rwh = tracker_->GetTargetRenderWidgetHost(); | 545 RenderWidgetHost* rwh = tracker_->GetTargetRenderWidgetHost(); |
546 RenderWidgetHostViewBase* view = | 546 RenderWidgetHostViewBase* view = |
547 rwh ? static_cast<RenderWidgetHostViewBase*>(rwh->GetView()) : NULL; | 547 rwh ? static_cast<RenderWidgetHostViewBase*>(rwh->GetView()) : NULL; |
548 if (!view) { | 548 if (!view) { |
549 deliver_frame_cb.Run(base::TimeTicks(), false); | 549 deliver_frame_cb.Run(base::TimeTicks(), false); |
550 return; | 550 return; |
551 } | 551 } |
552 | 552 |
553 gfx::Size view_size = view->GetViewBounds().size(); | 553 gfx::Size view_size = view->GetViewBounds().size(); |
554 gfx::Size fitted_size; | |
555 if (!view_size.IsEmpty()) { | |
556 fitted_size = ComputeYV12LetterboxRegion(target->visible_rect(), | |
557 view_size).size(); | |
558 } | |
559 if (view_size != last_view_size_) { | 554 if (view_size != last_view_size_) { |
560 last_view_size_ = view_size; | 555 last_view_size_ = view_size; |
561 | 556 |
562 // Measure the number of kilopixels. | 557 // Measure the number of kilopixels. |
563 UMA_HISTOGRAM_COUNTS_10000( | 558 UMA_HISTOGRAM_COUNTS_10000( |
564 "TabCapture.ViewChangeKiloPixels", | 559 "TabCapture.ViewChangeKiloPixels", |
565 view_size.width() * view_size.height() / 1024); | 560 view_size.width() * view_size.height() / 1024); |
566 } | 561 } |
567 | 562 |
568 if (view->CanCopyToVideoFrame()) { | 563 if (view->CanCopyToVideoFrame()) { |
569 view->CopyFromCompositingSurfaceToVideoFrame( | 564 view->CopyFromCompositingSurfaceToVideoFrame( |
570 gfx::Rect(view_size), | 565 gfx::Rect(view_size), |
571 target, | 566 target, |
572 base::Bind(&WebContentsCaptureMachine:: | 567 base::Bind(&WebContentsCaptureMachine:: |
573 DidCopyFromCompositingSurfaceToVideoFrame, | 568 DidCopyFromCompositingSurfaceToVideoFrame, |
574 weak_ptr_factory_.GetWeakPtr(), | 569 weak_ptr_factory_.GetWeakPtr(), |
575 start_time, deliver_frame_cb)); | 570 start_time, deliver_frame_cb)); |
576 } else { | 571 } else { |
| 572 const gfx::Size fitted_size = view_size.IsEmpty() ? gfx::Size() : |
| 573 media::ComputeLetterboxRegion(target->visible_rect(), view_size).size(); |
577 rwh->CopyFromBackingStore( | 574 rwh->CopyFromBackingStore( |
578 gfx::Rect(), | 575 gfx::Rect(), |
579 fitted_size, // Size here is a request not always honored. | 576 fitted_size, // Size here is a request not always honored. |
580 base::Bind(&WebContentsCaptureMachine::DidCopyFromBackingStore, | 577 base::Bind(&WebContentsCaptureMachine::DidCopyFromBackingStore, |
581 weak_ptr_factory_.GetWeakPtr(), | 578 weak_ptr_factory_.GetWeakPtr(), |
582 start_time, | 579 start_time, |
583 target, | 580 target, |
584 deliver_frame_cb), | 581 deliver_frame_cb), |
585 kN32_SkColorType); | 582 kN32_SkColorType); |
586 } | 583 } |
587 } | 584 } |
588 | 585 |
589 gfx::Size WebContentsCaptureMachine::ComputeOptimalTargetSize() const { | 586 gfx::Size WebContentsCaptureMachine::ComputeOptimalTargetSize() const { |
590 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 587 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
591 | 588 |
592 gfx::Size optimal_size = oracle_proxy_->GetCaptureSize(); | 589 // TODO(miu): Propagate capture frame size changes as new "preferred size" |
| 590 // updates, rather than just using the max frame size. |
| 591 // http://crbug.com/350491 |
| 592 gfx::Size optimal_size = oracle_proxy_->max_frame_size(); |
593 | 593 |
594 // If the ratio between physical and logical pixels is greater than 1:1, | 594 // If the ratio between physical and logical pixels is greater than 1:1, |
595 // shrink |optimal_size| by that amount. Then, when external code resizes the | 595 // shrink |optimal_size| by that amount. Then, when external code resizes the |
596 // render widget to the "preferred size," the widget will be physically | 596 // render widget to the "preferred size," the widget will be physically |
597 // rendered at the exact capture size, thereby eliminating unnecessary scaling | 597 // rendered at the exact capture size, thereby eliminating unnecessary scaling |
598 // operations in the graphics pipeline. | 598 // operations in the graphics pipeline. |
599 RenderWidgetHost* const rwh = tracker_->GetTargetRenderWidgetHost(); | 599 RenderWidgetHost* const rwh = tracker_->GetTargetRenderWidgetHost(); |
600 RenderWidgetHostView* const rwhv = rwh ? rwh->GetView() : NULL; | 600 RenderWidgetHostView* const rwhv = rwh ? rwh->GetView() : NULL; |
601 if (rwhv) { | 601 if (rwhv) { |
602 const gfx::NativeView view = rwhv->GetNativeView(); | 602 const gfx::NativeView view = rwhv->GetNativeView(); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
650 | 650 |
651 if (success) { | 651 if (success) { |
652 UMA_HISTOGRAM_TIMES("TabCapture.CopyTimeVideoFrame", now - start_time); | 652 UMA_HISTOGRAM_TIMES("TabCapture.CopyTimeVideoFrame", now - start_time); |
653 } else { | 653 } else { |
654 // Capture can fail due to transient issues, so just skip this frame. | 654 // Capture can fail due to transient issues, so just skip this frame. |
655 DVLOG(1) << "CopyFromCompositingSurface failed; skipping frame."; | 655 DVLOG(1) << "CopyFromCompositingSurface failed; skipping frame."; |
656 } | 656 } |
657 deliver_frame_cb.Run(start_time, success); | 657 deliver_frame_cb.Run(start_time, success); |
658 } | 658 } |
659 | 659 |
660 void WebContentsCaptureMachine::RenewFrameSubscription(RenderWidgetHost* rwh) { | 660 void WebContentsCaptureMachine::RenewFrameSubscription(bool had_target) { |
661 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 661 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
662 | 662 |
| 663 RenderWidgetHost* const rwh = |
| 664 had_target ? tracker_->GetTargetRenderWidgetHost() : nullptr; |
| 665 |
663 // Always destroy the old subscription before creating a new one. | 666 // Always destroy the old subscription before creating a new one. |
664 const bool had_subscription = !!subscription_; | 667 const bool had_subscription = !!subscription_; |
665 subscription_.reset(); | 668 subscription_.reset(); |
666 | 669 |
667 DVLOG(1) << "Renewing frame subscription to RWH@" << rwh | 670 DVLOG(1) << "Renewing frame subscription to RWH@" << rwh |
668 << ", had_subscription=" << had_subscription; | 671 << ", had_subscription=" << had_subscription; |
669 | 672 |
670 if (!rwh) { | 673 if (!rwh) { |
671 if (had_subscription && tracker_->web_contents()) | 674 if (had_subscription && tracker_->web_contents()) |
672 tracker_->web_contents()->DecrementCapturerCount(); | 675 tracker_->web_contents()->DecrementCapturerCount(); |
673 if (IsStarted()) { | 676 if (IsStarted()) { |
674 // Tracking of WebContents and/or its main frame has failed before Stop() | 677 // Tracking of WebContents and/or its main frame has failed before Stop() |
675 // was called, so report this as an error: | 678 // was called, so report this as an error: |
676 oracle_proxy_->ReportError("WebContents and/or main frame are gone."); | 679 oracle_proxy_->ReportError("WebContents and/or main frame are gone."); |
677 } | 680 } |
678 return; | 681 return; |
679 } | 682 } |
680 | 683 |
681 if (!had_subscription && tracker_->web_contents()) { | 684 if (!had_subscription && tracker_->web_contents()) { |
682 tracker_->web_contents()->IncrementCapturerCount( | 685 tracker_->web_contents()->IncrementCapturerCount( |
683 ComputeOptimalTargetSize()); | 686 ComputeOptimalTargetSize()); |
684 } | 687 } |
685 | 688 |
686 subscription_.reset(new ContentCaptureSubscription(*rwh, oracle_proxy_, | 689 subscription_.reset(new ContentCaptureSubscription(*rwh, oracle_proxy_, |
687 base::Bind(&WebContentsCaptureMachine::Capture, | 690 base::Bind(&WebContentsCaptureMachine::Capture, |
688 weak_ptr_factory_.GetWeakPtr()))); | 691 weak_ptr_factory_.GetWeakPtr()))); |
689 } | 692 } |
690 | 693 |
| 694 void WebContentsCaptureMachine::UpdateCaptureSize() { |
| 695 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 696 |
| 697 if (!oracle_proxy_) |
| 698 return; |
| 699 RenderWidgetHost* const rwh = tracker_->GetTargetRenderWidgetHost(); |
| 700 RenderWidgetHostView* const view = rwh ? rwh->GetView() : nullptr; |
| 701 if (!view) |
| 702 return; |
| 703 oracle_proxy_->UpdateCaptureSize(view->GetViewBounds().size()); |
| 704 } |
| 705 |
691 } // namespace | 706 } // namespace |
692 | 707 |
693 WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice( | 708 WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice( |
694 int render_process_id, int main_render_frame_id) | 709 int render_process_id, int main_render_frame_id) |
695 : core_(new ContentVideoCaptureDeviceCore(scoped_ptr<VideoCaptureMachine>( | 710 : core_(new ContentVideoCaptureDeviceCore(scoped_ptr<VideoCaptureMachine>( |
696 new WebContentsCaptureMachine( | 711 new WebContentsCaptureMachine( |
697 render_process_id, main_render_frame_id)))) {} | 712 render_process_id, main_render_frame_id)))) {} |
698 | 713 |
699 WebContentsVideoCaptureDevice::~WebContentsVideoCaptureDevice() { | 714 WebContentsVideoCaptureDevice::~WebContentsVideoCaptureDevice() { |
700 DVLOG(2) << "WebContentsVideoCaptureDevice@" << this << " destroying."; | 715 DVLOG(2) << "WebContentsVideoCaptureDevice@" << this << " destroying."; |
(...skipping 19 matching lines...) Expand all Loading... |
720 scoped_ptr<Client> client) { | 735 scoped_ptr<Client> client) { |
721 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString(); | 736 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString(); |
722 core_->AllocateAndStart(params, client.Pass()); | 737 core_->AllocateAndStart(params, client.Pass()); |
723 } | 738 } |
724 | 739 |
725 void WebContentsVideoCaptureDevice::StopAndDeAllocate() { | 740 void WebContentsVideoCaptureDevice::StopAndDeAllocate() { |
726 core_->StopAndDeAllocate(); | 741 core_->StopAndDeAllocate(); |
727 } | 742 } |
728 | 743 |
729 } // namespace content | 744 } // namespace content |
OLD | NEW |