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 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
635 } | 635 } |
636 | 636 |
637 gfx::Size WebContentsCaptureMachine::ComputeOptimalViewSize() const { | 637 gfx::Size WebContentsCaptureMachine::ComputeOptimalViewSize() const { |
638 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 638 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
639 | 639 |
640 // TODO(miu): Propagate capture frame size changes as new "preferred size" | 640 // TODO(miu): Propagate capture frame size changes as new "preferred size" |
641 // updates, rather than just using the max frame size. | 641 // updates, rather than just using the max frame size. |
642 // http://crbug.com/350491 | 642 // http://crbug.com/350491 |
643 gfx::Size optimal_size = oracle_proxy_->max_frame_size(); | 643 gfx::Size optimal_size = oracle_proxy_->max_frame_size(); |
644 | 644 |
| 645 switch (capture_params_.resolution_change_policy) { |
| 646 case media::RESOLUTION_POLICY_FIXED_RESOLUTION: |
| 647 break; |
| 648 case media::RESOLUTION_POLICY_FIXED_ASPECT_RATIO: |
| 649 case media::RESOLUTION_POLICY_ANY_WITHIN_LIMIT: { |
| 650 // If the max frame size is close to a common video aspect ratio, compute |
| 651 // a standard resolution for that aspect ratio. For example, given |
| 652 // 1365x768, which is very close to 16:9, the optimal size would be |
| 653 // 1280x720. The purpose of this logic is to prevent scaling quality |
| 654 // issues caused by "one pixel stretching" and/or odd-to-even dimension |
| 655 // scaling, and to improve the performance of consumers of the captured |
| 656 // video. |
| 657 const auto HasIntendedAspectRatio = |
| 658 [](const gfx::Size& size, int width_units, int height_units) { |
| 659 const int a = height_units * size.width(); |
| 660 const int b = width_units * size.height(); |
| 661 const int percentage_diff = 100 * std::abs((a - b)) / b; |
| 662 return percentage_diff <= 1; // Effectively, anything strictly <2%. |
| 663 }; |
| 664 const auto RoundToExactAspectRatio = |
| 665 [](const gfx::Size& size, int width_step, int height_step) { |
| 666 const int adjusted_height = |
| 667 std::max(size.height() - (size.height() % height_step), |
| 668 height_step); |
| 669 DCHECK_EQ((adjusted_height * width_step) % height_step, 0); |
| 670 return gfx::Size(adjusted_height * width_step / height_step, |
| 671 adjusted_height); |
| 672 }; |
| 673 if (HasIntendedAspectRatio(optimal_size, 16, 9)) |
| 674 optimal_size = RoundToExactAspectRatio(optimal_size, 160, 90); |
| 675 else if (HasIntendedAspectRatio(optimal_size, 4, 3)) |
| 676 optimal_size = RoundToExactAspectRatio(optimal_size, 64, 48); |
| 677 // Else, do not make an adjustment. |
| 678 break; |
| 679 } |
| 680 } |
| 681 |
645 // If the ratio between physical and logical pixels is greater than 1:1, | 682 // If the ratio between physical and logical pixels is greater than 1:1, |
646 // shrink |optimal_size| by that amount. Then, when external code resizes the | 683 // shrink |optimal_size| by that amount. Then, when external code resizes the |
647 // render widget to the "preferred size," the widget will be physically | 684 // render widget to the "preferred size," the widget will be physically |
648 // rendered at the exact capture size, thereby eliminating unnecessary scaling | 685 // rendered at the exact capture size, thereby eliminating unnecessary scaling |
649 // operations in the graphics pipeline. | 686 // operations in the graphics pipeline. |
650 RenderWidgetHost* const rwh = tracker_->GetTargetRenderWidgetHost(); | 687 RenderWidgetHost* const rwh = tracker_->GetTargetRenderWidgetHost(); |
651 RenderWidgetHostView* const rwhv = rwh ? rwh->GetView() : NULL; | 688 RenderWidgetHostView* const rwhv = rwh ? rwh->GetView() : NULL; |
652 if (rwhv) { | 689 if (rwhv) { |
653 const gfx::NativeView view = rwhv->GetNativeView(); | 690 const gfx::NativeView view = rwhv->GetNativeView(); |
654 const float scale = ui::GetScaleFactorForNativeView(view); | 691 const float scale = ui::GetScaleFactorForNativeView(view); |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
799 scoped_ptr<Client> client) { | 836 scoped_ptr<Client> client) { |
800 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString(); | 837 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString(); |
801 core_->AllocateAndStart(params, client.Pass()); | 838 core_->AllocateAndStart(params, client.Pass()); |
802 } | 839 } |
803 | 840 |
804 void WebContentsVideoCaptureDevice::StopAndDeAllocate() { | 841 void WebContentsVideoCaptureDevice::StopAndDeAllocate() { |
805 core_->StopAndDeAllocate(); | 842 core_->StopAndDeAllocate(); |
806 } | 843 } |
807 | 844 |
808 } // namespace content | 845 } // namespace content |
OLD | NEW |