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

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

Issue 91343002: Added supported formats caching to VideoCaptureManager. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Mad formatting corrected in certain files. Created 7 years 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 <set> 7 #include <set>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/message_loop/message_loop.h" 12 #include "base/message_loop/message_loop.h"
13 #include "base/stl_util.h" 13 #include "base/stl_util.h"
14 #include "base/task_runner_util.h"
14 #include "base/threading/sequenced_worker_pool.h" 15 #include "base/threading/sequenced_worker_pool.h"
15 #include "content/browser/renderer_host/media/video_capture_controller.h" 16 #include "content/browser/renderer_host/media/video_capture_controller.h"
16 #include "content/browser/renderer_host/media/video_capture_controller_event_han dler.h" 17 #include "content/browser/renderer_host/media/video_capture_controller_event_han dler.h"
17 #include "content/browser/renderer_host/media/web_contents_video_capture_device. h" 18 #include "content/browser/renderer_host/media/web_contents_video_capture_device. h"
18 #include "content/public/browser/browser_thread.h" 19 #include "content/public/browser/browser_thread.h"
19 #include "content/public/common/content_switches.h" 20 #include "content/public/common/content_switches.h"
20 #include "content/public/common/desktop_media_id.h" 21 #include "content/public/common/desktop_media_id.h"
21 #include "content/public/common/media_stream_request.h" 22 #include "content/public/common/media_stream_request.h"
22 #include "media/base/media_switches.h" 23 #include "media/base/media_switches.h"
23 #include "media/base/scoped_histogram_timer.h" 24 #include "media/base/scoped_histogram_timer.h"
(...skipping 13 matching lines...) Expand all
37 VideoCaptureManager::DeviceEntry::DeviceEntry( 38 VideoCaptureManager::DeviceEntry::DeviceEntry(
38 MediaStreamType stream_type, 39 MediaStreamType stream_type,
39 const std::string& id, 40 const std::string& id,
40 scoped_ptr<VideoCaptureController> controller) 41 scoped_ptr<VideoCaptureController> controller)
41 : stream_type(stream_type), 42 : stream_type(stream_type),
42 id(id), 43 id(id),
43 video_capture_controller(controller.Pass()) {} 44 video_capture_controller(controller.Pass()) {}
44 45
45 VideoCaptureManager::DeviceEntry::~DeviceEntry() {} 46 VideoCaptureManager::DeviceEntry::~DeviceEntry() {}
46 47
48 VideoCaptureManager::DeviceInfo::DeviceInfo() {}
49
50 VideoCaptureManager::DeviceInfo::DeviceInfo(
51 const media::VideoCaptureDevice::Name& name,
52 const media::VideoCaptureFormats& supported_formats)
53 : name(name),
54 supported_formats(supported_formats) {}
55
56 VideoCaptureManager::DeviceInfo::~DeviceInfo() {}
57
47 VideoCaptureManager::VideoCaptureManager() 58 VideoCaptureManager::VideoCaptureManager()
48 : listener_(NULL), 59 : listener_(NULL),
49 new_capture_session_id_(1), 60 new_capture_session_id_(1),
50 artificial_device_source_for_testing_ (DISABLED) { 61 artificial_device_source_for_testing_(DISABLED) {
51 } 62 }
52 63
53 VideoCaptureManager::~VideoCaptureManager() { 64 VideoCaptureManager::~VideoCaptureManager() {
54 DCHECK(devices_.empty()); 65 DCHECK(devices_.empty());
55 } 66 }
56 67
57 void VideoCaptureManager::Register(MediaStreamProviderListener* listener, 68 void VideoCaptureManager::Register(MediaStreamProviderListener* listener,
58 base::MessageLoopProxy* device_thread_loop) { 69 base::MessageLoopProxy* device_thread_loop) {
59 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 70 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
60 DCHECK(!listener_); 71 DCHECK(!listener_);
61 DCHECK(!device_loop_.get()); 72 DCHECK(!device_loop_.get());
62 listener_ = listener; 73 listener_ = listener;
63 device_loop_ = device_thread_loop; 74 device_loop_ = device_thread_loop;
64 } 75 }
65 76
66 void VideoCaptureManager::Unregister() { 77 void VideoCaptureManager::Unregister() {
67 DCHECK(listener_); 78 DCHECK(listener_);
68 listener_ = NULL; 79 listener_ = NULL;
69 } 80 }
70 81
71 void VideoCaptureManager::EnumerateDevices(MediaStreamType stream_type) { 82 void VideoCaptureManager::EnumerateDevices(MediaStreamType stream_type) {
72 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 83 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
73 DVLOG(1) << "VideoCaptureManager::EnumerateDevices, type " << stream_type; 84 DVLOG(1) << "VideoCaptureManager::EnumerateDevices, type " << stream_type;
74 DCHECK(listener_); 85 DCHECK(listener_);
75 base::PostTaskAndReplyWithResult( 86 base::PostTaskAndReplyWithResult(
76 device_loop_, FROM_HERE, 87 device_loop_, FROM_HERE,
77 base::Bind(&VideoCaptureManager::GetAvailableDevicesOnDeviceThread, this, 88 base::Bind(&VideoCaptureManager::GetAvailableDevicesInfoOnDeviceThread,
78 stream_type), 89 this, stream_type, devices_info_cache_),
79 base::Bind(&VideoCaptureManager::OnDevicesEnumerated, this, stream_type)); 90 base::Bind(&VideoCaptureManager::OnDevicesInfoEnumerated, this,
91 stream_type));
80 } 92 }
81 93
82 int VideoCaptureManager::Open(const StreamDeviceInfo& device_info) { 94 int VideoCaptureManager::Open(const StreamDeviceInfo& device_info) {
83 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 95 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
84 DCHECK(listener_); 96 DCHECK(listener_);
85 97
86 // Generate a new id for the session being opened. 98 // Generate a new id for the session being opened.
87 const int capture_session_id = new_capture_session_id_++; 99 const int capture_session_id = new_capture_session_id_++;
88 100
89 DCHECK(sessions_.find(capture_session_id) == sessions_.end()); 101 DCHECK(sessions_.find(capture_session_id) == sessions_.end());
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 scoped_ptr<media::VideoCaptureDevice::Client> device_client) { 159 scoped_ptr<media::VideoCaptureDevice::Client> device_client) {
148 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime"); 160 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime");
149 DCHECK(IsOnDeviceThread()); 161 DCHECK(IsOnDeviceThread());
150 162
151 scoped_ptr<media::VideoCaptureDevice> video_capture_device; 163 scoped_ptr<media::VideoCaptureDevice> video_capture_device;
152 switch (entry->stream_type) { 164 switch (entry->stream_type) {
153 case MEDIA_DEVICE_VIDEO_CAPTURE: { 165 case MEDIA_DEVICE_VIDEO_CAPTURE: {
154 // We look up the device id from the renderer in our local enumeration 166 // We look up the device id from the renderer in our local enumeration
155 // since the renderer does not have all the information that might be 167 // since the renderer does not have all the information that might be
156 // held in the browser-side VideoCaptureDevice::Name structure. 168 // held in the browser-side VideoCaptureDevice::Name structure.
157 media::VideoCaptureDevice::Name* found = 169 DeviceInfo* found = FindDeviceInfoById(entry->id, devices_info_cache_);
158 video_capture_devices_.FindById(entry->id);
159 if (found) { 170 if (found) {
160 switch (artificial_device_source_for_testing_) { 171 switch (artificial_device_source_for_testing_) {
161 case DISABLED: 172 case DISABLED:
162 video_capture_device.reset( 173 video_capture_device.reset(
163 media::VideoCaptureDevice::Create(*found)); 174 media::VideoCaptureDevice::Create(found->name));
164 break; 175 break;
165 case TEST_PATTERN: 176 case TEST_PATTERN:
166 video_capture_device.reset( 177 video_capture_device.reset(
167 media::FakeVideoCaptureDevice::Create(*found)); 178 media::FakeVideoCaptureDevice::Create(found->name));
168 break; 179 break;
169 case Y4M_FILE: 180 case Y4M_FILE:
170 video_capture_device.reset( 181 video_capture_device.reset(
171 media::FileVideoCaptureDevice::Create(*found)); 182 media::FileVideoCaptureDevice::Create(found->name));
172 break; 183 break;
173 } 184 }
174 } 185 }
175 break; 186 break;
176 } 187 }
177 case MEDIA_TAB_VIDEO_CAPTURE: { 188 case MEDIA_TAB_VIDEO_CAPTURE: {
178 video_capture_device.reset( 189 video_capture_device.reset(
179 WebContentsVideoCaptureDevice::Create(entry->id)); 190 WebContentsVideoCaptureDevice::Create(entry->id));
180 break; 191 break;
181 } 192 }
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 275
265 // Detach client from controller. 276 // Detach client from controller.
266 int session_id = controller->RemoveClient(client_id, client_handler); 277 int session_id = controller->RemoveClient(client_id, client_handler);
267 DVLOG(1) << "VideoCaptureManager::StopCaptureForClient, session_id = " 278 DVLOG(1) << "VideoCaptureManager::StopCaptureForClient, session_id = "
268 << session_id; 279 << session_id;
269 280
270 // If controller has no more clients, delete controller and device. 281 // If controller has no more clients, delete controller and device.
271 DestroyDeviceEntryIfNoClients(entry); 282 DestroyDeviceEntryIfNoClients(entry);
272 } 283 }
273 284
285 void VideoCaptureManager::GetDeviceSupportedFormats(
286 int capture_session_id,
287 media::VideoCaptureFormats* supported_formats) {
288 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
289 supported_formats->clear();
290
291 std::map<int, MediaStreamDevice>::iterator it =
292 sessions_.find(capture_session_id);
293 DCHECK(it != sessions_.end());
294 DVLOG(1) << "GetDeviceSupportedFormats for device: " << it->second.name;
295
296 DeviceInfo* device_in_use =
297 FindDeviceInfoById(it->second.id, devices_info_cache_);
298 if (device_in_use) {
299 DeviceEntry* const existing_device =
300 GetDeviceEntryForMediaStreamDevice(it->second);
301 if (!existing_device) {
302 // If the device is not in use, return all its cached supported formats.
303 *supported_formats = device_in_use->supported_formats;
304 return;
305 }
306 // Otherwise, get the video capture parameters in use from the controller
307 // associated to the device.
308 supported_formats->push_back(
309 existing_device->video_capture_controller->GetVideoCaptureFormat());
310 }
311 }
312
274 void VideoCaptureManager::DoStopDeviceOnDeviceThread(DeviceEntry* entry) { 313 void VideoCaptureManager::DoStopDeviceOnDeviceThread(DeviceEntry* entry) {
275 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime"); 314 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime");
276 DCHECK(IsOnDeviceThread()); 315 DCHECK(IsOnDeviceThread());
277 if (entry->video_capture_device) { 316 if (entry->video_capture_device) {
278 entry->video_capture_device->StopAndDeAllocate(); 317 entry->video_capture_device->StopAndDeAllocate();
279 } 318 }
280 entry->video_capture_device.reset(); 319 entry->video_capture_device.reset();
281 } 320 }
282 321
283 void VideoCaptureManager::OnOpened(MediaStreamType stream_type, 322 void VideoCaptureManager::OnOpened(MediaStreamType stream_type,
284 int capture_session_id) { 323 int capture_session_id) {
285 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 324 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
286 if (!listener_) { 325 if (!listener_) {
287 // Listener has been removed. 326 // Listener has been removed.
288 return; 327 return;
289 } 328 }
290 listener_->Opened(stream_type, capture_session_id); 329 listener_->Opened(stream_type, capture_session_id);
291 } 330 }
292 331
293 void VideoCaptureManager::OnClosed(MediaStreamType stream_type, 332 void VideoCaptureManager::OnClosed(MediaStreamType stream_type,
294 int capture_session_id) { 333 int capture_session_id) {
295 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 334 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
296 if (!listener_) { 335 if (!listener_) {
297 // Listener has been removed. 336 // Listener has been removed.
298 return; 337 return;
299 } 338 }
300 listener_->Closed(stream_type, capture_session_id); 339 listener_->Closed(stream_type, capture_session_id);
301 } 340 }
302 341
303 void VideoCaptureManager::OnDevicesEnumerated( 342 void VideoCaptureManager::OnDevicesInfoEnumerated(
304 MediaStreamType stream_type, 343 MediaStreamType stream_type,
305 const media::VideoCaptureDevice::Names& device_names) { 344 const DeviceInfos& new_devices_info_cache) {
306 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 345 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
307 346
308 if (!listener_) { 347 if (!listener_) {
309 // Listener has been removed. 348 // Listener has been removed.
310 return; 349 return;
311 } 350 }
351 devices_info_cache_ = new_devices_info_cache;
312 352
313 // Transform from VCD::Name to StreamDeviceInfo. 353 // Walk the |devices_info_cache_| and transform from VCD::Name to
354 // StreamDeviceInfo for return purposes.
314 StreamDeviceInfoArray devices; 355 StreamDeviceInfoArray devices;
315 for (media::VideoCaptureDevice::Names::const_iterator it = 356 for (DeviceInfos::const_iterator it = devices_info_cache_.begin();
316 device_names.begin(); it != device_names.end(); ++it) { 357 it != devices_info_cache_.end(); ++it) {
317 devices.push_back(StreamDeviceInfo( 358 devices.push_back(StreamDeviceInfo(
318 stream_type, it->GetNameAndModel(), it->id())); 359 stream_type, it->name.GetNameAndModel(), it->name.id()));
319 } 360 }
320
321 listener_->DevicesEnumerated(stream_type, devices); 361 listener_->DevicesEnumerated(stream_type, devices);
322 } 362 }
323 363
324 bool VideoCaptureManager::IsOnDeviceThread() const { 364 bool VideoCaptureManager::IsOnDeviceThread() const {
325 return device_loop_->BelongsToCurrentThread(); 365 return device_loop_->BelongsToCurrentThread();
326 } 366 }
327 367
328 media::VideoCaptureDevice::Names 368 VideoCaptureManager::DeviceInfos
329 VideoCaptureManager::GetAvailableDevicesOnDeviceThread( 369 VideoCaptureManager::GetAvailableDevicesInfoOnDeviceThread(
330 MediaStreamType stream_type) { 370 MediaStreamType stream_type,
371 const DeviceInfos& old_device_info_cache) {
331 SCOPED_UMA_HISTOGRAM_TIMER( 372 SCOPED_UMA_HISTOGRAM_TIMER(
332 "Media.VideoCaptureManager.GetAvailableDevicesTime"); 373 "Media.VideoCaptureManager.GetAvailableDevicesInfoOnDeviceThreadTime");
333 DCHECK(IsOnDeviceThread()); 374 DCHECK(IsOnDeviceThread());
334 media::VideoCaptureDevice::Names result; 375 media::VideoCaptureDevice::Names names_snapshot;
335
336 switch (stream_type) { 376 switch (stream_type) {
337 case MEDIA_DEVICE_VIDEO_CAPTURE: 377 case MEDIA_DEVICE_VIDEO_CAPTURE:
338 // Cache the latest enumeration of video capture devices. 378 // Cache the latest enumeration of video capture devices.
339 // We'll refer to this list again in OnOpen to avoid having to 379 // We'll refer to this list again in OnOpen to avoid having to
340 // enumerate the devices again. 380 // enumerate the devices again.
341 switch (artificial_device_source_for_testing_) { 381 switch (artificial_device_source_for_testing_) {
342 case DISABLED: 382 case DISABLED:
343 media::VideoCaptureDevice::GetDeviceNames(&result); 383 media::VideoCaptureDevice::GetDeviceNames(&names_snapshot);
344 break; 384 break;
345 case TEST_PATTERN: 385 case TEST_PATTERN:
346 media::FakeVideoCaptureDevice::GetDeviceNames(&result); 386 media::FakeVideoCaptureDevice::GetDeviceNames(&names_snapshot);
347 break; 387 break;
348 case Y4M_FILE: 388 case Y4M_FILE:
349 media::FileVideoCaptureDevice::GetDeviceNames(&result); 389 media::FileVideoCaptureDevice::GetDeviceNames(&names_snapshot);
350 break; 390 break;
351 } 391 }
352
353 // TODO(nick): The correctness of device start depends on this cache being
354 // maintained, but it seems a little odd to keep a cache here. Can we
355 // eliminate it?
356 video_capture_devices_ = result;
357 break; 392 break;
358 393
359 case MEDIA_DESKTOP_VIDEO_CAPTURE: 394 case MEDIA_DESKTOP_VIDEO_CAPTURE:
360 // Do nothing. 395 // Do nothing.
361 break; 396 break;
362 397
363 default: 398 default:
364 NOTREACHED(); 399 NOTREACHED();
365 break; 400 break;
366 } 401 }
367 return result; 402
403 // Construct |new_devices_info_cache| with the cached devices that are still
404 // present in the system, and remove their names from |names_snapshot|, so we
405 // keep there the truly new devices.
406 DeviceInfos new_devices_info_cache;
407 for (DeviceInfos::const_iterator it_device_info =
408 old_device_info_cache.begin();
409 it_device_info != old_device_info_cache.end(); ++it_device_info) {
410 media::VideoCaptureDevice::Names::iterator it;
perkj_chrome 2013/12/10 12:27:14 nit: prefer to minimize the scope and put this in
mcasas 2013/12/12 10:38:05 Done.
411 for (it = names_snapshot.begin(); it != names_snapshot.end(); ++it) {
412 if (it_device_info->name.id() == it->id()) {
413 new_devices_info_cache.push_back(*it_device_info);
414 names_snapshot.erase(it);
415 break;
416 }
417 }
418 }
419
420 // Get the supported capture formats for the new devices in |names_snapshot|.
421 for (media::VideoCaptureDevice::Names::const_iterator it =
422 names_snapshot.begin();
423 it != names_snapshot.end(); ++it) {
424 media::VideoCaptureFormats supported_formats;
425 DeviceInfo device_info(*it, media::VideoCaptureFormats());
426 switch (artificial_device_source_for_testing_) {
427 case DISABLED:
428 media::VideoCaptureDevice::GetDeviceSupportedFormats(
429 *it, &(device_info.supported_formats));
430 break;
431 case TEST_PATTERN:
432 media::FakeVideoCaptureDevice::GetDeviceSupportedFormats(
433 *it, &(device_info.supported_formats));
434 break;
435 case Y4M_FILE:
436 media::FileVideoCaptureDevice::GetDeviceSupportedFormats(
437 *it, &(device_info.supported_formats));
438 break;
439 }
440 new_devices_info_cache.push_back(device_info);
441 }
442 return new_devices_info_cache;
368 } 443 }
369 444
370 VideoCaptureManager::DeviceEntry* 445 VideoCaptureManager::DeviceEntry*
371 VideoCaptureManager::GetDeviceEntryForMediaStreamDevice( 446 VideoCaptureManager::GetDeviceEntryForMediaStreamDevice(
372 const MediaStreamDevice& device_info) { 447 const MediaStreamDevice& device_info) {
373 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 448 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
374 449
375 for (DeviceEntries::iterator it = devices_.begin(); 450 for (DeviceEntries::iterator it = devices_.begin();
376 it != devices_.end(); ++it) { 451 it != devices_.end(); ++it) {
377 DeviceEntry* device = *it; 452 DeviceEntry* device = *it;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 std::map<int, MediaStreamDevice>::iterator session_it = 498 std::map<int, MediaStreamDevice>::iterator session_it =
424 sessions_.find(capture_session_id); 499 sessions_.find(capture_session_id);
425 if (session_it == sessions_.end()) { 500 if (session_it == sessions_.end()) {
426 return NULL; 501 return NULL;
427 } 502 }
428 const MediaStreamDevice& device_info = session_it->second; 503 const MediaStreamDevice& device_info = session_it->second;
429 504
430 // Check if another session has already opened this device. If so, just 505 // Check if another session has already opened this device. If so, just
431 // use that opened device. 506 // use that opened device.
432 DeviceEntry* const existing_device = 507 DeviceEntry* const existing_device =
433 GetDeviceEntryForMediaStreamDevice(device_info); 508 GetDeviceEntryForMediaStreamDevice(device_info);
434 if (existing_device) { 509 if (existing_device) {
435 DCHECK_EQ(device_info.type, existing_device->stream_type); 510 DCHECK_EQ(device_info.type, existing_device->stream_type);
436 return existing_device; 511 return existing_device;
437 } 512 }
438 513
439 scoped_ptr<VideoCaptureController> video_capture_controller( 514 scoped_ptr<VideoCaptureController> video_capture_controller(
440 new VideoCaptureController()); 515 new VideoCaptureController());
441 DeviceEntry* new_device = new DeviceEntry(device_info.type, 516 DeviceEntry* new_device = new DeviceEntry(device_info.type,
442 device_info.id, 517 device_info.id,
443 video_capture_controller.Pass()); 518 video_capture_controller.Pass());
444 devices_.insert(new_device); 519 devices_.insert(new_device);
445 return new_device; 520 return new_device;
446 } 521 }
447 522
523 VideoCaptureManager::DeviceInfo* VideoCaptureManager::FindDeviceInfoById(
524 const std::string& id,
525 DeviceInfos& device_vector) {
526 for (DeviceInfos::iterator it = device_vector.begin();
527 it != device_vector.end(); ++it) {
528 if (it->name.id() == id)
529 return &(*it);
530 }
531 return NULL;
532 }
533
448 } // namespace content 534 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698