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 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 base::WeakPtrFactory<WebContentsCaptureMachine> weak_ptr_factory_; | 287 base::WeakPtrFactory<WebContentsCaptureMachine> weak_ptr_factory_; |
288 | 288 |
289 DISALLOW_COPY_AND_ASSIGN(WebContentsCaptureMachine); | 289 DISALLOW_COPY_AND_ASSIGN(WebContentsCaptureMachine); |
290 }; | 290 }; |
291 | 291 |
292 bool FrameSubscriber::ShouldCaptureFrame( | 292 bool FrameSubscriber::ShouldCaptureFrame( |
293 const gfx::Rect& damage_rect, | 293 const gfx::Rect& damage_rect, |
294 base::TimeTicks present_time, | 294 base::TimeTicks present_time, |
295 scoped_refptr<media::VideoFrame>* storage, | 295 scoped_refptr<media::VideoFrame>* storage, |
296 DeliverFrameCallback* deliver_frame_cb) { | 296 DeliverFrameCallback* deliver_frame_cb) { |
297 TRACE_EVENT1("mirroring", "FrameSubscriber::ShouldCaptureFrame", | 297 TRACE_EVENT1("gpu.capture", "FrameSubscriber::ShouldCaptureFrame", |
298 "instance", this); | 298 "instance", this); |
299 | 299 |
300 ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb; | 300 ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb; |
301 bool oracle_decision = oracle_proxy_->ObserveEventAndDecideCapture( | 301 bool oracle_decision = oracle_proxy_->ObserveEventAndDecideCapture( |
302 event_type_, damage_rect, present_time, storage, &capture_frame_cb); | 302 event_type_, damage_rect, present_time, storage, &capture_frame_cb); |
303 | 303 |
304 if (!capture_frame_cb.is_null()) | 304 if (!capture_frame_cb.is_null()) |
305 *deliver_frame_cb = base::Bind(capture_frame_cb, *storage); | 305 *deliver_frame_cb = base::Bind(capture_frame_cb, *storage); |
306 if (oracle_decision) | 306 if (oracle_decision) |
307 delivery_log_->ChronicleFrameDelivery(present_time); | 307 delivery_log_->ChronicleFrameDelivery(present_time); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 348 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
349 RenderWidgetHost* const source = | 349 RenderWidgetHost* const source = |
350 RenderWidgetHost::FromID(render_process_id_, render_widget_id_); | 350 RenderWidgetHost::FromID(render_process_id_, render_widget_id_); |
351 RenderWidgetHostView* const view = source ? source->GetView() : NULL; | 351 RenderWidgetHostView* const view = source ? source->GetView() : NULL; |
352 if (view) | 352 if (view) |
353 view->EndFrameSubscription(); | 353 view->EndFrameSubscription(); |
354 } | 354 } |
355 | 355 |
356 void ContentCaptureSubscription::OnTimer() { | 356 void ContentCaptureSubscription::OnTimer() { |
357 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 357 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
358 TRACE_EVENT0("mirroring", "ContentCaptureSubscription::OnTimer"); | 358 TRACE_EVENT0("gpu.capture", "ContentCaptureSubscription::OnTimer"); |
359 | 359 |
360 scoped_refptr<media::VideoFrame> frame; | 360 scoped_refptr<media::VideoFrame> frame; |
361 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback deliver_frame_cb; | 361 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback deliver_frame_cb; |
362 | 362 |
363 const base::TimeTicks start_time = base::TimeTicks::Now(); | 363 const base::TimeTicks start_time = base::TimeTicks::Now(); |
364 if (timer_subscriber_.ShouldCaptureFrame(gfx::Rect(), | 364 if (timer_subscriber_.ShouldCaptureFrame(gfx::Rect(), |
365 start_time, | 365 start_time, |
366 &frame, | 366 &frame, |
367 &deliver_frame_cb)) { | 367 &deliver_frame_cb)) { |
368 capture_callback_.Run(start_time, frame, deliver_frame_cb); | 368 capture_callback_.Run(start_time, frame, deliver_frame_cb); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 skia::ImageOperations::ResizeMethod method; | 407 skia::ImageOperations::ResizeMethod method; |
408 if (input.width() < region_in_frame.width() || | 408 if (input.width() < region_in_frame.width() || |
409 input.height() < region_in_frame.height()) { | 409 input.height() < region_in_frame.height()) { |
410 // Avoid box filtering when magnifying, because it's actually | 410 // Avoid box filtering when magnifying, because it's actually |
411 // nearest-neighbor. | 411 // nearest-neighbor. |
412 method = skia::ImageOperations::RESIZE_HAMMING1; | 412 method = skia::ImageOperations::RESIZE_HAMMING1; |
413 } else { | 413 } else { |
414 method = skia::ImageOperations::RESIZE_BOX; | 414 method = skia::ImageOperations::RESIZE_BOX; |
415 } | 415 } |
416 | 416 |
417 TRACE_EVENT_ASYNC_STEP_INTO0("mirroring", "Capture", output.get(), "Scale"); | 417 TRACE_EVENT_ASYNC_STEP_INTO0("gpu.capture", |
| 418 "Capture", output.get(), "Scale"); |
418 scaled_bitmap = skia::ImageOperations::Resize(input, method, | 419 scaled_bitmap = skia::ImageOperations::Resize(input, method, |
419 region_in_frame.width(), | 420 region_in_frame.width(), |
420 region_in_frame.height()); | 421 region_in_frame.height()); |
421 } else { | 422 } else { |
422 scaled_bitmap = input; | 423 scaled_bitmap = input; |
423 } | 424 } |
424 | 425 |
425 TRACE_EVENT_ASYNC_STEP_INTO0("mirroring", "Capture", output.get(), "YUV"); | 426 TRACE_EVENT_ASYNC_STEP_INTO0("gpu.capture", "Capture", output.get(), "YUV"); |
426 { | 427 { |
427 SkAutoLockPixels scaled_bitmap_locker(scaled_bitmap); | 428 SkAutoLockPixels scaled_bitmap_locker(scaled_bitmap); |
428 | 429 |
429 media::CopyRGBToVideoFrame( | 430 media::CopyRGBToVideoFrame( |
430 reinterpret_cast<uint8*>(scaled_bitmap.getPixels()), | 431 reinterpret_cast<uint8*>(scaled_bitmap.getPixels()), |
431 scaled_bitmap.rowBytes(), | 432 scaled_bitmap.rowBytes(), |
432 region_in_frame, | 433 region_in_frame, |
433 output.get()); | 434 output.get()); |
434 } | 435 } |
435 | 436 |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
620 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback& | 621 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback& |
621 deliver_frame_cb, | 622 deliver_frame_cb, |
622 const SkBitmap& bitmap, | 623 const SkBitmap& bitmap, |
623 ReadbackResponse response) { | 624 ReadbackResponse response) { |
624 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 625 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
625 | 626 |
626 base::TimeTicks now = base::TimeTicks::Now(); | 627 base::TimeTicks now = base::TimeTicks::Now(); |
627 DCHECK(render_thread_.get()); | 628 DCHECK(render_thread_.get()); |
628 if (response == READBACK_SUCCESS) { | 629 if (response == READBACK_SUCCESS) { |
629 UMA_HISTOGRAM_TIMES("TabCapture.CopyTimeBitmap", now - start_time); | 630 UMA_HISTOGRAM_TIMES("TabCapture.CopyTimeBitmap", now - start_time); |
630 TRACE_EVENT_ASYNC_STEP_INTO0("mirroring", "Capture", target.get(), | 631 TRACE_EVENT_ASYNC_STEP_INTO0("gpu.capture", "Capture", target.get(), |
631 "Render"); | 632 "Render"); |
632 render_thread_->message_loop_proxy()->PostTask(FROM_HERE, base::Bind( | 633 render_thread_->message_loop_proxy()->PostTask(FROM_HERE, base::Bind( |
633 &RenderVideoFrame, bitmap, target, | 634 &RenderVideoFrame, bitmap, target, |
634 base::Bind(deliver_frame_cb, start_time))); | 635 base::Bind(deliver_frame_cb, start_time))); |
635 } else { | 636 } else { |
636 // Capture can fail due to transient issues, so just skip this frame. | 637 // Capture can fail due to transient issues, so just skip this frame. |
637 DVLOG(1) << "CopyFromBackingStore failed; skipping frame."; | 638 DVLOG(1) << "CopyFromBackingStore failed; skipping frame."; |
638 deliver_frame_cb.Run(start_time, false); | 639 deliver_frame_cb.Run(start_time, false); |
639 } | 640 } |
640 } | 641 } |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
719 scoped_ptr<Client> client) { | 720 scoped_ptr<Client> client) { |
720 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString(); | 721 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString(); |
721 core_->AllocateAndStart(params, client.Pass()); | 722 core_->AllocateAndStart(params, client.Pass()); |
722 } | 723 } |
723 | 724 |
724 void WebContentsVideoCaptureDevice::StopAndDeAllocate() { | 725 void WebContentsVideoCaptureDevice::StopAndDeAllocate() { |
725 core_->StopAndDeAllocate(); | 726 core_->StopAndDeAllocate(); |
726 } | 727 } |
727 | 728 |
728 } // namespace content | 729 } // namespace content |
OLD | NEW |