| 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() { |
| 115 DCHECK(thread_checker_.CalledOnValidThread()); |
| 116 } |
| 117 |
| 118 void VideoCaptureManager::DeviceEntry::SetVideoCaptureDevice( |
| 119 scoped_ptr<media::VideoCaptureDevice> device) { |
| 120 DCHECK(thread_checker_.CalledOnValidThread()); |
| 121 video_capture_device_.swap(device); |
| 122 } |
| 123 |
| 124 scoped_ptr<media::VideoCaptureDevice> |
| 125 VideoCaptureManager::DeviceEntry::ReleaseVideoCaptureDevice() { |
| 126 DCHECK(thread_checker_.CalledOnValidThread()); |
| 127 return video_capture_device_.Pass(); |
| 128 } |
| 129 |
| 130 VideoCaptureController* |
| 131 VideoCaptureManager::DeviceEntry::video_capture_controller() { |
| 132 DCHECK(thread_checker_.CalledOnValidThread()); |
| 133 return video_capture_controller_.get(); |
| 134 } |
| 135 |
| 136 media::VideoCaptureDevice* |
| 137 VideoCaptureManager::DeviceEntry::video_capture_device() { |
| 138 DCHECK(thread_checker_.CalledOnValidThread()); |
| 139 return video_capture_device_.get(); |
| 140 } |
| 141 |
| 142 VideoCaptureManager::CaptureDeviceStartRequest::CaptureDeviceStartRequest( |
| 143 int serial_id, |
| 144 media::VideoCaptureSessionId session_id, |
| 145 const media::VideoCaptureParams& params) |
| 146 : serial_id_(serial_id), |
| 147 session_id_(session_id), |
| 148 params_(params), |
| 149 abort_start_(false) { |
| 150 } |
| 110 | 151 |
| 111 | 152 |
| 112 VideoCaptureManager::VideoCaptureManager( | 153 VideoCaptureManager::VideoCaptureManager( |
| 113 scoped_ptr<media::VideoCaptureDeviceFactory> factory) | 154 scoped_ptr<media::VideoCaptureDeviceFactory> factory) |
| 114 : listener_(NULL), | 155 : listener_(NULL), |
| 115 new_capture_session_id_(1), | 156 new_capture_session_id_(1), |
| 116 video_capture_device_factory_(factory.Pass()) { | 157 video_capture_device_factory_(factory.Pass()) { |
| 117 } | 158 } |
| 118 | 159 |
| 119 VideoCaptureManager::~VideoCaptureManager() { | 160 VideoCaptureManager::~VideoCaptureManager() { |
| 120 DCHECK(devices_.empty()); | 161 DCHECK(devices_.empty()); |
| 162 DCHECK(device_start_queue_.empty()); |
| 121 } | 163 } |
| 122 | 164 |
| 123 void VideoCaptureManager::Register( | 165 void VideoCaptureManager::Register( |
| 124 MediaStreamProviderListener* listener, | 166 MediaStreamProviderListener* listener, |
| 125 const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner) { | 167 const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner) { |
| 126 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 168 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 127 DCHECK(!listener_); | 169 DCHECK(!listener_); |
| 128 DCHECK(!device_task_runner_.get()); | 170 DCHECK(!device_task_runner_.get()); |
| 129 listener_ = listener; | 171 listener_ = listener; |
| 130 device_task_runner_ = device_task_runner; | 172 device_task_runner_ = device_task_runner; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 if (session_it == sessions_.end()) { | 237 if (session_it == sessions_.end()) { |
| 196 NOTREACHED(); | 238 NOTREACHED(); |
| 197 return; | 239 return; |
| 198 } | 240 } |
| 199 | 241 |
| 200 DeviceEntry* const existing_device = GetDeviceEntryForMediaStreamDevice( | 242 DeviceEntry* const existing_device = GetDeviceEntryForMediaStreamDevice( |
| 201 session_it->second); | 243 session_it->second); |
| 202 if (existing_device) { | 244 if (existing_device) { |
| 203 // Remove any client that is still using the session. This is safe to call | 245 // Remove any client that is still using the session. This is safe to call |
| 204 // even if there are no clients using the session. | 246 // even if there are no clients using the session. |
| 205 existing_device->video_capture_controller->StopSession(capture_session_id); | 247 existing_device->video_capture_controller() |
| 248 ->StopSession(capture_session_id); |
| 206 | 249 |
| 207 // StopSession() may have removed the last client, so we might need to | 250 // StopSession() may have removed the last client, so we might need to |
| 208 // close the device. | 251 // close the device. |
| 209 DestroyDeviceEntryIfNoClients(existing_device); | 252 DestroyDeviceEntryIfNoClients(existing_device); |
| 210 } | 253 } |
| 211 | 254 |
| 212 // Notify listeners asynchronously, and forget the session. | 255 // Notify listeners asynchronously, and forget the session. |
| 213 base::MessageLoop::current()->PostTask(FROM_HERE, | 256 base::MessageLoop::current()->PostTask(FROM_HERE, |
| 214 base::Bind(&VideoCaptureManager::OnClosed, this, session_it->second.type, | 257 base::Bind(&VideoCaptureManager::OnClosed, this, session_it->second.type, |
| 215 capture_session_id)); | 258 capture_session_id)); |
| 216 sessions_.erase(session_it); | 259 sessions_.erase(session_it); |
| 217 } | 260 } |
| 218 | 261 |
| 219 void VideoCaptureManager::DoStartDeviceOnDeviceThread( | 262 void VideoCaptureManager::QueueStartDevice( |
| 220 media::VideoCaptureSessionId session_id, | 263 media::VideoCaptureSessionId session_id, |
| 221 DeviceEntry* entry, | 264 DeviceEntry* entry, |
| 265 const media::VideoCaptureParams& params) { |
| 266 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 267 device_start_queue_.push_back( |
| 268 CaptureDeviceStartRequest(entry->serial_id, session_id, params)); |
| 269 if (device_start_queue_.size() == 1) |
| 270 HandleQueuedStartRequest(); |
| 271 } |
| 272 |
| 273 void VideoCaptureManager::DoStopDevice(DeviceEntry* entry) { |
| 274 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 275 DCHECK(std::find(devices_.begin(), devices_.end(), entry) != devices_.end()); |
| 276 |
| 277 // Find the matching start request. |
| 278 for (DeviceStartQueue::reverse_iterator request = |
| 279 device_start_queue_.rbegin(); |
| 280 request != device_start_queue_.rend(); ++request) { |
| 281 if (request->serial_id() == entry->serial_id) { |
| 282 request->set_abort_start(); |
| 283 DVLOG(3) << "DoStopDevice, aborting start request for device " |
| 284 << entry->id << " serial_id = " << entry->serial_id; |
| 285 return; |
| 286 } |
| 287 } |
| 288 |
| 289 DVLOG(3) << "DoStopDevice. Send stop request for device = " << entry->id |
| 290 << " serial_id = " << entry->serial_id << "."; |
| 291 if (entry->video_capture_device()) { |
| 292 // |entry->video_capture_device| can be null if creating the device fails. |
| 293 device_task_runner_->PostTask( |
| 294 FROM_HERE, |
| 295 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, |
| 296 base::Passed(entry->ReleaseVideoCaptureDevice()))); |
| 297 } |
| 298 } |
| 299 |
| 300 void VideoCaptureManager::HandleQueuedStartRequest() { |
| 301 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 302 // Remove all start requests that have been aborted. |
| 303 while (device_start_queue_.begin() != device_start_queue_.end() && |
| 304 device_start_queue_.begin()->abort_start()) { |
| 305 device_start_queue_.pop_front(); |
| 306 } |
| 307 DeviceStartQueue::iterator request = device_start_queue_.begin(); |
| 308 if (request == device_start_queue_.end()) |
| 309 return; |
| 310 |
| 311 const int serial_id = request->serial_id(); |
| 312 DeviceEntries::iterator entry_it = std::find_if( |
| 313 devices_.begin(), devices_.end(), |
| 314 [serial_id] (const DeviceEntry* e) { |
| 315 return e->serial_id == serial_id; |
| 316 }); |
| 317 DCHECK(entry_it != devices_.end()); |
| 318 DeviceEntry* entry = (*entry_it); |
| 319 |
| 320 DVLOG(3) << "HandleQueuedStartRequest, Post start to device thread, device = " |
| 321 << entry->id << " start id = " << entry->serial_id; |
| 322 base::PostTaskAndReplyWithResult( |
| 323 device_task_runner_.get(), |
| 324 FROM_HERE, |
| 325 base::Bind( |
| 326 &VideoCaptureManager::DoStartDeviceOnDeviceThread, |
| 327 this, |
| 328 request->session_id(), |
| 329 entry->id, |
| 330 entry->stream_type, |
| 331 request->params(), |
| 332 base::Passed(entry->video_capture_controller()->NewDeviceClient())), |
| 333 base::Bind(&VideoCaptureManager::OnDeviceStarted, this, |
| 334 request->serial_id())); |
| 335 } |
| 336 |
| 337 void VideoCaptureManager::OnDeviceStarted( |
| 338 int serial_id, |
| 339 scoped_ptr<media::VideoCaptureDevice> device) { |
| 340 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 341 DCHECK(serial_id == device_start_queue_.begin()->serial_id()); |
| 342 DVLOG(3) << "OnDeviceStarted"; |
| 343 if (device_start_queue_.front().abort_start()) { |
| 344 // |device| can be null if creation failed in DoStartDeviceOnDeviceThread. |
| 345 // The device is no longer wanted. Stop the device again. |
| 346 DVLOG(3) << "OnDeviceStarted but start request have been aborted."; |
| 347 media::VideoCaptureDevice* device_ptr = device.get(); |
| 348 base::Closure closure = |
| 349 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, |
| 350 base::Passed(&device)); |
| 351 if (device_ptr && !device_task_runner_->PostTask(FROM_HERE, closure)) { |
| 352 // PostTask failed. The device must be stopped anyway. |
| 353 device_ptr->StopAndDeAllocate(); |
| 354 } |
| 355 } else { |
| 356 DeviceEntries::iterator entry_it = std::find_if( |
| 357 devices_.begin(), devices_.end(), |
| 358 [serial_id] (const DeviceEntry* e) { |
| 359 return e->serial_id == serial_id; |
| 360 }); |
| 361 DCHECK(entry_it != devices_.end()); |
| 362 DCHECK(!(*entry_it)->video_capture_device()); |
| 363 (*entry_it)->SetVideoCaptureDevice(device.Pass()); |
| 364 } |
| 365 |
| 366 device_start_queue_.pop_front(); |
| 367 HandleQueuedStartRequest(); |
| 368 } |
| 369 |
| 370 scoped_ptr<media::VideoCaptureDevice> |
| 371 VideoCaptureManager::DoStartDeviceOnDeviceThread( |
| 372 media::VideoCaptureSessionId session_id, |
| 373 const std::string& id, |
| 374 MediaStreamType stream_type, |
| 222 const media::VideoCaptureParams& params, | 375 const media::VideoCaptureParams& params, |
| 223 scoped_ptr<media::VideoCaptureDevice::Client> device_client) { | 376 scoped_ptr<media::VideoCaptureDevice::Client> device_client) { |
| 224 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime"); | 377 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime"); |
| 225 DCHECK(IsOnDeviceThread()); | 378 DCHECK(IsOnDeviceThread()); |
| 226 | 379 |
| 227 scoped_ptr<media::VideoCaptureDevice> video_capture_device; | 380 scoped_ptr<media::VideoCaptureDevice> video_capture_device; |
| 228 switch (entry->stream_type) { | 381 switch (stream_type) { |
| 229 case MEDIA_DEVICE_VIDEO_CAPTURE: { | 382 case MEDIA_DEVICE_VIDEO_CAPTURE: { |
| 230 // We look up the device id from the renderer in our local enumeration | 383 // 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 | 384 // since the renderer does not have all the information that might be |
| 232 // held in the browser-side VideoCaptureDevice::Name structure. | 385 // held in the browser-side VideoCaptureDevice::Name structure. |
| 233 media::VideoCaptureDeviceInfo* found = | 386 media::VideoCaptureDeviceInfo* found = |
| 234 FindDeviceInfoById(entry->id, devices_info_cache_); | 387 FindDeviceInfoById(id, devices_info_cache_); |
| 235 if (found) { | 388 if (found) { |
| 236 video_capture_device = | 389 video_capture_device = |
| 237 video_capture_device_factory_->Create(found->name); | 390 video_capture_device_factory_->Create(found->name); |
| 238 } | 391 } |
| 239 break; | 392 break; |
| 240 } | 393 } |
| 241 case MEDIA_TAB_VIDEO_CAPTURE: { | 394 case MEDIA_TAB_VIDEO_CAPTURE: { |
| 242 video_capture_device.reset( | 395 video_capture_device.reset( |
| 243 WebContentsVideoCaptureDevice::Create(entry->id)); | 396 WebContentsVideoCaptureDevice::Create(id)); |
| 244 break; | 397 break; |
| 245 } | 398 } |
| 246 case MEDIA_DESKTOP_VIDEO_CAPTURE: { | 399 case MEDIA_DESKTOP_VIDEO_CAPTURE: { |
| 247 #if defined(ENABLE_SCREEN_CAPTURE) | 400 #if defined(ENABLE_SCREEN_CAPTURE) |
| 248 DesktopMediaID id = DesktopMediaID::Parse(entry->id); | 401 DesktopMediaID desktop_id = DesktopMediaID::Parse(id); |
| 249 #if defined(USE_AURA) | 402 #if defined(USE_AURA) |
| 250 if (id.type == DesktopMediaID::TYPE_AURA_WINDOW) { | 403 if (desktop_id.type == DesktopMediaID::TYPE_AURA_WINDOW) { |
| 251 video_capture_device.reset(DesktopCaptureDeviceAura::Create(id)); | 404 video_capture_device.reset( |
| 405 DesktopCaptureDeviceAura::Create(desktop_id)); |
| 252 } else | 406 } else |
| 253 #endif | 407 #endif |
| 254 if (id.type != DesktopMediaID::TYPE_NONE && | 408 if (desktop_id.type != DesktopMediaID::TYPE_NONE && |
| 255 id.type != DesktopMediaID::TYPE_AURA_WINDOW) { | 409 desktop_id.type != DesktopMediaID::TYPE_AURA_WINDOW) { |
| 256 video_capture_device = DesktopCaptureDevice::Create(id); | 410 video_capture_device = DesktopCaptureDevice::Create(desktop_id); |
| 257 if (notification_window_ids_.find(session_id) != | 411 if (notification_window_ids_.find(session_id) != |
| 258 notification_window_ids_.end()) { | 412 notification_window_ids_.end()) { |
| 259 static_cast<DesktopCaptureDevice*>(video_capture_device.get()) | 413 static_cast<DesktopCaptureDevice*>(video_capture_device.get()) |
| 260 ->SetNotificationWindowId(notification_window_ids_[session_id]); | 414 ->SetNotificationWindowId(notification_window_ids_[session_id]); |
| 261 VLOG(2) << "Screen capture notification window passed for session " | 415 VLOG(2) << "Screen capture notification window passed for session " |
| 262 << session_id; | 416 << session_id; |
| 263 } | 417 } |
| 264 } | 418 } |
| 265 #endif // defined(ENABLE_SCREEN_CAPTURE) | 419 #endif // defined(ENABLE_SCREEN_CAPTURE) |
| 266 break; | 420 break; |
| 267 } | 421 } |
| 268 default: { | 422 default: { |
| 269 NOTIMPLEMENTED(); | 423 NOTIMPLEMENTED(); |
| 270 break; | 424 break; |
| 271 } | 425 } |
| 272 } | 426 } |
| 273 | 427 |
| 274 if (!video_capture_device) { | 428 if (!video_capture_device) { |
| 275 device_client->OnError("Could not create capture device"); | 429 device_client->OnError("Could not create capture device"); |
| 276 return; | 430 return nullptr; |
| 277 } | 431 } |
| 278 | 432 |
| 279 video_capture_device->AllocateAndStart(params, device_client.Pass()); | 433 video_capture_device->AllocateAndStart(params, device_client.Pass()); |
| 280 entry->video_capture_device = video_capture_device.Pass(); | 434 return video_capture_device.Pass(); |
| 281 } | 435 } |
| 282 | 436 |
| 283 void VideoCaptureManager::StartCaptureForClient( | 437 void VideoCaptureManager::StartCaptureForClient( |
| 284 media::VideoCaptureSessionId session_id, | 438 media::VideoCaptureSessionId session_id, |
| 285 const media::VideoCaptureParams& params, | 439 const media::VideoCaptureParams& params, |
| 286 base::ProcessHandle client_render_process, | 440 base::ProcessHandle client_render_process, |
| 287 VideoCaptureControllerID client_id, | 441 VideoCaptureControllerID client_id, |
| 288 VideoCaptureControllerEventHandler* client_handler, | 442 VideoCaptureControllerEventHandler* client_handler, |
| 289 const DoneCB& done_cb) { | 443 const DoneCB& done_cb) { |
| 290 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 444 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 291 DVLOG(1) << "VideoCaptureManager::StartCaptureForClient, " | 445 DVLOG(1) << "VideoCaptureManager::StartCaptureForClient, " |
| 292 << params.requested_format.frame_size.ToString() << ", " | 446 << params.requested_format.frame_size.ToString() << ", " |
| 293 << params.requested_format.frame_rate << ", #" << session_id << ")"; | 447 << params.requested_format.frame_rate << ", #" << session_id << ")"; |
| 294 | 448 |
| 295 DeviceEntry* entry = GetOrCreateDeviceEntry(session_id); | 449 DeviceEntry* entry = GetOrCreateDeviceEntry(session_id); |
| 296 if (!entry) { | 450 if (!entry) { |
| 297 done_cb.Run(base::WeakPtr<VideoCaptureController>()); | 451 done_cb.Run(base::WeakPtr<VideoCaptureController>()); |
| 298 return; | 452 return; |
| 299 } | 453 } |
| 300 | 454 |
| 301 DCHECK(entry->video_capture_controller); | 455 DCHECK(entry->video_capture_controller()); |
| 302 | 456 |
| 303 LogVideoCaptureEvent(VIDEO_CAPTURE_START_CAPTURE); | 457 LogVideoCaptureEvent(VIDEO_CAPTURE_START_CAPTURE); |
| 304 | 458 |
| 305 // First client starts the device. | 459 // First client starts the device. |
| 306 if (entry->video_capture_controller->GetActiveClientCount() == 0) { | 460 if (entry->video_capture_controller()->GetActiveClientCount() == 0) { |
| 307 DVLOG(1) << "VideoCaptureManager starting device (type = " | 461 DVLOG(1) << "VideoCaptureManager starting device (type = " |
| 308 << entry->stream_type << ", id = " << entry->id << ")"; | 462 << entry->stream_type << ", id = " << entry->id << ")"; |
| 309 | 463 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 } | 464 } |
| 320 // Run the callback first, as AddClient() may trigger OnFrameInfo(). | 465 // Run the callback first, as AddClient() may trigger OnFrameInfo(). |
| 321 done_cb.Run(entry->video_capture_controller->GetWeakPtr()); | 466 done_cb.Run(entry->video_capture_controller()->GetWeakPtr()); |
| 322 entry->video_capture_controller->AddClient( | 467 entry->video_capture_controller()->AddClient( |
| 323 client_id, client_handler, client_render_process, session_id, params); | 468 client_id, client_handler, client_render_process, session_id, params); |
| 324 } | 469 } |
| 325 | 470 |
| 326 void VideoCaptureManager::StopCaptureForClient( | 471 void VideoCaptureManager::StopCaptureForClient( |
| 327 VideoCaptureController* controller, | 472 VideoCaptureController* controller, |
| 328 VideoCaptureControllerID client_id, | 473 VideoCaptureControllerID client_id, |
| 329 VideoCaptureControllerEventHandler* client_handler, | 474 VideoCaptureControllerEventHandler* client_handler, |
| 330 bool aborted_due_to_error) { | 475 bool aborted_due_to_error) { |
| 331 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 476 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 332 DCHECK(controller); | 477 DCHECK(controller); |
| (...skipping 52 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 | 530 // We only pause the MEDIA_DEVICE_VIDEO_CAPTURE entry to release camera to |
| 386 // system. | 531 // system. |
| 387 if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE) | 532 if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE) |
| 388 return; | 533 return; |
| 389 | 534 |
| 390 controller->PauseOrResumeClient(client_id, client_handler, true); | 535 controller->PauseOrResumeClient(client_id, client_handler, true); |
| 391 if (controller->GetActiveClientCount() != 0) | 536 if (controller->GetActiveClientCount() != 0) |
| 392 return; | 537 return; |
| 393 | 538 |
| 394 // There is no more client, release the camera. | 539 // There is no more client, release the camera. |
| 395 device_task_runner_->PostTask( | 540 DoStopDevice(entry); |
| 396 FROM_HERE, | |
| 397 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, | |
| 398 base::Unretained(entry))); | |
| 399 } | 541 } |
| 400 | 542 |
| 401 void VideoCaptureManager::ResumeCaptureForClient( | 543 void VideoCaptureManager::ResumeCaptureForClient( |
| 402 media::VideoCaptureSessionId session_id, | 544 media::VideoCaptureSessionId session_id, |
| 403 const media::VideoCaptureParams& params, | 545 const media::VideoCaptureParams& params, |
| 404 VideoCaptureController* controller, | 546 VideoCaptureController* controller, |
| 405 VideoCaptureControllerID client_id, | 547 VideoCaptureControllerID client_id, |
| 406 VideoCaptureControllerEventHandler* client_handler) { | 548 VideoCaptureControllerEventHandler* client_handler) { |
| 407 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 549 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 408 DCHECK(controller); | 550 DCHECK(controller); |
| 409 DCHECK(client_handler); | 551 DCHECK(client_handler); |
| 410 | 552 |
| 411 DeviceEntry* entry = GetDeviceEntryForController(controller); | 553 DeviceEntry* entry = GetDeviceEntryForController(controller); |
| 412 if (!entry) { | 554 if (!entry) { |
| 413 NOTREACHED(); | 555 NOTREACHED(); |
| 414 return; | 556 return; |
| 415 } | 557 } |
| 416 | 558 |
| 417 // We only pause/resume the MEDIA_DEVICE_VIDEO_CAPTURE entry. | 559 // We only pause/resume the MEDIA_DEVICE_VIDEO_CAPTURE entry. |
| 418 if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE) | 560 if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE) |
| 419 return; | 561 return; |
| 420 | 562 |
| 421 controller->PauseOrResumeClient(client_id, client_handler, false); | 563 controller->PauseOrResumeClient(client_id, client_handler, false); |
| 422 if (controller->GetActiveClientCount() != 1) | 564 if (controller->GetActiveClientCount() != 1) |
| 423 return; | 565 return; |
| 424 | 566 |
| 425 // This is first active client, allocate the camera. | 567 // This is first active client, allocate the camera. |
| 426 device_task_runner_->PostTask( | 568 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 } | 569 } |
| 436 | 570 |
| 437 bool VideoCaptureManager::GetDeviceSupportedFormats( | 571 bool VideoCaptureManager::GetDeviceSupportedFormats( |
| 438 media::VideoCaptureSessionId capture_session_id, | 572 media::VideoCaptureSessionId capture_session_id, |
| 439 media::VideoCaptureFormats* supported_formats) { | 573 media::VideoCaptureFormats* supported_formats) { |
| 440 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 574 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 441 DCHECK(supported_formats->empty()); | 575 DCHECK(supported_formats->empty()); |
| 442 | 576 |
| 443 SessionMap::iterator it = sessions_.find(capture_session_id); | 577 SessionMap::iterator it = sessions_.find(capture_session_id); |
| 444 if (it == sessions_.end()) | 578 if (it == sessions_.end()) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 463 if (it == sessions_.end()) | 597 if (it == sessions_.end()) |
| 464 return false; | 598 return false; |
| 465 DVLOG(1) << "GetDeviceFormatsInUse for device: " << it->second.name; | 599 DVLOG(1) << "GetDeviceFormatsInUse for device: " << it->second.name; |
| 466 | 600 |
| 467 // Return the currently in-use format(s) of the device, if it's started. | 601 // Return the currently in-use format(s) of the device, if it's started. |
| 468 DeviceEntry* device_in_use = | 602 DeviceEntry* device_in_use = |
| 469 GetDeviceEntryForMediaStreamDevice(it->second); | 603 GetDeviceEntryForMediaStreamDevice(it->second); |
| 470 if (device_in_use) { | 604 if (device_in_use) { |
| 471 // Currently only one format-in-use is supported at the VCC level. | 605 // Currently only one format-in-use is supported at the VCC level. |
| 472 formats_in_use->push_back( | 606 formats_in_use->push_back( |
| 473 device_in_use->video_capture_controller->GetVideoCaptureFormat()); | 607 device_in_use->video_capture_controller()->GetVideoCaptureFormat()); |
| 474 } | 608 } |
| 475 return true; | 609 return true; |
| 476 } | 610 } |
| 477 | 611 |
| 478 void VideoCaptureManager::SetDesktopCaptureWindowId( | 612 void VideoCaptureManager::SetDesktopCaptureWindowId( |
| 479 media::VideoCaptureSessionId session_id, | 613 media::VideoCaptureSessionId session_id, |
| 480 gfx::NativeViewId window_id) { | 614 gfx::NativeViewId window_id) { |
| 481 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 615 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 482 VLOG(2) << "SetDesktopCaptureWindowId called for session " << session_id; | 616 VLOG(2) << "SetDesktopCaptureWindowId called for session " << session_id; |
| 483 | 617 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 502 } | 636 } |
| 503 | 637 |
| 504 DCHECK_EQ(MEDIA_DESKTOP_VIDEO_CAPTURE, existing_device->stream_type); | 638 DCHECK_EQ(MEDIA_DESKTOP_VIDEO_CAPTURE, existing_device->stream_type); |
| 505 DesktopMediaID id = DesktopMediaID::Parse(existing_device->id); | 639 DesktopMediaID id = DesktopMediaID::Parse(existing_device->id); |
| 506 if (id.type == DesktopMediaID::TYPE_NONE || | 640 if (id.type == DesktopMediaID::TYPE_NONE || |
| 507 id.type == DesktopMediaID::TYPE_AURA_WINDOW) { | 641 id.type == DesktopMediaID::TYPE_AURA_WINDOW) { |
| 508 VLOG(2) << "Video capture device type mismatch."; | 642 VLOG(2) << "Video capture device type mismatch."; |
| 509 return; | 643 return; |
| 510 } | 644 } |
| 511 | 645 |
| 646 // Post |existing_device->video_capture_device| to the VideoCaptureDevice to |
| 647 // the device_task_runner_. This is safe since the device is destroyed on the |
| 648 // device_task_runner_. |
| 512 device_task_runner_->PostTask( | 649 device_task_runner_->PostTask( |
| 513 FROM_HERE, | 650 FROM_HERE, |
| 514 base::Bind(&VideoCaptureManager::SetDesktopCaptureWindowIdOnDeviceThread, | 651 base::Bind(&VideoCaptureManager::SetDesktopCaptureWindowIdOnDeviceThread, |
| 515 this, | 652 this, |
| 516 existing_device, | 653 existing_device->video_capture_device(), |
| 517 window_id)); | 654 window_id)); |
| 518 } | 655 } |
| 519 | 656 |
| 520 void VideoCaptureManager::DoStopDeviceOnDeviceThread(DeviceEntry* entry) { | 657 void VideoCaptureManager::DoStopDeviceOnDeviceThread( |
| 658 scoped_ptr<media::VideoCaptureDevice> device) { |
| 521 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime"); | 659 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime"); |
| 522 DCHECK(IsOnDeviceThread()); | 660 DCHECK(IsOnDeviceThread()); |
| 523 if (entry->video_capture_device) { | 661 device->StopAndDeAllocate(); |
| 524 entry->video_capture_device->StopAndDeAllocate(); | 662 DVLOG(3) << "DoStopDeviceOnDeviceThread"; |
| 525 } | |
| 526 entry->video_capture_device.reset(); | |
| 527 } | 663 } |
| 528 | 664 |
| 529 void VideoCaptureManager::OnOpened( | 665 void VideoCaptureManager::OnOpened( |
| 530 MediaStreamType stream_type, | 666 MediaStreamType stream_type, |
| 531 media::VideoCaptureSessionId capture_session_id) { | 667 media::VideoCaptureSessionId capture_session_id) { |
| 532 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 668 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 533 if (!listener_) { | 669 if (!listener_) { |
| 534 // Listener has been removed. | 670 // Listener has been removed. |
| 535 return; | 671 return; |
| 536 } | 672 } |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 628 } | 764 } |
| 629 return NULL; | 765 return NULL; |
| 630 } | 766 } |
| 631 | 767 |
| 632 VideoCaptureManager::DeviceEntry* | 768 VideoCaptureManager::DeviceEntry* |
| 633 VideoCaptureManager::GetDeviceEntryForController( | 769 VideoCaptureManager::GetDeviceEntryForController( |
| 634 const VideoCaptureController* controller) const { | 770 const VideoCaptureController* controller) const { |
| 635 // Look up |controller| in |devices_|. | 771 // Look up |controller| in |devices_|. |
| 636 for (DeviceEntries::const_iterator it = devices_.begin(); | 772 for (DeviceEntries::const_iterator it = devices_.begin(); |
| 637 it != devices_.end(); ++it) { | 773 it != devices_.end(); ++it) { |
| 638 if ((*it)->video_capture_controller.get() == controller) { | 774 if ((*it)->video_capture_controller() == controller) { |
| 639 return *it; | 775 return *it; |
| 640 } | 776 } |
| 641 } | 777 } |
| 642 return NULL; | 778 return NULL; |
| 643 } | 779 } |
| 644 | 780 |
| 645 void VideoCaptureManager::DestroyDeviceEntryIfNoClients(DeviceEntry* entry) { | 781 void VideoCaptureManager::DestroyDeviceEntryIfNoClients(DeviceEntry* entry) { |
| 646 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 782 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 647 // Removal of the last client stops the device. | 783 // Removal of the last client stops the device. |
| 648 if (entry->video_capture_controller->GetClientCount() == 0) { | 784 if (entry->video_capture_controller()->GetClientCount() == 0) { |
| 649 DVLOG(1) << "VideoCaptureManager stopping device (type = " | 785 DVLOG(1) << "VideoCaptureManager stopping device (type = " |
| 650 << entry->stream_type << ", id = " << entry->id << ")"; | 786 << entry->stream_type << ", id = " << entry->id << ")"; |
| 651 | 787 |
| 652 // The DeviceEntry is removed from |devices_| immediately. The controller is | 788 // The DeviceEntry is removed from |devices_| immediately. The controller is |
| 653 // deleted immediately, and the device is freed asynchronously. After this | 789 // deleted immediately, and the device is freed asynchronously. After this |
| 654 // point, subsequent requests to open this same device ID will create a new | 790 // point, subsequent requests to open this same device ID will create a new |
| 655 // DeviceEntry, VideoCaptureController, and VideoCaptureDevice. | 791 // DeviceEntry, VideoCaptureController, and VideoCaptureDevice. |
| 656 devices_.erase(entry); | 792 DoStopDevice(entry); |
| 657 entry->video_capture_controller.reset(); | 793 DeviceEntries::iterator device_it = std::find(devices_.begin(), |
| 658 device_task_runner_->PostTask( | 794 devices_.end(), |
| 659 FROM_HERE, | 795 entry); |
| 660 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, | 796 devices_.erase(device_it); |
| 661 base::Owned(entry))); | |
| 662 } | 797 } |
| 663 } | 798 } |
| 664 | 799 |
| 665 VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry( | 800 VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry( |
| 666 media::VideoCaptureSessionId capture_session_id) { | 801 media::VideoCaptureSessionId capture_session_id) { |
| 667 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 802 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 668 | 803 |
| 669 SessionMap::iterator session_it = sessions_.find(capture_session_id); | 804 SessionMap::iterator session_it = sessions_.find(capture_session_id); |
| 670 if (session_it == sessions_.end()) { | 805 if (session_it == sessions_.end()) { |
| 671 return NULL; | 806 return NULL; |
| 672 } | 807 } |
| 673 const MediaStreamDevice& device_info = session_it->second; | 808 const MediaStreamDevice& device_info = session_it->second; |
| 674 | 809 |
| 675 // Check if another session has already opened this device. If so, just | 810 // Check if another session has already opened this device. If so, just |
| 676 // use that opened device. | 811 // use that opened device. |
| 677 DeviceEntry* const existing_device = | 812 DeviceEntry* const existing_device = |
| 678 GetDeviceEntryForMediaStreamDevice(device_info); | 813 GetDeviceEntryForMediaStreamDevice(device_info); |
| 679 if (existing_device) { | 814 if (existing_device) { |
| 680 DCHECK_EQ(device_info.type, existing_device->stream_type); | 815 DCHECK_EQ(device_info.type, existing_device->stream_type); |
| 681 return existing_device; | 816 return existing_device; |
| 682 } | 817 } |
| 683 | 818 |
| 684 const int max_buffers = device_info.type == MEDIA_TAB_VIDEO_CAPTURE ? | 819 const int max_buffers = device_info.type == MEDIA_TAB_VIDEO_CAPTURE ? |
| 685 kMaxNumberOfBuffersForTabCapture : kMaxNumberOfBuffers; | 820 kMaxNumberOfBuffersForTabCapture : kMaxNumberOfBuffers; |
| 686 scoped_ptr<VideoCaptureController> video_capture_controller( | 821 scoped_ptr<VideoCaptureController> video_capture_controller( |
| 687 new VideoCaptureController(max_buffers)); | 822 new VideoCaptureController(max_buffers)); |
| 688 DeviceEntry* new_device = new DeviceEntry(device_info.type, | 823 DeviceEntry* new_device = new DeviceEntry(device_info.type, |
| 689 device_info.id, | 824 device_info.id, |
| 690 video_capture_controller.Pass()); | 825 video_capture_controller.Pass()); |
| 691 devices_.insert(new_device); | 826 devices_.push_back(new_device); |
| 692 return new_device; | 827 return new_device; |
| 693 } | 828 } |
| 694 | 829 |
| 695 media::VideoCaptureDeviceInfo* VideoCaptureManager::FindDeviceInfoById( | 830 media::VideoCaptureDeviceInfo* VideoCaptureManager::FindDeviceInfoById( |
| 696 const std::string& id, | 831 const std::string& id, |
| 697 media::VideoCaptureDeviceInfos& device_vector) { | 832 media::VideoCaptureDeviceInfos& device_vector) { |
| 698 for (auto& it : device_vector) { | 833 for (auto& it : device_vector) { |
| 699 if (it.name.id() == id) | 834 if (it.name.id() == id) |
| 700 return &(it); | 835 return &(it); |
| 701 } | 836 } |
| 702 return NULL; | 837 return NULL; |
| 703 } | 838 } |
| 704 | 839 |
| 705 void VideoCaptureManager::SetDesktopCaptureWindowIdOnDeviceThread( | 840 void VideoCaptureManager::SetDesktopCaptureWindowIdOnDeviceThread( |
| 706 DeviceEntry* entry, | 841 media::VideoCaptureDevice* device, |
| 707 gfx::NativeViewId window_id) { | 842 gfx::NativeViewId window_id) { |
| 708 DCHECK(IsOnDeviceThread()); | 843 DCHECK(IsOnDeviceThread()); |
| 709 DCHECK(entry->stream_type == MEDIA_DESKTOP_VIDEO_CAPTURE); | |
| 710 #if defined(ENABLE_SCREEN_CAPTURE) | 844 #if defined(ENABLE_SCREEN_CAPTURE) |
| 711 DesktopCaptureDevice* device = | 845 DesktopCaptureDevice* desktop_device = |
| 712 static_cast<DesktopCaptureDevice*>(entry->video_capture_device.get()); | 846 static_cast<DesktopCaptureDevice*>(device); |
| 713 device->SetNotificationWindowId(window_id); | 847 desktop_device->SetNotificationWindowId(window_id); |
| 714 VLOG(2) << "Screen capture notification window passed on device thread."; | 848 VLOG(2) << "Screen capture notification window passed on device thread."; |
| 715 #endif | 849 #endif |
| 716 } | 850 } |
| 717 | 851 |
| 718 void VideoCaptureManager::SaveDesktopCaptureWindowIdOnDeviceThread( | 852 void VideoCaptureManager::SaveDesktopCaptureWindowIdOnDeviceThread( |
| 719 media::VideoCaptureSessionId session_id, | 853 media::VideoCaptureSessionId session_id, |
| 720 gfx::NativeViewId window_id) { | 854 gfx::NativeViewId window_id) { |
| 721 DCHECK(IsOnDeviceThread()); | 855 DCHECK(IsOnDeviceThread()); |
| 722 DCHECK(notification_window_ids_.find(session_id) == | 856 DCHECK(notification_window_ids_.find(session_id) == |
| 723 notification_window_ids_.end()); | 857 notification_window_ids_.end()); |
| 724 notification_window_ids_[session_id] = window_id; | 858 notification_window_ids_[session_id] = window_id; |
| 725 VLOG(2) << "Screen capture notification window saved for session " | 859 VLOG(2) << "Screen capture notification window saved for session " |
| 726 << session_id << " on device thread."; | 860 << session_id << " on device thread."; |
| 727 } | 861 } |
| 728 | 862 |
| 729 } // namespace content | 863 } // namespace content |
| OLD | NEW |