OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 #include "content/browser/media/capture/desktop_capture_device.h" | 5 #include "content/browser/media/capture/desktop_capture_device.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 #include <string.h> | 9 #include <string.h> |
10 #include <utility> | 10 #include <utility> |
11 | 11 |
12 #include "base/bind.h" | 12 #include "base/bind.h" |
13 #include "base/feature_list.h" | 13 #include "base/feature_list.h" |
14 #include "base/location.h" | 14 #include "base/location.h" |
15 #include "base/logging.h" | 15 #include "base/logging.h" |
16 #include "base/macros.h" | 16 #include "base/macros.h" |
17 #include "base/message_loop/message_loop.h" | 17 #include "base/message_loop/message_loop.h" |
18 #include "base/metrics/histogram_macros.h" | 18 #include "base/metrics/histogram_macros.h" |
19 #include "base/single_thread_task_runner.h" | 19 #include "base/single_thread_task_runner.h" |
20 #include "base/strings/string_number_conversions.h" | 20 #include "base/strings/string_number_conversions.h" |
21 #include "base/synchronization/lock.h" | 21 #include "base/synchronization/lock.h" |
22 #include "base/threading/thread.h" | 22 #include "base/threading/thread.h" |
23 #include "base/threading/thread_restrictions.h" | 23 #include "base/threading/thread_restrictions.h" |
24 #include "base/timer/timer.h" | 24 #include "base/timer/timer.h" |
25 #include "build/build_config.h" | 25 #include "build/build_config.h" |
26 #include "content/browser/media/capture/desktop_capture_device_uma_types.h" | 26 #include "content/browser/media/capture/desktop_capture_device_uma_types.h" |
27 #include "content/public/browser/browser_thread.h" | 27 #include "content/public/browser/browser_thread.h" |
28 #include "content/public/browser/desktop_media_id.h" | 28 #include "content/public/browser/desktop_media_id.h" |
29 #include "content/public/common/content_switches.h" | 29 #include "content/public/common/content_switches.h" |
30 #include "device/power_save_blocker/power_save_blocker.h" | 30 #include "content/public/common/service_manager_connection.h" |
| 31 #include "device/wake_lock/public/interfaces/wake_lock_provider.mojom.h" |
| 32 #include "device/wake_lock/public/interfaces/wake_lock_service.mojom.h" |
31 #include "media/base/video_util.h" | 33 #include "media/base/video_util.h" |
32 #include "media/capture/content/capture_resolution_chooser.h" | 34 #include "media/capture/content/capture_resolution_chooser.h" |
| 35 #include "services/device/public/interfaces/constants.mojom.h" |
| 36 #include "services/service_manager/public/cpp/connector.h" |
33 #include "third_party/libyuv/include/libyuv/scale_argb.h" | 37 #include "third_party/libyuv/include/libyuv/scale_argb.h" |
34 #include "third_party/webrtc/modules/desktop_capture/cropping_window_capturer.h" | 38 #include "third_party/webrtc/modules/desktop_capture/cropping_window_capturer.h" |
35 #include "third_party/webrtc/modules/desktop_capture/desktop_and_cursor_composer
.h" | 39 #include "third_party/webrtc/modules/desktop_capture/desktop_and_cursor_composer
.h" |
36 #include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h" | 40 #include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h" |
37 #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h" | 41 #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h" |
38 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" | 42 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" |
39 #include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h" | 43 #include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h" |
40 | 44 |
41 namespace content { | 45 namespace content { |
42 | 46 |
(...skipping 13 matching lines...) Expand all Loading... |
56 gfx::Size(source_size.width(), source_size.height())); | 60 gfx::Size(source_size.width(), source_size.height())); |
57 return webrtc::DesktopRect::MakeLTRB( | 61 return webrtc::DesktopRect::MakeLTRB( |
58 result.x(), result.y(), result.right(), result.bottom()); | 62 result.x(), result.y(), result.right(), result.bottom()); |
59 } | 63 } |
60 | 64 |
61 bool IsFrameUnpackedOrInverted(webrtc::DesktopFrame* frame) { | 65 bool IsFrameUnpackedOrInverted(webrtc::DesktopFrame* frame) { |
62 return frame->stride() != | 66 return frame->stride() != |
63 frame->size().width() * webrtc::DesktopFrame::kBytesPerPixel; | 67 frame->size().width() * webrtc::DesktopFrame::kBytesPerPixel; |
64 } | 68 } |
65 | 69 |
| 70 std::unique_ptr<service_manager::Connector> GetServiceConnector() { |
| 71 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 72 |
| 73 service_manager::Connector* connector = |
| 74 ServiceManagerConnection::GetForProcess()->GetConnector(); |
| 75 |
| 76 DCHECK(connector); |
| 77 return connector->Clone(); |
| 78 } |
| 79 |
66 } // namespace | 80 } // namespace |
67 | 81 |
68 #if defined(OS_WIN) | 82 #if defined(OS_WIN) |
69 const base::Feature kDirectXCapturer{"DirectXCapturer", | 83 const base::Feature kDirectXCapturer{"DirectXCapturer", |
70 base::FEATURE_ENABLED_BY_DEFAULT}; | 84 base::FEATURE_ENABLED_BY_DEFAULT}; |
71 #endif | 85 #endif |
72 | 86 |
73 class DesktopCaptureDevice::Core : public webrtc::DesktopCapturer::Callback { | 87 class DesktopCaptureDevice::Core : public webrtc::DesktopCapturer::Callback { |
74 public: | 88 public: |
75 Core(scoped_refptr<base::SingleThreadTaskRunner> task_runner, | 89 Core(scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
(...skipping 16 matching lines...) Expand all Loading... |
92 // Method that is scheduled on |task_runner_| to be called on regular interval | 106 // Method that is scheduled on |task_runner_| to be called on regular interval |
93 // to capture a frame. | 107 // to capture a frame. |
94 void OnCaptureTimer(); | 108 void OnCaptureTimer(); |
95 | 109 |
96 // Captures a frame and schedules timer for the next one. | 110 // Captures a frame and schedules timer for the next one. |
97 void CaptureFrameAndScheduleNext(); | 111 void CaptureFrameAndScheduleNext(); |
98 | 112 |
99 // Captures a single frame. | 113 // Captures a single frame. |
100 void DoCapture(); | 114 void DoCapture(); |
101 | 115 |
| 116 void RequestWakeLock(std::unique_ptr<service_manager::Connector> connector); |
| 117 |
102 // Task runner used for capturing operations. | 118 // Task runner used for capturing operations. |
103 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | 119 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
104 | 120 |
105 // The underlying DesktopCapturer instance used to capture frames. | 121 // The underlying DesktopCapturer instance used to capture frames. |
106 std::unique_ptr<webrtc::DesktopCapturer> desktop_capturer_; | 122 std::unique_ptr<webrtc::DesktopCapturer> desktop_capturer_; |
107 | 123 |
108 // The device client which proxies device events to the controller. Accessed | 124 // The device client which proxies device events to the controller. Accessed |
109 // on the task_runner_ thread. | 125 // on the task_runner_ thread. |
110 std::unique_ptr<Client> client_; | 126 std::unique_ptr<Client> client_; |
111 | 127 |
(...skipping 22 matching lines...) Expand all Loading... |
134 bool first_capture_returned_; | 150 bool first_capture_returned_; |
135 | 151 |
136 // The type of the capturer. | 152 // The type of the capturer. |
137 DesktopMediaID::Type capturer_type_; | 153 DesktopMediaID::Type capturer_type_; |
138 | 154 |
139 // The system time when we receive the first frame. | 155 // The system time when we receive the first frame. |
140 base::TimeTicks first_ref_time_; | 156 base::TimeTicks first_ref_time_; |
141 | 157 |
142 std::unique_ptr<webrtc::BasicDesktopFrame> black_frame_; | 158 std::unique_ptr<webrtc::BasicDesktopFrame> black_frame_; |
143 | 159 |
144 // TODO(jiayl): Remove power_save_blocker_ when there is an API to keep the | 160 // TODO(jiayl): Remove wake_lock_ when there is an API to keep the |
145 // screen from sleeping for the drive-by web. | 161 // screen from sleeping for the drive-by web. |
146 std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_; | 162 device::mojom::WakeLockServicePtr wake_lock_; |
| 163 |
| 164 base::WeakPtrFactory<Core> weak_factory_; |
147 | 165 |
148 DISALLOW_COPY_AND_ASSIGN(Core); | 166 DISALLOW_COPY_AND_ASSIGN(Core); |
149 }; | 167 }; |
150 | 168 |
151 DesktopCaptureDevice::Core::Core( | 169 DesktopCaptureDevice::Core::Core( |
152 scoped_refptr<base::SingleThreadTaskRunner> task_runner, | 170 scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
153 std::unique_ptr<webrtc::DesktopCapturer> capturer, | 171 std::unique_ptr<webrtc::DesktopCapturer> capturer, |
154 DesktopMediaID::Type type) | 172 DesktopMediaID::Type type) |
155 : task_runner_(task_runner), | 173 : task_runner_(task_runner), |
156 desktop_capturer_(std::move(capturer)), | 174 desktop_capturer_(std::move(capturer)), |
157 capture_in_progress_(false), | 175 capture_in_progress_(false), |
158 first_capture_returned_(false), | 176 first_capture_returned_(false), |
159 capturer_type_(type) {} | 177 capturer_type_(type), |
| 178 weak_factory_(this) {} |
160 | 179 |
161 DesktopCaptureDevice::Core::~Core() { | 180 DesktopCaptureDevice::Core::~Core() { |
162 DCHECK(task_runner_->BelongsToCurrentThread()); | 181 DCHECK(task_runner_->BelongsToCurrentThread()); |
163 client_.reset(); | 182 client_.reset(); |
164 output_frame_.reset(); | 183 output_frame_.reset(); |
165 previous_frame_size_.set(0, 0); | 184 previous_frame_size_.set(0, 0); |
166 desktop_capturer_.reset(); | 185 desktop_capturer_.reset(); |
167 } | 186 } |
168 | 187 |
169 void DesktopCaptureDevice::Core::AllocateAndStart( | 188 void DesktopCaptureDevice::Core::AllocateAndStart( |
170 const media::VideoCaptureParams& params, | 189 const media::VideoCaptureParams& params, |
171 std::unique_ptr<Client> client) { | 190 std::unique_ptr<Client> client) { |
172 DCHECK(task_runner_->BelongsToCurrentThread()); | 191 DCHECK(task_runner_->BelongsToCurrentThread()); |
173 DCHECK_GT(params.requested_format.frame_size.GetArea(), 0); | 192 DCHECK_GT(params.requested_format.frame_size.GetArea(), 0); |
174 DCHECK_GT(params.requested_format.frame_rate, 0); | 193 DCHECK_GT(params.requested_format.frame_rate, 0); |
175 DCHECK(desktop_capturer_); | 194 DCHECK(desktop_capturer_); |
176 DCHECK(client); | 195 DCHECK(client); |
177 DCHECK(!client_); | 196 DCHECK(!client_); |
178 | 197 |
179 client_ = std::move(client); | 198 client_ = std::move(client); |
180 requested_frame_rate_ = params.requested_format.frame_rate; | 199 requested_frame_rate_ = params.requested_format.frame_rate; |
181 resolution_chooser_.reset(new media::CaptureResolutionChooser( | 200 resolution_chooser_.reset(new media::CaptureResolutionChooser( |
182 params.requested_format.frame_size, | 201 params.requested_format.frame_size, |
183 params.resolution_change_policy)); | 202 params.resolution_change_policy)); |
184 | 203 |
185 power_save_blocker_.reset(new device::PowerSaveBlocker( | 204 DCHECK(!wake_lock_); |
186 device::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, | 205 // Gets a service_manager::Connector first, then request a wake lock. |
187 device::PowerSaveBlocker::kReasonOther, "DesktopCaptureDevice is running", | 206 BrowserThread::PostTaskAndReplyWithResult( |
188 BrowserThread::GetTaskRunnerForThread(BrowserThread::UI), | 207 BrowserThread::UI, FROM_HERE, base::BindOnce(&GetServiceConnector), |
189 BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE))); | 208 base::BindOnce(&DesktopCaptureDevice::Core::RequestWakeLock, |
| 209 weak_factory_.GetWeakPtr())); |
190 | 210 |
191 desktop_capturer_->Start(this); | 211 desktop_capturer_->Start(this); |
192 // Assume it will be always started successfully for now. | 212 // Assume it will be always started successfully for now. |
193 client_->OnStarted(); | 213 client_->OnStarted(); |
194 | 214 |
195 CaptureFrameAndScheduleNext(); | 215 CaptureFrameAndScheduleNext(); |
196 } | 216 } |
197 | 217 |
198 void DesktopCaptureDevice::Core::SetNotificationWindowId( | 218 void DesktopCaptureDevice::Core::SetNotificationWindowId( |
199 gfx::NativeViewId window_id) { | 219 gfx::NativeViewId window_id) { |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 DCHECK(!capture_in_progress_); | 378 DCHECK(!capture_in_progress_); |
359 | 379 |
360 capture_in_progress_ = true; | 380 capture_in_progress_ = true; |
361 desktop_capturer_->CaptureFrame(); | 381 desktop_capturer_->CaptureFrame(); |
362 | 382 |
363 // Currently only synchronous implementations of DesktopCapturer are | 383 // Currently only synchronous implementations of DesktopCapturer are |
364 // supported. | 384 // supported. |
365 DCHECK(!capture_in_progress_); | 385 DCHECK(!capture_in_progress_); |
366 } | 386 } |
367 | 387 |
| 388 void DesktopCaptureDevice::Core::RequestWakeLock( |
| 389 std::unique_ptr<service_manager::Connector> connector) { |
| 390 device::mojom::WakeLockProviderPtr wake_lock_provider; |
| 391 connector->BindInterface(device::mojom::kServiceName, |
| 392 mojo::MakeRequest(&wake_lock_provider)); |
| 393 wake_lock_provider->GetWakeLockWithoutContext( |
| 394 device::mojom::WakeLockType::PreventDisplaySleep, |
| 395 device::mojom::WakeLockReason::ReasonOther, "Desktop capture is running", |
| 396 mojo::MakeRequest(&wake_lock_)); |
| 397 |
| 398 wake_lock_->RequestWakeLock(); |
| 399 } |
| 400 |
368 // static | 401 // static |
369 std::unique_ptr<media::VideoCaptureDevice> DesktopCaptureDevice::Create( | 402 std::unique_ptr<media::VideoCaptureDevice> DesktopCaptureDevice::Create( |
370 const DesktopMediaID& source) { | 403 const DesktopMediaID& source) { |
371 webrtc::DesktopCaptureOptions options = | 404 webrtc::DesktopCaptureOptions options = |
372 webrtc::DesktopCaptureOptions::CreateDefault(); | 405 webrtc::DesktopCaptureOptions::CreateDefault(); |
373 // Leave desktop effects enabled during WebRTC captures. | 406 // Leave desktop effects enabled during WebRTC captures. |
374 options.set_disable_effects(false); | 407 options.set_disable_effects(false); |
375 | 408 |
376 #if defined(OS_WIN) | 409 #if defined(OS_WIN) |
377 if (!base::FeatureList::IsEnabled(kDirectXCapturer)) { | 410 if (!base::FeatureList::IsEnabled(kDirectXCapturer)) { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 thread_.Stop(); | 476 thread_.Stop(); |
444 } | 477 } |
445 } | 478 } |
446 | 479 |
447 void DesktopCaptureDevice::SetNotificationWindowId( | 480 void DesktopCaptureDevice::SetNotificationWindowId( |
448 gfx::NativeViewId window_id) { | 481 gfx::NativeViewId window_id) { |
449 // This may be called after the capturer has been stopped. | 482 // This may be called after the capturer has been stopped. |
450 if (!core_) | 483 if (!core_) |
451 return; | 484 return; |
452 thread_.task_runner()->PostTask( | 485 thread_.task_runner()->PostTask( |
453 FROM_HERE, | 486 FROM_HERE, base::Bind(&Core::SetNotificationWindowId, |
454 base::Bind(&Core::SetNotificationWindowId, | 487 base::Unretained(core_.get()), window_id)); |
455 base::Unretained(core_.get()), | |
456 window_id)); | |
457 } | 488 } |
458 | 489 |
459 DesktopCaptureDevice::DesktopCaptureDevice( | 490 DesktopCaptureDevice::DesktopCaptureDevice( |
460 std::unique_ptr<webrtc::DesktopCapturer> capturer, | 491 std::unique_ptr<webrtc::DesktopCapturer> capturer, |
461 DesktopMediaID::Type type) | 492 DesktopMediaID::Type type) |
462 : thread_("desktopCaptureThread") { | 493 : thread_("desktopCaptureThread") { |
463 #if defined(OS_WIN) | 494 #if defined(OS_WIN) |
464 // On Windows the thread must be a UI thread. | 495 // On Windows the thread must be a UI thread. |
465 base::MessageLoop::Type thread_type = base::MessageLoop::TYPE_UI; | 496 base::MessageLoop::Type thread_type = base::MessageLoop::TYPE_UI; |
466 #else | 497 #else |
467 base::MessageLoop::Type thread_type = base::MessageLoop::TYPE_DEFAULT; | 498 base::MessageLoop::Type thread_type = base::MessageLoop::TYPE_DEFAULT; |
468 #endif | 499 #endif |
469 | 500 |
470 thread_.StartWithOptions(base::Thread::Options(thread_type, 0)); | 501 thread_.StartWithOptions(base::Thread::Options(thread_type, 0)); |
471 | 502 |
472 core_.reset(new Core(thread_.task_runner(), std::move(capturer), type)); | 503 core_.reset(new Core(thread_.task_runner(), std::move(capturer), type)); |
473 } | 504 } |
474 | 505 |
475 } // namespace content | 506 } // namespace content |
OLD | NEW |