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