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()))); |
97 | 99 |
98 return result; | 100 return result; |
99 } | 101 } |
100 | 102 |
| 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 |
101 void DeleteOnWorkerThread(scoped_ptr<base::Thread> render_thread, | 112 void DeleteOnWorkerThread(scoped_ptr<base::Thread> render_thread, |
102 const base::Closure& callback) { | 113 const base::Closure& callback) { |
103 render_thread.reset(); | 114 render_thread.reset(); |
104 | 115 |
105 // After thread join call the callback on UI thread. | 116 // After thread join call the callback on UI thread. |
106 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); | 117 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); |
107 } | 118 } |
108 | 119 |
109 // Responsible for logging the effective frame rate. | 120 // Responsible for logging the effective frame rate. |
110 class VideoFrameDeliveryLog { | 121 class VideoFrameDeliveryLog { |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 // notification would get posted back to the UI thread and processed later, and | 231 // notification would get posted back to the UI thread and processed later, and |
221 // this seems disadvantageous. | 232 // this seems disadvantageous. |
222 class WebContentsCaptureMachine | 233 class WebContentsCaptureMachine |
223 : public VideoCaptureMachine, | 234 : public VideoCaptureMachine, |
224 public WebContentsObserver { | 235 public WebContentsObserver { |
225 public: | 236 public: |
226 WebContentsCaptureMachine(int render_process_id, int render_view_id); | 237 WebContentsCaptureMachine(int render_process_id, int render_view_id); |
227 virtual ~WebContentsCaptureMachine(); | 238 virtual ~WebContentsCaptureMachine(); |
228 | 239 |
229 // VideoCaptureMachine overrides. | 240 // VideoCaptureMachine overrides. |
230 virtual bool Start(const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy, | 241 virtual bool Start( |
231 const media::VideoCaptureParams& params) OVERRIDE; | 242 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy) OVERRIDE; |
232 virtual void Stop(const base::Closure& callback) OVERRIDE; | 243 virtual void Stop(const base::Closure& callback) OVERRIDE; |
233 | 244 |
234 // Starts a copy from the backing store or the composited surface. Must be run | 245 // Starts a copy from the backing store or the composited surface. Must be run |
235 // on the UI BrowserThread. |deliver_frame_cb| will be run when the operation | 246 // on the UI BrowserThread. |deliver_frame_cb| will be run when the operation |
236 // completes. The copy will occur to |target|. | 247 // completes. The copy will occur to |target|. |
237 // | 248 // |
238 // This may be used as a ContentCaptureSubscription::CaptureCallback. | 249 // This may be used as a ContentCaptureSubscription::CaptureCallback. |
239 void Capture(const base::TimeTicks& start_time, | 250 void Capture(const base::TimeTicks& start_time, |
240 const scoped_refptr<media::VideoFrame>& target, | 251 const scoped_refptr<media::VideoFrame>& target, |
241 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback& | 252 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback& |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
301 const int initial_render_process_id_; | 312 const int initial_render_process_id_; |
302 const int initial_render_view_id_; | 313 const int initial_render_view_id_; |
303 | 314 |
304 // A dedicated worker thread on which SkBitmap->VideoFrame conversion will | 315 // A dedicated worker thread on which SkBitmap->VideoFrame conversion will |
305 // occur. Only used when this activity cannot be done on the GPU. | 316 // occur. Only used when this activity cannot be done on the GPU. |
306 scoped_ptr<base::Thread> render_thread_; | 317 scoped_ptr<base::Thread> render_thread_; |
307 | 318 |
308 // Makes all the decisions about which frames to copy, and how. | 319 // Makes all the decisions about which frames to copy, and how. |
309 scoped_refptr<ThreadSafeCaptureOracle> oracle_proxy_; | 320 scoped_refptr<ThreadSafeCaptureOracle> oracle_proxy_; |
310 | 321 |
311 // Video capture parameters that this machine is started with. | |
312 media::VideoCaptureParams capture_params_; | |
313 | |
314 // Routing ID of any active fullscreen render widget or MSG_ROUTING_NONE | 322 // Routing ID of any active fullscreen render widget or MSG_ROUTING_NONE |
315 // otherwise. | 323 // otherwise. |
316 int fullscreen_widget_id_; | 324 int fullscreen_widget_id_; |
317 | 325 |
318 // Last known RenderView size. | 326 // Last known RenderView size. |
319 gfx::Size last_view_size_; | 327 gfx::Size last_view_size_; |
320 | 328 |
321 // Responsible for forwarding events from the active RenderWidgetHost to the | 329 // Responsible for forwarding events from the active RenderWidgetHost to the |
322 // oracle, and initiating captures accordingly. | 330 // oracle, and initiating captures accordingly. |
323 scoped_ptr<ContentCaptureSubscription> subscription_; | 331 scoped_ptr<ContentCaptureSubscription> subscription_; |
324 | 332 |
325 // Weak pointer factory used to invalidate callbacks. | 333 // Weak pointer factory used to invalidate callbacks. |
326 // NOTE: Weak pointers must be invalidated before all other member variables. | 334 // NOTE: Weak pointers must be invalidated before all other member variables. |
327 base::WeakPtrFactory<WebContentsCaptureMachine> weak_ptr_factory_; | 335 base::WeakPtrFactory<WebContentsCaptureMachine> weak_ptr_factory_; |
328 | 336 |
329 DISALLOW_COPY_AND_ASSIGN(WebContentsCaptureMachine); | 337 DISALLOW_COPY_AND_ASSIGN(WebContentsCaptureMachine); |
330 }; | 338 }; |
331 | 339 |
332 bool FrameSubscriber::ShouldCaptureFrame( | 340 bool FrameSubscriber::ShouldCaptureFrame( |
333 base::TimeTicks present_time, | 341 base::TimeTicks present_time, |
334 scoped_refptr<media::VideoFrame>* storage, | 342 scoped_refptr<media::VideoFrame>* storage, |
335 DeliverFrameCallback* deliver_frame_cb) { | 343 DeliverFrameCallback* deliver_frame_cb) { |
336 TRACE_EVENT1("mirroring", "FrameSubscriber::ShouldCaptureFrame", | 344 TRACE_EVENT1("mirroring", "FrameSubscriber::ShouldCaptureFrame", |
337 "instance", this); | 345 "instance", this); |
338 | 346 |
339 ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb; | 347 ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb; |
340 bool oracle_decision = oracle_proxy_->ObserveEventAndDecideCapture( | 348 bool oracle_decision = oracle_proxy_->ObserveEventAndDecideCapture( |
341 event_type_, present_time, storage, &capture_frame_cb); | 349 event_type_, present_time, storage, &capture_frame_cb); |
342 | 350 |
343 if (!capture_frame_cb.is_null()) | 351 *deliver_frame_cb = base::Bind(&InvokeCaptureFrameCallback, capture_frame_cb); |
344 *deliver_frame_cb = base::Bind(capture_frame_cb, *storage); | |
345 if (oracle_decision) | 352 if (oracle_decision) |
346 delivery_log_->ChronicleFrameDelivery(present_time); | 353 delivery_log_->ChronicleFrameDelivery(present_time); |
347 return oracle_decision; | 354 return oracle_decision; |
348 } | 355 } |
349 | 356 |
350 ContentCaptureSubscription::ContentCaptureSubscription( | 357 ContentCaptureSubscription::ContentCaptureSubscription( |
351 const RenderWidgetHost& source, | 358 const RenderWidgetHost& source, |
352 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy, | 359 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy, |
353 const CaptureCallback& capture_callback) | 360 const CaptureCallback& capture_callback) |
354 : render_process_id_(source.GetProcess()->GetID()), | 361 : render_process_id_(source.GetProcess()->GetID()), |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
564 weak_ptr_factory_(this) {} | 571 weak_ptr_factory_(this) {} |
565 | 572 |
566 WebContentsCaptureMachine::~WebContentsCaptureMachine() { | 573 WebContentsCaptureMachine::~WebContentsCaptureMachine() { |
567 BrowserThread::PostBlockingPoolTask( | 574 BrowserThread::PostBlockingPoolTask( |
568 FROM_HERE, | 575 FROM_HERE, |
569 base::Bind(&DeleteOnWorkerThread, base::Passed(&render_thread_), | 576 base::Bind(&DeleteOnWorkerThread, base::Passed(&render_thread_), |
570 base::Bind(&base::DoNothing))); | 577 base::Bind(&base::DoNothing))); |
571 } | 578 } |
572 | 579 |
573 bool WebContentsCaptureMachine::Start( | 580 bool WebContentsCaptureMachine::Start( |
574 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy, | 581 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy) { |
575 const media::VideoCaptureParams& params) { | |
576 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 582 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
577 DCHECK(!started_); | 583 DCHECK(!started_); |
578 | 584 |
579 DCHECK(oracle_proxy.get()); | 585 DCHECK(oracle_proxy.get()); |
580 oracle_proxy_ = oracle_proxy; | 586 oracle_proxy_ = oracle_proxy; |
581 capture_params_ = params; | |
582 | 587 |
583 render_thread_.reset(new base::Thread("WebContentsVideo_RenderThread")); | 588 render_thread_.reset(new base::Thread("WebContentsVideo_RenderThread")); |
584 if (!render_thread_->Start()) { | 589 if (!render_thread_->Start()) { |
585 DVLOG(1) << "Failed to spawn render thread."; | 590 DVLOG(1) << "Failed to spawn render thread."; |
586 render_thread_.reset(); | 591 render_thread_.reset(); |
587 return false; | 592 return false; |
588 } | 593 } |
589 | 594 |
590 if (!StartObservingWebContents()) { | 595 if (!StartObservingWebContents()) { |
591 DVLOG(1) << "Failed to observe web contents."; | 596 DVLOG(1) << "Failed to observe web contents."; |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
813 scoped_ptr<Client> client) { | 818 scoped_ptr<Client> client) { |
814 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString(); | 819 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString(); |
815 core_->AllocateAndStart(params, client.Pass()); | 820 core_->AllocateAndStart(params, client.Pass()); |
816 } | 821 } |
817 | 822 |
818 void WebContentsVideoCaptureDevice::StopAndDeAllocate() { | 823 void WebContentsVideoCaptureDevice::StopAndDeAllocate() { |
819 core_->StopAndDeAllocate(); | 824 core_->StopAndDeAllocate(); |
820 } | 825 } |
821 | 826 |
822 } // namespace content | 827 } // namespace content |
OLD | NEW |