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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 | 54 |
55 #include <algorithm> | 55 #include <algorithm> |
56 #include <memory> | 56 #include <memory> |
57 #include <utility> | 57 #include <utility> |
58 | 58 |
59 #include "base/bind.h" | 59 #include "base/bind.h" |
60 #include "base/callback_helpers.h" | 60 #include "base/callback_helpers.h" |
61 #include "base/location.h" | 61 #include "base/location.h" |
62 #include "base/logging.h" | 62 #include "base/logging.h" |
63 #include "base/macros.h" | 63 #include "base/macros.h" |
| 64 #include "base/memory/ptr_util.h" |
64 #include "base/memory/weak_ptr.h" | 65 #include "base/memory/weak_ptr.h" |
65 #include "base/metrics/histogram_macros.h" | 66 #include "base/metrics/histogram_macros.h" |
66 #include "base/sequenced_task_runner.h" | 67 #include "base/sequenced_task_runner.h" |
67 #include "base/single_thread_task_runner.h" | 68 #include "base/single_thread_task_runner.h" |
68 #include "base/threading/thread.h" | 69 #include "base/threading/thread.h" |
69 #include "base/threading/thread_checker.h" | 70 #include "base/threading/thread_checker.h" |
70 #include "base/time/time.h" | 71 #include "base/time/time.h" |
71 #include "build/build_config.h" | 72 #include "build/build_config.h" |
72 #include "content/browser/media/capture/cursor_renderer.h" | 73 #include "content/browser/media/capture/cursor_renderer.h" |
73 #include "content/browser/media/capture/web_contents_tracker.h" | 74 #include "content/browser/media/capture/web_contents_tracker.h" |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 public: | 258 public: |
258 WebContentsCaptureMachine(int render_process_id, | 259 WebContentsCaptureMachine(int render_process_id, |
259 int main_render_frame_id, | 260 int main_render_frame_id, |
260 bool enable_auto_throttling); | 261 bool enable_auto_throttling); |
261 ~WebContentsCaptureMachine() override; | 262 ~WebContentsCaptureMachine() override; |
262 | 263 |
263 // VideoCaptureMachine overrides. | 264 // VideoCaptureMachine overrides. |
264 void Start(const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy, | 265 void Start(const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy, |
265 const media::VideoCaptureParams& params, | 266 const media::VideoCaptureParams& params, |
266 const base::Callback<void(bool)> callback) override; | 267 const base::Callback<void(bool)> callback) override; |
| 268 void Suspend() override; |
| 269 void Resume() override; |
267 void Stop(const base::Closure& callback) override; | 270 void Stop(const base::Closure& callback) override; |
268 bool IsAutoThrottlingEnabled() const override { | 271 bool IsAutoThrottlingEnabled() const override { |
269 return auto_throttling_enabled_; | 272 return auto_throttling_enabled_; |
270 } | 273 } |
271 void MaybeCaptureForRefresh() override; | 274 void MaybeCaptureForRefresh() override; |
272 | 275 |
273 // Starts a copy from the backing store or the composited surface. Must be run | 276 // Starts a copy from the backing store or the composited surface. Must be run |
274 // on the UI BrowserThread. |deliver_frame_cb| will be run when the operation | 277 // on the UI BrowserThread. |deliver_frame_cb| will be run when the operation |
275 // completes. The copy will occur to |target|. | 278 // completes. The copy will occur to |target|. |
276 // | 279 // |
277 // This may be used as a ContentCaptureSubscription::CaptureCallback. | 280 // This may be used as a ContentCaptureSubscription::CaptureCallback. |
278 void Capture(const base::TimeTicks& start_time, | 281 void Capture(const base::TimeTicks& start_time, |
279 const scoped_refptr<media::VideoFrame>& target, | 282 const scoped_refptr<media::VideoFrame>& target, |
280 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback& | 283 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback& |
281 deliver_frame_cb); | 284 deliver_frame_cb); |
282 | 285 |
283 private: | 286 private: |
284 bool InternalStart( | 287 bool InternalStart( |
285 const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy, | 288 const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy, |
286 const media::VideoCaptureParams& params); | 289 const media::VideoCaptureParams& params); |
| 290 void InternalSuspend(); |
| 291 void InternalResume(); |
287 void InternalStop(const base::Closure& callback); | 292 void InternalStop(const base::Closure& callback); |
288 void InternalMaybeCaptureForRefresh(); | 293 void InternalMaybeCaptureForRefresh(); |
289 bool IsStarted() const; | 294 bool IsStarted() const; |
290 | 295 |
291 // Computes the preferred size of the target RenderWidget for optimal capture. | 296 // Computes the preferred size of the target RenderWidget for optimal capture. |
292 gfx::Size ComputeOptimalViewSize() const; | 297 gfx::Size ComputeOptimalViewSize() const; |
293 | 298 |
294 // Response callback for RenderWidgetHost::CopyFromBackingStore(). | 299 // Response callback for RenderWidgetHost::CopyFromBackingStore(). |
295 void DidCopyFromBackingStore( | 300 void DidCopyFromBackingStore( |
296 const base::TimeTicks& start_time, | 301 const base::TimeTicks& start_time, |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
338 // Video capture parameters that this machine is started with. | 343 // Video capture parameters that this machine is started with. |
339 media::VideoCaptureParams capture_params_; | 344 media::VideoCaptureParams capture_params_; |
340 | 345 |
341 // Last known RenderView size. | 346 // Last known RenderView size. |
342 gfx::Size last_view_size_; | 347 gfx::Size last_view_size_; |
343 | 348 |
344 // Responsible for forwarding events from the active RenderWidgetHost to the | 349 // Responsible for forwarding events from the active RenderWidgetHost to the |
345 // oracle, and initiating captures accordingly. | 350 // oracle, and initiating captures accordingly. |
346 std::unique_ptr<ContentCaptureSubscription> subscription_; | 351 std::unique_ptr<ContentCaptureSubscription> subscription_; |
347 | 352 |
| 353 // False while frame capture has been suspended. This prevents subscriptions |
| 354 // from being created by RenewFrameSubscription() until frame capture is |
| 355 // resumed. |
| 356 bool frame_capture_active_; |
| 357 |
348 // Weak pointer factory used to invalidate callbacks. | 358 // Weak pointer factory used to invalidate callbacks. |
349 // NOTE: Weak pointers must be invalidated before all other member variables. | 359 // NOTE: Weak pointers must be invalidated before all other member variables. |
350 base::WeakPtrFactory<WebContentsCaptureMachine> weak_ptr_factory_; | 360 base::WeakPtrFactory<WebContentsCaptureMachine> weak_ptr_factory_; |
351 | 361 |
352 DISALLOW_COPY_AND_ASSIGN(WebContentsCaptureMachine); | 362 DISALLOW_COPY_AND_ASSIGN(WebContentsCaptureMachine); |
353 }; | 363 }; |
354 | 364 |
355 bool FrameSubscriber::ShouldCaptureFrame( | 365 bool FrameSubscriber::ShouldCaptureFrame( |
356 const gfx::Rect& damage_rect, | 366 const gfx::Rect& damage_rect, |
357 base::TimeTicks present_time, | 367 base::TimeTicks present_time, |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 } | 621 } |
612 | 622 |
613 WebContentsCaptureMachine::WebContentsCaptureMachine( | 623 WebContentsCaptureMachine::WebContentsCaptureMachine( |
614 int render_process_id, | 624 int render_process_id, |
615 int main_render_frame_id, | 625 int main_render_frame_id, |
616 bool enable_auto_throttling) | 626 bool enable_auto_throttling) |
617 : initial_render_process_id_(render_process_id), | 627 : initial_render_process_id_(render_process_id), |
618 initial_main_render_frame_id_(main_render_frame_id), | 628 initial_main_render_frame_id_(main_render_frame_id), |
619 tracker_(new WebContentsTracker(true)), | 629 tracker_(new WebContentsTracker(true)), |
620 auto_throttling_enabled_(enable_auto_throttling), | 630 auto_throttling_enabled_(enable_auto_throttling), |
| 631 frame_capture_active_(true), |
621 weak_ptr_factory_(this) { | 632 weak_ptr_factory_(this) { |
622 DVLOG(1) << "Created WebContentsCaptureMachine for " << render_process_id | 633 DVLOG(1) << "Created WebContentsCaptureMachine for " << render_process_id |
623 << ':' << main_render_frame_id | 634 << ':' << main_render_frame_id |
624 << (auto_throttling_enabled_ ? " with auto-throttling enabled" : ""); | 635 << (auto_throttling_enabled_ ? " with auto-throttling enabled" : ""); |
625 } | 636 } |
626 | 637 |
627 WebContentsCaptureMachine::~WebContentsCaptureMachine() {} | 638 WebContentsCaptureMachine::~WebContentsCaptureMachine() {} |
628 | 639 |
629 bool WebContentsCaptureMachine::IsStarted() const { | 640 bool WebContentsCaptureMachine::IsStarted() const { |
630 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 641 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
(...skipping 30 matching lines...) Expand all Loading... |
661 } | 672 } |
662 | 673 |
663 // Note: Creation of the first WeakPtr in the following statement will cause | 674 // Note: Creation of the first WeakPtr in the following statement will cause |
664 // IsStarted() to return true from now on. | 675 // IsStarted() to return true from now on. |
665 tracker_->SetResizeChangeCallback( | 676 tracker_->SetResizeChangeCallback( |
666 base::Bind(&WebContentsCaptureMachine::UpdateCaptureSize, | 677 base::Bind(&WebContentsCaptureMachine::UpdateCaptureSize, |
667 weak_ptr_factory_.GetWeakPtr())); | 678 weak_ptr_factory_.GetWeakPtr())); |
668 tracker_->Start(initial_render_process_id_, initial_main_render_frame_id_, | 679 tracker_->Start(initial_render_process_id_, initial_main_render_frame_id_, |
669 base::Bind(&WebContentsCaptureMachine::RenewFrameSubscription, | 680 base::Bind(&WebContentsCaptureMachine::RenewFrameSubscription, |
670 weak_ptr_factory_.GetWeakPtr())); | 681 weak_ptr_factory_.GetWeakPtr())); |
| 682 if (WebContents* contents = tracker_->web_contents()) |
| 683 contents->IncrementCapturerCount(ComputeOptimalViewSize()); |
671 | 684 |
672 return true; | 685 return true; |
673 } | 686 } |
674 | 687 |
| 688 void WebContentsCaptureMachine::Suspend() { |
| 689 BrowserThread::PostTask( |
| 690 BrowserThread::UI, FROM_HERE, |
| 691 base::Bind(&WebContentsCaptureMachine::InternalSuspend, |
| 692 base::Unretained(this))); |
| 693 } |
| 694 |
| 695 void WebContentsCaptureMachine::InternalSuspend() { |
| 696 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 697 if (!frame_capture_active_) |
| 698 return; |
| 699 frame_capture_active_ = false; |
| 700 if (IsStarted()) |
| 701 RenewFrameSubscription(true); |
| 702 } |
| 703 |
| 704 void WebContentsCaptureMachine::Resume() { |
| 705 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 706 base::Bind(&WebContentsCaptureMachine::InternalResume, |
| 707 base::Unretained(this))); |
| 708 } |
| 709 |
| 710 void WebContentsCaptureMachine::InternalResume() { |
| 711 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 712 if (frame_capture_active_) |
| 713 return; |
| 714 frame_capture_active_ = true; |
| 715 if (IsStarted()) |
| 716 RenewFrameSubscription(true); |
| 717 } |
| 718 |
675 void WebContentsCaptureMachine::Stop(const base::Closure& callback) { | 719 void WebContentsCaptureMachine::Stop(const base::Closure& callback) { |
676 // Stops the capture machine asynchronously. | 720 // Stops the capture machine asynchronously. |
677 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 721 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
678 base::Bind(&WebContentsCaptureMachine::InternalStop, | 722 base::Bind(&WebContentsCaptureMachine::InternalStop, |
679 base::Unretained(this), callback)); | 723 base::Unretained(this), callback)); |
680 } | 724 } |
681 | 725 |
682 void WebContentsCaptureMachine::InternalStop(const base::Closure& callback) { | 726 void WebContentsCaptureMachine::InternalStop(const base::Closure& callback) { |
683 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 727 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
684 | 728 |
685 if (!IsStarted()) { | 729 if (!IsStarted()) { |
686 callback.Run(); | 730 callback.Run(); |
687 return; | 731 return; |
688 } | 732 } |
689 | 733 |
690 // The following cancels any outstanding callbacks and causes IsStarted() to | 734 // The following cancels any outstanding callbacks and causes IsStarted() to |
691 // return false from here onward. | 735 // return false from here onward. |
692 weak_ptr_factory_.InvalidateWeakPtrs(); | 736 weak_ptr_factory_.InvalidateWeakPtrs(); |
693 | 737 |
694 // Note: RenewFrameSubscription() must be called before stopping |tracker_| so | |
695 // the web_contents() can be notified that the capturing is ending. | |
696 RenewFrameSubscription(false); | 738 RenewFrameSubscription(false); |
| 739 if (WebContents* contents = tracker_->web_contents()) |
| 740 contents->DecrementCapturerCount(); |
697 tracker_->Stop(); | 741 tracker_->Stop(); |
698 | 742 |
699 // The render thread cannot be stopped on the UI thread, so post a message | 743 // The render thread cannot be stopped on the UI thread, so post a message |
700 // to the thread pool used for blocking operations. | 744 // to the thread pool used for blocking operations. |
701 if (render_thread_) { | 745 if (render_thread_) { |
702 BrowserThread::PostBlockingPoolTask( | 746 BrowserThread::PostBlockingPoolTask( |
703 FROM_HERE, base::Bind(&DeleteOnWorkerThread, | 747 FROM_HERE, base::Bind(&DeleteOnWorkerThread, |
704 base::Passed(&render_thread_), callback)); | 748 base::Passed(&render_thread_), callback)); |
705 } | 749 } |
706 } | 750 } |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
877 deliver_frame_cb.Run(start_time, region_in_frame, success); | 921 deliver_frame_cb.Run(start_time, region_in_frame, success); |
878 } | 922 } |
879 | 923 |
880 void WebContentsCaptureMachine::RenewFrameSubscription(bool had_target) { | 924 void WebContentsCaptureMachine::RenewFrameSubscription(bool had_target) { |
881 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 925 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
882 | 926 |
883 RenderWidgetHost* const rwh = | 927 RenderWidgetHost* const rwh = |
884 had_target ? tracker_->GetTargetRenderWidgetHost() : nullptr; | 928 had_target ? tracker_->GetTargetRenderWidgetHost() : nullptr; |
885 | 929 |
886 // Always destroy the old subscription before creating a new one. | 930 // Always destroy the old subscription before creating a new one. |
887 const bool had_subscription = !!subscription_; | 931 if (subscription_) { |
888 subscription_.reset(); | 932 DVLOG(1) << "Cancelling existing ContentCaptureSubscription."; |
889 | 933 subscription_.reset(); |
890 DVLOG(1) << "Renewing frame subscription to RWH@" << rwh | 934 } |
891 << ", had_subscription=" << had_subscription; | |
892 | 935 |
893 if (!rwh) { | 936 if (!rwh) { |
894 if (had_subscription && tracker_->web_contents()) | 937 DVLOG(1) << "Cannot renew ContentCaptureSubscription: no RWH target."; |
895 tracker_->web_contents()->DecrementCapturerCount(); | |
896 if (IsStarted()) { | 938 if (IsStarted()) { |
897 // Tracking of WebContents and/or its main frame has failed before Stop() | 939 // Tracking of WebContents and/or its main frame has failed before Stop() |
898 // was called, so report this as an error: | 940 // was called, so report this as an error: |
899 oracle_proxy_->ReportError(FROM_HERE, | 941 oracle_proxy_->ReportError(FROM_HERE, |
900 "WebContents and/or main frame are gone."); | 942 "WebContents and/or main frame are gone."); |
901 } | 943 } |
902 return; | 944 return; |
903 } | 945 } |
904 | 946 |
905 if (!had_subscription && tracker_->web_contents()) | 947 if (frame_capture_active_) { |
906 tracker_->web_contents()->IncrementCapturerCount(ComputeOptimalViewSize()); | 948 DVLOG(1) << "Renewing ContentCaptureSubscription to RWH@" << rwh; |
907 | 949 subscription_.reset(new ContentCaptureSubscription( |
908 subscription_.reset(new ContentCaptureSubscription( | 950 *rwh, oracle_proxy_, base::Bind(&WebContentsCaptureMachine::Capture, |
909 *rwh, oracle_proxy_, base::Bind(&WebContentsCaptureMachine::Capture, | 951 weak_ptr_factory_.GetWeakPtr()))); |
910 weak_ptr_factory_.GetWeakPtr()))); | 952 } |
911 } | 953 } |
912 | 954 |
913 void WebContentsCaptureMachine::UpdateCaptureSize() { | 955 void WebContentsCaptureMachine::UpdateCaptureSize() { |
914 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 956 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
915 | 957 |
916 if (!oracle_proxy_) | 958 if (!oracle_proxy_) |
917 return; | 959 return; |
918 RenderWidgetHost* const rwh = tracker_->GetTargetRenderWidgetHost(); | 960 RenderWidgetHost* const rwh = tracker_->GetTargetRenderWidgetHost(); |
919 RenderWidgetHostView* const view = rwh ? rwh->GetView() : nullptr; | 961 RenderWidgetHostView* const view = rwh ? rwh->GetView() : nullptr; |
920 if (!view) | 962 if (!view) |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
969 const media::VideoCaptureParams& params, | 1011 const media::VideoCaptureParams& params, |
970 std::unique_ptr<Client> client) { | 1012 std::unique_ptr<Client> client) { |
971 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString(); | 1013 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString(); |
972 core_->AllocateAndStart(params, std::move(client)); | 1014 core_->AllocateAndStart(params, std::move(client)); |
973 } | 1015 } |
974 | 1016 |
975 void WebContentsVideoCaptureDevice::RequestRefreshFrame() { | 1017 void WebContentsVideoCaptureDevice::RequestRefreshFrame() { |
976 core_->RequestRefreshFrame(); | 1018 core_->RequestRefreshFrame(); |
977 } | 1019 } |
978 | 1020 |
| 1021 void WebContentsVideoCaptureDevice::MaybeSuspend() { |
| 1022 core_->Suspend(); |
| 1023 } |
| 1024 |
| 1025 void WebContentsVideoCaptureDevice::Resume() { |
| 1026 core_->Resume(); |
| 1027 } |
| 1028 |
979 void WebContentsVideoCaptureDevice::StopAndDeAllocate() { | 1029 void WebContentsVideoCaptureDevice::StopAndDeAllocate() { |
980 core_->StopAndDeAllocate(); | 1030 core_->StopAndDeAllocate(); |
981 } | 1031 } |
982 | 1032 |
983 } // namespace content | 1033 } // namespace content |
OLD | NEW |