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 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 scoped_refptr<media::ThreadSafeCaptureOracle> oracle_proxy_; | 148 scoped_refptr<media::ThreadSafeCaptureOracle> oracle_proxy_; |
149 // We need a weak pointer since FrameSubscriber is owned externally and | 149 // We need a weak pointer since FrameSubscriber is owned externally and |
150 // may outlive the cursor renderer. | 150 // may outlive the cursor renderer. |
151 base::WeakPtr<CursorRenderer> cursor_renderer_; | 151 base::WeakPtr<CursorRenderer> cursor_renderer_; |
152 // We need a weak pointer since FrameSubscriber is owned externally and | 152 // We need a weak pointer since FrameSubscriber is owned externally and |
153 // may outlive the ui activity tracker. | 153 // may outlive the ui activity tracker. |
154 base::WeakPtr<WindowActivityTracker> window_activity_tracker_; | 154 base::WeakPtr<WindowActivityTracker> window_activity_tracker_; |
155 base::WeakPtrFactory<FrameSubscriber> weak_ptr_factory_; | 155 base::WeakPtrFactory<FrameSubscriber> weak_ptr_factory_; |
156 }; | 156 }; |
157 | 157 |
158 // ContentCaptureSubscription is the relationship between a RenderWidgetHost | 158 // ContentCaptureSubscription is the relationship between a RenderWidgetHostView |
159 // whose content is updating, a subscriber that is deciding which of these | 159 // whose content is updating, a subscriber that is deciding which of these |
160 // updates to capture (and where to deliver them to), and a callback that | 160 // updates to capture (and where to deliver them to), and a callback that |
161 // knows how to do the capture and prepare the result for delivery. | 161 // knows how to do the capture and prepare the result for delivery. |
162 // | 162 // |
163 // In practice, this means (a) installing a RenderWidgetHostFrameSubscriber in | 163 // In practice, this means (a) installing a RenderWidgetHostFrameSubscriber in |
164 // the RenderWidgetHostView, to process compositor updates, and (b) occasionally | 164 // the RenderWidgetHostView, to process compositor updates, and (b) occasionally |
165 // initiating forced, non-event-driven captures needed by downstream consumers | 165 // initiating forced, non-event-driven captures needed by downstream consumers |
166 // that request "refresh frames" of unchanged content. | 166 // that request "refresh frames" of unchanged content. |
167 // | 167 // |
168 // All of this happens on the UI thread, although the | 168 // All of this happens on the UI thread, although the |
169 // RenderWidgetHostViewFrameSubscriber we install may be dispatching updates | 169 // RenderWidgetHostViewFrameSubscriber we install may be dispatching updates |
170 // autonomously on some other thread. | 170 // autonomously on some other thread. |
171 class ContentCaptureSubscription { | 171 class ContentCaptureSubscription { |
172 public: | 172 public: |
173 typedef base::Callback<void( | 173 typedef base::Callback<void( |
174 const base::TimeTicks&, | 174 const base::TimeTicks&, |
175 const scoped_refptr<media::VideoFrame>&, | 175 const scoped_refptr<media::VideoFrame>&, |
176 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback&)> | 176 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback&)> |
177 CaptureCallback; | 177 CaptureCallback; |
178 | 178 |
179 // Create a subscription. Whenever a manual capture is required, the | 179 // Create a subscription. Whenever a manual capture is required, the |
180 // subscription will invoke |capture_callback| on the UI thread to do the | 180 // subscription will invoke |capture_callback| on the UI thread to do the |
181 // work. | 181 // work. |
182 ContentCaptureSubscription( | 182 ContentCaptureSubscription( |
183 const RenderWidgetHost& source, | 183 base::WeakPtr<RenderWidgetHostViewBase> source_view, |
184 const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy, | 184 const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy, |
185 const CaptureCallback& capture_callback); | 185 const CaptureCallback& capture_callback); |
186 ~ContentCaptureSubscription(); | 186 ~ContentCaptureSubscription(); |
187 | 187 |
188 void MaybeCaptureForRefresh(); | 188 void MaybeCaptureForRefresh(); |
189 | 189 |
190 private: | 190 private: |
191 // Called for active frame refresh requests, or mouse activity events. | 191 // Called for active frame refresh requests, or mouse activity events. |
192 void OnEvent(FrameSubscriber* subscriber); | 192 void OnEvent(FrameSubscriber* subscriber); |
193 | 193 |
194 // Maintain a weak reference to the RenderWidgetHost (via its routing ID), | 194 const base::WeakPtr<RenderWidgetHostViewBase> source_view_; |
195 // since the instance could be destroyed externally during the lifetime of | |
196 // |this|. | |
197 const int render_process_id_; | |
198 const int render_widget_id_; | |
199 | 195 |
200 std::unique_ptr<FrameSubscriber> refresh_subscriber_; | 196 std::unique_ptr<FrameSubscriber> refresh_subscriber_; |
201 std::unique_ptr<FrameSubscriber> mouse_activity_subscriber_; | 197 std::unique_ptr<FrameSubscriber> mouse_activity_subscriber_; |
202 CaptureCallback capture_callback_; | 198 CaptureCallback capture_callback_; |
203 | 199 |
204 // Responsible for tracking the cursor state and input events to make | 200 // Responsible for tracking the cursor state and input events to make |
205 // decisions and then render the mouse cursor on the video frame after | 201 // decisions and then render the mouse cursor on the video frame after |
206 // capture is completed. | 202 // capture is completed. |
207 std::unique_ptr<content::CursorRenderer> cursor_renderer_; | 203 std::unique_ptr<content::CursorRenderer> cursor_renderer_; |
208 | 204 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 ReadbackResponse response); | 277 ReadbackResponse response); |
282 | 278 |
283 // Response callback for RWHVP::CopyFromCompositingSurfaceToVideoFrame(). | 279 // Response callback for RWHVP::CopyFromCompositingSurfaceToVideoFrame(). |
284 void DidCopyFromCompositingSurfaceToVideoFrame( | 280 void DidCopyFromCompositingSurfaceToVideoFrame( |
285 const base::TimeTicks& start_time, | 281 const base::TimeTicks& start_time, |
286 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback& | 282 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback& |
287 deliver_frame_cb, | 283 deliver_frame_cb, |
288 const gfx::Rect& region_in_frame, | 284 const gfx::Rect& region_in_frame, |
289 bool success); | 285 bool success); |
290 | 286 |
291 // Remove the old subscription, and attempt to start a new one if |had_target| | 287 // Remove the old subscription, and attempt to start a new one. If |
292 // is true. | 288 // |is_still_tracking| is false, emit an error rather than attempt to start a |
293 void RenewFrameSubscription(bool had_target); | 289 // new subscription. |
| 290 void RenewFrameSubscription(bool is_still_tracking); |
294 | 291 |
295 // Called whenever the render widget is resized. | 292 // Called whenever the render widget is resized. |
296 void UpdateCaptureSize(); | 293 void UpdateCaptureSize(); |
297 | 294 |
298 // Parameters saved in constructor. | 295 // Parameters saved in constructor. |
299 const int initial_render_process_id_; | 296 const int initial_render_process_id_; |
300 const int initial_main_render_frame_id_; | 297 const int initial_main_render_frame_id_; |
301 | 298 |
302 // Tracks events and calls back to RenewFrameSubscription() to maintain | 299 // Tracks events and calls back to RenewFrameSubscription() to maintain |
303 // capture on the correct RenderWidgetHost. | 300 // capture on the correct RenderWidgetHostView. |
304 const scoped_refptr<WebContentsTracker> tracker_; | 301 const scoped_refptr<WebContentsTracker> tracker_; |
305 | 302 |
306 // Set to false to prevent the capture size from automatically adjusting in | 303 // Set to false to prevent the capture size from automatically adjusting in |
307 // response to end-to-end utilization. This is enabled via the throttling | 304 // response to end-to-end utilization. This is enabled via the throttling |
308 // option in the WebContentsVideoCaptureDevice device ID. | 305 // option in the WebContentsVideoCaptureDevice device ID. |
309 const bool auto_throttling_enabled_; | 306 const bool auto_throttling_enabled_; |
310 | 307 |
311 // A dedicated worker thread on which SkBitmap->VideoFrame conversion will | 308 // A dedicated worker thread on which SkBitmap->VideoFrame conversion will |
312 // occur. Only used when this activity cannot be done on the GPU. | 309 // occur. Only used when this activity cannot be done on the GPU. |
313 std::unique_ptr<base::Thread> render_thread_; | 310 std::unique_ptr<base::Thread> render_thread_; |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 if (ui_activity && !animation_active) { | 394 if (ui_activity && !animation_active) { |
398 interactive_mode = true; | 395 interactive_mode = true; |
399 } else if (animation_active && window_activity_tracker_.get()) { | 396 } else if (animation_active && window_activity_tracker_.get()) { |
400 window_activity_tracker_->Reset(); | 397 window_activity_tracker_->Reset(); |
401 } | 398 } |
402 } | 399 } |
403 return interactive_mode; | 400 return interactive_mode; |
404 } | 401 } |
405 | 402 |
406 ContentCaptureSubscription::ContentCaptureSubscription( | 403 ContentCaptureSubscription::ContentCaptureSubscription( |
407 const RenderWidgetHost& source, | 404 base::WeakPtr<RenderWidgetHostViewBase> source_view, |
408 const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy, | 405 const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy, |
409 const CaptureCallback& capture_callback) | 406 const CaptureCallback& capture_callback) |
410 : render_process_id_(source.GetProcess()->GetID()), | 407 : source_view_(source_view), capture_callback_(capture_callback) { |
411 render_widget_id_(source.GetRoutingID()), | |
412 capture_callback_(capture_callback) { | |
413 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 408 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 409 DCHECK(source_view_); |
414 | 410 |
415 RenderWidgetHostView* const view = source.GetView(); | |
416 #if defined(USE_AURA) || defined(OS_MACOSX) | 411 #if defined(USE_AURA) || defined(OS_MACOSX) |
417 if (view) { | 412 cursor_renderer_ = CursorRenderer::Create(source_view_->GetNativeView()); |
418 cursor_renderer_ = CursorRenderer::Create(view->GetNativeView()); | 413 window_activity_tracker_ = |
419 window_activity_tracker_ = | 414 WindowActivityTracker::Create(source_view_->GetNativeView()); |
420 WindowActivityTracker::Create(view->GetNativeView()); | |
421 } | |
422 #endif | 415 #endif |
423 refresh_subscriber_.reset(new FrameSubscriber( | 416 refresh_subscriber_.reset(new FrameSubscriber( |
424 media::VideoCaptureOracle::kActiveRefreshRequest, oracle_proxy, | 417 media::VideoCaptureOracle::kActiveRefreshRequest, oracle_proxy, |
425 cursor_renderer_ ? cursor_renderer_->GetWeakPtr() | 418 cursor_renderer_ ? cursor_renderer_->GetWeakPtr() |
426 : base::WeakPtr<CursorRenderer>(), | 419 : base::WeakPtr<CursorRenderer>(), |
427 window_activity_tracker_ ? window_activity_tracker_->GetWeakPtr() | 420 window_activity_tracker_ ? window_activity_tracker_->GetWeakPtr() |
428 : base::WeakPtr<WindowActivityTracker>())); | 421 : base::WeakPtr<WindowActivityTracker>())); |
429 mouse_activity_subscriber_.reset(new FrameSubscriber( | 422 mouse_activity_subscriber_.reset(new FrameSubscriber( |
430 media::VideoCaptureOracle::kMouseCursorUpdate, oracle_proxy, | 423 media::VideoCaptureOracle::kMouseCursorUpdate, oracle_proxy, |
431 cursor_renderer_ ? cursor_renderer_->GetWeakPtr() | 424 cursor_renderer_ ? cursor_renderer_->GetWeakPtr() |
432 : base::WeakPtr<CursorRenderer>(), | 425 : base::WeakPtr<CursorRenderer>(), |
433 window_activity_tracker_ ? window_activity_tracker_->GetWeakPtr() | 426 window_activity_tracker_ ? window_activity_tracker_->GetWeakPtr() |
434 : base::WeakPtr<WindowActivityTracker>())); | 427 : base::WeakPtr<WindowActivityTracker>())); |
435 | 428 |
436 // Subscribe to compositor updates. These will be serviced directly by the | 429 // Subscribe to compositor updates. These will be serviced directly by the |
437 // oracle. | 430 // oracle. |
438 if (view) { | 431 std::unique_ptr<RenderWidgetHostViewFrameSubscriber> subscriber( |
439 std::unique_ptr<RenderWidgetHostViewFrameSubscriber> subscriber( | 432 new FrameSubscriber( |
440 new FrameSubscriber( | 433 media::VideoCaptureOracle::kCompositorUpdate, oracle_proxy, |
441 media::VideoCaptureOracle::kCompositorUpdate, oracle_proxy, | 434 cursor_renderer_ ? cursor_renderer_->GetWeakPtr() |
442 cursor_renderer_ ? cursor_renderer_->GetWeakPtr() | 435 : base::WeakPtr<CursorRenderer>(), |
443 : base::WeakPtr<CursorRenderer>(), | 436 window_activity_tracker_ ? window_activity_tracker_->GetWeakPtr() |
444 window_activity_tracker_ ? window_activity_tracker_->GetWeakPtr() | 437 : base::WeakPtr<WindowActivityTracker>())); |
445 : base::WeakPtr<WindowActivityTracker>())); | 438 source_view_->BeginFrameSubscription(std::move(subscriber)); |
446 view->BeginFrameSubscription(std::move(subscriber)); | |
447 } | |
448 | 439 |
449 // Subscribe to mouse movement and mouse cursor update events. | 440 // Subscribe to mouse movement and mouse cursor update events. |
450 if (window_activity_tracker_) { | 441 if (window_activity_tracker_) { |
451 window_activity_tracker_->RegisterMouseInteractionObserver( | 442 window_activity_tracker_->RegisterMouseInteractionObserver( |
452 base::Bind(&ContentCaptureSubscription::OnEvent, base::Unretained(this), | 443 base::Bind(&ContentCaptureSubscription::OnEvent, base::Unretained(this), |
453 mouse_activity_subscriber_.get())); | 444 mouse_activity_subscriber_.get())); |
454 } | 445 } |
455 } | 446 } |
456 | 447 |
457 ContentCaptureSubscription::~ContentCaptureSubscription() { | 448 ContentCaptureSubscription::~ContentCaptureSubscription() { |
458 // If the BrowserThreads have been torn down, then the browser is in the final | 449 // If the BrowserThreads have been torn down, then the browser is in the final |
459 // stages of exiting and it is dangerous to take any further action. We must | 450 // stages of exiting and it is dangerous to take any further action. We must |
460 // return early. http://crbug.com/396413 | 451 // return early. http://crbug.com/396413 |
461 if (!BrowserThread::IsMessageLoopValid(BrowserThread::UI)) | 452 if (!BrowserThread::IsMessageLoopValid(BrowserThread::UI)) |
462 return; | 453 return; |
463 | 454 |
464 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 455 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
465 RenderWidgetHost* const source = | 456 // If the RWHV weak pointer is still valid, make sure the view is still |
466 RenderWidgetHost::FromID(render_process_id_, render_widget_id_); | 457 // associated with a RWH before attempting to end the frame subscription. This |
467 RenderWidgetHostView* const view = source ? source->GetView() : NULL; | 458 // is because a null RWH indicates the RWHV has had its Destroy() method |
468 if (view) | 459 // called, which makes it invalid to call any of its methods that assume the |
469 view->EndFrameSubscription(); | 460 // compositor is present. |
| 461 if (source_view_ && source_view_->GetRenderWidgetHost()) |
| 462 source_view_->EndFrameSubscription(); |
470 } | 463 } |
471 | 464 |
472 void ContentCaptureSubscription::MaybeCaptureForRefresh() { | 465 void ContentCaptureSubscription::MaybeCaptureForRefresh() { |
473 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 466 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
474 OnEvent(refresh_subscriber_.get()); | 467 OnEvent(refresh_subscriber_.get()); |
475 } | 468 } |
476 | 469 |
477 void ContentCaptureSubscription::OnEvent(FrameSubscriber* subscriber) { | 470 void ContentCaptureSubscription::OnEvent(FrameSubscriber* subscriber) { |
478 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 471 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
479 TRACE_EVENT0("gpu.capture", "ContentCaptureSubscription::OnEvent"); | 472 TRACE_EVENT0("gpu.capture", "ContentCaptureSubscription::OnEvent"); |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
634 base::Bind(&WebContentsCaptureMachine::InternalSuspend, | 627 base::Bind(&WebContentsCaptureMachine::InternalSuspend, |
635 base::Unretained(this))); | 628 base::Unretained(this))); |
636 } | 629 } |
637 | 630 |
638 void WebContentsCaptureMachine::InternalSuspend() { | 631 void WebContentsCaptureMachine::InternalSuspend() { |
639 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 632 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
640 if (!frame_capture_active_) | 633 if (!frame_capture_active_) |
641 return; | 634 return; |
642 frame_capture_active_ = false; | 635 frame_capture_active_ = false; |
643 if (IsStarted()) | 636 if (IsStarted()) |
644 RenewFrameSubscription(true); | 637 RenewFrameSubscription(tracker_->is_still_tracking()); |
645 } | 638 } |
646 | 639 |
647 void WebContentsCaptureMachine::Resume() { | 640 void WebContentsCaptureMachine::Resume() { |
648 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 641 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
649 base::Bind(&WebContentsCaptureMachine::InternalResume, | 642 base::Bind(&WebContentsCaptureMachine::InternalResume, |
650 base::Unretained(this))); | 643 base::Unretained(this))); |
651 } | 644 } |
652 | 645 |
653 void WebContentsCaptureMachine::InternalResume() { | 646 void WebContentsCaptureMachine::InternalResume() { |
654 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 647 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
655 if (frame_capture_active_) | 648 if (frame_capture_active_) |
656 return; | 649 return; |
657 frame_capture_active_ = true; | 650 frame_capture_active_ = true; |
658 if (IsStarted()) | 651 if (IsStarted()) |
659 RenewFrameSubscription(true); | 652 RenewFrameSubscription(tracker_->is_still_tracking()); |
660 } | 653 } |
661 | 654 |
662 void WebContentsCaptureMachine::Stop(const base::Closure& callback) { | 655 void WebContentsCaptureMachine::Stop(const base::Closure& callback) { |
663 // Stops the capture machine asynchronously. | 656 // Stops the capture machine asynchronously. |
664 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 657 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
665 base::Bind(&WebContentsCaptureMachine::InternalStop, | 658 base::Bind(&WebContentsCaptureMachine::InternalStop, |
666 base::Unretained(this), callback)); | 659 base::Unretained(this), callback)); |
667 } | 660 } |
668 | 661 |
669 void WebContentsCaptureMachine::InternalStop(const base::Closure& callback) { | 662 void WebContentsCaptureMachine::InternalStop(const base::Closure& callback) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
707 subscription_->MaybeCaptureForRefresh(); | 700 subscription_->MaybeCaptureForRefresh(); |
708 } | 701 } |
709 | 702 |
710 void WebContentsCaptureMachine::Capture( | 703 void WebContentsCaptureMachine::Capture( |
711 const base::TimeTicks& start_time, | 704 const base::TimeTicks& start_time, |
712 const scoped_refptr<media::VideoFrame>& target, | 705 const scoped_refptr<media::VideoFrame>& target, |
713 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback& | 706 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback& |
714 deliver_frame_cb) { | 707 deliver_frame_cb) { |
715 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 708 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
716 | 709 |
717 RenderWidgetHost* rwh = tracker_->GetTargetRenderWidgetHost(); | 710 auto* const view = |
718 RenderWidgetHostViewBase* view = | 711 static_cast<RenderWidgetHostViewBase*>(tracker_->GetTargetView()); |
719 rwh ? static_cast<RenderWidgetHostViewBase*>(rwh->GetView()) : NULL; | |
720 if (!view) { | 712 if (!view) { |
721 deliver_frame_cb.Run(base::TimeTicks(), gfx::Rect(), false); | 713 deliver_frame_cb.Run(base::TimeTicks(), gfx::Rect(), false); |
722 return; | 714 return; |
723 } | 715 } |
724 | 716 |
725 const gfx::Size view_size = view->GetViewBounds().size(); | 717 const gfx::Size view_size = view->GetViewBounds().size(); |
726 if (view->CanCopyToVideoFrame()) { | 718 if (view->CanCopyToVideoFrame()) { |
727 view->CopyFromCompositingSurfaceToVideoFrame( | 719 view->CopyFromCompositingSurfaceToVideoFrame( |
728 gfx::Rect(view_size), target, | 720 gfx::Rect(view_size), target, |
729 base::Bind(&WebContentsCaptureMachine:: | 721 base::Bind(&WebContentsCaptureMachine:: |
730 DidCopyFromCompositingSurfaceToVideoFrame, | 722 DidCopyFromCompositingSurfaceToVideoFrame, |
731 weak_ptr_factory_.GetWeakPtr(), start_time, | 723 weak_ptr_factory_.GetWeakPtr(), start_time, |
732 deliver_frame_cb)); | 724 deliver_frame_cb)); |
733 } else { | 725 } else { |
734 const gfx::Size fitted_size = | 726 const gfx::Size fitted_size = |
735 view_size.IsEmpty() | 727 view_size.IsEmpty() |
736 ? gfx::Size() | 728 ? gfx::Size() |
737 : media::ComputeLetterboxRegion(target->visible_rect(), view_size) | 729 : media::ComputeLetterboxRegion(target->visible_rect(), view_size) |
738 .size(); | 730 .size(); |
739 rwh->CopyFromBackingStore( | 731 if (auto* rwh = view->GetRenderWidgetHost()) { |
740 gfx::Rect(), | 732 rwh->CopyFromBackingStore( |
741 fitted_size, // Size here is a request not always honored. | 733 gfx::Rect(), |
742 base::Bind(&WebContentsCaptureMachine::DidCopyFromBackingStore, | 734 fitted_size, // Size here is a request not always honored. |
743 weak_ptr_factory_.GetWeakPtr(), start_time, target, | 735 base::Bind(&WebContentsCaptureMachine::DidCopyFromBackingStore, |
744 deliver_frame_cb), | 736 weak_ptr_factory_.GetWeakPtr(), start_time, target, |
745 kN32_SkColorType); | 737 deliver_frame_cb), |
| 738 kN32_SkColorType); |
| 739 } |
746 } | 740 } |
747 } | 741 } |
748 | 742 |
749 gfx::Size WebContentsCaptureMachine::ComputeOptimalViewSize() const { | 743 gfx::Size WebContentsCaptureMachine::ComputeOptimalViewSize() const { |
750 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 744 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
751 | 745 |
752 // TODO(miu): Propagate capture frame size changes as new "preferred size" | 746 // TODO(miu): Propagate capture frame size changes as new "preferred size" |
753 // updates, rather than just using the max frame size. | 747 // updates, rather than just using the max frame size. |
754 // http://crbug.com/350491 | 748 // http://crbug.com/350491 |
755 gfx::Size optimal_size = oracle_proxy_->max_frame_size(); | 749 gfx::Size optimal_size = oracle_proxy_->max_frame_size(); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
788 // Else, do not make an adjustment. | 782 // Else, do not make an adjustment. |
789 break; | 783 break; |
790 } | 784 } |
791 } | 785 } |
792 | 786 |
793 // If the ratio between physical and logical pixels is greater than 1:1, | 787 // If the ratio between physical and logical pixels is greater than 1:1, |
794 // shrink |optimal_size| by that amount. Then, when external code resizes the | 788 // shrink |optimal_size| by that amount. Then, when external code resizes the |
795 // render widget to the "preferred size," the widget will be physically | 789 // render widget to the "preferred size," the widget will be physically |
796 // rendered at the exact capture size, thereby eliminating unnecessary scaling | 790 // rendered at the exact capture size, thereby eliminating unnecessary scaling |
797 // operations in the graphics pipeline. | 791 // operations in the graphics pipeline. |
798 RenderWidgetHost* const rwh = tracker_->GetTargetRenderWidgetHost(); | 792 if (auto* rwhv = tracker_->GetTargetView()) { |
799 RenderWidgetHostView* const rwhv = rwh ? rwh->GetView() : NULL; | |
800 if (rwhv) { | |
801 const gfx::NativeView view = rwhv->GetNativeView(); | 793 const gfx::NativeView view = rwhv->GetNativeView(); |
802 const float scale = ui::GetScaleFactorForNativeView(view); | 794 const float scale = ui::GetScaleFactorForNativeView(view); |
803 if (scale > 1.0f) { | 795 if (scale > 1.0f) { |
804 const gfx::Size shrunk_size = | 796 const gfx::Size shrunk_size = |
805 gfx::ScaleToFlooredSize(optimal_size, 1.0f / scale); | 797 gfx::ScaleToFlooredSize(optimal_size, 1.0f / scale); |
806 if (shrunk_size.width() > 0 && shrunk_size.height() > 0) | 798 if (shrunk_size.width() > 0 && shrunk_size.height() > 0) |
807 optimal_size = shrunk_size; | 799 optimal_size = shrunk_size; |
808 } | 800 } |
809 } | 801 } |
810 | 802 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
842 deliver_frame_cb, | 834 deliver_frame_cb, |
843 const gfx::Rect& region_in_frame, | 835 const gfx::Rect& region_in_frame, |
844 bool success) { | 836 bool success) { |
845 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 837 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
846 | 838 |
847 // Capture can fail due to transient issues, so just skip this frame. | 839 // Capture can fail due to transient issues, so just skip this frame. |
848 DVLOG_IF(1, !success) << "CopyFromCompositingSurface failed; skipping frame."; | 840 DVLOG_IF(1, !success) << "CopyFromCompositingSurface failed; skipping frame."; |
849 deliver_frame_cb.Run(start_time, region_in_frame, success); | 841 deliver_frame_cb.Run(start_time, region_in_frame, success); |
850 } | 842 } |
851 | 843 |
852 void WebContentsCaptureMachine::RenewFrameSubscription(bool had_target) { | 844 void WebContentsCaptureMachine::RenewFrameSubscription(bool is_still_tracking) { |
853 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 845 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
854 | 846 |
855 RenderWidgetHost* const rwh = | |
856 had_target ? tracker_->GetTargetRenderWidgetHost() : nullptr; | |
857 | |
858 // Always destroy the old subscription before creating a new one. | 847 // Always destroy the old subscription before creating a new one. |
859 if (subscription_) { | 848 if (subscription_) { |
860 DVLOG(1) << "Cancelling existing ContentCaptureSubscription."; | 849 DVLOG(1) << "Cancelling existing subscription."; |
861 subscription_.reset(); | 850 subscription_.reset(); |
862 } | 851 } |
863 | 852 |
864 if (!rwh) { | 853 if (!is_still_tracking) { |
865 DVLOG(1) << "Cannot renew ContentCaptureSubscription: no RWH target."; | |
866 if (IsStarted()) { | 854 if (IsStarted()) { |
867 // Tracking of WebContents and/or its main frame has failed before Stop() | 855 // Tracking of WebContents and/or its main frame has failed before Stop() |
868 // was called, so report this as an error: | 856 // was called, so report this as an error: |
869 oracle_proxy_->ReportError(FROM_HERE, | 857 oracle_proxy_->ReportError(FROM_HERE, |
870 "WebContents and/or main frame are gone."); | 858 "WebContents and/or main frame are gone."); |
871 } | 859 } |
872 return; | 860 return; |
873 } | 861 } |
874 | 862 |
875 if (frame_capture_active_) { | 863 if (!frame_capture_active_) { |
876 DVLOG(1) << "Renewing ContentCaptureSubscription to RWH@" << rwh; | 864 DVLOG(1) << "Not renewing subscription: Frame capture is suspended."; |
877 subscription_.reset(new ContentCaptureSubscription( | 865 return; |
878 *rwh, oracle_proxy_, base::Bind(&WebContentsCaptureMachine::Capture, | |
879 weak_ptr_factory_.GetWeakPtr()))); | |
880 } | 866 } |
| 867 |
| 868 auto* const view = |
| 869 static_cast<RenderWidgetHostViewBase*>(tracker_->GetTargetView()); |
| 870 if (!view) { |
| 871 DVLOG(1) << "Cannot renew subscription: No view to capture."; |
| 872 return; |
| 873 } |
| 874 |
| 875 DVLOG(1) << "Renewing subscription to RenderWidgetHostView@" << view; |
| 876 subscription_.reset(new ContentCaptureSubscription( |
| 877 view->GetWeakPtr(), oracle_proxy_, |
| 878 base::Bind(&WebContentsCaptureMachine::Capture, |
| 879 weak_ptr_factory_.GetWeakPtr()))); |
881 } | 880 } |
882 | 881 |
883 void WebContentsCaptureMachine::UpdateCaptureSize() { | 882 void WebContentsCaptureMachine::UpdateCaptureSize() { |
884 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 883 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
885 | 884 |
886 if (!oracle_proxy_) | 885 if (!oracle_proxy_) |
887 return; | 886 return; |
888 RenderWidgetHost* const rwh = tracker_->GetTargetRenderWidgetHost(); | 887 RenderWidgetHostView* const view = tracker_->GetTargetView(); |
889 RenderWidgetHostView* const view = rwh ? rwh->GetView() : nullptr; | |
890 if (!view) | 888 if (!view) |
891 return; | 889 return; |
892 | 890 |
893 // Convert the view's size from the DIP coordinate space to the pixel | 891 // Convert the view's size from the DIP coordinate space to the pixel |
894 // coordinate space. When the view is being rendered on a high-DPI display, | 892 // coordinate space. When the view is being rendered on a high-DPI display, |
895 // this allows the high-resolution image detail to propagate through to the | 893 // this allows the high-resolution image detail to propagate through to the |
896 // captured video. | 894 // captured video. |
897 const gfx::Size view_size = view->GetViewBounds().size(); | 895 const gfx::Size view_size = view->GetViewBounds().size(); |
898 const gfx::Size physical_size = gfx::ConvertSizeToPixel( | 896 const gfx::Size physical_size = gfx::ConvertSizeToPixel( |
899 ui::GetScaleFactorForNativeView(view->GetNativeView()), view_size); | 897 ui::GetScaleFactorForNativeView(view->GetNativeView()), view_size); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
956 void WebContentsVideoCaptureDevice::StopAndDeAllocate() { | 954 void WebContentsVideoCaptureDevice::StopAndDeAllocate() { |
957 core_->StopAndDeAllocate(); | 955 core_->StopAndDeAllocate(); |
958 } | 956 } |
959 | 957 |
960 void WebContentsVideoCaptureDevice::OnUtilizationReport(int frame_feedback_id, | 958 void WebContentsVideoCaptureDevice::OnUtilizationReport(int frame_feedback_id, |
961 double utilization) { | 959 double utilization) { |
962 core_->OnConsumerReportingUtilization(frame_feedback_id, utilization); | 960 core_->OnConsumerReportingUtilization(frame_feedback_id, utilization); |
963 } | 961 } |
964 | 962 |
965 } // namespace content | 963 } // namespace content |
OLD | NEW |