OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/video_capture_manager.h" | 5 #include "content/browser/renderer_host/media/video_capture_manager.h" |
6 | 6 |
| 7 #include <algorithm> |
7 #include <set> | 8 #include <set> |
8 | 9 |
9 #include "base/bind.h" | 10 #include "base/bind.h" |
10 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
11 #include "base/logging.h" | 12 #include "base/logging.h" |
12 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" |
13 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
14 #include "base/task_runner_util.h" | 15 #include "base/task_runner_util.h" |
15 #include "base/threading/sequenced_worker_pool.h" | 16 #include "base/threading/sequenced_worker_pool.h" |
16 #include "content/browser/media/capture/web_contents_video_capture_device.h" | 17 #include "content/browser/media/capture/web_contents_video_capture_device.h" |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DESKTOP_OR_TAB = 4, | 88 VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DESKTOP_OR_TAB = 4, |
88 NUM_VIDEO_CAPTURE_EVENT | 89 NUM_VIDEO_CAPTURE_EVENT |
89 }; | 90 }; |
90 | 91 |
91 void LogVideoCaptureEvent(VideoCaptureEvent event) { | 92 void LogVideoCaptureEvent(VideoCaptureEvent event) { |
92 UMA_HISTOGRAM_ENUMERATION("Media.VideoCaptureManager.Event", | 93 UMA_HISTOGRAM_ENUMERATION("Media.VideoCaptureManager.Event", |
93 event, | 94 event, |
94 NUM_VIDEO_CAPTURE_EVENT); | 95 NUM_VIDEO_CAPTURE_EVENT); |
95 } | 96 } |
96 | 97 |
| 98 // Counter used for identifying a DeviceRequest to start a capture device. |
| 99 static int g_device_start_id = 0; |
| 100 |
97 } // namespace | 101 } // namespace |
98 | 102 |
99 namespace content { | 103 namespace content { |
100 | 104 |
101 VideoCaptureManager::DeviceEntry::DeviceEntry( | 105 VideoCaptureManager::DeviceEntry::DeviceEntry( |
102 MediaStreamType stream_type, | 106 MediaStreamType stream_type, |
103 const std::string& id, | 107 const std::string& id, |
104 scoped_ptr<VideoCaptureController> controller) | 108 scoped_ptr<VideoCaptureController> controller) |
105 : stream_type(stream_type), | 109 : serial_id(g_device_start_id++), |
| 110 stream_type(stream_type), |
106 id(id), | 111 id(id), |
107 video_capture_controller(controller.Pass()) {} | 112 video_capture_controller(controller.Pass()) {} |
108 | 113 |
109 VideoCaptureManager::DeviceEntry::~DeviceEntry() {} | 114 VideoCaptureManager::DeviceEntry::~DeviceEntry() {} |
110 | 115 |
| 116 VideoCaptureManager::CaptureDeviceStartRequest::CaptureDeviceStartRequest( |
| 117 int serial_id, |
| 118 media::VideoCaptureSessionId session_id, |
| 119 const media::VideoCaptureParams& params) |
| 120 : serial_id_(serial_id), |
| 121 session_id_(session_id), |
| 122 params_(params), |
| 123 abort_start_(false) { |
| 124 } |
| 125 |
111 | 126 |
112 VideoCaptureManager::VideoCaptureManager( | 127 VideoCaptureManager::VideoCaptureManager( |
113 scoped_ptr<media::VideoCaptureDeviceFactory> factory) | 128 scoped_ptr<media::VideoCaptureDeviceFactory> factory) |
114 : listener_(NULL), | 129 : listener_(NULL), |
115 new_capture_session_id_(1), | 130 new_capture_session_id_(1), |
116 video_capture_device_factory_(factory.Pass()) { | 131 video_capture_device_factory_(factory.Pass()) { |
117 } | 132 } |
118 | 133 |
119 VideoCaptureManager::~VideoCaptureManager() { | 134 VideoCaptureManager::~VideoCaptureManager() { |
120 DCHECK(devices_.empty()); | 135 DCHECK(devices_.empty()); |
| 136 DCHECK(device_start_queue_.empty()); |
121 } | 137 } |
122 | 138 |
123 void VideoCaptureManager::Register( | 139 void VideoCaptureManager::Register( |
124 MediaStreamProviderListener* listener, | 140 MediaStreamProviderListener* listener, |
125 const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner) { | 141 const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner) { |
126 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 142 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
127 DCHECK(!listener_); | 143 DCHECK(!listener_); |
128 DCHECK(!device_task_runner_.get()); | 144 DCHECK(!device_task_runner_.get()); |
129 listener_ = listener; | 145 listener_ = listener; |
130 device_task_runner_ = device_task_runner; | 146 device_task_runner_ = device_task_runner; |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 DestroyDeviceEntryIfNoClients(existing_device); | 225 DestroyDeviceEntryIfNoClients(existing_device); |
210 } | 226 } |
211 | 227 |
212 // Notify listeners asynchronously, and forget the session. | 228 // Notify listeners asynchronously, and forget the session. |
213 base::MessageLoop::current()->PostTask(FROM_HERE, | 229 base::MessageLoop::current()->PostTask(FROM_HERE, |
214 base::Bind(&VideoCaptureManager::OnClosed, this, session_it->second.type, | 230 base::Bind(&VideoCaptureManager::OnClosed, this, session_it->second.type, |
215 capture_session_id)); | 231 capture_session_id)); |
216 sessions_.erase(session_it); | 232 sessions_.erase(session_it); |
217 } | 233 } |
218 | 234 |
219 void VideoCaptureManager::DoStartDeviceOnDeviceThread( | 235 void VideoCaptureManager::QueueStartDevice( |
220 media::VideoCaptureSessionId session_id, | 236 media::VideoCaptureSessionId session_id, |
221 DeviceEntry* entry, | 237 DeviceEntry* entry, |
| 238 const media::VideoCaptureParams& params) { |
| 239 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 240 device_start_queue_.push_back( |
| 241 CaptureDeviceStartRequest(entry->serial_id, session_id, params)); |
| 242 if (device_start_queue_.size() == 1) |
| 243 HandleQueuedStartRequest(); |
| 244 } |
| 245 |
| 246 void VideoCaptureManager::DoStopDevice(DeviceEntry* entry) { |
| 247 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 248 DCHECK(std::find(devices_.begin(), devices_.end(), entry) != devices_.end()); |
| 249 |
| 250 // Find the matching start request. |
| 251 for (DeviceStartQueue::reverse_iterator request = |
| 252 device_start_queue_.rbegin(); |
| 253 request != device_start_queue_.rend(); ++request) { |
| 254 if (request->serial_id() == entry->serial_id) { |
| 255 request->set_abort_start(); |
| 256 DVLOG(3) << "DoStopDevice, aborting start request for device " |
| 257 << entry->id << " serial_id = " << entry->serial_id; |
| 258 return; |
| 259 } |
| 260 } |
| 261 |
| 262 DVLOG(3) << "DoStopDevice. Send stop request for device = " << entry->id |
| 263 << " serial_id = " << entry->serial_id << "."; |
| 264 if (entry->video_capture_device.get()) { |
| 265 // |entry->video_capture_device| can be null if creating the device fails. |
| 266 device_task_runner_->PostTask( |
| 267 FROM_HERE, |
| 268 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, |
| 269 base::Passed(&entry->video_capture_device))); |
| 270 } |
| 271 } |
| 272 |
| 273 void VideoCaptureManager::HandleQueuedStartRequest() { |
| 274 // Remove all start requests that have been aborted. |
| 275 while (device_start_queue_.begin() != device_start_queue_.end() && |
| 276 device_start_queue_.begin()->abort_start()) { |
| 277 device_start_queue_.pop_front(); |
| 278 } |
| 279 DeviceStartQueue::iterator request = device_start_queue_.begin(); |
| 280 if (request == device_start_queue_.end()) |
| 281 return; |
| 282 |
| 283 const int serial_id = request->serial_id(); |
| 284 DeviceEntries::iterator entry_it = std::find_if( |
| 285 devices_.begin(), devices_.end(), |
| 286 [serial_id] (const DeviceEntry* e) { |
| 287 return e->serial_id == serial_id; |
| 288 }); |
| 289 DCHECK(entry_it != devices_.end()); |
| 290 DeviceEntry* entry = (*entry_it); |
| 291 |
| 292 DVLOG(3) << "HandleQueuedStartRequest, Post start to device thread, device = " |
| 293 << entry->id << " start id = " << entry->serial_id; |
| 294 base::PostTaskAndReplyWithResult( |
| 295 device_task_runner_.get(), |
| 296 FROM_HERE, |
| 297 base::Bind( |
| 298 &VideoCaptureManager::DoStartDeviceOnDeviceThread, |
| 299 this, |
| 300 request->session_id(), |
| 301 entry->id, |
| 302 entry->stream_type, |
| 303 request->params(), |
| 304 base::Passed(entry->video_capture_controller->NewDeviceClient())), |
| 305 base::Bind(&VideoCaptureManager::OnDeviceStarted, this, |
| 306 request->serial_id())); |
| 307 } |
| 308 |
| 309 void VideoCaptureManager::OnDeviceStarted( |
| 310 int serial_id, |
| 311 scoped_ptr<media::VideoCaptureDevice> device) { |
| 312 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 313 DCHECK(serial_id == device_start_queue_.begin()->serial_id()); |
| 314 DVLOG(3) << "OnDeviceStarted"; |
| 315 if (device_start_queue_.front().abort_start()) { |
| 316 // |device| can be null if creation failed in DoStartDeviceOnDeviceThread. |
| 317 // The device is no longer wanted. Stop the device again. |
| 318 DVLOG(3) << "OnDeviceStarted but start request have been aborted."; |
| 319 media::VideoCaptureDevice* device_ptr = device.get(); |
| 320 base::Closure closure = |
| 321 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, |
| 322 base::Passed(&device)); |
| 323 if (device_ptr && !device_task_runner_->PostTask(FROM_HERE, closure)) { |
| 324 // PostTask failed. The device must be stopped anyway. |
| 325 device_ptr->StopAndDeAllocate(); |
| 326 } |
| 327 } else { |
| 328 DeviceEntries::iterator entry_it = std::find_if( |
| 329 devices_.begin(), devices_.end(), |
| 330 [serial_id] (const DeviceEntry* e) { |
| 331 return e->serial_id == serial_id; |
| 332 }); |
| 333 DCHECK(entry_it != devices_.end()); |
| 334 DCHECK(!(*entry_it)->video_capture_device.get()); |
| 335 (*entry_it)->video_capture_device.swap(device); |
| 336 } |
| 337 |
| 338 device_start_queue_.pop_front(); |
| 339 HandleQueuedStartRequest(); |
| 340 } |
| 341 |
| 342 scoped_ptr<media::VideoCaptureDevice> |
| 343 VideoCaptureManager::DoStartDeviceOnDeviceThread( |
| 344 media::VideoCaptureSessionId session_id, |
| 345 const std::string& id, |
| 346 MediaStreamType stream_type, |
222 const media::VideoCaptureParams& params, | 347 const media::VideoCaptureParams& params, |
223 scoped_ptr<media::VideoCaptureDevice::Client> device_client) { | 348 scoped_ptr<media::VideoCaptureDevice::Client> device_client) { |
224 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime"); | 349 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime"); |
225 DCHECK(IsOnDeviceThread()); | 350 DCHECK(IsOnDeviceThread()); |
226 | 351 |
227 scoped_ptr<media::VideoCaptureDevice> video_capture_device; | 352 scoped_ptr<media::VideoCaptureDevice> video_capture_device; |
228 switch (entry->stream_type) { | 353 switch (stream_type) { |
229 case MEDIA_DEVICE_VIDEO_CAPTURE: { | 354 case MEDIA_DEVICE_VIDEO_CAPTURE: { |
230 // We look up the device id from the renderer in our local enumeration | 355 // We look up the device id from the renderer in our local enumeration |
231 // since the renderer does not have all the information that might be | 356 // since the renderer does not have all the information that might be |
232 // held in the browser-side VideoCaptureDevice::Name structure. | 357 // held in the browser-side VideoCaptureDevice::Name structure. |
233 media::VideoCaptureDeviceInfo* found = | 358 media::VideoCaptureDeviceInfo* found = |
234 FindDeviceInfoById(entry->id, devices_info_cache_); | 359 FindDeviceInfoById(id, devices_info_cache_); |
235 if (found) { | 360 if (found) { |
236 video_capture_device = | 361 video_capture_device = |
237 video_capture_device_factory_->Create(found->name); | 362 video_capture_device_factory_->Create(found->name); |
238 } | 363 } |
239 break; | 364 break; |
240 } | 365 } |
241 case MEDIA_TAB_VIDEO_CAPTURE: { | 366 case MEDIA_TAB_VIDEO_CAPTURE: { |
242 video_capture_device.reset( | 367 video_capture_device.reset( |
243 WebContentsVideoCaptureDevice::Create(entry->id)); | 368 WebContentsVideoCaptureDevice::Create(id)); |
244 break; | 369 break; |
245 } | 370 } |
246 case MEDIA_DESKTOP_VIDEO_CAPTURE: { | 371 case MEDIA_DESKTOP_VIDEO_CAPTURE: { |
247 #if defined(ENABLE_SCREEN_CAPTURE) | 372 #if defined(ENABLE_SCREEN_CAPTURE) |
248 DesktopMediaID id = DesktopMediaID::Parse(entry->id); | 373 DesktopMediaID desktop_id = DesktopMediaID::Parse(id); |
249 #if defined(USE_AURA) | 374 #if defined(USE_AURA) |
250 if (id.type == DesktopMediaID::TYPE_AURA_WINDOW) { | 375 if (desktop_id.type == DesktopMediaID::TYPE_AURA_WINDOW) { |
251 video_capture_device.reset(DesktopCaptureDeviceAura::Create(id)); | 376 video_capture_device.reset( |
| 377 DesktopCaptureDeviceAura::Create(desktop_id)); |
252 } else | 378 } else |
253 #endif | 379 #endif |
254 if (id.type != DesktopMediaID::TYPE_NONE && | 380 if (desktop_id.type != DesktopMediaID::TYPE_NONE && |
255 id.type != DesktopMediaID::TYPE_AURA_WINDOW) { | 381 desktop_id.type != DesktopMediaID::TYPE_AURA_WINDOW) { |
256 video_capture_device = DesktopCaptureDevice::Create(id); | 382 video_capture_device = DesktopCaptureDevice::Create(desktop_id); |
257 if (notification_window_ids_.find(session_id) != | 383 if (notification_window_ids_.find(session_id) != |
258 notification_window_ids_.end()) { | 384 notification_window_ids_.end()) { |
259 static_cast<DesktopCaptureDevice*>(video_capture_device.get()) | 385 static_cast<DesktopCaptureDevice*>(video_capture_device.get()) |
260 ->SetNotificationWindowId(notification_window_ids_[session_id]); | 386 ->SetNotificationWindowId(notification_window_ids_[session_id]); |
261 VLOG(2) << "Screen capture notification window passed for session " | 387 VLOG(2) << "Screen capture notification window passed for session " |
262 << session_id; | 388 << session_id; |
263 } | 389 } |
264 } | 390 } |
265 #endif // defined(ENABLE_SCREEN_CAPTURE) | 391 #endif // defined(ENABLE_SCREEN_CAPTURE) |
266 break; | 392 break; |
267 } | 393 } |
268 default: { | 394 default: { |
269 NOTIMPLEMENTED(); | 395 NOTIMPLEMENTED(); |
270 break; | 396 break; |
271 } | 397 } |
272 } | 398 } |
273 | 399 |
274 if (!video_capture_device) { | 400 if (!video_capture_device) { |
275 device_client->OnError("Could not create capture device"); | 401 device_client->OnError("Could not create capture device"); |
276 return; | 402 return nullptr; |
277 } | 403 } |
278 | 404 |
279 video_capture_device->AllocateAndStart(params, device_client.Pass()); | 405 video_capture_device->AllocateAndStart(params, device_client.Pass()); |
280 entry->video_capture_device = video_capture_device.Pass(); | 406 return video_capture_device.Pass(); |
281 } | 407 } |
282 | 408 |
283 void VideoCaptureManager::StartCaptureForClient( | 409 void VideoCaptureManager::StartCaptureForClient( |
284 media::VideoCaptureSessionId session_id, | 410 media::VideoCaptureSessionId session_id, |
285 const media::VideoCaptureParams& params, | 411 const media::VideoCaptureParams& params, |
286 base::ProcessHandle client_render_process, | 412 base::ProcessHandle client_render_process, |
287 VideoCaptureControllerID client_id, | 413 VideoCaptureControllerID client_id, |
288 VideoCaptureControllerEventHandler* client_handler, | 414 VideoCaptureControllerEventHandler* client_handler, |
289 const DoneCB& done_cb) { | 415 const DoneCB& done_cb) { |
290 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 416 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
291 DVLOG(1) << "VideoCaptureManager::StartCaptureForClient, " | 417 DVLOG(1) << "VideoCaptureManager::StartCaptureForClient, " |
292 << params.requested_format.frame_size.ToString() << ", " | 418 << params.requested_format.frame_size.ToString() << ", " |
293 << params.requested_format.frame_rate << ", #" << session_id << ")"; | 419 << params.requested_format.frame_rate << ", #" << session_id << ")"; |
294 | 420 |
295 DeviceEntry* entry = GetOrCreateDeviceEntry(session_id); | 421 DeviceEntry* entry = GetOrCreateDeviceEntry(session_id); |
296 if (!entry) { | 422 if (!entry) { |
297 done_cb.Run(base::WeakPtr<VideoCaptureController>()); | 423 done_cb.Run(base::WeakPtr<VideoCaptureController>()); |
298 return; | 424 return; |
299 } | 425 } |
300 | 426 |
301 DCHECK(entry->video_capture_controller); | 427 DCHECK(entry->video_capture_controller); |
302 | 428 |
303 LogVideoCaptureEvent(VIDEO_CAPTURE_START_CAPTURE); | 429 LogVideoCaptureEvent(VIDEO_CAPTURE_START_CAPTURE); |
304 | 430 |
305 // First client starts the device. | 431 // First client starts the device. |
306 if (entry->video_capture_controller->GetActiveClientCount() == 0) { | 432 if (entry->video_capture_controller->GetActiveClientCount() == 0) { |
307 DVLOG(1) << "VideoCaptureManager starting device (type = " | 433 DVLOG(1) << "VideoCaptureManager starting device (type = " |
308 << entry->stream_type << ", id = " << entry->id << ")"; | 434 << entry->stream_type << ", id = " << entry->id << ")"; |
309 | 435 QueueStartDevice(session_id, entry, params); |
310 device_task_runner_->PostTask( | |
311 FROM_HERE, | |
312 base::Bind( | |
313 &VideoCaptureManager::DoStartDeviceOnDeviceThread, | |
314 this, | |
315 session_id, | |
316 entry, | |
317 params, | |
318 base::Passed(entry->video_capture_controller->NewDeviceClient()))); | |
319 } | 436 } |
320 // Run the callback first, as AddClient() may trigger OnFrameInfo(). | 437 // Run the callback first, as AddClient() may trigger OnFrameInfo(). |
321 done_cb.Run(entry->video_capture_controller->GetWeakPtr()); | 438 done_cb.Run(entry->video_capture_controller->GetWeakPtr()); |
322 entry->video_capture_controller->AddClient( | 439 entry->video_capture_controller->AddClient( |
323 client_id, client_handler, client_render_process, session_id, params); | 440 client_id, client_handler, client_render_process, session_id, params); |
324 } | 441 } |
325 | 442 |
326 void VideoCaptureManager::StopCaptureForClient( | 443 void VideoCaptureManager::StopCaptureForClient( |
327 VideoCaptureController* controller, | 444 VideoCaptureController* controller, |
328 VideoCaptureControllerID client_id, | 445 VideoCaptureControllerID client_id, |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 // We only pause the MEDIA_DEVICE_VIDEO_CAPTURE entry to release camera to | 502 // We only pause the MEDIA_DEVICE_VIDEO_CAPTURE entry to release camera to |
386 // system. | 503 // system. |
387 if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE) | 504 if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE) |
388 return; | 505 return; |
389 | 506 |
390 controller->PauseOrResumeClient(client_id, client_handler, true); | 507 controller->PauseOrResumeClient(client_id, client_handler, true); |
391 if (controller->GetActiveClientCount() != 0) | 508 if (controller->GetActiveClientCount() != 0) |
392 return; | 509 return; |
393 | 510 |
394 // There is no more client, release the camera. | 511 // There is no more client, release the camera. |
395 device_task_runner_->PostTask( | 512 DoStopDevice(entry); |
396 FROM_HERE, | |
397 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, | |
398 base::Unretained(entry))); | |
399 } | 513 } |
400 | 514 |
401 void VideoCaptureManager::ResumeCaptureForClient( | 515 void VideoCaptureManager::ResumeCaptureForClient( |
402 media::VideoCaptureSessionId session_id, | 516 media::VideoCaptureSessionId session_id, |
403 const media::VideoCaptureParams& params, | 517 const media::VideoCaptureParams& params, |
404 VideoCaptureController* controller, | 518 VideoCaptureController* controller, |
405 VideoCaptureControllerID client_id, | 519 VideoCaptureControllerID client_id, |
406 VideoCaptureControllerEventHandler* client_handler) { | 520 VideoCaptureControllerEventHandler* client_handler) { |
407 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 521 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
408 DCHECK(controller); | 522 DCHECK(controller); |
409 DCHECK(client_handler); | 523 DCHECK(client_handler); |
410 | 524 |
411 DeviceEntry* entry = GetDeviceEntryForController(controller); | 525 DeviceEntry* entry = GetDeviceEntryForController(controller); |
412 if (!entry) { | 526 if (!entry) { |
413 NOTREACHED(); | 527 NOTREACHED(); |
414 return; | 528 return; |
415 } | 529 } |
416 | 530 |
417 // We only pause/resume the MEDIA_DEVICE_VIDEO_CAPTURE entry. | 531 // We only pause/resume the MEDIA_DEVICE_VIDEO_CAPTURE entry. |
418 if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE) | 532 if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE) |
419 return; | 533 return; |
420 | 534 |
421 controller->PauseOrResumeClient(client_id, client_handler, false); | 535 controller->PauseOrResumeClient(client_id, client_handler, false); |
422 if (controller->GetActiveClientCount() != 1) | 536 if (controller->GetActiveClientCount() != 1) |
423 return; | 537 return; |
424 | 538 |
425 // This is first active client, allocate the camera. | 539 // This is first active client, allocate the camera. |
426 device_task_runner_->PostTask( | 540 QueueStartDevice(session_id, entry, params); |
427 FROM_HERE, | |
428 base::Bind( | |
429 &VideoCaptureManager::DoStartDeviceOnDeviceThread, | |
430 this, | |
431 session_id, | |
432 entry, | |
433 params, | |
434 base::Passed(entry->video_capture_controller->NewDeviceClient()))); | |
435 } | 541 } |
436 | 542 |
437 bool VideoCaptureManager::GetDeviceSupportedFormats( | 543 bool VideoCaptureManager::GetDeviceSupportedFormats( |
438 media::VideoCaptureSessionId capture_session_id, | 544 media::VideoCaptureSessionId capture_session_id, |
439 media::VideoCaptureFormats* supported_formats) { | 545 media::VideoCaptureFormats* supported_formats) { |
440 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 546 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
441 DCHECK(supported_formats->empty()); | 547 DCHECK(supported_formats->empty()); |
442 | 548 |
443 SessionMap::iterator it = sessions_.find(capture_session_id); | 549 SessionMap::iterator it = sessions_.find(capture_session_id); |
444 if (it == sessions_.end()) | 550 if (it == sessions_.end()) |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 } | 616 } |
511 | 617 |
512 device_task_runner_->PostTask( | 618 device_task_runner_->PostTask( |
513 FROM_HERE, | 619 FROM_HERE, |
514 base::Bind(&VideoCaptureManager::SetDesktopCaptureWindowIdOnDeviceThread, | 620 base::Bind(&VideoCaptureManager::SetDesktopCaptureWindowIdOnDeviceThread, |
515 this, | 621 this, |
516 existing_device, | 622 existing_device, |
517 window_id)); | 623 window_id)); |
518 } | 624 } |
519 | 625 |
520 void VideoCaptureManager::DoStopDeviceOnDeviceThread(DeviceEntry* entry) { | 626 void VideoCaptureManager::DoStopDeviceOnDeviceThread( |
| 627 scoped_ptr<media::VideoCaptureDevice> device) { |
521 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime"); | 628 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime"); |
522 DCHECK(IsOnDeviceThread()); | 629 DCHECK(IsOnDeviceThread()); |
523 if (entry->video_capture_device) { | 630 device->StopAndDeAllocate(); |
524 entry->video_capture_device->StopAndDeAllocate(); | 631 DVLOG(3) << "DoStopDeviceOnDeviceThread"; |
525 } | |
526 entry->video_capture_device.reset(); | |
527 } | 632 } |
528 | 633 |
529 void VideoCaptureManager::OnOpened( | 634 void VideoCaptureManager::OnOpened( |
530 MediaStreamType stream_type, | 635 MediaStreamType stream_type, |
531 media::VideoCaptureSessionId capture_session_id) { | 636 media::VideoCaptureSessionId capture_session_id) { |
532 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 637 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
533 if (!listener_) { | 638 if (!listener_) { |
534 // Listener has been removed. | 639 // Listener has been removed. |
535 return; | 640 return; |
536 } | 641 } |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
646 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 751 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
647 // Removal of the last client stops the device. | 752 // Removal of the last client stops the device. |
648 if (entry->video_capture_controller->GetClientCount() == 0) { | 753 if (entry->video_capture_controller->GetClientCount() == 0) { |
649 DVLOG(1) << "VideoCaptureManager stopping device (type = " | 754 DVLOG(1) << "VideoCaptureManager stopping device (type = " |
650 << entry->stream_type << ", id = " << entry->id << ")"; | 755 << entry->stream_type << ", id = " << entry->id << ")"; |
651 | 756 |
652 // The DeviceEntry is removed from |devices_| immediately. The controller is | 757 // The DeviceEntry is removed from |devices_| immediately. The controller is |
653 // deleted immediately, and the device is freed asynchronously. After this | 758 // deleted immediately, and the device is freed asynchronously. After this |
654 // point, subsequent requests to open this same device ID will create a new | 759 // point, subsequent requests to open this same device ID will create a new |
655 // DeviceEntry, VideoCaptureController, and VideoCaptureDevice. | 760 // DeviceEntry, VideoCaptureController, and VideoCaptureDevice. |
656 devices_.erase(entry); | 761 DoStopDevice(entry); |
657 entry->video_capture_controller.reset(); | 762 DeviceEntries::iterator device_it = std::find(devices_.begin(), |
658 device_task_runner_->PostTask( | 763 devices_.end(), |
659 FROM_HERE, | 764 entry); |
660 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, | 765 devices_.erase(device_it); |
661 base::Owned(entry))); | |
662 } | 766 } |
663 } | 767 } |
664 | 768 |
665 VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry( | 769 VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry( |
666 media::VideoCaptureSessionId capture_session_id) { | 770 media::VideoCaptureSessionId capture_session_id) { |
667 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 771 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
668 | 772 |
669 SessionMap::iterator session_it = sessions_.find(capture_session_id); | 773 SessionMap::iterator session_it = sessions_.find(capture_session_id); |
670 if (session_it == sessions_.end()) { | 774 if (session_it == sessions_.end()) { |
671 return NULL; | 775 return NULL; |
672 } | 776 } |
673 const MediaStreamDevice& device_info = session_it->second; | 777 const MediaStreamDevice& device_info = session_it->second; |
674 | 778 |
675 // Check if another session has already opened this device. If so, just | 779 // Check if another session has already opened this device. If so, just |
676 // use that opened device. | 780 // use that opened device. |
677 DeviceEntry* const existing_device = | 781 DeviceEntry* const existing_device = |
678 GetDeviceEntryForMediaStreamDevice(device_info); | 782 GetDeviceEntryForMediaStreamDevice(device_info); |
679 if (existing_device) { | 783 if (existing_device) { |
680 DCHECK_EQ(device_info.type, existing_device->stream_type); | 784 DCHECK_EQ(device_info.type, existing_device->stream_type); |
681 return existing_device; | 785 return existing_device; |
682 } | 786 } |
683 | 787 |
684 const int max_buffers = device_info.type == MEDIA_TAB_VIDEO_CAPTURE ? | 788 const int max_buffers = device_info.type == MEDIA_TAB_VIDEO_CAPTURE ? |
685 kMaxNumberOfBuffersForTabCapture : kMaxNumberOfBuffers; | 789 kMaxNumberOfBuffersForTabCapture : kMaxNumberOfBuffers; |
686 scoped_ptr<VideoCaptureController> video_capture_controller( | 790 scoped_ptr<VideoCaptureController> video_capture_controller( |
687 new VideoCaptureController(max_buffers)); | 791 new VideoCaptureController(max_buffers)); |
688 DeviceEntry* new_device = new DeviceEntry(device_info.type, | 792 DeviceEntry* new_device = new DeviceEntry(device_info.type, |
689 device_info.id, | 793 device_info.id, |
690 video_capture_controller.Pass()); | 794 video_capture_controller.Pass()); |
691 devices_.insert(new_device); | 795 devices_.push_back(new_device); |
692 return new_device; | 796 return new_device; |
693 } | 797 } |
694 | 798 |
695 media::VideoCaptureDeviceInfo* VideoCaptureManager::FindDeviceInfoById( | 799 media::VideoCaptureDeviceInfo* VideoCaptureManager::FindDeviceInfoById( |
696 const std::string& id, | 800 const std::string& id, |
697 media::VideoCaptureDeviceInfos& device_vector) { | 801 media::VideoCaptureDeviceInfos& device_vector) { |
698 for (auto& it : device_vector) { | 802 for (auto& it : device_vector) { |
699 if (it.name.id() == id) | 803 if (it.name.id() == id) |
700 return &(it); | 804 return &(it); |
701 } | 805 } |
(...skipping 18 matching lines...) Expand all Loading... |
720 gfx::NativeViewId window_id) { | 824 gfx::NativeViewId window_id) { |
721 DCHECK(IsOnDeviceThread()); | 825 DCHECK(IsOnDeviceThread()); |
722 DCHECK(notification_window_ids_.find(session_id) == | 826 DCHECK(notification_window_ids_.find(session_id) == |
723 notification_window_ids_.end()); | 827 notification_window_ids_.end()); |
724 notification_window_ids_[session_id] = window_id; | 828 notification_window_ids_[session_id] = window_id; |
725 VLOG(2) << "Screen capture notification window saved for session " | 829 VLOG(2) << "Screen capture notification window saved for session " |
726 << session_id << " on device thread."; | 830 << session_id << " on device thread."; |
727 } | 831 } |
728 | 832 |
729 } // namespace content | 833 } // namespace content |
OLD | NEW |