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 <algorithm> |
8 #include <set> | 8 #include <set> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
13 #include "base/location.h" | 13 #include "base/location.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "base/metrics/histogram_macros.h" | 15 #include "base/metrics/histogram_macros.h" |
16 #include "base/single_thread_task_runner.h" | 16 #include "base/single_thread_task_runner.h" |
17 #include "base/stl_util.h" | 17 #include "base/stl_util.h" |
| 18 #include "base/strings/stringprintf.h" |
18 #include "base/task_runner_util.h" | 19 #include "base/task_runner_util.h" |
19 #include "base/thread_task_runner_handle.h" | 20 #include "base/thread_task_runner_handle.h" |
20 #include "base/threading/sequenced_worker_pool.h" | 21 #include "base/threading/sequenced_worker_pool.h" |
21 #include "content/browser/media/capture/web_contents_video_capture_device.h" | 22 #include "content/browser/media/capture/web_contents_video_capture_device.h" |
22 #include "content/browser/media/media_internals.h" | 23 #include "content/browser/media/media_internals.h" |
23 #include "content/browser/renderer_host/media/video_capture_controller.h" | 24 #include "content/browser/renderer_host/media/video_capture_controller.h" |
24 #include "content/browser/renderer_host/media/video_capture_controller_event_han
dler.h" | 25 #include "content/browser/renderer_host/media/video_capture_controller_event_han
dler.h" |
25 #include "content/public/browser/browser_thread.h" | 26 #include "content/public/browser/browser_thread.h" |
26 #include "content/public/browser/desktop_media_id.h" | 27 #include "content/public/browser/desktop_media_id.h" |
27 #include "content/public/common/media_stream_request.h" | 28 #include "content/public/common/media_stream_request.h" |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 if (request->serial_id() == entry->serial_id) { | 290 if (request->serial_id() == entry->serial_id) { |
290 request->set_abort_start(); | 291 request->set_abort_start(); |
291 DVLOG(3) << "DoStopDevice, aborting start request for device " | 292 DVLOG(3) << "DoStopDevice, aborting start request for device " |
292 << entry->id << " serial_id = " << entry->serial_id; | 293 << entry->id << " serial_id = " << entry->serial_id; |
293 return; | 294 return; |
294 } | 295 } |
295 } | 296 } |
296 | 297 |
297 DVLOG(3) << "DoStopDevice. Send stop request for device = " << entry->id | 298 DVLOG(3) << "DoStopDevice. Send stop request for device = " << entry->id |
298 << " serial_id = " << entry->serial_id << "."; | 299 << " serial_id = " << entry->serial_id << "."; |
| 300 entry->video_capture_controller()->DoLogOnIOThread( |
| 301 base::StringPrintf("Stopping device: id: %s\n", entry->id.c_str())); |
| 302 |
299 if (entry->video_capture_device()) { | 303 if (entry->video_capture_device()) { |
300 // |entry->video_capture_device| can be null if creating the device fails. | 304 // |entry->video_capture_device| can be null if creating the device fails. |
301 device_task_runner_->PostTask( | 305 device_task_runner_->PostTask( |
302 FROM_HERE, | 306 FROM_HERE, |
303 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, | 307 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, |
304 base::Passed(entry->ReleaseVideoCaptureDevice()))); | 308 base::Passed(entry->ReleaseVideoCaptureDevice()))); |
305 } | 309 } |
306 } | 310 } |
307 | 311 |
308 void VideoCaptureManager::HandleQueuedStartRequest() { | 312 void VideoCaptureManager::HandleQueuedStartRequest() { |
(...skipping 11 matching lines...) Expand all Loading... |
320 DeviceEntries::iterator entry_it = std::find_if( | 324 DeviceEntries::iterator entry_it = std::find_if( |
321 devices_.begin(), devices_.end(), | 325 devices_.begin(), devices_.end(), |
322 [serial_id] (const DeviceEntry* e) { | 326 [serial_id] (const DeviceEntry* e) { |
323 return e->serial_id == serial_id; | 327 return e->serial_id == serial_id; |
324 }); | 328 }); |
325 DCHECK(entry_it != devices_.end()); | 329 DCHECK(entry_it != devices_.end()); |
326 DeviceEntry* entry = (*entry_it); | 330 DeviceEntry* entry = (*entry_it); |
327 | 331 |
328 DVLOG(3) << "HandleQueuedStartRequest, Post start to device thread, device = " | 332 DVLOG(3) << "HandleQueuedStartRequest, Post start to device thread, device = " |
329 << entry->id << " start id = " << entry->serial_id; | 333 << entry->id << " start id = " << entry->serial_id; |
| 334 |
| 335 base::Callback<scoped_ptr<media::VideoCaptureDevice>(void)> |
| 336 start_capture_function; |
| 337 |
| 338 switch (entry->stream_type) { |
| 339 case MEDIA_DEVICE_VIDEO_CAPTURE: { |
| 340 // We look up the device id from the renderer in our local enumeration |
| 341 // since the renderer does not have all the information that might be |
| 342 // held in the browser-side VideoCaptureDevice::Name structure. |
| 343 const media::VideoCaptureDeviceInfo* found = |
| 344 FindDeviceInfoById(entry->id, devices_info_cache_); |
| 345 if (found) { |
| 346 entry->video_capture_controller()->DoLogOnIOThread(base::StringPrintf( |
| 347 "Starting device: id: %s, name: %s, api: %s", |
| 348 found->name.id().c_str(), found->name.GetNameAndModel().c_str(), |
| 349 found->name.GetCaptureApiTypeString())); |
| 350 |
| 351 start_capture_function = base::Bind( |
| 352 &VideoCaptureManager::DoStartDeviceCaptureOnDeviceThread, this, |
| 353 found->name, request->params(), |
| 354 base::Passed(entry->video_capture_controller()->NewDeviceClient())); |
| 355 } else { |
| 356 // Errors from DoStartDeviceCaptureOnDeviceThread go via |
| 357 // VideoCaptureDeviceClient::OnError, which needs some thread |
| 358 // dancing to get errors processed on the IO thread. But since |
| 359 // we're on that thread, we call VideoCaptureController |
| 360 // methods directly. |
| 361 const std::string log_message = base::StringPrintf( |
| 362 "Error on %s:%d: device %s unknown. Maybe recently disconnected?", |
| 363 __FILE__, __LINE__, entry->id.c_str()); |
| 364 DLOG(ERROR) << log_message; |
| 365 entry->video_capture_controller()->DoLogOnIOThread(log_message); |
| 366 entry->video_capture_controller()->DoErrorOnIOThread(); |
| 367 // Drop the failed start request. |
| 368 device_start_queue_.pop_front(); |
| 369 |
| 370 return; |
| 371 } |
| 372 break; |
| 373 } |
| 374 case MEDIA_TAB_VIDEO_CAPTURE: |
| 375 start_capture_function = base::Bind( |
| 376 &VideoCaptureManager::DoStartTabCaptureOnDeviceThread, this, |
| 377 entry->id, request->params(), |
| 378 base::Passed(entry->video_capture_controller()->NewDeviceClient())); |
| 379 break; |
| 380 |
| 381 case MEDIA_DESKTOP_VIDEO_CAPTURE: |
| 382 start_capture_function = base::Bind( |
| 383 &VideoCaptureManager::DoStartDesktopCaptureOnDeviceThread, this, |
| 384 entry->id, request->params(), |
| 385 base::Passed(entry->video_capture_controller()->NewDeviceClient())); |
| 386 break; |
| 387 |
| 388 default: { |
| 389 NOTIMPLEMENTED(); |
| 390 return; |
| 391 } |
| 392 } |
330 base::PostTaskAndReplyWithResult( | 393 base::PostTaskAndReplyWithResult( |
331 device_task_runner_.get(), | 394 device_task_runner_.get(), FROM_HERE, start_capture_function, |
332 FROM_HERE, | |
333 base::Bind( | |
334 &VideoCaptureManager::DoStartDeviceOnDeviceThread, | |
335 this, | |
336 request->session_id(), | |
337 entry->id, | |
338 entry->stream_type, | |
339 request->params(), | |
340 base::Passed(entry->video_capture_controller()->NewDeviceClient())), | |
341 base::Bind(&VideoCaptureManager::OnDeviceStarted, this, | 395 base::Bind(&VideoCaptureManager::OnDeviceStarted, this, |
342 request->serial_id())); | 396 request->serial_id())); |
343 } | 397 } |
344 | 398 |
345 void VideoCaptureManager::OnDeviceStarted( | 399 void VideoCaptureManager::OnDeviceStarted( |
346 int serial_id, | 400 int serial_id, |
347 scoped_ptr<media::VideoCaptureDevice> device) { | 401 scoped_ptr<media::VideoCaptureDevice> device) { |
348 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 402 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
349 DCHECK(serial_id == device_start_queue_.begin()->serial_id()); | 403 DCHECK(serial_id == device_start_queue_.begin()->serial_id()); |
350 DVLOG(3) << "OnDeviceStarted"; | 404 DVLOG(3) << "OnDeviceStarted"; |
351 if (device_start_queue_.front().abort_start()) { | 405 if (device_start_queue_.front().abort_start()) { |
352 // |device| can be null if creation failed in DoStartDeviceOnDeviceThread. | 406 // |device| can be null if creation failed in |
| 407 // DoStartDeviceCaptureOnDeviceThread. |
353 // The device is no longer wanted. Stop the device again. | 408 // The device is no longer wanted. Stop the device again. |
354 DVLOG(3) << "OnDeviceStarted but start request have been aborted."; | 409 DVLOG(3) << "OnDeviceStarted but start request have been aborted."; |
355 media::VideoCaptureDevice* device_ptr = device.get(); | 410 media::VideoCaptureDevice* device_ptr = device.get(); |
356 base::Closure closure = | 411 base::Closure closure = |
357 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, | 412 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, |
358 base::Passed(&device)); | 413 base::Passed(&device)); |
359 if (device_ptr && !device_task_runner_->PostTask(FROM_HERE, closure)) { | 414 if (device_ptr && !device_task_runner_->PostTask(FROM_HERE, closure)) { |
360 // PostTask failed. The device must be stopped anyway. | 415 // PostTask failed. The device must be stopped anyway. |
361 device_ptr->StopAndDeAllocate(); | 416 device_ptr->StopAndDeAllocate(); |
362 } | 417 } |
(...skipping 13 matching lines...) Expand all Loading... |
376 device_start_queue_.front().session_id(); | 431 device_start_queue_.front().session_id(); |
377 MaybePostDesktopCaptureWindowId(session_id); | 432 MaybePostDesktopCaptureWindowId(session_id); |
378 } | 433 } |
379 } | 434 } |
380 | 435 |
381 device_start_queue_.pop_front(); | 436 device_start_queue_.pop_front(); |
382 HandleQueuedStartRequest(); | 437 HandleQueuedStartRequest(); |
383 } | 438 } |
384 | 439 |
385 scoped_ptr<media::VideoCaptureDevice> | 440 scoped_ptr<media::VideoCaptureDevice> |
386 VideoCaptureManager::DoStartDeviceOnDeviceThread( | 441 VideoCaptureManager::DoStartDeviceCaptureOnDeviceThread( |
387 media::VideoCaptureSessionId session_id, | 442 const media::VideoCaptureDevice::Name& name, |
388 const std::string& id, | |
389 MediaStreamType stream_type, | |
390 const media::VideoCaptureParams& params, | 443 const media::VideoCaptureParams& params, |
391 scoped_ptr<media::VideoCaptureDevice::Client> device_client) { | 444 scoped_ptr<media::VideoCaptureDevice::Client> device_client) { |
392 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime"); | 445 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime"); |
393 DCHECK(IsOnDeviceThread()); | 446 DCHECK(IsOnDeviceThread()); |
394 | 447 |
395 scoped_ptr<media::VideoCaptureDevice> video_capture_device; | 448 scoped_ptr<media::VideoCaptureDevice> video_capture_device; |
396 switch (stream_type) { | 449 video_capture_device = video_capture_device_factory_->Create(name); |
397 case MEDIA_DEVICE_VIDEO_CAPTURE: { | |
398 // We look up the device id from the renderer in our local enumeration | |
399 // since the renderer does not have all the information that might be | |
400 // held in the browser-side VideoCaptureDevice::Name structure. | |
401 const media::VideoCaptureDeviceInfo* found = | |
402 FindDeviceInfoById(id, devices_info_cache_); | |
403 if (found) { | |
404 video_capture_device = | |
405 video_capture_device_factory_->Create(found->name); | |
406 } | |
407 break; | |
408 } | |
409 case MEDIA_TAB_VIDEO_CAPTURE: { | |
410 video_capture_device.reset( | |
411 WebContentsVideoCaptureDevice::Create(id)); | |
412 break; | |
413 } | |
414 case MEDIA_DESKTOP_VIDEO_CAPTURE: { | |
415 #if defined(ENABLE_SCREEN_CAPTURE) | |
416 DesktopMediaID desktop_id = DesktopMediaID::Parse(id); | |
417 if (!desktop_id.is_null()) { | |
418 #if defined(USE_AURA) | |
419 video_capture_device = DesktopCaptureDeviceAura::Create(desktop_id); | |
420 #endif | |
421 if (!video_capture_device) | |
422 video_capture_device = DesktopCaptureDevice::Create(desktop_id); | |
423 } | |
424 #endif // defined(ENABLE_SCREEN_CAPTURE) | |
425 break; | |
426 } | |
427 default: { | |
428 NOTIMPLEMENTED(); | |
429 break; | |
430 } | |
431 } | |
432 | 450 |
433 if (!video_capture_device) { | 451 if (!video_capture_device) { |
434 device_client->OnError(FROM_HERE, "Could not create capture device"); | 452 device_client->OnError(FROM_HERE, "Could not create capture device"); |
| 453 return nullptr; |
| 454 } |
| 455 |
| 456 video_capture_device->AllocateAndStart(params, device_client.Pass()); |
| 457 return video_capture_device.Pass(); |
| 458 } |
| 459 |
| 460 scoped_ptr<media::VideoCaptureDevice> |
| 461 VideoCaptureManager::DoStartTabCaptureOnDeviceThread( |
| 462 const std::string& id, |
| 463 const media::VideoCaptureParams& params, |
| 464 scoped_ptr<media::VideoCaptureDevice::Client> device_client) { |
| 465 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime"); |
| 466 DCHECK(IsOnDeviceThread()); |
| 467 |
| 468 scoped_ptr<media::VideoCaptureDevice> video_capture_device; |
| 469 video_capture_device.reset(WebContentsVideoCaptureDevice::Create(id)); |
| 470 |
| 471 if (!video_capture_device) { |
| 472 device_client->OnError(FROM_HERE, "Could not create capture device"); |
| 473 return nullptr; |
| 474 } |
| 475 |
| 476 video_capture_device->AllocateAndStart(params, device_client.Pass()); |
| 477 return video_capture_device.Pass(); |
| 478 } |
| 479 |
| 480 scoped_ptr<media::VideoCaptureDevice> |
| 481 VideoCaptureManager::DoStartDesktopCaptureOnDeviceThread( |
| 482 const std::string& id, |
| 483 const media::VideoCaptureParams& params, |
| 484 scoped_ptr<media::VideoCaptureDevice::Client> device_client) { |
| 485 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime"); |
| 486 DCHECK(IsOnDeviceThread()); |
| 487 |
| 488 scoped_ptr<media::VideoCaptureDevice> video_capture_device; |
| 489 #if defined(ENABLE_SCREEN_CAPTURE) |
| 490 DesktopMediaID desktop_id = DesktopMediaID::Parse(id); |
| 491 if (!desktop_id.is_null()) { |
| 492 #if defined(USE_AURA) |
| 493 video_capture_device = DesktopCaptureDeviceAura::Create(desktop_id); |
| 494 #endif |
| 495 if (!video_capture_device) |
| 496 video_capture_device = DesktopCaptureDevice::Create(desktop_id); |
| 497 } |
| 498 #endif // defined(ENABLE_SCREEN_CAPTURE) |
| 499 |
| 500 if (!video_capture_device) { |
| 501 device_client->OnError(FROM_HERE, "Could not create capture device"); |
435 return nullptr; | 502 return nullptr; |
436 } | 503 } |
437 | 504 |
438 video_capture_device->AllocateAndStart(params, device_client.Pass()); | 505 video_capture_device->AllocateAndStart(params, device_client.Pass()); |
439 return video_capture_device.Pass(); | 506 return video_capture_device.Pass(); |
440 } | 507 } |
441 | 508 |
442 void VideoCaptureManager::StartCaptureForClient( | 509 void VideoCaptureManager::StartCaptureForClient( |
443 media::VideoCaptureSessionId session_id, | 510 media::VideoCaptureSessionId session_id, |
444 const media::VideoCaptureParams& params, | 511 const media::VideoCaptureParams& params, |
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
859 DCHECK(IsOnDeviceThread()); | 926 DCHECK(IsOnDeviceThread()); |
860 #if defined(ENABLE_SCREEN_CAPTURE) | 927 #if defined(ENABLE_SCREEN_CAPTURE) |
861 DesktopCaptureDevice* desktop_device = | 928 DesktopCaptureDevice* desktop_device = |
862 static_cast<DesktopCaptureDevice*>(device); | 929 static_cast<DesktopCaptureDevice*>(device); |
863 desktop_device->SetNotificationWindowId(window_id); | 930 desktop_device->SetNotificationWindowId(window_id); |
864 VLOG(2) << "Screen capture notification window passed on device thread."; | 931 VLOG(2) << "Screen capture notification window passed on device thread."; |
865 #endif | 932 #endif |
866 } | 933 } |
867 | 934 |
868 } // namespace content | 935 } // namespace content |
OLD | NEW |