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

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

Issue 989683004: Remove software paint FrameSubscriber from tab capture. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 9 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
« no previous file with comments | « content/browser/media/capture/video_capture_oracle.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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. 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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 #include "base/threading/thread.h" 62 #include "base/threading/thread.h"
63 #include "base/threading/thread_checker.h" 63 #include "base/threading/thread_checker.h"
64 #include "base/time/time.h" 64 #include "base/time/time.h"
65 #include "content/browser/media/capture/content_video_capture_device_core.h" 65 #include "content/browser/media/capture/content_video_capture_device_core.h"
66 #include "content/browser/media/capture/video_capture_oracle.h" 66 #include "content/browser/media/capture/video_capture_oracle.h"
67 #include "content/browser/media/capture/web_contents_capture_util.h" 67 #include "content/browser/media/capture/web_contents_capture_util.h"
68 #include "content/browser/media/capture/web_contents_tracker.h" 68 #include "content/browser/media/capture/web_contents_tracker.h"
69 #include "content/browser/renderer_host/render_widget_host_impl.h" 69 #include "content/browser/renderer_host/render_widget_host_impl.h"
70 #include "content/browser/renderer_host/render_widget_host_view_base.h" 70 #include "content/browser/renderer_host/render_widget_host_view_base.h"
71 #include "content/public/browser/browser_thread.h" 71 #include "content/public/browser/browser_thread.h"
72 #include "content/public/browser/notification_observer.h"
73 #include "content/public/browser/notification_registrar.h"
74 #include "content/public/browser/notification_source.h"
75 #include "content/public/browser/notification_types.h"
76 #include "content/public/browser/render_process_host.h" 72 #include "content/public/browser/render_process_host.h"
77 #include "content/public/browser/render_widget_host_view.h" 73 #include "content/public/browser/render_widget_host_view.h"
78 #include "content/public/browser/render_widget_host_view_frame_subscriber.h" 74 #include "content/public/browser/render_widget_host_view_frame_subscriber.h"
79 #include "content/public/browser/web_contents.h" 75 #include "content/public/browser/web_contents.h"
80 #include "media/base/video_capture_types.h" 76 #include "media/base/video_capture_types.h"
81 #include "media/base/video_util.h" 77 #include "media/base/video_util.h"
82 #include "skia/ext/image_operations.h" 78 #include "skia/ext/image_operations.h"
83 #include "third_party/skia/include/core/SkBitmap.h" 79 #include "third_party/skia/include/core/SkBitmap.h"
84 #include "third_party/skia/include/core/SkColor.h" 80 #include "third_party/skia/include/core/SkColor.h"
85 #include "ui/gfx/display.h" 81 #include "ui/gfx/display.h"
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 scoped_refptr<ThreadSafeCaptureOracle> oracle_proxy_; 149 scoped_refptr<ThreadSafeCaptureOracle> oracle_proxy_;
154 VideoFrameDeliveryLog* const delivery_log_; 150 VideoFrameDeliveryLog* const delivery_log_;
155 }; 151 };
156 152
157 // ContentCaptureSubscription is the relationship between a RenderWidgetHost 153 // ContentCaptureSubscription is the relationship between a RenderWidgetHost
158 // whose content is updating, a subscriber that is deciding which of these 154 // whose content is updating, a subscriber that is deciding which of these
159 // updates to capture (and where to deliver them to), and a callback that 155 // updates to capture (and where to deliver them to), and a callback that
160 // knows how to do the capture and prepare the result for delivery. 156 // knows how to do the capture and prepare the result for delivery.
161 // 157 //
162 // In practice, this means (a) installing a RenderWidgetHostFrameSubscriber in 158 // In practice, this means (a) installing a RenderWidgetHostFrameSubscriber in
163 // the RenderWidgetHostView, to process updates that occur via accelerated 159 // the RenderWidgetHostView, to process compositor updates, and (b) running a
164 // compositing, (b) installing itself as an observer of updates to the 160 // timer to possibly initiate forced, non-event-driven captures needed by
165 // RenderWidgetHost's backing store, to hook updates that occur via software 161 // downstream consumers that require frame repeats of unchanged content.
166 // rendering, and (c) running a timer to possibly initiate non-event-driven
167 // captures that the subscriber might request.
168 // 162 //
169 // All of this happens on the UI thread, although the 163 // All of this happens on the UI thread, although the
170 // RenderWidgetHostViewFrameSubscriber we install may be dispatching updates 164 // RenderWidgetHostViewFrameSubscriber we install may be dispatching updates
171 // autonomously on some other thread. 165 // autonomously on some other thread.
172 class ContentCaptureSubscription : public content::NotificationObserver { 166 class ContentCaptureSubscription {
173 public: 167 public:
174 typedef base::Callback< 168 typedef base::Callback<
175 void(const base::TimeTicks&, 169 void(const base::TimeTicks&,
176 const scoped_refptr<media::VideoFrame>&, 170 const scoped_refptr<media::VideoFrame>&,
177 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback&)> 171 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback&)>
178 CaptureCallback; 172 CaptureCallback;
179 173
180 // Create a subscription. Whenever a manual capture is required, the 174 // Create a subscription. Whenever a manual capture is required, the
181 // subscription will invoke |capture_callback| on the UI thread to do the 175 // subscription will invoke |capture_callback| on the UI thread to do the
182 // work. 176 // work.
183 ContentCaptureSubscription( 177 ContentCaptureSubscription(
184 const RenderWidgetHost& source, 178 const RenderWidgetHost& source,
185 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy, 179 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy,
186 const CaptureCallback& capture_callback); 180 const CaptureCallback& capture_callback);
187 ~ContentCaptureSubscription() override; 181 ~ContentCaptureSubscription();
188
189 // content::NotificationObserver implementation.
190 void Observe(int type,
191 const content::NotificationSource& source,
192 const content::NotificationDetails& details) override;
193 182
194 private: 183 private:
195 void OnTimer(); 184 void OnTimer();
196 185
197 // Maintain a weak reference to the RenderWidgetHost (via its routing ID), 186 // Maintain a weak reference to the RenderWidgetHost (via its routing ID),
198 // since the instance could be destroyed externally during the lifetime of 187 // since the instance could be destroyed externally during the lifetime of
199 // |this|. 188 // |this|.
200 const int render_process_id_; 189 const int render_process_id_;
201 const int render_widget_id_; 190 const int render_widget_id_;
202 191
203 VideoFrameDeliveryLog delivery_log_; 192 VideoFrameDeliveryLog delivery_log_;
204 FrameSubscriber paint_subscriber_;
205 FrameSubscriber timer_subscriber_; 193 FrameSubscriber timer_subscriber_;
206 content::NotificationRegistrar registrar_;
207 CaptureCallback capture_callback_; 194 CaptureCallback capture_callback_;
208 base::Timer timer_; 195 base::Timer timer_;
209 196
210 DISALLOW_COPY_AND_ASSIGN(ContentCaptureSubscription); 197 DISALLOW_COPY_AND_ASSIGN(ContentCaptureSubscription);
211 }; 198 };
212 199
213 // Render the SkBitmap |input| into the given VideoFrame buffer |output|, then 200 // Render the SkBitmap |input| into the given VideoFrame buffer |output|, then
214 // invoke |done_cb| to indicate success or failure. |input| is expected to be 201 // invoke |done_cb| to indicate success or failure. |input| is expected to be
215 // ARGB. |output| must be YV12 or I420. Colorspace conversion is always done. 202 // ARGB. |output| must be YV12 or I420. Colorspace conversion is always done.
216 // Scaling and letterboxing will be done as needed. 203 // Scaling and letterboxing will be done as needed.
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 return oracle_decision; 308 return oracle_decision;
322 } 309 }
323 310
324 ContentCaptureSubscription::ContentCaptureSubscription( 311 ContentCaptureSubscription::ContentCaptureSubscription(
325 const RenderWidgetHost& source, 312 const RenderWidgetHost& source,
326 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy, 313 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy,
327 const CaptureCallback& capture_callback) 314 const CaptureCallback& capture_callback)
328 : render_process_id_(source.GetProcess()->GetID()), 315 : render_process_id_(source.GetProcess()->GetID()),
329 render_widget_id_(source.GetRoutingID()), 316 render_widget_id_(source.GetRoutingID()),
330 delivery_log_(), 317 delivery_log_(),
331 paint_subscriber_(VideoCaptureOracle::kSoftwarePaint, oracle_proxy,
332 &delivery_log_),
333 timer_subscriber_(VideoCaptureOracle::kTimerPoll, oracle_proxy, 318 timer_subscriber_(VideoCaptureOracle::kTimerPoll, oracle_proxy,
334 &delivery_log_), 319 &delivery_log_),
335 capture_callback_(capture_callback), 320 capture_callback_(capture_callback),
336 timer_(true, true) { 321 timer_(true, true) {
337 DCHECK_CURRENTLY_ON(BrowserThread::UI); 322 DCHECK_CURRENTLY_ON(BrowserThread::UI);
338 323
339 RenderWidgetHostView* const view = source.GetView(); 324 RenderWidgetHostView* const view = source.GetView();
340 325
341 // Subscribe to accelerated presents. These will be serviced directly by the 326 // Subscribe to compositor updates. These will be serviced directly by the
342 // oracle. 327 // oracle.
343 if (view) { 328 if (view) {
344 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber( 329 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber(
345 new FrameSubscriber(VideoCaptureOracle::kCompositorUpdate, 330 new FrameSubscriber(VideoCaptureOracle::kCompositorUpdate,
346 oracle_proxy, &delivery_log_)); 331 oracle_proxy, &delivery_log_));
347 view->BeginFrameSubscription(subscriber.Pass()); 332 view->BeginFrameSubscription(subscriber.Pass());
348 } 333 }
349 334
350 // Subscribe to software paint events. This instance will service these by
351 // reflecting them back to the WebContentsCaptureMachine via
352 // |capture_callback|.
353 registrar_.Add(
354 this, content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
355 Source<RenderWidgetHost>(&source));
356
357 // Subscribe to timer events. This instance will service these as well. 335 // Subscribe to timer events. This instance will service these as well.
358 timer_.Start(FROM_HERE, oracle_proxy->min_capture_period(), 336 timer_.Start(FROM_HERE, oracle_proxy->min_capture_period(),
359 base::Bind(&ContentCaptureSubscription::OnTimer, 337 base::Bind(&ContentCaptureSubscription::OnTimer,
360 base::Unretained(this))); 338 base::Unretained(this)));
361 } 339 }
362 340
363 ContentCaptureSubscription::~ContentCaptureSubscription() { 341 ContentCaptureSubscription::~ContentCaptureSubscription() {
364 // If the BrowserThreads have been torn down, then the browser is in the final 342 // If the BrowserThreads have been torn down, then the browser is in the final
365 // stages of exiting and it is dangerous to take any further action. We must 343 // stages of exiting and it is dangerous to take any further action. We must
366 // return early. http://crbug.com/396413 344 // return early. http://crbug.com/396413
367 if (!BrowserThread::IsMessageLoopValid(BrowserThread::UI)) 345 if (!BrowserThread::IsMessageLoopValid(BrowserThread::UI))
368 return; 346 return;
369 347
370 DCHECK_CURRENTLY_ON(BrowserThread::UI); 348 DCHECK_CURRENTLY_ON(BrowserThread::UI);
371 RenderWidgetHost* const source = 349 RenderWidgetHost* const source =
372 RenderWidgetHost::FromID(render_process_id_, render_widget_id_); 350 RenderWidgetHost::FromID(render_process_id_, render_widget_id_);
373 RenderWidgetHostView* const view = source ? source->GetView() : NULL; 351 RenderWidgetHostView* const view = source ? source->GetView() : NULL;
374 if (view) 352 if (view)
375 view->EndFrameSubscription(); 353 view->EndFrameSubscription();
376 } 354 }
377 355
378 void ContentCaptureSubscription::Observe(
379 int type,
380 const content::NotificationSource& source,
381 const content::NotificationDetails& details) {
382 DCHECK_CURRENTLY_ON(BrowserThread::UI);
383 DCHECK_EQ(NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE, type);
384
385 RenderWidgetHostImpl* rwh =
386 RenderWidgetHostImpl::From(Source<RenderWidgetHost>(source).ptr());
387
388 // This message occurs on window resizes and visibility changes even when
389 // accelerated compositing is active, so we need to filter out these cases.
390 if (!rwh || !rwh->GetView())
391 return;
392 // Mac sends DID_UPDATE_BACKING_STORE messages to inform the capture system
393 // of new software compositor frames, so always treat these messages as
394 // signals of a new frame on Mac.
395 // http://crbug.com/333986
396 #if !defined(OS_MACOSX)
397 if (rwh->GetView()->IsSurfaceAvailableForCopy())
398 return;
399 #endif
400
401 TRACE_EVENT1("mirroring", "ContentCaptureSubscription::Observe",
402 "instance", this);
403
404 base::Closure copy_done_callback;
405 scoped_refptr<media::VideoFrame> frame;
406 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback deliver_frame_cb;
407 const base::TimeTicks start_time = base::TimeTicks::Now();
408 if (paint_subscriber_.ShouldCaptureFrame(gfx::Rect(),
409 start_time,
410 &frame,
411 &deliver_frame_cb)) {
412 // This message happens just before paint. If we post a task to do the copy,
413 // it should run soon after the paint.
414 BrowserThread::PostTask(
415 BrowserThread::UI, FROM_HERE,
416 base::Bind(capture_callback_, start_time, frame, deliver_frame_cb));
417 }
418 }
419
420 void ContentCaptureSubscription::OnTimer() { 356 void ContentCaptureSubscription::OnTimer() {
421 DCHECK_CURRENTLY_ON(BrowserThread::UI); 357 DCHECK_CURRENTLY_ON(BrowserThread::UI);
422 TRACE_EVENT0("mirroring", "ContentCaptureSubscription::OnTimer"); 358 TRACE_EVENT0("mirroring", "ContentCaptureSubscription::OnTimer");
423 359
424 scoped_refptr<media::VideoFrame> frame; 360 scoped_refptr<media::VideoFrame> frame;
425 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback deliver_frame_cb; 361 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback deliver_frame_cb;
426 362
427 const base::TimeTicks start_time = base::TimeTicks::Now(); 363 const base::TimeTicks start_time = base::TimeTicks::Now();
428 if (timer_subscriber_.ShouldCaptureFrame(gfx::Rect(), 364 if (timer_subscriber_.ShouldCaptureFrame(gfx::Rect(),
429 start_time, 365 start_time,
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after
783 scoped_ptr<Client> client) { 719 scoped_ptr<Client> client) {
784 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString(); 720 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString();
785 core_->AllocateAndStart(params, client.Pass()); 721 core_->AllocateAndStart(params, client.Pass());
786 } 722 }
787 723
788 void WebContentsVideoCaptureDevice::StopAndDeAllocate() { 724 void WebContentsVideoCaptureDevice::StopAndDeAllocate() {
789 core_->StopAndDeAllocate(); 725 core_->StopAndDeAllocate();
790 } 726 }
791 727
792 } // namespace content 728 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/media/capture/video_capture_oracle.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698