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