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 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 | 87 |
88 // Compute a letterbox region, aligned to even coordinates. | 88 // Compute a letterbox region, aligned to even coordinates. |
89 gfx::Rect ComputeYV12LetterboxRegion(const gfx::Size& frame_size, | 89 gfx::Rect ComputeYV12LetterboxRegion(const gfx::Size& frame_size, |
90 const gfx::Size& content_size) { | 90 const gfx::Size& content_size) { |
91 | 91 |
92 gfx::Rect result = media::ComputeLetterboxRegion(gfx::Rect(frame_size), | 92 gfx::Rect result = media::ComputeLetterboxRegion(gfx::Rect(frame_size), |
93 content_size); | 93 content_size); |
94 | 94 |
95 result.set_x(MakeEven(result.x())); | 95 result.set_x(MakeEven(result.x())); |
96 result.set_y(MakeEven(result.y())); | 96 result.set_y(MakeEven(result.y())); |
97 result.set_width(std::max(kMinFrameWidth, MakeEven(result.width()))); | |
98 result.set_height(std::max(kMinFrameHeight, MakeEven(result.height()))); | |
99 | 97 |
100 return result; | 98 return result; |
101 } | 99 } |
102 | 100 |
103 // Wrapper function to invoke ThreadSafeCaptureOracle::CaptureFrameCallback, is | |
104 // compatible with RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback. | |
105 void InvokeCaptureFrameCallback( | |
106 const ThreadSafeCaptureOracle::CaptureFrameCallback& capture_frame_cb, | |
107 base::TimeTicks timestamp, | |
108 bool frame_captured) { | |
109 capture_frame_cb.Run(timestamp, frame_captured); | |
110 } | |
111 | |
112 void DeleteOnWorkerThread(scoped_ptr<base::Thread> render_thread, | 101 void DeleteOnWorkerThread(scoped_ptr<base::Thread> render_thread, |
113 const base::Closure& callback) { | 102 const base::Closure& callback) { |
114 render_thread.reset(); | 103 render_thread.reset(); |
115 | 104 |
116 // After thread join call the callback on UI thread. | 105 // After thread join call the callback on UI thread. |
117 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); | 106 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); |
118 } | 107 } |
119 | 108 |
120 // FrameSubscriber is a proxy to the ThreadSafeCaptureOracle that's compatible | 109 // FrameSubscriber is a proxy to the ThreadSafeCaptureOracle that's compatible |
121 // with RenderWidgetHostViewFrameSubscriber. We create one per event type. | 110 // with RenderWidgetHostViewFrameSubscriber. We create one per event type. |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 // notification would get posted back to the UI thread and processed later, and | 199 // notification would get posted back to the UI thread and processed later, and |
211 // this seems disadvantageous. | 200 // this seems disadvantageous. |
212 class WebContentsCaptureMachine | 201 class WebContentsCaptureMachine |
213 : public VideoCaptureMachine, | 202 : public VideoCaptureMachine, |
214 public WebContentsObserver { | 203 public WebContentsObserver { |
215 public: | 204 public: |
216 WebContentsCaptureMachine(int render_process_id, int render_view_id); | 205 WebContentsCaptureMachine(int render_process_id, int render_view_id); |
217 virtual ~WebContentsCaptureMachine(); | 206 virtual ~WebContentsCaptureMachine(); |
218 | 207 |
219 // VideoCaptureMachine overrides. | 208 // VideoCaptureMachine overrides. |
220 virtual bool Start( | 209 virtual bool Start(const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy, |
221 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy) OVERRIDE; | 210 const media::VideoCaptureParams& params) OVERRIDE; |
222 virtual void Stop(const base::Closure& callback) OVERRIDE; | 211 virtual void Stop(const base::Closure& callback) OVERRIDE; |
223 | 212 |
224 // Starts a copy from the backing store or the composited surface. Must be run | 213 // Starts a copy from the backing store or the composited surface. Must be run |
225 // on the UI BrowserThread. |deliver_frame_cb| will be run when the operation | 214 // on the UI BrowserThread. |deliver_frame_cb| will be run when the operation |
226 // completes. The copy will occur to |target|. | 215 // completes. The copy will occur to |target|. |
227 // | 216 // |
228 // This may be used as a ContentCaptureSubscription::CaptureCallback. | 217 // This may be used as a ContentCaptureSubscription::CaptureCallback. |
229 void Capture(const base::TimeTicks& start_time, | 218 void Capture(const base::TimeTicks& start_time, |
230 const scoped_refptr<media::VideoFrame>& target, | 219 const scoped_refptr<media::VideoFrame>& target, |
231 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback& | 220 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback& |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 const int initial_render_process_id_; | 280 const int initial_render_process_id_; |
292 const int initial_render_view_id_; | 281 const int initial_render_view_id_; |
293 | 282 |
294 // A dedicated worker thread on which SkBitmap->VideoFrame conversion will | 283 // A dedicated worker thread on which SkBitmap->VideoFrame conversion will |
295 // occur. Only used when this activity cannot be done on the GPU. | 284 // occur. Only used when this activity cannot be done on the GPU. |
296 scoped_ptr<base::Thread> render_thread_; | 285 scoped_ptr<base::Thread> render_thread_; |
297 | 286 |
298 // Makes all the decisions about which frames to copy, and how. | 287 // Makes all the decisions about which frames to copy, and how. |
299 scoped_refptr<ThreadSafeCaptureOracle> oracle_proxy_; | 288 scoped_refptr<ThreadSafeCaptureOracle> oracle_proxy_; |
300 | 289 |
| 290 // Video capture parameters that this machine is started with. |
| 291 media::VideoCaptureParams capture_params_; |
| 292 |
301 // Routing ID of any active fullscreen render widget or MSG_ROUTING_NONE | 293 // Routing ID of any active fullscreen render widget or MSG_ROUTING_NONE |
302 // otherwise. | 294 // otherwise. |
303 int fullscreen_widget_id_; | 295 int fullscreen_widget_id_; |
304 | 296 |
305 // Last known RenderView size. | 297 // Last known RenderView size. |
306 gfx::Size last_view_size_; | 298 gfx::Size last_view_size_; |
307 | 299 |
308 // Responsible for forwarding events from the active RenderWidgetHost to the | 300 // Responsible for forwarding events from the active RenderWidgetHost to the |
309 // oracle, and initiating captures accordingly. | 301 // oracle, and initiating captures accordingly. |
310 scoped_ptr<ContentCaptureSubscription> subscription_; | 302 scoped_ptr<ContentCaptureSubscription> subscription_; |
(...skipping 29 matching lines...) Expand all Loading... |
340 base::TimeTicks present_time, | 332 base::TimeTicks present_time, |
341 scoped_refptr<media::VideoFrame>* storage, | 333 scoped_refptr<media::VideoFrame>* storage, |
342 DeliverFrameCallback* deliver_frame_cb) { | 334 DeliverFrameCallback* deliver_frame_cb) { |
343 TRACE_EVENT1("mirroring", "FrameSubscriber::ShouldCaptureFrame", | 335 TRACE_EVENT1("mirroring", "FrameSubscriber::ShouldCaptureFrame", |
344 "instance", this); | 336 "instance", this); |
345 | 337 |
346 ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb; | 338 ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb; |
347 bool oracle_decision = oracle_proxy_->ObserveEventAndDecideCapture( | 339 bool oracle_decision = oracle_proxy_->ObserveEventAndDecideCapture( |
348 event_type_, present_time, storage, &capture_frame_cb); | 340 event_type_, present_time, storage, &capture_frame_cb); |
349 | 341 |
350 *deliver_frame_cb = base::Bind(&InvokeCaptureFrameCallback, capture_frame_cb); | 342 *deliver_frame_cb = base::Bind(capture_frame_cb, *storage); |
351 return oracle_decision; | 343 return oracle_decision; |
352 } | 344 } |
353 | 345 |
354 ContentCaptureSubscription::ContentCaptureSubscription( | 346 ContentCaptureSubscription::ContentCaptureSubscription( |
355 const RenderWidgetHost& source, | 347 const RenderWidgetHost& source, |
356 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy, | 348 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy, |
357 const CaptureCallback& capture_callback) | 349 const CaptureCallback& capture_callback) |
358 : render_process_id_(source.GetProcess()->GetID()), | 350 : render_process_id_(source.GetProcess()->GetID()), |
359 render_view_id_(source.GetRoutingID()), | 351 render_view_id_(source.GetRoutingID()), |
360 paint_subscriber_(VideoCaptureOracle::kSoftwarePaint, oracle_proxy), | 352 paint_subscriber_(VideoCaptureOracle::kSoftwarePaint, oracle_proxy), |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
567 weak_ptr_factory_(this) {} | 559 weak_ptr_factory_(this) {} |
568 | 560 |
569 WebContentsCaptureMachine::~WebContentsCaptureMachine() { | 561 WebContentsCaptureMachine::~WebContentsCaptureMachine() { |
570 BrowserThread::PostBlockingPoolTask( | 562 BrowserThread::PostBlockingPoolTask( |
571 FROM_HERE, | 563 FROM_HERE, |
572 base::Bind(&DeleteOnWorkerThread, base::Passed(&render_thread_), | 564 base::Bind(&DeleteOnWorkerThread, base::Passed(&render_thread_), |
573 base::Bind(&base::DoNothing))); | 565 base::Bind(&base::DoNothing))); |
574 } | 566 } |
575 | 567 |
576 bool WebContentsCaptureMachine::Start( | 568 bool WebContentsCaptureMachine::Start( |
577 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy) { | 569 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy, |
| 570 const media::VideoCaptureParams& params) { |
578 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 571 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
579 DCHECK(!started_); | 572 DCHECK(!started_); |
580 | 573 |
581 DCHECK(oracle_proxy.get()); | 574 DCHECK(oracle_proxy.get()); |
582 oracle_proxy_ = oracle_proxy; | 575 oracle_proxy_ = oracle_proxy; |
| 576 capture_params_ = params; |
583 | 577 |
584 render_thread_.reset(new base::Thread("WebContentsVideo_RenderThread")); | 578 render_thread_.reset(new base::Thread("WebContentsVideo_RenderThread")); |
585 if (!render_thread_->Start()) { | 579 if (!render_thread_->Start()) { |
586 DVLOG(1) << "Failed to spawn render thread."; | 580 DVLOG(1) << "Failed to spawn render thread."; |
587 render_thread_.reset(); | 581 render_thread_.reset(); |
588 return false; | 582 return false; |
589 } | 583 } |
590 | 584 |
591 if (!StartObservingWebContents()) { | 585 if (!StartObservingWebContents()) { |
592 DVLOG(1) << "Failed to observe web contents."; | 586 DVLOG(1) << "Failed to observe web contents."; |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
822 scoped_ptr<Client> client) { | 816 scoped_ptr<Client> client) { |
823 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString(); | 817 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString(); |
824 core_->AllocateAndStart(params, client.Pass()); | 818 core_->AllocateAndStart(params, client.Pass()); |
825 } | 819 } |
826 | 820 |
827 void WebContentsVideoCaptureDevice::StopAndDeAllocate() { | 821 void WebContentsVideoCaptureDevice::StopAndDeAllocate() { |
828 core_->StopAndDeAllocate(); | 822 core_->StopAndDeAllocate(); |
829 } | 823 } |
830 | 824 |
831 } // namespace content | 825 } // namespace content |
OLD | NEW |