| 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/renderer_host/media/desktop_capture_device.h" | 5 #include "content/browser/renderer_host/media/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/sequenced_task_runner.h" | 10 #include "base/sequenced_task_runner.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 } // namespace | 46 } // namespace |
| 47 | 47 |
| 48 class DesktopCaptureDevice::Core | 48 class DesktopCaptureDevice::Core |
| 49 : public base::RefCountedThreadSafe<Core>, | 49 : public base::RefCountedThreadSafe<Core>, |
| 50 public webrtc::DesktopCapturer::Callback { | 50 public webrtc::DesktopCapturer::Callback { |
| 51 public: | 51 public: |
| 52 Core(scoped_refptr<base::SequencedTaskRunner> task_runner, | 52 Core(scoped_refptr<base::SequencedTaskRunner> task_runner, |
| 53 scoped_ptr<webrtc::DesktopCapturer> capturer); | 53 scoped_ptr<webrtc::DesktopCapturer> capturer); |
| 54 | 54 |
| 55 // Implementation of VideoCaptureDevice methods. | 55 // Implementation of VideoCaptureDevice methods. |
| 56 void AllocateAndStart(const media::VideoCaptureParams& params, | 56 void AllocateAndStart(const media::VideoCaptureCapability& capture_format, |
| 57 scoped_ptr<Client> client); | 57 scoped_ptr<Client> client); |
| 58 void StopAndDeAllocate(); | 58 void StopAndDeAllocate(); |
| 59 | 59 |
| 60 private: | 60 private: |
| 61 friend class base::RefCountedThreadSafe<Core>; | 61 friend class base::RefCountedThreadSafe<Core>; |
| 62 virtual ~Core(); | 62 virtual ~Core(); |
| 63 | 63 |
| 64 // webrtc::DesktopCapturer::Callback interface | 64 // webrtc::DesktopCapturer::Callback interface |
| 65 virtual webrtc::SharedMemory* CreateSharedMemory(size_t size) OVERRIDE; | 65 virtual webrtc::SharedMemory* CreateSharedMemory(size_t size) OVERRIDE; |
| 66 virtual void OnCaptureCompleted(webrtc::DesktopFrame* frame) OVERRIDE; | 66 virtual void OnCaptureCompleted(webrtc::DesktopFrame* frame) OVERRIDE; |
| 67 | 67 |
| 68 // Helper methods that run on the |task_runner_|. Posted from the | 68 // Helper methods that run on the |task_runner_|. Posted from the |
| 69 // corresponding public methods. | 69 // corresponding public methods. |
| 70 void DoAllocateAndStart(const media::VideoCaptureParams& params, | 70 void DoAllocateAndStart(const media::VideoCaptureCapability& capture_format, |
| 71 scoped_ptr<Client> client); | 71 scoped_ptr<Client> client); |
| 72 void DoStopAndDeAllocate(); | 72 void DoStopAndDeAllocate(); |
| 73 | 73 |
| 74 // Chooses new output properties based on the supplied source size and the | 74 // Chooses new output properties based on the supplied source size and the |
| 75 // properties requested to Allocate(), and dispatches OnFrameInfo[Changed] | 75 // properties requested to Allocate(), and dispatches OnFrameInfo[Changed] |
| 76 // notifications. | 76 // notifications. |
| 77 void RefreshCaptureFormat(const webrtc::DesktopSize& frame_size); | 77 void RefreshCaptureFormat(const webrtc::DesktopSize& frame_size); |
| 78 | 78 |
| 79 // Method that is scheduled on |task_runner_| to be called on regular interval | 79 // Method that is scheduled on |task_runner_| to be called on regular interval |
| 80 // to capture a frame. | 80 // to capture a frame. |
| 81 void OnCaptureTimer(); | 81 void OnCaptureTimer(); |
| 82 | 82 |
| 83 // Captures a frame and schedules timer for the next one. | 83 // Captures a frame and schedules timer for the next one. |
| 84 void CaptureFrameAndScheduleNext(); | 84 void CaptureFrameAndScheduleNext(); |
| 85 | 85 |
| 86 // Captures a single frame. | 86 // Captures a single frame. |
| 87 void DoCapture(); | 87 void DoCapture(); |
| 88 | 88 |
| 89 // Task runner used for capturing operations. | 89 // Task runner used for capturing operations. |
| 90 scoped_refptr<base::SequencedTaskRunner> task_runner_; | 90 scoped_refptr<base::SequencedTaskRunner> task_runner_; |
| 91 | 91 |
| 92 // The underlying DesktopCapturer instance used to capture frames. | 92 // The underlying DesktopCapturer instance used to capture frames. |
| 93 scoped_ptr<webrtc::DesktopCapturer> desktop_capturer_; | 93 scoped_ptr<webrtc::DesktopCapturer> desktop_capturer_; |
| 94 | 94 |
| 95 // The device client which proxies device events to the controller. Accessed | 95 // The device client which proxies device events to the controller. Accessed |
| 96 // on the task_runner_ thread. | 96 // on the task_runner_ thread. |
| 97 scoped_ptr<Client> client_; | 97 scoped_ptr<Client> client_; |
| 98 | 98 |
| 99 // Requested video capture format (width, height, frame rate, etc). | 99 // Requested video capture format (width, height, frame rate, etc). |
| 100 media::VideoCaptureParams requested_params_; | 100 media::VideoCaptureCapability requested_format_; |
| 101 | 101 |
| 102 // Actual video capture format being generated. | 102 // Actual video capture format being generated. |
| 103 media::VideoCaptureFormat capture_format_; | 103 media::VideoCaptureCapability capture_format_; |
| 104 | 104 |
| 105 // Size of frame most recently captured from the source. | 105 // Size of frame most recently captured from the source. |
| 106 webrtc::DesktopSize previous_frame_size_; | 106 webrtc::DesktopSize previous_frame_size_; |
| 107 | 107 |
| 108 // DesktopFrame into which captured frames are down-scaled and/or letterboxed, | 108 // DesktopFrame into which captured frames are down-scaled and/or letterboxed, |
| 109 // depending upon the caller's requested capture capabilities. If frames can | 109 // depending upon the caller's requested capture capabilities. If frames can |
| 110 // be returned to the caller directly then this is NULL. | 110 // be returned to the caller directly then this is NULL. |
| 111 scoped_ptr<webrtc::DesktopFrame> output_frame_; | 111 scoped_ptr<webrtc::DesktopFrame> output_frame_; |
| 112 | 112 |
| 113 // Sub-rectangle of |output_frame_| into which the source will be scaled | 113 // Sub-rectangle of |output_frame_| into which the source will be scaled |
| (...skipping 15 matching lines...) Expand all Loading... |
| 129 scoped_ptr<webrtc::DesktopCapturer> capturer) | 129 scoped_ptr<webrtc::DesktopCapturer> capturer) |
| 130 : task_runner_(task_runner), | 130 : task_runner_(task_runner), |
| 131 desktop_capturer_(capturer.Pass()), | 131 desktop_capturer_(capturer.Pass()), |
| 132 capture_task_posted_(false), | 132 capture_task_posted_(false), |
| 133 capture_in_progress_(false) {} | 133 capture_in_progress_(false) {} |
| 134 | 134 |
| 135 DesktopCaptureDevice::Core::~Core() { | 135 DesktopCaptureDevice::Core::~Core() { |
| 136 } | 136 } |
| 137 | 137 |
| 138 void DesktopCaptureDevice::Core::AllocateAndStart( | 138 void DesktopCaptureDevice::Core::AllocateAndStart( |
| 139 const media::VideoCaptureParams& params, | 139 const media::VideoCaptureCapability& capture_format, |
| 140 scoped_ptr<Client> client) { | 140 scoped_ptr<Client> client) { |
| 141 DCHECK_GT(params.requested_format.frame_size.GetArea(), 0); | 141 DCHECK_GT(capture_format.width, 0); |
| 142 DCHECK_GT(params.requested_format.frame_rate, 0); | 142 DCHECK_GT(capture_format.height, 0); |
| 143 DCHECK_GT(capture_format.frame_rate, 0); |
| 143 | 144 |
| 144 task_runner_->PostTask( | 145 task_runner_->PostTask( |
| 145 FROM_HERE, | 146 FROM_HERE, |
| 146 base::Bind( | 147 base::Bind(&Core::DoAllocateAndStart, |
| 147 &Core::DoAllocateAndStart, this, params, base::Passed(&client))); | 148 this, |
| 149 capture_format, |
| 150 base::Passed(&client))); |
| 148 } | 151 } |
| 149 | 152 |
| 150 void DesktopCaptureDevice::Core::StopAndDeAllocate() { | 153 void DesktopCaptureDevice::Core::StopAndDeAllocate() { |
| 151 task_runner_->PostTask(FROM_HERE, | 154 task_runner_->PostTask(FROM_HERE, |
| 152 base::Bind(&Core::DoStopAndDeAllocate, this)); | 155 base::Bind(&Core::DoStopAndDeAllocate, this)); |
| 153 } | 156 } |
| 154 | 157 |
| 155 webrtc::SharedMemory* | 158 webrtc::SharedMemory* |
| 156 DesktopCaptureDevice::Core::CreateSharedMemory(size_t size) { | 159 DesktopCaptureDevice::Core::CreateSharedMemory(size_t size) { |
| 157 return NULL; | 160 return NULL; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 171 } | 174 } |
| 172 | 175 |
| 173 if (!client_) | 176 if (!client_) |
| 174 return; | 177 return; |
| 175 | 178 |
| 176 scoped_ptr<webrtc::DesktopFrame> owned_frame(frame); | 179 scoped_ptr<webrtc::DesktopFrame> owned_frame(frame); |
| 177 | 180 |
| 178 // Handle initial frame size and size changes. | 181 // Handle initial frame size and size changes. |
| 179 RefreshCaptureFormat(frame->size()); | 182 RefreshCaptureFormat(frame->size()); |
| 180 | 183 |
| 181 webrtc::DesktopSize output_size(capture_format_.frame_size.width(), | 184 webrtc::DesktopSize output_size(capture_format_.width, |
| 182 capture_format_.frame_size.height()); | 185 capture_format_.height); |
| 183 size_t output_bytes = output_size.width() * output_size.height() * | 186 size_t output_bytes = output_size.width() * output_size.height() * |
| 184 webrtc::DesktopFrame::kBytesPerPixel; | 187 webrtc::DesktopFrame::kBytesPerPixel; |
| 185 const uint8_t* output_data = NULL; | 188 const uint8_t* output_data = NULL; |
| 186 | 189 |
| 187 if (frame->size().equals(output_size)) { | 190 if (frame->size().equals(output_size)) { |
| 188 // If the captured frame matches the output size, we can return the pixel | 191 // If the captured frame matches the output size, we can return the pixel |
| 189 // data directly, without scaling. | 192 // data directly, without scaling. |
| 190 output_data = frame->data(); | 193 output_data = frame->data(); |
| 191 } else { | 194 } else { |
| 192 // Otherwise we need to down-scale and/or letterbox to the target format. | 195 // Otherwise we need to down-scale and/or letterbox to the target format. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 218 output_bytes, | 221 output_bytes, |
| 219 base::Time::Now(), | 222 base::Time::Now(), |
| 220 0, | 223 0, |
| 221 false, | 224 false, |
| 222 false, | 225 false, |
| 223 capture_format_); | 226 capture_format_); |
| 224 } | 227 } |
| 225 } | 228 } |
| 226 | 229 |
| 227 void DesktopCaptureDevice::Core::DoAllocateAndStart( | 230 void DesktopCaptureDevice::Core::DoAllocateAndStart( |
| 228 const media::VideoCaptureParams& params, | 231 const media::VideoCaptureCapability& capture_format, |
| 229 scoped_ptr<Client> client) { | 232 scoped_ptr<Client> client) { |
| 230 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 233 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 231 DCHECK(desktop_capturer_); | 234 DCHECK(desktop_capturer_); |
| 232 DCHECK(client.get()); | 235 DCHECK(client.get()); |
| 233 DCHECK(!client_.get()); | 236 DCHECK(!client_.get()); |
| 234 | 237 |
| 235 client_ = client.Pass(); | 238 client_ = client.Pass(); |
| 236 requested_params_ = params; | 239 requested_format_ = capture_format; |
| 237 | 240 |
| 238 capture_format_ = requested_params_.requested_format; | 241 capture_format_.frame_rate = requested_format_.frame_rate; |
| 242 |
| 243 // Support dynamic changes in resolution only if requester also does. |
| 244 if (requested_format_.frame_size_type == |
| 245 media::VariableResolutionVideoCaptureDevice) { |
| 246 capture_format_.frame_size_type = |
| 247 media::VariableResolutionVideoCaptureDevice; |
| 248 } |
| 239 | 249 |
| 240 // This capturer always outputs ARGB, non-interlaced. | 250 // This capturer always outputs ARGB, non-interlaced. |
| 241 capture_format_.pixel_format = media::PIXEL_FORMAT_ARGB; | 251 capture_format_.color = media::PIXEL_FORMAT_ARGB; |
| 242 | 252 |
| 243 desktop_capturer_->Start(this); | 253 desktop_capturer_->Start(this); |
| 244 | 254 |
| 245 CaptureFrameAndScheduleNext(); | 255 CaptureFrameAndScheduleNext(); |
| 246 } | 256 } |
| 247 | 257 |
| 248 void DesktopCaptureDevice::Core::DoStopAndDeAllocate() { | 258 void DesktopCaptureDevice::Core::DoStopAndDeAllocate() { |
| 249 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 259 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 250 client_.reset(); | 260 client_.reset(); |
| 251 output_frame_.reset(); | 261 output_frame_.reset(); |
| 252 previous_frame_size_.set(0, 0); | 262 previous_frame_size_.set(0, 0); |
| 253 desktop_capturer_.reset(); | 263 desktop_capturer_.reset(); |
| 254 } | 264 } |
| 255 | 265 |
| 256 void DesktopCaptureDevice::Core::RefreshCaptureFormat( | 266 void DesktopCaptureDevice::Core::RefreshCaptureFormat( |
| 257 const webrtc::DesktopSize& frame_size) { | 267 const webrtc::DesktopSize& frame_size) { |
| 258 if (previous_frame_size_.equals(frame_size)) | 268 if (previous_frame_size_.equals(frame_size)) |
| 259 return; | 269 return; |
| 260 | 270 |
| 261 // Clear the output frame, if any, since it will either need resizing, or | 271 // Clear the output frame, if any, since it will either need resizing, or |
| 262 // clearing of stale data in letterbox areas, anyway. | 272 // clearing of stale data in letterbox areas, anyway. |
| 263 output_frame_.reset(); | 273 output_frame_.reset(); |
| 264 | 274 |
| 265 if (previous_frame_size_.is_empty() || | 275 if (previous_frame_size_.is_empty() || |
| 266 requested_params_.allow_resolution_change) { | 276 requested_format_.frame_size_type == |
| 277 media::VariableResolutionVideoCaptureDevice) { |
| 267 // If this is the first frame, or the receiver supports variable resolution | 278 // If this is the first frame, or the receiver supports variable resolution |
| 268 // then determine the output size by treating the requested width & height | 279 // then determine the output size by treating the requested width & height |
| 269 // as maxima. | 280 // as maxima. |
| 270 if (frame_size.width() > | 281 if (frame_size.width() > requested_format_.width || |
| 271 requested_params_.requested_format.frame_size.width() || | 282 frame_size.height() > requested_format_.height) { |
| 272 frame_size.height() > | |
| 273 requested_params_.requested_format.frame_size.height()) { | |
| 274 output_rect_ = ComputeLetterboxRect( | 283 output_rect_ = ComputeLetterboxRect( |
| 275 webrtc::DesktopSize( | 284 webrtc::DesktopSize(requested_format_.width, |
| 276 requested_params_.requested_format.frame_size.width(), | 285 requested_format_.height), |
| 277 requested_params_.requested_format.frame_size.height()), | |
| 278 frame_size); | 286 frame_size); |
| 279 output_rect_.Translate(-output_rect_.left(), -output_rect_.top()); | 287 output_rect_.Translate(-output_rect_.left(), -output_rect_.top()); |
| 280 } else { | 288 } else { |
| 281 output_rect_ = webrtc::DesktopRect::MakeSize(frame_size); | 289 output_rect_ = webrtc::DesktopRect::MakeSize(frame_size); |
| 282 } | 290 } |
| 283 capture_format_.frame_size.SetSize(output_rect_.width(), | 291 capture_format_.width = output_rect_.width(); |
| 284 output_rect_.height()); | 292 capture_format_.height = output_rect_.height(); |
| 285 } else { | 293 } else { |
| 286 // Otherwise the output frame size cannot change, so just scale and | 294 // Otherwise the output frame size cannot change, so just scale and |
| 287 // letterbox. | 295 // letterbox. |
| 288 output_rect_ = ComputeLetterboxRect( | 296 output_rect_ = ComputeLetterboxRect( |
| 289 webrtc::DesktopSize(capture_format_.frame_size.width(), | 297 webrtc::DesktopSize(capture_format_.width, capture_format_.height), |
| 290 capture_format_.frame_size.height()), | |
| 291 frame_size); | 298 frame_size); |
| 292 } | 299 } |
| 293 | 300 |
| 294 previous_frame_size_ = frame_size; | 301 previous_frame_size_ = frame_size; |
| 295 } | 302 } |
| 296 | 303 |
| 297 void DesktopCaptureDevice::Core::OnCaptureTimer() { | 304 void DesktopCaptureDevice::Core::OnCaptureTimer() { |
| 298 DCHECK(capture_task_posted_); | 305 DCHECK(capture_task_posted_); |
| 299 capture_task_posted_ = false; | 306 capture_task_posted_ = false; |
| 300 | 307 |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 DesktopCaptureDevice::DesktopCaptureDevice( | 404 DesktopCaptureDevice::DesktopCaptureDevice( |
| 398 scoped_refptr<base::SequencedTaskRunner> task_runner, | 405 scoped_refptr<base::SequencedTaskRunner> task_runner, |
| 399 scoped_ptr<webrtc::DesktopCapturer> capturer) | 406 scoped_ptr<webrtc::DesktopCapturer> capturer) |
| 400 : core_(new Core(task_runner, capturer.Pass())) {} | 407 : core_(new Core(task_runner, capturer.Pass())) {} |
| 401 | 408 |
| 402 DesktopCaptureDevice::~DesktopCaptureDevice() { | 409 DesktopCaptureDevice::~DesktopCaptureDevice() { |
| 403 StopAndDeAllocate(); | 410 StopAndDeAllocate(); |
| 404 } | 411 } |
| 405 | 412 |
| 406 void DesktopCaptureDevice::AllocateAndStart( | 413 void DesktopCaptureDevice::AllocateAndStart( |
| 407 const media::VideoCaptureParams& params, | 414 const media::VideoCaptureCapability& capture_format, |
| 408 scoped_ptr<Client> client) { | 415 scoped_ptr<Client> client) { |
| 409 core_->AllocateAndStart(params, client.Pass()); | 416 core_->AllocateAndStart(capture_format, client.Pass()); |
| 410 } | 417 } |
| 411 | 418 |
| 412 void DesktopCaptureDevice::StopAndDeAllocate() { | 419 void DesktopCaptureDevice::StopAndDeAllocate() { |
| 413 core_->StopAndDeAllocate(); | 420 core_->StopAndDeAllocate(); |
| 414 } | 421 } |
| 415 | 422 |
| 416 } // namespace content | 423 } // namespace content |
| OLD | NEW |