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 |