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

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

Issue 12179007: While screencasting a tab, do not disable rendering updates while hidden. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Execute delayed WasHidden() when capturer_count_ goes to zero. Created 7 years, 10 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 | Annotate | Revision Log
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. Therefore, the process of capturing has been split up into a 7 // performance. Therefore, the process of capturing has been split up into a
8 // pipeline of three stages. Each stage executes on its own thread: 8 // pipeline of three stages. Each stage executes on its own thread:
9 // 9 //
10 // 1. Capture: A bitmap is snapshotted/copied from the RenderView's backing 10 // 1. Capture: A bitmap is snapshotted/copied from the RenderView's backing
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 OK, 144 OK,
145 TRANSIENT_ERROR, 145 TRANSIENT_ERROR,
146 NO_SOURCE, 146 NO_SOURCE,
147 }; 147 };
148 typedef base::Callback<void(Result result, 148 typedef base::Callback<void(Result result,
149 const SkBitmap& capture, 149 const SkBitmap& capture,
150 const base::Time& capture_time)> DoneCB; 150 const base::Time& capture_time)> DoneCB;
151 151
152 BackingStoreCopier(int render_process_id, int render_view_id); 152 BackingStoreCopier(int render_process_id, int render_view_id);
153 153
154 virtual ~BackingStoreCopier();
155
154 // If non-NULL, use the given |override| to access the backing store. 156 // If non-NULL, use the given |override| to access the backing store.
155 // This is used for unit testing. 157 // This is used for unit testing.
156 void SetRenderWidgetHostForTesting(RenderWidgetHost* override); 158 void SetRenderWidgetHostForTesting(RenderWidgetHost* override);
157 159
158 // Starts the copy from the backing store. Must be run on the UI 160 // Starts the copy from the backing store. Must be run on the UI
159 // BrowserThread. |done_cb| is invoked with result status. When successful 161 // BrowserThread. |done_cb| is invoked with result status. When successful
160 // (OK), the bitmap of the capture is transferred to the callback along with 162 // (OK), the bitmap of the capture is transferred to the callback along with
161 // the timestamp at which the capture was completed. 163 // the timestamp at which the capture was completed.
162 void StartCopy(int frame_number, int desired_width, int desired_height, 164 void StartCopy(int frame_number, int desired_width, int desired_height,
163 const DoneCB& done_cb); 165 const DoneCB& done_cb);
164 166
167 // Stops observing an existing WebContents instance, if any. This must be
168 // called before BackingStoreCopier is destroyed. Must be run on the UI
169 // BrowserThread.
170 void StopObservingWebContents();
171
165 virtual void DidShowFullscreenWidget(int routing_id) OVERRIDE { 172 virtual void DidShowFullscreenWidget(int routing_id) OVERRIDE {
166 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 173 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
167 fullscreen_widget_id_ = routing_id; 174 fullscreen_widget_id_ = routing_id;
168 } 175 }
169 176
170 virtual void DidDestroyFullscreenWidget(int routing_id) OVERRIDE { 177 virtual void DidDestroyFullscreenWidget(int routing_id) OVERRIDE {
171 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 178 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
172 DCHECK_EQ(fullscreen_widget_id_, routing_id); 179 DCHECK_EQ(fullscreen_widget_id_, routing_id);
173 fullscreen_widget_id_ = MSG_ROUTING_NONE; 180 fullscreen_widget_id_ = MSG_ROUTING_NONE;
174 } 181 }
175 182
176 private: 183 private:
184 virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE;
185
177 void LookUpAndObserveWebContents(); 186 void LookUpAndObserveWebContents();
178 187
179 void CopyFromBackingStoreComplete(int frame_number, 188 void CopyFromBackingStoreComplete(int frame_number,
180 const DoneCB& done_cb, 189 const DoneCB& done_cb,
181 bool success, 190 bool success,
182 const SkBitmap& result); 191 const SkBitmap& result);
183 192
184 // The "starting point" to find the capture source. 193 // The "starting point" to find the capture source.
185 const int render_process_id_; 194 const int render_process_id_;
186 const int render_view_id_; 195 const int render_view_id_;
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 int last_frame_number_; 292 int last_frame_number_;
284 293
285 DISALLOW_COPY_AND_ASSIGN(VideoFrameDeliverer); 294 DISALLOW_COPY_AND_ASSIGN(VideoFrameDeliverer);
286 }; 295 };
287 296
288 BackingStoreCopier::BackingStoreCopier(int render_process_id, 297 BackingStoreCopier::BackingStoreCopier(int render_process_id,
289 int render_view_id) 298 int render_view_id)
290 : render_process_id_(render_process_id), render_view_id_(render_view_id), 299 : render_process_id_(render_process_id), render_view_id_(render_view_id),
291 fullscreen_widget_id_(MSG_ROUTING_NONE), rwh_for_testing_(NULL) {} 300 fullscreen_widget_id_(MSG_ROUTING_NONE), rwh_for_testing_(NULL) {}
292 301
302 BackingStoreCopier::~BackingStoreCopier() {
303 DCHECK(!web_contents());
304 }
305
306 void BackingStoreCopier::StopObservingWebContents() {
307 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
308
309 if (web_contents()) {
310 web_contents()->DecrementCapturerCount();
311 Observe(NULL);
312 }
313 }
314
315 void BackingStoreCopier::WebContentsDestroyed(WebContents* web_contents) {
316 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
317
318 web_contents->DecrementCapturerCount();
319 }
320
293 void BackingStoreCopier::LookUpAndObserveWebContents() { 321 void BackingStoreCopier::LookUpAndObserveWebContents() {
294 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 322 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
295 323
296 // Look-up the RenderViewHost and, from that, the WebContents that wraps it. 324 // Look-up the RenderViewHost and, from that, the WebContents that wraps it.
297 // If successful, begin observing the WebContents instance. If unsuccessful, 325 // If successful, begin observing the WebContents instance. If unsuccessful,
298 // stop observing and post an error. 326 // stop observing and post an error.
299 // 327 //
300 // Why this can be unsuccessful: The request for mirroring originates in a 328 // Why this can be unsuccessful: The request for mirroring originates in a
301 // render process, and this request is based on the current RenderView 329 // render process, and this request is based on the current RenderView
302 // associated with a tab. However, by the time we get up-and-running here, 330 // associated with a tab. However, by the time we get up-and-running here,
303 // there have been multiple back-and-forth IPCs between processes, as well as 331 // there have been multiple back-and-forth IPCs between processes, as well as
304 // a bit of indirection across threads. It's easily possible that, in the 332 // a bit of indirection across threads. It's easily possible that, in the
305 // meantime, the original RenderView may have gone away. 333 // meantime, the original RenderView may have gone away.
306 RenderViewHost* const rvh = 334 RenderViewHost* const rvh =
307 RenderViewHost::FromID(render_process_id_, render_view_id_); 335 RenderViewHost::FromID(render_process_id_, render_view_id_);
308 DVLOG_IF(1, !rvh) << "RenderViewHost::FromID(" 336 DVLOG_IF(1, !rvh) << "RenderViewHost::FromID("
309 << render_process_id_ << ", " << render_view_id_ 337 << render_process_id_ << ", " << render_view_id_
310 << ") returned NULL."; 338 << ") returned NULL.";
311 Observe(rvh ? WebContents::FromRenderViewHost(rvh) : NULL); 339 Observe(rvh ? WebContents::FromRenderViewHost(rvh) : NULL);
312 DVLOG_IF(1, !web_contents()) 340 if (web_contents())
313 << "WebContents::FromRenderViewHost(" << rvh << ") returned NULL."; 341 web_contents()->IncrementCapturerCount();
342 else
343 DVLOG(1) << "WebContents::FromRenderViewHost(" << rvh << ") returned NULL.";
314 344
315 if (fullscreen_widget_id_ == MSG_ROUTING_NONE && web_contents()) { 345 if (fullscreen_widget_id_ == MSG_ROUTING_NONE && web_contents()) {
316 fullscreen_widget_id_ = static_cast<WebContentsImpl*>(web_contents())-> 346 fullscreen_widget_id_ = static_cast<WebContentsImpl*>(web_contents())->
317 GetFullscreenWidgetRoutingID(); 347 GetFullscreenWidgetRoutingID();
318 } 348 }
319 } 349 }
320 350
321 void BackingStoreCopier::SetRenderWidgetHostForTesting( 351 void BackingStoreCopier::SetRenderWidgetHostForTesting(
322 RenderWidgetHost* override) { 352 RenderWidgetHost* override) {
323 rwh_for_testing_ = override; 353 rwh_for_testing_ = override;
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after
707 void SnapshotComplete(int frame_number, 737 void SnapshotComplete(int frame_number,
708 const base::Time& start_time, 738 const base::Time& start_time,
709 BackingStoreCopier::Result result, 739 BackingStoreCopier::Result result,
710 const SkBitmap& capture, 740 const SkBitmap& capture,
711 const base::Time& capture_time); 741 const base::Time& capture_time);
712 void RenderComplete(int frame_number, 742 void RenderComplete(int frame_number,
713 const base::Time& capture_time, 743 const base::Time& capture_time,
714 const SkBitmap* frame_buffer); 744 const SkBitmap* frame_buffer);
715 void DeliverComplete(const SkBitmap* frame_buffer); 745 void DeliverComplete(const SkBitmap* frame_buffer);
716 746
747 void DoShutdownTasksOnUIThread();
748
717 // Specialized RefCounted traits for CaptureMachine, so that operator delete 749 // Specialized RefCounted traits for CaptureMachine, so that operator delete
718 // is called from an "outside" thread. See comments for "traits" in 750 // is called from an "outside" thread. See comments for "traits" in
719 // base/memory/ref_counted.h. 751 // base/memory/ref_counted.h.
720 static void Destruct(const CaptureMachine* x); 752 static void Destruct(const CaptureMachine* x);
721 static void DeleteFromOutsideThread(const CaptureMachine* x); 753 static void DeleteFromOutsideThread(const CaptureMachine* x);
722 754
723 SynchronizedConsumer consumer_; // Recipient of frames. 755 SynchronizedConsumer consumer_; // Recipient of frames.
724 756
725 // Used to ensure state machine transitions occur synchronously, and that 757 // Used to ensure state machine transitions occur synchronously, and that
726 // capturing executes at regular intervals. 758 // capturing executes at regular intervals.
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
833 } 865 }
834 866
835 void CaptureMachine::DeAllocate() { 867 void CaptureMachine::DeAllocate() {
836 ENSURE_INVOKED_ON_THREAD(manager_thread_, 868 ENSURE_INVOKED_ON_THREAD(manager_thread_,
837 &CaptureMachine::DeAllocate, this); 869 &CaptureMachine::DeAllocate, this);
838 870
839 if (state_ == kCapturing) { 871 if (state_ == kCapturing) {
840 Stop(); 872 Stop();
841 } 873 }
842 if (state_ == kAllocated) { 874 if (state_ == kAllocated) {
875 BrowserThread::PostTask(
876 BrowserThread::UI, FROM_HERE,
877 base::Bind(&CaptureMachine::DoShutdownTasksOnUIThread, this));
878
843 TransitionStateTo(kIdle); 879 TransitionStateTo(kIdle);
844 } 880 }
845 } 881 }
846 882
847 CaptureMachine::~CaptureMachine() { 883 CaptureMachine::~CaptureMachine() {
848 DVLOG(1) << "CaptureMachine@" << this << " destroying."; 884 DVLOG(1) << "CaptureMachine@" << this << " destroying.";
849 state_ = kDestroyed; 885 state_ = kDestroyed;
850 // Note: Implicit destructors will be called after this, which will block the 886 // Note: Implicit destructors will be called after this, which will block the
851 // current thread while joining on the other threads. However, this should be 887 // current thread while joining on the other threads. However, this should be
852 // instantaneous since the other threads' task queues *must* be empty at this 888 // instantaneous since the other threads' task queues *must* be empty at this
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
1012 DCHECK(frame_buffer); 1048 DCHECK(frame_buffer);
1013 deliverer_.Deliver( 1049 deliverer_.Deliver(
1014 frame_number, *frame_buffer, capture_time, 1050 frame_number, *frame_buffer, capture_time,
1015 base::Bind(&CaptureMachine::DeliverComplete, this, frame_buffer)); 1051 base::Bind(&CaptureMachine::DeliverComplete, this, frame_buffer));
1016 } 1052 }
1017 1053
1018 void CaptureMachine::DeliverComplete(const SkBitmap* frame_buffer) { 1054 void CaptureMachine::DeliverComplete(const SkBitmap* frame_buffer) {
1019 renderer_.Release(frame_buffer); 1055 renderer_.Release(frame_buffer);
1020 } 1056 }
1021 1057
1058 void CaptureMachine::DoShutdownTasksOnUIThread() {
1059 copier_.StopObservingWebContents();
1060 }
1061
1022 WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice( 1062 WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice(
1023 const media::VideoCaptureDevice::Name& name, 1063 const media::VideoCaptureDevice::Name& name,
1024 int render_process_id, int render_view_id) 1064 int render_process_id, int render_view_id)
1025 : device_name_(name), 1065 : device_name_(name),
1026 capturer_(new CaptureMachine(render_process_id, render_view_id)) {} 1066 capturer_(new CaptureMachine(render_process_id, render_view_id)) {}
1027 1067
1028 WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice( 1068 WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice(
1029 RenderWidgetHost* test_source, const base::Closure& destroy_cb) 1069 RenderWidgetHost* test_source, const base::Closure& destroy_cb)
1030 : capturer_(new CaptureMachine(-1, -1)) { 1070 : capturer_(new CaptureMachine(-1, -1)) {
1031 device_name_.device_name = "WebContentsForTesting"; 1071 device_name_.device_name = "WebContentsForTesting";
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1087 capturer_->SetConsumer(NULL); 1127 capturer_->SetConsumer(NULL);
1088 capturer_->DeAllocate(); 1128 capturer_->DeAllocate();
1089 } 1129 }
1090 1130
1091 const media::VideoCaptureDevice::Name& 1131 const media::VideoCaptureDevice::Name&
1092 WebContentsVideoCaptureDevice::device_name() { 1132 WebContentsVideoCaptureDevice::device_name() {
1093 return device_name_; 1133 return device_name_;
1094 } 1134 }
1095 1135
1096 } // namespace content 1136 } // namespace content
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/tabs/tab_drag_controller.cc ('k') | content/browser/web_contents/web_contents_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698