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

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

Issue 1412173003: cast: support cursor rendering for tab capture (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Removed left over logs Created 5 years, 2 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
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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 // 43 //
44 // In the above example, both capturing and rendering *each* take almost the 44 // In the above example, both capturing and rendering *each* take almost the
45 // full 33 ms available between frames, yet we see that the required throughput 45 // full 33 ms available between frames, yet we see that the required throughput
46 // is obtained. 46 // is obtained.
47 // 47 //
48 // Turning on verbose logging will cause the effective frame rate to be logged 48 // Turning on verbose logging will cause the effective frame rate to be logged
49 // at 5-second intervals. 49 // at 5-second intervals.
50 50
51 #include "content/browser/media/capture/web_contents_video_capture_device.h" 51 #include "content/browser/media/capture/web_contents_video_capture_device.h"
52 52
53 #include <algorithm>
54
53 #include "base/basictypes.h" 55 #include "base/basictypes.h"
54 #include "base/bind.h" 56 #include "base/bind.h"
55 #include "base/callback_helpers.h" 57 #include "base/callback_helpers.h"
56 #include "base/location.h" 58 #include "base/location.h"
57 #include "base/logging.h" 59 #include "base/logging.h"
58 #include "base/memory/scoped_ptr.h" 60 #include "base/memory/scoped_ptr.h"
59 #include "base/memory/weak_ptr.h" 61 #include "base/memory/weak_ptr.h"
60 #include "base/metrics/histogram.h" 62 #include "base/metrics/histogram.h"
61 #include "base/sequenced_task_runner.h" 63 #include "base/sequenced_task_runner.h"
62 #include "base/single_thread_task_runner.h" 64 #include "base/single_thread_task_runner.h"
63 #include "base/threading/thread.h" 65 #include "base/threading/thread.h"
64 #include "base/threading/thread_checker.h" 66 #include "base/threading/thread_checker.h"
65 #include "base/time/time.h" 67 #include "base/time/time.h"
68 #include "content/browser/media/capture/cursor_renderer.h"
66 #include "content/browser/media/capture/web_contents_capture_util.h" 69 #include "content/browser/media/capture/web_contents_capture_util.h"
67 #include "content/browser/media/capture/web_contents_tracker.h" 70 #include "content/browser/media/capture/web_contents_tracker.h"
68 #include "content/browser/renderer_host/render_widget_host_impl.h" 71 #include "content/browser/renderer_host/render_widget_host_impl.h"
69 #include "content/browser/renderer_host/render_widget_host_view_base.h" 72 #include "content/browser/renderer_host/render_widget_host_view_base.h"
70 #include "content/public/browser/browser_thread.h" 73 #include "content/public/browser/browser_thread.h"
71 #include "content/public/browser/render_process_host.h" 74 #include "content/public/browser/render_process_host.h"
72 #include "content/public/browser/render_widget_host_view.h" 75 #include "content/public/browser/render_widget_host_view.h"
73 #include "content/public/browser/render_widget_host_view_frame_subscriber.h" 76 #include "content/public/browser/render_widget_host_view_frame_subscriber.h"
74 #include "content/public/browser/web_contents.h" 77 #include "content/public/browser/web_contents.h"
75 #include "media/base/video_capture_types.h" 78 #include "media/base/video_capture_types.h"
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 115
113 DISALLOW_COPY_AND_ASSIGN(VideoFrameDeliveryLog); 116 DISALLOW_COPY_AND_ASSIGN(VideoFrameDeliveryLog);
114 }; 117 };
115 118
116 // FrameSubscriber is a proxy to the ThreadSafeCaptureOracle that's compatible 119 // FrameSubscriber is a proxy to the ThreadSafeCaptureOracle that's compatible
117 // with RenderWidgetHostViewFrameSubscriber. We create one per event type. 120 // with RenderWidgetHostViewFrameSubscriber. We create one per event type.
118 class FrameSubscriber : public RenderWidgetHostViewFrameSubscriber { 121 class FrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
119 public: 122 public:
120 FrameSubscriber(media::VideoCaptureOracle::Event event_type, 123 FrameSubscriber(media::VideoCaptureOracle::Event event_type,
121 const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle, 124 const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle,
122 VideoFrameDeliveryLog* delivery_log) 125 VideoFrameDeliveryLog* delivery_log,
126 content::CursorRenderer* cursor_renderer)
123 : event_type_(event_type), 127 : event_type_(event_type),
124 oracle_proxy_(oracle), 128 oracle_proxy_(oracle),
125 delivery_log_(delivery_log) {} 129 delivery_log_(delivery_log),
130 cursor_renderer_(cursor_renderer) {}
126 131
127 bool ShouldCaptureFrame( 132 bool ShouldCaptureFrame(
128 const gfx::Rect& damage_rect, 133 const gfx::Rect& damage_rect,
129 base::TimeTicks present_time, 134 base::TimeTicks present_time,
130 scoped_refptr<media::VideoFrame>* storage, 135 scoped_refptr<media::VideoFrame>* storage,
131 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback* 136 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback*
132 deliver_frame_cb) override; 137 deliver_frame_cb) override;
133 138
139 void DidCaptureFrame(const scoped_refptr<media::VideoFrame>& frame,
140 base::TimeTicks timestamp,
141 gfx::Rect region_in_frame,
142 bool success);
143
134 private: 144 private:
135 const media::VideoCaptureOracle::Event event_type_; 145 const media::VideoCaptureOracle::Event event_type_;
136 scoped_refptr<media::ThreadSafeCaptureOracle> oracle_proxy_; 146 scoped_refptr<media::ThreadSafeCaptureOracle> oracle_proxy_;
137 VideoFrameDeliveryLog* const delivery_log_; 147 VideoFrameDeliveryLog* const delivery_log_;
148 content::CursorRenderer* const cursor_renderer_;
149
150 media::ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb_;
138 }; 151 };
139 152
140 // ContentCaptureSubscription is the relationship between a RenderWidgetHost 153 // ContentCaptureSubscription is the relationship between a RenderWidgetHost
141 // 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
142 // 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
143 // 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.
144 // 157 //
145 // In practice, this means (a) installing a RenderWidgetHostFrameSubscriber in 158 // In practice, this means (a) installing a RenderWidgetHostFrameSubscriber in
146 // the RenderWidgetHostView, to process compositor updates, and (b) running a 159 // the RenderWidgetHostView, to process compositor updates, and (b) running a
147 // timer to possibly initiate forced, non-event-driven captures needed by 160 // timer to possibly initiate forced, non-event-driven captures needed by
(...skipping 22 matching lines...) Expand all
170 private: 183 private:
171 void OnTimer(); 184 void OnTimer();
172 185
173 // Maintain a weak reference to the RenderWidgetHost (via its routing ID), 186 // Maintain a weak reference to the RenderWidgetHost (via its routing ID),
174 // since the instance could be destroyed externally during the lifetime of 187 // since the instance could be destroyed externally during the lifetime of
175 // |this|. 188 // |this|.
176 const int render_process_id_; 189 const int render_process_id_;
177 const int render_widget_id_; 190 const int render_widget_id_;
178 191
179 VideoFrameDeliveryLog delivery_log_; 192 VideoFrameDeliveryLog delivery_log_;
180 FrameSubscriber timer_subscriber_; 193 scoped_ptr<FrameSubscriber> timer_subscriber_;
181 CaptureCallback capture_callback_; 194 CaptureCallback capture_callback_;
182 base::Timer timer_; 195 base::Timer timer_;
183 196
197 // Responsible for tracking the cursor state and input events to make
198 // decisions and then render the mouse cursor on the video frame after
199 // capture is completed.
200 scoped_ptr<content::CursorRenderer> cursor_renderer_;
201
184 DISALLOW_COPY_AND_ASSIGN(ContentCaptureSubscription); 202 DISALLOW_COPY_AND_ASSIGN(ContentCaptureSubscription);
185 }; 203 };
186 204
187 // Render the SkBitmap |input| into the given VideoFrame buffer |output|, then 205 // Render the SkBitmap |input| into the given VideoFrame buffer |output|, then
188 // invoke |done_cb| to indicate success or failure. |input| is expected to be 206 // invoke |done_cb| to indicate success or failure. |input| is expected to be
189 // ARGB. |output| must be YV12 or I420. Colorspace conversion is always done. 207 // ARGB. |output| must be YV12 or I420. Colorspace conversion is always done.
190 // Scaling and letterboxing will be done as needed. 208 // Scaling and letterboxing will be done as needed.
191 // 209 //
192 // This software implementation should be used only when GPU acceleration of 210 // This software implementation should be used only when GPU acceleration of
193 // these activities is not possible. This operation may be expensive (tens to 211 // these activities is not possible. This operation may be expensive (tens to
194 // hundreds of milliseconds), so the caller should ensure that it runs on a 212 // hundreds of milliseconds), so the caller should ensure that it runs on a
195 // thread where such a pause would cause UI jank. 213 // thread where such a pause would cause UI jank.
196 void RenderVideoFrame(const SkBitmap& input, 214 void RenderVideoFrame(const SkBitmap& input,
197 const scoped_refptr<media::VideoFrame>& output, 215 const scoped_refptr<media::VideoFrame>& output,
198 const base::Callback<void(bool)>& done_cb); 216 const base::Callback<void(gfx::Rect, bool)>& done_cb);
199 217
200 // Renews capture subscriptions based on feedback from WebContentsTracker, and 218 // Renews capture subscriptions based on feedback from WebContentsTracker, and
201 // also executes copying of the backing store on the UI BrowserThread. 219 // also executes copying of the backing store on the UI BrowserThread.
202 class WebContentsCaptureMachine : public media::VideoCaptureMachine { 220 class WebContentsCaptureMachine : public media::VideoCaptureMachine {
203 public: 221 public:
204 WebContentsCaptureMachine(int render_process_id, 222 WebContentsCaptureMachine(int render_process_id,
205 int main_render_frame_id, 223 int main_render_frame_id,
206 bool enable_auto_throttling); 224 bool enable_auto_throttling);
207 ~WebContentsCaptureMachine() override; 225 ~WebContentsCaptureMachine() override;
208 226
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback& 260 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback&
243 deliver_frame_cb, 261 deliver_frame_cb,
244 const SkBitmap& bitmap, 262 const SkBitmap& bitmap,
245 ReadbackResponse response); 263 ReadbackResponse response);
246 264
247 // Response callback for RWHVP::CopyFromCompositingSurfaceToVideoFrame(). 265 // Response callback for RWHVP::CopyFromCompositingSurfaceToVideoFrame().
248 void DidCopyFromCompositingSurfaceToVideoFrame( 266 void DidCopyFromCompositingSurfaceToVideoFrame(
249 const base::TimeTicks& start_time, 267 const base::TimeTicks& start_time,
250 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback& 268 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback&
251 deliver_frame_cb, 269 deliver_frame_cb,
270 gfx::Rect region_in_frame,
252 bool success); 271 bool success);
253 272
254 // Remove the old subscription, and attempt to start a new one if |had_target| 273 // Remove the old subscription, and attempt to start a new one if |had_target|
255 // is true. 274 // is true.
256 void RenewFrameSubscription(bool had_target); 275 void RenewFrameSubscription(bool had_target);
257 276
258 // Called whenever the render widget is resized. 277 // Called whenever the render widget is resized.
259 void UpdateCaptureSize(); 278 void UpdateCaptureSize();
260 279
261 // Parameters saved in constructor. 280 // Parameters saved in constructor.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 }; 315 };
297 316
298 bool FrameSubscriber::ShouldCaptureFrame( 317 bool FrameSubscriber::ShouldCaptureFrame(
299 const gfx::Rect& damage_rect, 318 const gfx::Rect& damage_rect,
300 base::TimeTicks present_time, 319 base::TimeTicks present_time,
301 scoped_refptr<media::VideoFrame>* storage, 320 scoped_refptr<media::VideoFrame>* storage,
302 DeliverFrameCallback* deliver_frame_cb) { 321 DeliverFrameCallback* deliver_frame_cb) {
303 TRACE_EVENT1("gpu.capture", "FrameSubscriber::ShouldCaptureFrame", 322 TRACE_EVENT1("gpu.capture", "FrameSubscriber::ShouldCaptureFrame",
304 "instance", this); 323 "instance", this);
305 324
306 media::ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb;
307 bool oracle_decision = oracle_proxy_->ObserveEventAndDecideCapture( 325 bool oracle_decision = oracle_proxy_->ObserveEventAndDecideCapture(
308 event_type_, damage_rect, present_time, storage, &capture_frame_cb); 326 event_type_, damage_rect, present_time, storage, &capture_frame_cb_);
miu 2015/10/20 02:12:44 Unfortunately, you can't store this in a single |c
Irfan 2015/10/21 23:01:08 Done.
309 327
310 if (!capture_frame_cb.is_null()) 328 if (!capture_frame_cb_.is_null())
311 *deliver_frame_cb = base::Bind(capture_frame_cb, *storage); 329 *deliver_frame_cb = base::Bind(&FrameSubscriber::DidCaptureFrame,
330 base::Unretained(this), *storage);
312 if (oracle_decision) 331 if (oracle_decision)
313 delivery_log_->ChronicleFrameDelivery(present_time); 332 delivery_log_->ChronicleFrameDelivery(present_time);
314 return oracle_decision; 333 return oracle_decision;
315 } 334 }
316 335
336 void FrameSubscriber::DidCaptureFrame(
337 const scoped_refptr<media::VideoFrame>& frame,
338 base::TimeTicks timestamp,
339 gfx::Rect region_in_frame,
340 bool success) {
341 if (cursor_renderer_ && success) {
342 if (cursor_renderer_->Update(region_in_frame))
343 cursor_renderer_->RenderOnVideoFrame(frame);
344 }
345 capture_frame_cb_.Run(frame, timestamp, success);
346 }
347
317 ContentCaptureSubscription::ContentCaptureSubscription( 348 ContentCaptureSubscription::ContentCaptureSubscription(
318 const RenderWidgetHost& source, 349 const RenderWidgetHost& source,
319 const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy, 350 const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy,
320 const CaptureCallback& capture_callback) 351 const CaptureCallback& capture_callback)
321 : render_process_id_(source.GetProcess()->GetID()), 352 : render_process_id_(source.GetProcess()->GetID()),
322 render_widget_id_(source.GetRoutingID()), 353 render_widget_id_(source.GetRoutingID()),
323 delivery_log_(), 354 delivery_log_(),
324 timer_subscriber_(media::VideoCaptureOracle::kTimerPoll, oracle_proxy,
325 &delivery_log_),
326 capture_callback_(capture_callback), 355 capture_callback_(capture_callback),
327 timer_(true, true) { 356 timer_(true, true) {
328 DCHECK_CURRENTLY_ON(BrowserThread::UI); 357 DCHECK_CURRENTLY_ON(BrowserThread::UI);
329 358
330 RenderWidgetHostView* const view = source.GetView(); 359 RenderWidgetHostView* const view = source.GetView();
360 cursor_renderer_.reset(new content::CursorRenderer(
miu 2015/10/20 02:12:44 nit: These can go back into the initializer list a
Irfan 2015/10/21 23:01:08 I retained this mainly because it depends on fetch
361 view->GetNativeView(), content::ENABLE_MOUSE_EVENTS));
362 timer_subscriber_.reset(
363 new FrameSubscriber(media::VideoCaptureOracle::kTimerPoll, oracle_proxy,
364 &delivery_log_, cursor_renderer_.get()));
331 365
332 // Subscribe to compositor updates. These will be serviced directly by the 366 // Subscribe to compositor updates. These will be serviced directly by the
333 // oracle. 367 // oracle.
334 if (view) { 368 if (view) {
335 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber( 369 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber(
336 new FrameSubscriber(media::VideoCaptureOracle::kCompositorUpdate, 370 new FrameSubscriber(media::VideoCaptureOracle::kCompositorUpdate,
337 oracle_proxy, &delivery_log_)); 371 oracle_proxy, &delivery_log_,
372 cursor_renderer_.get()));
338 view->BeginFrameSubscription(subscriber.Pass()); 373 view->BeginFrameSubscription(subscriber.Pass());
339 } 374 }
340 375
341 // Subscribe to timer events. This instance will service these as well. 376 // Subscribe to timer events. This instance will service these as well.
342 timer_.Start(FROM_HERE, 377 timer_.Start(FROM_HERE,
343 std::max(oracle_proxy->min_capture_period(), 378 std::max(oracle_proxy->min_capture_period(),
344 base::TimeDelta::FromMilliseconds(media 379 base::TimeDelta::FromMilliseconds(media
345 ::VideoCaptureOracle::kMinTimerPollPeriodMillis)), 380 ::VideoCaptureOracle::kMinTimerPollPeriodMillis)),
346 base::Bind(&ContentCaptureSubscription::OnTimer, 381 base::Bind(&ContentCaptureSubscription::OnTimer,
347 base::Unretained(this))); 382 base::Unretained(this)));
(...skipping 15 matching lines...) Expand all
363 } 398 }
364 399
365 void ContentCaptureSubscription::OnTimer() { 400 void ContentCaptureSubscription::OnTimer() {
366 DCHECK_CURRENTLY_ON(BrowserThread::UI); 401 DCHECK_CURRENTLY_ON(BrowserThread::UI);
367 TRACE_EVENT0("gpu.capture", "ContentCaptureSubscription::OnTimer"); 402 TRACE_EVENT0("gpu.capture", "ContentCaptureSubscription::OnTimer");
368 403
369 scoped_refptr<media::VideoFrame> frame; 404 scoped_refptr<media::VideoFrame> frame;
370 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback deliver_frame_cb; 405 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback deliver_frame_cb;
371 406
372 const base::TimeTicks start_time = base::TimeTicks::Now(); 407 const base::TimeTicks start_time = base::TimeTicks::Now();
373 if (timer_subscriber_.ShouldCaptureFrame(gfx::Rect(), 408 if (timer_subscriber_->ShouldCaptureFrame(gfx::Rect(), start_time, &frame,
374 start_time, 409 &deliver_frame_cb)) {
375 &frame,
376 &deliver_frame_cb)) {
377 capture_callback_.Run(start_time, frame, deliver_frame_cb); 410 capture_callback_.Run(start_time, frame, deliver_frame_cb);
378 } 411 }
379 } 412 }
380 413
381 void RenderVideoFrame(const SkBitmap& input, 414 void RenderVideoFrame(const SkBitmap& input,
382 const scoped_refptr<media::VideoFrame>& output, 415 const scoped_refptr<media::VideoFrame>& output,
383 const base::Callback<void(bool)>& done_cb) { 416 const base::Callback<void(gfx::Rect, bool)>& done_cb) {
384 base::ScopedClosureRunner failure_handler(base::Bind(done_cb, false)); 417 base::ScopedClosureRunner failure_handler(
418 base::Bind(done_cb, gfx::Rect(), false));
385 419
386 SkAutoLockPixels locker(input); 420 SkAutoLockPixels locker(input);
387 421
388 // Sanity-check the captured bitmap. 422 // Sanity-check the captured bitmap.
389 if (input.empty() || 423 if (input.empty() ||
390 !input.readyToDraw() || 424 !input.readyToDraw() ||
391 input.colorType() != kN32_SkColorType || 425 input.colorType() != kN32_SkColorType ||
392 input.width() < 2 || input.height() < 2) { 426 input.width() < 2 || input.height() < 2) {
393 DVLOG(1) << "input unacceptable (size=" 427 DVLOG(1) << "input unacceptable (size="
394 << input.getSize() 428 << input.getSize()
(...skipping 10 matching lines...) Expand all
405 439
406 // Calculate the width and height of the content region in the |output|, based 440 // Calculate the width and height of the content region in the |output|, based
407 // on the aspect ratio of |input|. 441 // on the aspect ratio of |input|.
408 const gfx::Rect region_in_frame = media::ComputeLetterboxRegion( 442 const gfx::Rect region_in_frame = media::ComputeLetterboxRegion(
409 output->visible_rect(), gfx::Size(input.width(), input.height())); 443 output->visible_rect(), gfx::Size(input.width(), input.height()));
410 444
411 // Scale the bitmap to the required size, if necessary. 445 // Scale the bitmap to the required size, if necessary.
412 SkBitmap scaled_bitmap; 446 SkBitmap scaled_bitmap;
413 if (input.width() != region_in_frame.width() || 447 if (input.width() != region_in_frame.width() ||
414 input.height() != region_in_frame.height()) { 448 input.height() != region_in_frame.height()) {
415
416 skia::ImageOperations::ResizeMethod method; 449 skia::ImageOperations::ResizeMethod method;
417 if (input.width() < region_in_frame.width() || 450 if (input.width() < region_in_frame.width() ||
418 input.height() < region_in_frame.height()) { 451 input.height() < region_in_frame.height()) {
419 // Avoid box filtering when magnifying, because it's actually 452 // Avoid box filtering when magnifying, because it's actually
420 // nearest-neighbor. 453 // nearest-neighbor.
421 method = skia::ImageOperations::RESIZE_HAMMING1; 454 method = skia::ImageOperations::RESIZE_HAMMING1;
422 } else { 455 } else {
423 method = skia::ImageOperations::RESIZE_BOX; 456 method = skia::ImageOperations::RESIZE_BOX;
424 } 457 }
425 458
(...skipping 20 matching lines...) Expand all
446 SkAutoLockPixels scaled_bitmap_locker(scaled_bitmap); 479 SkAutoLockPixels scaled_bitmap_locker(scaled_bitmap);
447 media::CopyRGBToVideoFrame( 480 media::CopyRGBToVideoFrame(
448 reinterpret_cast<uint8*>(scaled_bitmap.getPixels()), 481 reinterpret_cast<uint8*>(scaled_bitmap.getPixels()),
449 scaled_bitmap.rowBytes(), 482 scaled_bitmap.rowBytes(),
450 region_in_yv12_frame, 483 region_in_yv12_frame,
451 output.get()); 484 output.get());
452 } 485 }
453 486
454 // The result is now ready. 487 // The result is now ready.
455 ignore_result(failure_handler.Release()); 488 ignore_result(failure_handler.Release());
456 done_cb.Run(true); 489 done_cb.Run(region_in_frame, true);
457 } 490 }
458 491
459 VideoFrameDeliveryLog::VideoFrameDeliveryLog() 492 VideoFrameDeliveryLog::VideoFrameDeliveryLog()
460 : last_frame_rate_log_time_(), 493 : last_frame_rate_log_time_(),
461 count_frames_rendered_(0) { 494 count_frames_rendered_(0) {
462 } 495 }
463 496
464 void VideoFrameDeliveryLog::ChronicleFrameDelivery(base::TimeTicks frame_time) { 497 void VideoFrameDeliveryLog::ChronicleFrameDelivery(base::TimeTicks frame_time) {
465 // Log frame rate, if verbose logging is turned on. 498 // Log frame rate, if verbose logging is turned on.
466 static const base::TimeDelta kFrameRateLogInterval = 499 static const base::TimeDelta kFrameRateLogInterval =
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 const base::TimeTicks& start_time, 623 const base::TimeTicks& start_time,
591 const scoped_refptr<media::VideoFrame>& target, 624 const scoped_refptr<media::VideoFrame>& target,
592 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback& 625 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback&
593 deliver_frame_cb) { 626 deliver_frame_cb) {
594 DCHECK_CURRENTLY_ON(BrowserThread::UI); 627 DCHECK_CURRENTLY_ON(BrowserThread::UI);
595 628
596 RenderWidgetHost* rwh = tracker_->GetTargetRenderWidgetHost(); 629 RenderWidgetHost* rwh = tracker_->GetTargetRenderWidgetHost();
597 RenderWidgetHostViewBase* view = 630 RenderWidgetHostViewBase* view =
598 rwh ? static_cast<RenderWidgetHostViewBase*>(rwh->GetView()) : NULL; 631 rwh ? static_cast<RenderWidgetHostViewBase*>(rwh->GetView()) : NULL;
599 if (!view) { 632 if (!view) {
600 deliver_frame_cb.Run(base::TimeTicks(), false); 633 deliver_frame_cb.Run(base::TimeTicks(), gfx::Rect(), false);
601 return; 634 return;
602 } 635 }
603 636
604 gfx::Size view_size = view->GetViewBounds().size(); 637 gfx::Size view_size = view->GetViewBounds().size();
605 if (view_size != last_view_size_) { 638 if (view_size != last_view_size_) {
606 last_view_size_ = view_size; 639 last_view_size_ = view_size;
607 640
608 // Measure the number of kilopixels. 641 // Measure the number of kilopixels.
609 UMA_HISTOGRAM_COUNTS_10000( 642 UMA_HISTOGRAM_COUNTS_10000(
610 "TabCapture.ViewChangeKiloPixels", 643 "TabCapture.ViewChangeKiloPixels",
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
715 if (response == READBACK_SUCCESS) { 748 if (response == READBACK_SUCCESS) {
716 UMA_HISTOGRAM_TIMES("TabCapture.CopyTimeBitmap", now - start_time); 749 UMA_HISTOGRAM_TIMES("TabCapture.CopyTimeBitmap", now - start_time);
717 TRACE_EVENT_ASYNC_STEP_INTO0("gpu.capture", "Capture", target.get(), 750 TRACE_EVENT_ASYNC_STEP_INTO0("gpu.capture", "Capture", target.get(),
718 "Render"); 751 "Render");
719 render_thread_->task_runner()->PostTask( 752 render_thread_->task_runner()->PostTask(
720 FROM_HERE, base::Bind(&RenderVideoFrame, bitmap, target, 753 FROM_HERE, base::Bind(&RenderVideoFrame, bitmap, target,
721 base::Bind(deliver_frame_cb, start_time))); 754 base::Bind(deliver_frame_cb, start_time)));
722 } else { 755 } else {
723 // Capture can fail due to transient issues, so just skip this frame. 756 // Capture can fail due to transient issues, so just skip this frame.
724 DVLOG(1) << "CopyFromBackingStore failed; skipping frame."; 757 DVLOG(1) << "CopyFromBackingStore failed; skipping frame.";
725 deliver_frame_cb.Run(start_time, false); 758 deliver_frame_cb.Run(start_time, gfx::Rect(), false);
726 } 759 }
727 } 760 }
728 761
729 void WebContentsCaptureMachine::DidCopyFromCompositingSurfaceToVideoFrame( 762 void WebContentsCaptureMachine::DidCopyFromCompositingSurfaceToVideoFrame(
730 const base::TimeTicks& start_time, 763 const base::TimeTicks& start_time,
731 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback& 764 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback&
732 deliver_frame_cb, 765 deliver_frame_cb,
766 gfx::Rect region_in_frame,
733 bool success) { 767 bool success) {
734 DCHECK_CURRENTLY_ON(BrowserThread::UI); 768 DCHECK_CURRENTLY_ON(BrowserThread::UI);
735 base::TimeTicks now = base::TimeTicks::Now(); 769 base::TimeTicks now = base::TimeTicks::Now();
736 770
737 if (success) { 771 if (success) {
738 UMA_HISTOGRAM_TIMES("TabCapture.CopyTimeVideoFrame", now - start_time); 772 UMA_HISTOGRAM_TIMES("TabCapture.CopyTimeVideoFrame", now - start_time);
739 } else { 773 } else {
740 // Capture can fail due to transient issues, so just skip this frame. 774 // Capture can fail due to transient issues, so just skip this frame.
741 DVLOG(1) << "CopyFromCompositingSurface failed; skipping frame."; 775 DVLOG(1) << "CopyFromCompositingSurface failed; skipping frame.";
742 } 776 }
743 deliver_frame_cb.Run(start_time, success); 777 deliver_frame_cb.Run(start_time, region_in_frame, success);
744 } 778 }
745 779
746 void WebContentsCaptureMachine::RenewFrameSubscription(bool had_target) { 780 void WebContentsCaptureMachine::RenewFrameSubscription(bool had_target) {
747 DCHECK_CURRENTLY_ON(BrowserThread::UI); 781 DCHECK_CURRENTLY_ON(BrowserThread::UI);
748 782
749 RenderWidgetHost* const rwh = 783 RenderWidgetHost* const rwh =
750 had_target ? tracker_->GetTargetRenderWidgetHost() : nullptr; 784 had_target ? tracker_->GetTargetRenderWidgetHost() : nullptr;
751 785
752 // Always destroy the old subscription before creating a new one. 786 // Always destroy the old subscription before creating a new one.
753 const bool had_subscription = !!subscription_; 787 const bool had_subscription = !!subscription_;
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
836 scoped_ptr<Client> client) { 870 scoped_ptr<Client> client) {
837 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString(); 871 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString();
838 core_->AllocateAndStart(params, client.Pass()); 872 core_->AllocateAndStart(params, client.Pass());
839 } 873 }
840 874
841 void WebContentsVideoCaptureDevice::StopAndDeAllocate() { 875 void WebContentsVideoCaptureDevice::StopAndDeAllocate() {
842 core_->StopAndDeAllocate(); 876 core_->StopAndDeAllocate();
843 } 877 }
844 878
845 } // namespace content 879 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698