Chromium Code Reviews| 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 <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 111 | 111 |
| 112 VideoCaptureManager::VideoCaptureManager( | 112 VideoCaptureManager::VideoCaptureManager( |
| 113 scoped_ptr<media::VideoCaptureDeviceFactory> factory) | 113 scoped_ptr<media::VideoCaptureDeviceFactory> factory) |
| 114 : listener_(NULL), | 114 : listener_(NULL), |
| 115 new_capture_session_id_(1), | 115 new_capture_session_id_(1), |
| 116 video_capture_device_factory_(factory.Pass()) { | 116 video_capture_device_factory_(factory.Pass()) { |
| 117 } | 117 } |
| 118 | 118 |
| 119 VideoCaptureManager::~VideoCaptureManager() { | 119 VideoCaptureManager::~VideoCaptureManager() { |
| 120 DCHECK(devices_.empty()); | 120 DCHECK(devices_.empty()); |
| 121 DCHECK(device_start_queue_.empty()); | |
| 121 } | 122 } |
| 122 | 123 |
| 123 void VideoCaptureManager::Register( | 124 void VideoCaptureManager::Register( |
| 124 MediaStreamProviderListener* listener, | 125 MediaStreamProviderListener* listener, |
| 125 const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner) { | 126 const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner) { |
| 126 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 127 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 127 DCHECK(!listener_); | 128 DCHECK(!listener_); |
| 128 DCHECK(!device_task_runner_.get()); | 129 DCHECK(!device_task_runner_.get()); |
| 129 listener_ = listener; | 130 listener_ = listener; |
| 130 device_task_runner_ = device_task_runner; | 131 device_task_runner_ = device_task_runner; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 209 DestroyDeviceEntryIfNoClients(existing_device); | 210 DestroyDeviceEntryIfNoClients(existing_device); |
| 210 } | 211 } |
| 211 | 212 |
| 212 // Notify listeners asynchronously, and forget the session. | 213 // Notify listeners asynchronously, and forget the session. |
| 213 base::MessageLoop::current()->PostTask(FROM_HERE, | 214 base::MessageLoop::current()->PostTask(FROM_HERE, |
| 214 base::Bind(&VideoCaptureManager::OnClosed, this, session_it->second.type, | 215 base::Bind(&VideoCaptureManager::OnClosed, this, session_it->second.type, |
| 215 capture_session_id)); | 216 capture_session_id)); |
| 216 sessions_.erase(session_it); | 217 sessions_.erase(session_it); |
| 217 } | 218 } |
| 218 | 219 |
| 220 // Creates a start request. | |
| 221 VideoCaptureManager:: | |
| 222 CaptureDeviceStartRequest::CaptureDeviceStartRequest( | |
|
tommi (sloooow) - chröme
2014/12/15 16:25:05
no need to wrap?
perkj_chrome
2014/12/16 20:15:05
media::VideoCaptureSessionId session_id, does not
tommi (sloooow) - chröme
2014/12/16 22:31:25
I meant the function:
VideoCaptureManager::Captur
| |
| 223 DeviceEntry* device_entry, | |
| 224 media::VideoCaptureSessionId session_id, | |
| 225 const media::VideoCaptureParams& params) | |
| 226 : device_entry(device_entry), | |
| 227 session_id(session_id), | |
| 228 params(params) { | |
| 229 } | |
| 230 | |
| 231 void VideoCaptureManager::QueueStartDevice( | |
| 232 media::VideoCaptureSessionId session_id, | |
| 233 DeviceEntry* entry, | |
| 234 const media::VideoCaptureParams& params) { | |
| 235 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 236 DCHECK(entry->video_capture_controller.get()); | |
| 237 DVLOG(3) << "QueueStartDevice, device = " << entry->id; | |
| 238 | |
| 239 device_start_queue_.push_back( | |
| 240 CaptureDeviceStartRequest(entry, session_id, params)); | |
| 241 if (device_start_queue_.size() == 1) { | |
| 242 HandleQueuedStartRequest(); | |
| 243 } | |
| 244 } | |
| 245 | |
| 246 void VideoCaptureManager::DoStopDevice(DeviceEntry* entry, bool delete_entry) { | |
| 247 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 248 // Check if the start request has not yet been sent to the device thread. | |
| 249 // If so, delete the request. | |
| 250 if (device_start_queue_.size() > 1) { | |
| 251 for (DeviceStartQueue::iterator request = ++device_start_queue_.begin(); | |
| 252 request != device_start_queue_.end(); ++request) { | |
| 253 if (request->device_entry->id == entry->id && | |
| 254 request->device_entry->stream_type == entry->stream_type) { | |
| 255 device_start_queue_.erase(request); | |
| 256 DVLOG(3) << "DoStopDevice, erasing start request for device " | |
| 257 << entry->id << "."; | |
| 258 if (delete_entry) { | |
| 259 delete entry; | |
|
tommi (sloooow) - chröme
2014/12/15 16:25:05
can we use a scoped_ptr<> for this instead?
| |
| 260 } | |
| 261 return; | |
| 262 } | |
| 263 } | |
| 264 } | |
| 265 | |
| 266 DVLOG(3) << "DoStopDevice. Send stop request for device " << entry->id << "."; | |
| 267 if (delete_entry) { | |
|
tommi (sloooow) - chröme
2014/12/15 16:25:05
FYI - here there are two call sites + bindings for
| |
| 268 device_task_runner_->PostTask( | |
| 269 FROM_HERE, | |
| 270 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, | |
| 271 base::Owned(entry))); | |
| 272 } else { | |
| 273 device_task_runner_->PostTask( | |
| 274 FROM_HERE, | |
| 275 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, | |
| 276 base::Unretained(entry))); | |
| 277 } | |
| 278 } | |
| 279 | |
| 280 void VideoCaptureManager::HandleQueuedStartRequest() { | |
| 281 auto request = device_start_queue_.begin(); | |
| 282 if (request == device_start_queue_.end()) | |
| 283 return; | |
| 284 | |
| 285 DVLOG(3) << "HandleQueuedStartRequest, Post start to device thread, device = " | |
| 286 << request->device_entry->id; | |
| 287 | |
| 288 device_task_runner_->PostTaskAndReply( | |
| 289 FROM_HERE, | |
| 290 base::Bind( | |
| 291 &VideoCaptureManager::DoStartDeviceOnDeviceThread, | |
| 292 this, | |
| 293 request->session_id, | |
| 294 request->device_entry, | |
| 295 request->params, | |
| 296 base::Passed(request->device_entry->video_capture_controller-> | |
| 297 NewDeviceClient())), | |
| 298 base::Bind(&VideoCaptureManager::OnDeviceStarted, this)); | |
| 299 } | |
| 300 | |
| 301 void VideoCaptureManager::OnDeviceStarted() { | |
| 302 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 303 DVLOG(3) << "OnDeviceStarted"; | |
| 304 device_start_queue_.pop_front(); | |
| 305 HandleQueuedStartRequest(); | |
| 306 } | |
| 307 | |
| 219 void VideoCaptureManager::DoStartDeviceOnDeviceThread( | 308 void VideoCaptureManager::DoStartDeviceOnDeviceThread( |
| 220 media::VideoCaptureSessionId session_id, | 309 media::VideoCaptureSessionId session_id, |
| 221 DeviceEntry* entry, | 310 DeviceEntry* entry, |
| 222 const media::VideoCaptureParams& params, | 311 const media::VideoCaptureParams& params, |
| 223 scoped_ptr<media::VideoCaptureDevice::Client> device_client) { | 312 scoped_ptr<media::VideoCaptureDevice::Client> device_client) { |
| 224 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime"); | 313 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime"); |
| 225 DCHECK(IsOnDeviceThread()); | 314 DCHECK(IsOnDeviceThread()); |
| 226 | 315 |
| 227 scoped_ptr<media::VideoCaptureDevice> video_capture_device; | 316 scoped_ptr<media::VideoCaptureDevice> video_capture_device; |
| 228 switch (entry->stream_type) { | 317 switch (entry->stream_type) { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 299 } | 388 } |
| 300 | 389 |
| 301 DCHECK(entry->video_capture_controller); | 390 DCHECK(entry->video_capture_controller); |
| 302 | 391 |
| 303 LogVideoCaptureEvent(VIDEO_CAPTURE_START_CAPTURE); | 392 LogVideoCaptureEvent(VIDEO_CAPTURE_START_CAPTURE); |
| 304 | 393 |
| 305 // First client starts the device. | 394 // First client starts the device. |
| 306 if (entry->video_capture_controller->GetActiveClientCount() == 0) { | 395 if (entry->video_capture_controller->GetActiveClientCount() == 0) { |
| 307 DVLOG(1) << "VideoCaptureManager starting device (type = " | 396 DVLOG(1) << "VideoCaptureManager starting device (type = " |
| 308 << entry->stream_type << ", id = " << entry->id << ")"; | 397 << entry->stream_type << ", id = " << entry->id << ")"; |
| 309 | 398 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 } | 399 } |
| 320 // Run the callback first, as AddClient() may trigger OnFrameInfo(). | 400 // Run the callback first, as AddClient() may trigger OnFrameInfo(). |
| 321 done_cb.Run(entry->video_capture_controller->GetWeakPtr()); | 401 done_cb.Run(entry->video_capture_controller->GetWeakPtr()); |
| 322 entry->video_capture_controller->AddClient( | 402 entry->video_capture_controller->AddClient( |
| 323 client_id, client_handler, client_render_process, session_id, params); | 403 client_id, client_handler, client_render_process, session_id, params); |
| 324 } | 404 } |
| 325 | 405 |
| 326 void VideoCaptureManager::StopCaptureForClient( | 406 void VideoCaptureManager::StopCaptureForClient( |
| 327 VideoCaptureController* controller, | 407 VideoCaptureController* controller, |
| 328 VideoCaptureControllerID client_id, | 408 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 | 465 // We only pause the MEDIA_DEVICE_VIDEO_CAPTURE entry to release camera to |
| 386 // system. | 466 // system. |
| 387 if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE) | 467 if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE) |
| 388 return; | 468 return; |
| 389 | 469 |
| 390 controller->PauseOrResumeClient(client_id, client_handler, true); | 470 controller->PauseOrResumeClient(client_id, client_handler, true); |
| 391 if (controller->GetActiveClientCount() != 0) | 471 if (controller->GetActiveClientCount() != 0) |
| 392 return; | 472 return; |
| 393 | 473 |
| 394 // There is no more client, release the camera. | 474 // There is no more client, release the camera. |
| 395 device_task_runner_->PostTask( | 475 DoStopDevice(entry, false); |
| 396 FROM_HERE, | |
| 397 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, | |
| 398 base::Unretained(entry))); | |
| 399 } | 476 } |
| 400 | 477 |
| 401 void VideoCaptureManager::ResumeCaptureForClient( | 478 void VideoCaptureManager::ResumeCaptureForClient( |
| 402 media::VideoCaptureSessionId session_id, | 479 media::VideoCaptureSessionId session_id, |
| 403 const media::VideoCaptureParams& params, | 480 const media::VideoCaptureParams& params, |
| 404 VideoCaptureController* controller, | 481 VideoCaptureController* controller, |
| 405 VideoCaptureControllerID client_id, | 482 VideoCaptureControllerID client_id, |
| 406 VideoCaptureControllerEventHandler* client_handler) { | 483 VideoCaptureControllerEventHandler* client_handler) { |
| 407 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 484 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 408 DCHECK(controller); | 485 DCHECK(controller); |
| 409 DCHECK(client_handler); | 486 DCHECK(client_handler); |
| 410 | 487 |
| 411 DeviceEntry* entry = GetDeviceEntryForController(controller); | 488 DeviceEntry* entry = GetDeviceEntryForController(controller); |
| 412 if (!entry) { | 489 if (!entry) { |
| 413 NOTREACHED(); | 490 NOTREACHED(); |
| 414 return; | 491 return; |
| 415 } | 492 } |
| 416 | 493 |
| 417 // We only pause/resume the MEDIA_DEVICE_VIDEO_CAPTURE entry. | 494 // We only pause/resume the MEDIA_DEVICE_VIDEO_CAPTURE entry. |
| 418 if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE) | 495 if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE) |
| 419 return; | 496 return; |
| 420 | 497 |
| 421 controller->PauseOrResumeClient(client_id, client_handler, false); | 498 controller->PauseOrResumeClient(client_id, client_handler, false); |
| 422 if (controller->GetActiveClientCount() != 1) | 499 if (controller->GetActiveClientCount() != 1) |
| 423 return; | 500 return; |
| 424 | 501 |
| 425 // This is first active client, allocate the camera. | 502 // This is first active client, allocate the camera. |
| 426 device_task_runner_->PostTask( | 503 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 } | 504 } |
| 436 | 505 |
| 437 bool VideoCaptureManager::GetDeviceSupportedFormats( | 506 bool VideoCaptureManager::GetDeviceSupportedFormats( |
| 438 media::VideoCaptureSessionId capture_session_id, | 507 media::VideoCaptureSessionId capture_session_id, |
| 439 media::VideoCaptureFormats* supported_formats) { | 508 media::VideoCaptureFormats* supported_formats) { |
| 440 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 509 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 441 DCHECK(supported_formats->empty()); | 510 DCHECK(supported_formats->empty()); |
| 442 | 511 |
| 443 SessionMap::iterator it = sessions_.find(capture_session_id); | 512 SessionMap::iterator it = sessions_.find(capture_session_id); |
| 444 if (it == sessions_.end()) | 513 if (it == sessions_.end()) |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 648 if (entry->video_capture_controller->GetClientCount() == 0) { | 717 if (entry->video_capture_controller->GetClientCount() == 0) { |
| 649 DVLOG(1) << "VideoCaptureManager stopping device (type = " | 718 DVLOG(1) << "VideoCaptureManager stopping device (type = " |
| 650 << entry->stream_type << ", id = " << entry->id << ")"; | 719 << entry->stream_type << ", id = " << entry->id << ")"; |
| 651 | 720 |
| 652 // The DeviceEntry is removed from |devices_| immediately. The controller is | 721 // The DeviceEntry is removed from |devices_| immediately. The controller is |
| 653 // deleted immediately, and the device is freed asynchronously. After this | 722 // deleted immediately, and the device is freed asynchronously. After this |
| 654 // point, subsequent requests to open this same device ID will create a new | 723 // point, subsequent requests to open this same device ID will create a new |
| 655 // DeviceEntry, VideoCaptureController, and VideoCaptureDevice. | 724 // DeviceEntry, VideoCaptureController, and VideoCaptureDevice. |
| 656 devices_.erase(entry); | 725 devices_.erase(entry); |
| 657 entry->video_capture_controller.reset(); | 726 entry->video_capture_controller.reset(); |
| 658 device_task_runner_->PostTask( | 727 DoStopDevice(entry, true); |
| 659 FROM_HERE, | |
| 660 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, | |
| 661 base::Owned(entry))); | |
| 662 } | 728 } |
| 663 } | 729 } |
| 664 | 730 |
| 665 VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry( | 731 VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry( |
| 666 media::VideoCaptureSessionId capture_session_id) { | 732 media::VideoCaptureSessionId capture_session_id) { |
| 667 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 733 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 668 | 734 |
| 669 SessionMap::iterator session_it = sessions_.find(capture_session_id); | 735 SessionMap::iterator session_it = sessions_.find(capture_session_id); |
| 670 if (session_it == sessions_.end()) { | 736 if (session_it == sessions_.end()) { |
| 671 return NULL; | 737 return NULL; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 720 gfx::NativeViewId window_id) { | 786 gfx::NativeViewId window_id) { |
| 721 DCHECK(IsOnDeviceThread()); | 787 DCHECK(IsOnDeviceThread()); |
| 722 DCHECK(notification_window_ids_.find(session_id) == | 788 DCHECK(notification_window_ids_.find(session_id) == |
| 723 notification_window_ids_.end()); | 789 notification_window_ids_.end()); |
| 724 notification_window_ids_[session_id] = window_id; | 790 notification_window_ids_[session_id] = window_id; |
| 725 VLOG(2) << "Screen capture notification window saved for session " | 791 VLOG(2) << "Screen capture notification window saved for session " |
| 726 << session_id << " on device thread."; | 792 << session_id << " on device thread."; |
| 727 } | 793 } |
| 728 | 794 |
| 729 } // namespace content | 795 } // namespace content |
| OLD | NEW |