| 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 |