Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(699)

Side by Side Diff: content/browser/media/capture/web_contents_video_capture_device.cc

Issue 2602923002: Tab capture: Tracking continues after renderer crash. (Closed)
Patch Set: nits Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/browser/media/capture/web_contents_tracker.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « content/browser/media/capture/web_contents_tracker.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698