Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(275)

Side by Side Diff: content/browser/renderer_host/media/video_capture_manager.cc

Issue 801363002: Queue commands to the Os to start a video device. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Adressed comments. Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698