| 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 |