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