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 "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/location.h" | 8 #include "base/location.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/metrics/histogram.h" |
10 #include "base/sequenced_task_runner.h" | 11 #include "base/sequenced_task_runner.h" |
11 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
12 #include "base/synchronization/lock.h" | 13 #include "base/synchronization/lock.h" |
13 #include "base/threading/sequenced_worker_pool.h" | 14 #include "base/threading/sequenced_worker_pool.h" |
| 15 #include "content/browser/media/capture/desktop_capture_device_uma_types.h" |
14 #include "content/public/browser/browser_thread.h" | 16 #include "content/public/browser/browser_thread.h" |
15 #include "content/public/browser/desktop_media_id.h" | 17 #include "content/public/browser/desktop_media_id.h" |
16 #include "media/base/video_util.h" | 18 #include "media/base/video_util.h" |
17 #include "third_party/libyuv/include/libyuv/scale_argb.h" | 19 #include "third_party/libyuv/include/libyuv/scale_argb.h" |
18 #include "third_party/webrtc/modules/desktop_capture/desktop_and_cursor_composer
.h" | 20 #include "third_party/webrtc/modules/desktop_capture/desktop_and_cursor_composer
.h" |
19 #include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h" | 21 #include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h" |
20 #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h" | 22 #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h" |
21 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" | 23 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" |
22 #include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h" | 24 #include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h" |
23 #include "third_party/webrtc/modules/desktop_capture/screen_capturer.h" | 25 #include "third_party/webrtc/modules/desktop_capture/screen_capturer.h" |
(...skipping 19 matching lines...) Expand all Loading... |
43 result.x(), result.y(), result.right(), result.bottom()); | 45 result.x(), result.y(), result.right(), result.bottom()); |
44 } | 46 } |
45 | 47 |
46 } // namespace | 48 } // namespace |
47 | 49 |
48 class DesktopCaptureDevice::Core | 50 class DesktopCaptureDevice::Core |
49 : public base::RefCountedThreadSafe<Core>, | 51 : public base::RefCountedThreadSafe<Core>, |
50 public webrtc::DesktopCapturer::Callback { | 52 public webrtc::DesktopCapturer::Callback { |
51 public: | 53 public: |
52 Core(scoped_refptr<base::SequencedTaskRunner> task_runner, | 54 Core(scoped_refptr<base::SequencedTaskRunner> task_runner, |
53 scoped_ptr<webrtc::DesktopCapturer> capturer); | 55 scoped_ptr<webrtc::DesktopCapturer> capturer, |
| 56 DesktopMediaID::Type type); |
54 | 57 |
55 // Implementation of VideoCaptureDevice methods. | 58 // Implementation of VideoCaptureDevice methods. |
56 void AllocateAndStart(const media::VideoCaptureParams& params, | 59 void AllocateAndStart(const media::VideoCaptureParams& params, |
57 scoped_ptr<Client> client); | 60 scoped_ptr<Client> client); |
58 void StopAndDeAllocate(); | 61 void StopAndDeAllocate(); |
59 | 62 |
60 void SetNotificationWindowId(gfx::NativeViewId window_id); | 63 void SetNotificationWindowId(gfx::NativeViewId window_id); |
61 | 64 |
62 private: | 65 private: |
63 friend class base::RefCountedThreadSafe<Core>; | 66 friend class base::RefCountedThreadSafe<Core>; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 // and/or letterboxed. | 121 // and/or letterboxed. |
119 webrtc::DesktopRect output_rect_; | 122 webrtc::DesktopRect output_rect_; |
120 | 123 |
121 // True when we have delayed OnCaptureTimer() task posted on | 124 // True when we have delayed OnCaptureTimer() task posted on |
122 // |task_runner_|. | 125 // |task_runner_|. |
123 bool capture_task_posted_; | 126 bool capture_task_posted_; |
124 | 127 |
125 // True when waiting for |desktop_capturer_| to capture current frame. | 128 // True when waiting for |desktop_capturer_| to capture current frame. |
126 bool capture_in_progress_; | 129 bool capture_in_progress_; |
127 | 130 |
| 131 // The type of the capturer. |
| 132 DesktopMediaID::Type capturer_type_; |
| 133 |
128 DISALLOW_COPY_AND_ASSIGN(Core); | 134 DISALLOW_COPY_AND_ASSIGN(Core); |
129 }; | 135 }; |
130 | 136 |
131 DesktopCaptureDevice::Core::Core( | 137 DesktopCaptureDevice::Core::Core( |
132 scoped_refptr<base::SequencedTaskRunner> task_runner, | 138 scoped_refptr<base::SequencedTaskRunner> task_runner, |
133 scoped_ptr<webrtc::DesktopCapturer> capturer) | 139 scoped_ptr<webrtc::DesktopCapturer> capturer, |
| 140 DesktopMediaID::Type type) |
134 : task_runner_(task_runner), | 141 : task_runner_(task_runner), |
135 desktop_capturer_(capturer.Pass()), | 142 desktop_capturer_(capturer.Pass()), |
136 capture_task_posted_(false), | 143 capture_task_posted_(false), |
137 capture_in_progress_(false) {} | 144 capture_in_progress_(false), |
| 145 capturer_type_(type) { |
| 146 } |
138 | 147 |
139 DesktopCaptureDevice::Core::~Core() { | 148 DesktopCaptureDevice::Core::~Core() { |
140 } | 149 } |
141 | 150 |
142 void DesktopCaptureDevice::Core::AllocateAndStart( | 151 void DesktopCaptureDevice::Core::AllocateAndStart( |
143 const media::VideoCaptureParams& params, | 152 const media::VideoCaptureParams& params, |
144 scoped_ptr<Client> client) { | 153 scoped_ptr<Client> client) { |
145 DCHECK_GT(params.requested_format.frame_size.GetArea(), 0); | 154 DCHECK_GT(params.requested_format.frame_size.GetArea(), 0); |
146 DCHECK_GT(params.requested_format.frame_rate, 0); | 155 DCHECK_GT(params.requested_format.frame_rate, 0); |
147 | 156 |
(...skipping 17 matching lines...) Expand all Loading... |
165 webrtc::SharedMemory* | 174 webrtc::SharedMemory* |
166 DesktopCaptureDevice::Core::CreateSharedMemory(size_t size) { | 175 DesktopCaptureDevice::Core::CreateSharedMemory(size_t size) { |
167 return NULL; | 176 return NULL; |
168 } | 177 } |
169 | 178 |
170 void DesktopCaptureDevice::Core::OnCaptureCompleted( | 179 void DesktopCaptureDevice::Core::OnCaptureCompleted( |
171 webrtc::DesktopFrame* frame) { | 180 webrtc::DesktopFrame* frame) { |
172 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 181 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
173 DCHECK(capture_in_progress_); | 182 DCHECK(capture_in_progress_); |
174 | 183 |
| 184 static bool first_call = true; |
| 185 if (first_call) { |
| 186 first_call = false; |
| 187 if (capturer_type_ == DesktopMediaID::TYPE_SCREEN) { |
| 188 IncrementDesktopCaptureCounter(frame ? FIRST_SCREEN_CAPTURE_SUCCEEDED |
| 189 : FIRST_SCREEN_CAPTURE_FAILED); |
| 190 } else { |
| 191 IncrementDesktopCaptureCounter(frame ? FIRST_WINDOW_CAPTURE_SUCCEEDED |
| 192 : FIRST_WINDOW_CAPTURE_FAILED); |
| 193 } |
| 194 } |
| 195 |
175 capture_in_progress_ = false; | 196 capture_in_progress_ = false; |
176 | 197 |
177 if (!frame) { | 198 if (!frame) { |
178 std::string log("Failed to capture a frame."); | 199 std::string log("Failed to capture a frame."); |
179 LOG(ERROR) << log; | 200 LOG(ERROR) << log; |
180 client_->OnError(log); | 201 client_->OnError(log); |
181 return; | 202 return; |
182 } | 203 } |
183 | 204 |
184 if (!client_) | 205 if (!client_) |
185 return; | 206 return; |
186 | 207 |
| 208 base::TimeDelta capture_time( |
| 209 base::TimeDelta::FromMilliseconds(frame->capture_time_ms())); |
| 210 UMA_HISTOGRAM_TIMES( |
| 211 capturer_type_ == DesktopMediaID::TYPE_SCREEN ? kUmaScreenCaptureTime |
| 212 : kUmaWindowCaptureTime, |
| 213 capture_time); |
| 214 |
187 scoped_ptr<webrtc::DesktopFrame> owned_frame(frame); | 215 scoped_ptr<webrtc::DesktopFrame> owned_frame(frame); |
188 | 216 |
189 // Handle initial frame size and size changes. | 217 // Handle initial frame size and size changes. |
190 RefreshCaptureFormat(frame->size()); | 218 RefreshCaptureFormat(frame->size()); |
191 | 219 |
192 webrtc::DesktopSize output_size(capture_format_.frame_size.width(), | 220 webrtc::DesktopSize output_size(capture_format_.frame_size.width(), |
193 capture_format_.frame_size.height()); | 221 capture_format_.frame_size.height()); |
194 size_t output_bytes = output_size.width() * output_size.height() * | 222 size_t output_bytes = output_size.width() * output_size.height() * |
195 webrtc::DesktopFrame::kBytesPerPixel; | 223 webrtc::DesktopFrame::kBytesPerPixel; |
196 const uint8_t* output_data = NULL; | 224 const uint8_t* output_data = NULL; |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 scoped_ptr<webrtc::DesktopCapturer> capturer; | 410 scoped_ptr<webrtc::DesktopCapturer> capturer; |
383 | 411 |
384 switch (source.type) { | 412 switch (source.type) { |
385 case DesktopMediaID::TYPE_SCREEN: { | 413 case DesktopMediaID::TYPE_SCREEN: { |
386 scoped_ptr<webrtc::ScreenCapturer> screen_capturer; | 414 scoped_ptr<webrtc::ScreenCapturer> screen_capturer; |
387 screen_capturer.reset(webrtc::ScreenCapturer::Create(options)); | 415 screen_capturer.reset(webrtc::ScreenCapturer::Create(options)); |
388 if (screen_capturer && screen_capturer->SelectScreen(source.id)) { | 416 if (screen_capturer && screen_capturer->SelectScreen(source.id)) { |
389 capturer.reset(new webrtc::DesktopAndCursorComposer( | 417 capturer.reset(new webrtc::DesktopAndCursorComposer( |
390 screen_capturer.release(), | 418 screen_capturer.release(), |
391 webrtc::MouseCursorMonitor::CreateForScreen(options, source.id))); | 419 webrtc::MouseCursorMonitor::CreateForScreen(options, source.id))); |
| 420 IncrementDesktopCaptureCounter(SCREEN_CAPTURER_CREATED); |
392 } | 421 } |
393 break; | 422 break; |
394 } | 423 } |
395 | 424 |
396 case DesktopMediaID::TYPE_WINDOW: { | 425 case DesktopMediaID::TYPE_WINDOW: { |
397 scoped_ptr<webrtc::WindowCapturer> window_capturer( | 426 scoped_ptr<webrtc::WindowCapturer> window_capturer( |
398 webrtc::WindowCapturer::Create(options)); | 427 webrtc::WindowCapturer::Create(options)); |
399 if (window_capturer && window_capturer->SelectWindow(source.id)) { | 428 if (window_capturer && window_capturer->SelectWindow(source.id)) { |
400 window_capturer->BringSelectedWindowToFront(); | 429 window_capturer->BringSelectedWindowToFront(); |
401 capturer.reset(new webrtc::DesktopAndCursorComposer( | 430 capturer.reset(new webrtc::DesktopAndCursorComposer( |
402 window_capturer.release(), | 431 window_capturer.release(), |
403 webrtc::MouseCursorMonitor::CreateForWindow(options, source.id))); | 432 webrtc::MouseCursorMonitor::CreateForWindow(options, source.id))); |
| 433 IncrementDesktopCaptureCounter(WINDOW_CATPTURER_CREATED); |
404 } | 434 } |
405 break; | 435 break; |
406 } | 436 } |
407 | 437 |
408 default: { | 438 default: { |
409 NOTREACHED(); | 439 NOTREACHED(); |
410 } | 440 } |
411 } | 441 } |
412 | 442 |
413 scoped_ptr<media::VideoCaptureDevice> result; | 443 scoped_ptr<media::VideoCaptureDevice> result; |
414 if (capturer) | 444 if (capturer) { |
415 result.reset(new DesktopCaptureDevice(task_runner, capturer.Pass())); | 445 result.reset( |
| 446 new DesktopCaptureDevice(task_runner, capturer.Pass(), source.type)); |
| 447 } |
416 | 448 |
417 return result.Pass(); | 449 return result.Pass(); |
418 } | 450 } |
419 | 451 |
420 DesktopCaptureDevice::DesktopCaptureDevice( | 452 DesktopCaptureDevice::DesktopCaptureDevice( |
421 scoped_refptr<base::SequencedTaskRunner> task_runner, | 453 scoped_refptr<base::SequencedTaskRunner> task_runner, |
422 scoped_ptr<webrtc::DesktopCapturer> capturer) | 454 scoped_ptr<webrtc::DesktopCapturer> capturer, |
423 : core_(new Core(task_runner, capturer.Pass())) {} | 455 DesktopMediaID::Type type) |
| 456 : core_(new Core(task_runner, capturer.Pass(), type)) { |
| 457 } |
424 | 458 |
425 DesktopCaptureDevice::~DesktopCaptureDevice() { | 459 DesktopCaptureDevice::~DesktopCaptureDevice() { |
426 StopAndDeAllocate(); | 460 StopAndDeAllocate(); |
427 } | 461 } |
428 | 462 |
429 void DesktopCaptureDevice::AllocateAndStart( | 463 void DesktopCaptureDevice::AllocateAndStart( |
430 const media::VideoCaptureParams& params, | 464 const media::VideoCaptureParams& params, |
431 scoped_ptr<Client> client) { | 465 scoped_ptr<Client> client) { |
432 core_->AllocateAndStart(params, client.Pass()); | 466 core_->AllocateAndStart(params, client.Pass()); |
433 } | 467 } |
434 | 468 |
435 void DesktopCaptureDevice::StopAndDeAllocate() { | 469 void DesktopCaptureDevice::StopAndDeAllocate() { |
436 core_->StopAndDeAllocate(); | 470 core_->StopAndDeAllocate(); |
437 } | 471 } |
438 | 472 |
439 void DesktopCaptureDevice::SetNotificationWindowId( | 473 void DesktopCaptureDevice::SetNotificationWindowId( |
440 gfx::NativeViewId window_id) { | 474 gfx::NativeViewId window_id) { |
441 core_->SetNotificationWindowId(window_id); | 475 core_->SetNotificationWindowId(window_id); |
442 } | 476 } |
443 | 477 |
444 } // namespace content | 478 } // namespace content |
OLD | NEW |