| 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::VideoCaptureCapability& capture_format, | 56 void AllocateAndStart(const media::VideoCaptureParams& params, |
| 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::VideoCaptureCapability& capture_format, | 70 void DoAllocateAndStart(const media::VideoCaptureParams& params, |
| 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::VideoCaptureCapability requested_format_; | 100 media::VideoCaptureParams requested_params_; |
| 101 | 101 |
| 102 // Actual video capture format being generated. | 102 // Actual video capture format being generated. |
| 103 media::VideoCaptureCapability capture_format_; | 103 media::VideoCaptureFormat 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::VideoCaptureCapability& capture_format, | 139 const media::VideoCaptureParams& params, |
| 140 scoped_ptr<Client> client) { | 140 scoped_ptr<Client> client) { |
| 141 DCHECK_GT(capture_format.width, 0); | 141 DCHECK_GT(params.requested_format.frame_size.GetArea(), 0); |
| 142 DCHECK_GT(capture_format.height, 0); | 142 DCHECK_GT(params.requested_format.frame_rate, 0); |
| 143 DCHECK_GT(capture_format.frame_rate, 0); | |
| 144 | 143 |
| 145 task_runner_->PostTask( | 144 task_runner_->PostTask( |
| 146 FROM_HERE, | 145 FROM_HERE, |
| 147 base::Bind(&Core::DoAllocateAndStart, | 146 base::Bind( |
| 148 this, | 147 &Core::DoAllocateAndStart, this, params, base::Passed(&client))); |
| 149 capture_format, | |
| 150 base::Passed(&client))); | |
| 151 } | 148 } |
| 152 | 149 |
| 153 void DesktopCaptureDevice::Core::StopAndDeAllocate() { | 150 void DesktopCaptureDevice::Core::StopAndDeAllocate() { |
| 154 task_runner_->PostTask(FROM_HERE, | 151 task_runner_->PostTask(FROM_HERE, |
| 155 base::Bind(&Core::DoStopAndDeAllocate, this)); | 152 base::Bind(&Core::DoStopAndDeAllocate, this)); |
| 156 } | 153 } |
| 157 | 154 |
| 158 webrtc::SharedMemory* | 155 webrtc::SharedMemory* |
| 159 DesktopCaptureDevice::Core::CreateSharedMemory(size_t size) { | 156 DesktopCaptureDevice::Core::CreateSharedMemory(size_t size) { |
| 160 return NULL; | 157 return NULL; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 174 } | 171 } |
| 175 | 172 |
| 176 if (!client_) | 173 if (!client_) |
| 177 return; | 174 return; |
| 178 | 175 |
| 179 scoped_ptr<webrtc::DesktopFrame> owned_frame(frame); | 176 scoped_ptr<webrtc::DesktopFrame> owned_frame(frame); |
| 180 | 177 |
| 181 // Handle initial frame size and size changes. | 178 // Handle initial frame size and size changes. |
| 182 RefreshCaptureFormat(frame->size()); | 179 RefreshCaptureFormat(frame->size()); |
| 183 | 180 |
| 184 webrtc::DesktopSize output_size(capture_format_.width, | 181 webrtc::DesktopSize output_size(capture_format_.frame_size.width(), |
| 185 capture_format_.height); | 182 capture_format_.frame_size.height()); |
| 186 size_t output_bytes = output_size.width() * output_size.height() * | 183 size_t output_bytes = output_size.width() * output_size.height() * |
| 187 webrtc::DesktopFrame::kBytesPerPixel; | 184 webrtc::DesktopFrame::kBytesPerPixel; |
| 188 const uint8_t* output_data = NULL; | 185 const uint8_t* output_data = NULL; |
| 189 | 186 |
| 190 if (frame->size().equals(output_size)) { | 187 if (frame->size().equals(output_size)) { |
| 191 // If the captured frame matches the output size, we can return the pixel | 188 // If the captured frame matches the output size, we can return the pixel |
| 192 // data directly, without scaling. | 189 // data directly, without scaling. |
| 193 output_data = frame->data(); | 190 output_data = frame->data(); |
| 194 } else { | 191 } else { |
| 195 // Otherwise we need to down-scale and/or letterbox to the target format. | 192 // Otherwise we need to down-scale and/or letterbox to the target format. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 221 output_bytes, | 218 output_bytes, |
| 222 base::Time::Now(), | 219 base::Time::Now(), |
| 223 0, | 220 0, |
| 224 false, | 221 false, |
| 225 false, | 222 false, |
| 226 capture_format_); | 223 capture_format_); |
| 227 } | 224 } |
| 228 } | 225 } |
| 229 | 226 |
| 230 void DesktopCaptureDevice::Core::DoAllocateAndStart( | 227 void DesktopCaptureDevice::Core::DoAllocateAndStart( |
| 231 const media::VideoCaptureCapability& capture_format, | 228 const media::VideoCaptureParams& params, |
| 232 scoped_ptr<Client> client) { | 229 scoped_ptr<Client> client) { |
| 233 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 230 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 234 DCHECK(desktop_capturer_); | 231 DCHECK(desktop_capturer_); |
| 235 DCHECK(client.get()); | 232 DCHECK(client.get()); |
| 236 DCHECK(!client_.get()); | 233 DCHECK(!client_.get()); |
| 237 | 234 |
| 238 client_ = client.Pass(); | 235 client_ = client.Pass(); |
| 239 requested_format_ = capture_format; | 236 requested_params_ = params; |
| 240 | 237 |
| 241 capture_format_.frame_rate = requested_format_.frame_rate; | 238 capture_format_ = requested_params_.requested_format; |
| 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 } | |
| 249 | 239 |
| 250 // This capturer always outputs ARGB, non-interlaced. | 240 // This capturer always outputs ARGB, non-interlaced. |
| 251 capture_format_.color = media::PIXEL_FORMAT_ARGB; | 241 capture_format_.pixel_format = media::PIXEL_FORMAT_ARGB; |
| 252 | 242 |
| 253 desktop_capturer_->Start(this); | 243 desktop_capturer_->Start(this); |
| 254 | 244 |
| 255 CaptureFrameAndScheduleNext(); | 245 CaptureFrameAndScheduleNext(); |
| 256 } | 246 } |
| 257 | 247 |
| 258 void DesktopCaptureDevice::Core::DoStopAndDeAllocate() { | 248 void DesktopCaptureDevice::Core::DoStopAndDeAllocate() { |
| 259 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 249 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 260 client_.reset(); | 250 client_.reset(); |
| 261 output_frame_.reset(); | 251 output_frame_.reset(); |
| 262 previous_frame_size_.set(0, 0); | 252 previous_frame_size_.set(0, 0); |
| 263 desktop_capturer_.reset(); | 253 desktop_capturer_.reset(); |
| 264 } | 254 } |
| 265 | 255 |
| 266 void DesktopCaptureDevice::Core::RefreshCaptureFormat( | 256 void DesktopCaptureDevice::Core::RefreshCaptureFormat( |
| 267 const webrtc::DesktopSize& frame_size) { | 257 const webrtc::DesktopSize& frame_size) { |
| 268 if (previous_frame_size_.equals(frame_size)) | 258 if (previous_frame_size_.equals(frame_size)) |
| 269 return; | 259 return; |
| 270 | 260 |
| 271 // Clear the output frame, if any, since it will either need resizing, or | 261 // Clear the output frame, if any, since it will either need resizing, or |
| 272 // clearing of stale data in letterbox areas, anyway. | 262 // clearing of stale data in letterbox areas, anyway. |
| 273 output_frame_.reset(); | 263 output_frame_.reset(); |
| 274 | 264 |
| 275 if (previous_frame_size_.is_empty() || | 265 if (previous_frame_size_.is_empty() || |
| 276 requested_format_.frame_size_type == | 266 requested_params_.allow_resolution_change) { |
| 277 media::VariableResolutionVideoCaptureDevice) { | |
| 278 // If this is the first frame, or the receiver supports variable resolution | 267 // If this is the first frame, or the receiver supports variable resolution |
| 279 // then determine the output size by treating the requested width & height | 268 // then determine the output size by treating the requested width & height |
| 280 // as maxima. | 269 // as maxima. |
| 281 if (frame_size.width() > requested_format_.width || | 270 if (frame_size.width() > |
| 282 frame_size.height() > requested_format_.height) { | 271 requested_params_.requested_format.frame_size.width() || |
| 272 frame_size.height() > |
| 273 requested_params_.requested_format.frame_size.height()) { |
| 283 output_rect_ = ComputeLetterboxRect( | 274 output_rect_ = ComputeLetterboxRect( |
| 284 webrtc::DesktopSize(requested_format_.width, | 275 webrtc::DesktopSize( |
| 285 requested_format_.height), | 276 requested_params_.requested_format.frame_size.width(), |
| 277 requested_params_.requested_format.frame_size.height()), |
| 286 frame_size); | 278 frame_size); |
| 287 output_rect_.Translate(-output_rect_.left(), -output_rect_.top()); | 279 output_rect_.Translate(-output_rect_.left(), -output_rect_.top()); |
| 288 } else { | 280 } else { |
| 289 output_rect_ = webrtc::DesktopRect::MakeSize(frame_size); | 281 output_rect_ = webrtc::DesktopRect::MakeSize(frame_size); |
| 290 } | 282 } |
| 291 capture_format_.width = output_rect_.width(); | 283 capture_format_.frame_size.SetSize(output_rect_.width(), |
| 292 capture_format_.height = output_rect_.height(); | 284 output_rect_.height()); |
| 293 } else { | 285 } else { |
| 294 // Otherwise the output frame size cannot change, so just scale and | 286 // Otherwise the output frame size cannot change, so just scale and |
| 295 // letterbox. | 287 // letterbox. |
| 296 output_rect_ = ComputeLetterboxRect( | 288 output_rect_ = ComputeLetterboxRect( |
| 297 webrtc::DesktopSize(capture_format_.width, capture_format_.height), | 289 webrtc::DesktopSize(capture_format_.frame_size.width(), |
| 290 capture_format_.frame_size.height()), |
| 298 frame_size); | 291 frame_size); |
| 299 } | 292 } |
| 300 | 293 |
| 301 previous_frame_size_ = frame_size; | 294 previous_frame_size_ = frame_size; |
| 302 } | 295 } |
| 303 | 296 |
| 304 void DesktopCaptureDevice::Core::OnCaptureTimer() { | 297 void DesktopCaptureDevice::Core::OnCaptureTimer() { |
| 305 DCHECK(capture_task_posted_); | 298 DCHECK(capture_task_posted_); |
| 306 capture_task_posted_ = false; | 299 capture_task_posted_ = false; |
| 307 | 300 |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 404 DesktopCaptureDevice::DesktopCaptureDevice( | 397 DesktopCaptureDevice::DesktopCaptureDevice( |
| 405 scoped_refptr<base::SequencedTaskRunner> task_runner, | 398 scoped_refptr<base::SequencedTaskRunner> task_runner, |
| 406 scoped_ptr<webrtc::DesktopCapturer> capturer) | 399 scoped_ptr<webrtc::DesktopCapturer> capturer) |
| 407 : core_(new Core(task_runner, capturer.Pass())) {} | 400 : core_(new Core(task_runner, capturer.Pass())) {} |
| 408 | 401 |
| 409 DesktopCaptureDevice::~DesktopCaptureDevice() { | 402 DesktopCaptureDevice::~DesktopCaptureDevice() { |
| 410 StopAndDeAllocate(); | 403 StopAndDeAllocate(); |
| 411 } | 404 } |
| 412 | 405 |
| 413 void DesktopCaptureDevice::AllocateAndStart( | 406 void DesktopCaptureDevice::AllocateAndStart( |
| 414 const media::VideoCaptureCapability& capture_format, | 407 const media::VideoCaptureParams& params, |
| 415 scoped_ptr<Client> client) { | 408 scoped_ptr<Client> client) { |
| 416 core_->AllocateAndStart(capture_format, client.Pass()); | 409 core_->AllocateAndStart(params, client.Pass()); |
| 417 } | 410 } |
| 418 | 411 |
| 419 void DesktopCaptureDevice::StopAndDeAllocate() { | 412 void DesktopCaptureDevice::StopAndDeAllocate() { |
| 420 core_->StopAndDeAllocate(); | 413 core_->StopAndDeAllocate(); |
| 421 } | 414 } |
| 422 | 415 |
| 423 } // namespace content | 416 } // namespace content |
| OLD | NEW |