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

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

Issue 29423003: Added video capture capabilities retrieval and caching to VideoCaptureManager (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Overhauled following all the inputs. Created 7 years, 1 month 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"
(...skipping 21 matching lines...) Expand all
32 VideoCaptureManager::DeviceEntry::DeviceEntry( 32 VideoCaptureManager::DeviceEntry::DeviceEntry(
33 MediaStreamType stream_type, 33 MediaStreamType stream_type,
34 const std::string& id, 34 const std::string& id,
35 scoped_ptr<VideoCaptureController> controller) 35 scoped_ptr<VideoCaptureController> controller)
36 : stream_type(stream_type), 36 : stream_type(stream_type),
37 id(id), 37 id(id),
38 video_capture_controller(controller.Pass()) {} 38 video_capture_controller(controller.Pass()) {}
39 39
40 VideoCaptureManager::DeviceEntry::~DeviceEntry() {} 40 VideoCaptureManager::DeviceEntry::~DeviceEntry() {}
41 41
42 VideoCaptureManager::DeviceInfo::DeviceInfo() {}
43
44 VideoCaptureManager::DeviceInfo::DeviceInfo(
45 const media::VideoCaptureDevice::Name& name,
46 const media::VideoCaptureCapabilities& capabilities)
47 : name_(name), capabilities_(capabilities) {}
48
49 VideoCaptureManager::DeviceInfo::~DeviceInfo() {}
50
42 VideoCaptureManager::VideoCaptureManager() 51 VideoCaptureManager::VideoCaptureManager()
43 : listener_(NULL), 52 : listener_(NULL),
44 new_capture_session_id_(1), 53 new_capture_session_id_(1),
45 use_fake_device_(false) { 54 use_fake_device_(false) {
46 } 55 }
47 56
48 VideoCaptureManager::~VideoCaptureManager() { 57 VideoCaptureManager::~VideoCaptureManager() {
49 DCHECK(devices_.empty()); 58 DCHECK(devices_.empty());
50 } 59 }
51 60
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 capture_session_id)); 135 capture_session_id));
127 sessions_.erase(session_it); 136 sessions_.erase(session_it);
128 } 137 }
129 138
130 void VideoCaptureManager::UseFakeDevice() { 139 void VideoCaptureManager::UseFakeDevice() {
131 use_fake_device_ = true; 140 use_fake_device_ = true;
132 } 141 }
133 142
134 void VideoCaptureManager::DoStartDeviceOnDeviceThread( 143 void VideoCaptureManager::DoStartDeviceOnDeviceThread(
135 DeviceEntry* entry, 144 DeviceEntry* entry,
145 DeviceInfo* device_info,
perkj_chrome 2013/10/31 09:46:00 can you just pass the media::VideoCaptureDevice::N
mcasas 2013/10/31 14:25:23 Done.
136 const media::VideoCaptureCapability& capture_params, 146 const media::VideoCaptureCapability& capture_params,
137 scoped_ptr<media::VideoCaptureDevice::Client> device_client) { 147 scoped_ptr<media::VideoCaptureDevice::Client> device_client) {
138 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime"); 148 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime");
139 DCHECK(IsOnDeviceThread()); 149 DCHECK(IsOnDeviceThread());
140 150
141 scoped_ptr<media::VideoCaptureDevice> video_capture_device; 151 scoped_ptr<media::VideoCaptureDevice> video_capture_device;
142 switch (entry->stream_type) { 152 switch (entry->stream_type) {
143 case MEDIA_DEVICE_VIDEO_CAPTURE: { 153 case MEDIA_DEVICE_VIDEO_CAPTURE: {
144 // We look up the device id from the renderer in our local enumeration 154 // We look up the device id from the renderer in our local enumeration
145 // since the renderer does not have all the information that might be 155 // since the renderer does not have all the information that might be
146 // held in the browser-side VideoCaptureDevice::Name structure. 156 // held in the browser-side VideoCaptureDevice::Name structure.
147 media::VideoCaptureDevice::Name* found = 157 if (device_info) {
148 video_capture_devices_.FindById(entry->id);
149 if (found) {
150 video_capture_device.reset(use_fake_device_ ? 158 video_capture_device.reset(use_fake_device_ ?
151 media::FakeVideoCaptureDevice::Create(*found) : 159 media::FakeVideoCaptureDevice::Create(device_info->name_) :
152 media::VideoCaptureDevice::Create(*found)); 160 media::VideoCaptureDevice::Create(device_info->name_));
153 } 161 }
154 break; 162 break;
155 } 163 }
156 case MEDIA_TAB_VIDEO_CAPTURE: { 164 case MEDIA_TAB_VIDEO_CAPTURE: {
157 video_capture_device.reset( 165 video_capture_device.reset(
158 WebContentsVideoCaptureDevice::Create(entry->id)); 166 WebContentsVideoCaptureDevice::Create(entry->id));
159 break; 167 break;
160 } 168 }
161 case MEDIA_DESKTOP_VIDEO_CAPTURE: { 169 case MEDIA_DESKTOP_VIDEO_CAPTURE: {
162 #if defined(ENABLE_SCREEN_CAPTURE) 170 #if defined(ENABLE_SCREEN_CAPTURE)
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 DVLOG(1) << "VideoCaptureManager starting device (type = " 217 DVLOG(1) << "VideoCaptureManager starting device (type = "
210 << entry->stream_type << ", id = " << entry->id << ")"; 218 << entry->stream_type << ", id = " << entry->id << ")";
211 219
212 media::VideoCaptureCapability params_as_capability; 220 media::VideoCaptureCapability params_as_capability;
213 params_as_capability.width = params.requested_format.width; 221 params_as_capability.width = params.requested_format.width;
214 params_as_capability.height = params.requested_format.height; 222 params_as_capability.height = params.requested_format.height;
215 params_as_capability.frame_rate = params.requested_format.frame_rate; 223 params_as_capability.frame_rate = params.requested_format.frame_rate;
216 params_as_capability.frame_size_type = 224 params_as_capability.frame_size_type =
217 params.requested_format.frame_size_type; 225 params.requested_format.frame_size_type;
218 226
227 DeviceInfo* found = FindDeviceInfoById(entry->id);
219 device_loop_->PostTask(FROM_HERE, base::Bind( 228 device_loop_->PostTask(FROM_HERE, base::Bind(
220 &VideoCaptureManager::DoStartDeviceOnDeviceThread, this, 229 &VideoCaptureManager::DoStartDeviceOnDeviceThread, this,
221 entry, params_as_capability, 230 entry, found, params_as_capability,
perkj_chrome 2013/10/31 09:46:00 Just pass the name?
mcasas 2013/10/31 14:25:23 Done.
222 base::Passed(entry->video_capture_controller->NewDeviceClient()))); 231 base::Passed(entry->video_capture_controller->NewDeviceClient())));
232
233 if (found) {
234 // After opening a device, we currently assume that it cannot be opened
235 // in any other format than the actual, so we clear the capabilities.
236 found->capabilities_.clear();
237 found->capabilities_.push_back(params_as_capability);
238 }
223 } 239 }
224 // Run the callback first, as AddClient() may trigger OnFrameInfo(). 240 // Run the callback first, as AddClient() may trigger OnFrameInfo().
225 done_cb.Run(entry->video_capture_controller->GetWeakPtr()); 241 done_cb.Run(entry->video_capture_controller->GetWeakPtr());
226 entry->video_capture_controller->AddClient(client_id, 242 entry->video_capture_controller->AddClient(client_id,
227 client_handler, 243 client_handler,
228 client_render_process, 244 client_render_process,
229 params); 245 params);
230 } 246 }
231 247
232 void VideoCaptureManager::StopCaptureForClient( 248 void VideoCaptureManager::StopCaptureForClient(
(...skipping 12 matching lines...) Expand all
245 261
246 // Detach client from controller. 262 // Detach client from controller.
247 int session_id = controller->RemoveClient(client_id, client_handler); 263 int session_id = controller->RemoveClient(client_id, client_handler);
248 DVLOG(1) << "VideoCaptureManager::StopCaptureForClient, session_id = " 264 DVLOG(1) << "VideoCaptureManager::StopCaptureForClient, session_id = "
249 << session_id; 265 << session_id;
250 266
251 // If controller has no more clients, delete controller and device. 267 // If controller has no more clients, delete controller and device.
252 DestroyDeviceEntryIfNoClients(entry); 268 DestroyDeviceEntryIfNoClients(entry);
253 } 269 }
254 270
271 media::VideoCaptureCapabilities VideoCaptureManager::GetDeviceCapabilities(
perkj_chrome 2013/10/31 09:46:00 would it make more sence to have this void GetDev
mcasas 2013/10/31 14:25:23 Done.
272 int capture_session_id) {
273 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
274
275 std::map<int, MediaStreamDevice>::iterator it =
276 sessions_.find(capture_session_id);
277 if (it != sessions_.end()) {
perkj_chrome 2013/10/31 09:46:00 suggest (D)CHECK(it != sessions_end()) - It should
mcasas 2013/10/31 14:25:23 Done.
278 DVLOG(1) << "EnumerateDeviceCapabilites for: " << it->second.name;
perkj_chrome 2013/10/31 09:46:00 nit: This function is not called EnumerateDeviceCa
mcasas 2013/10/31 14:25:23 Done.
279
280 DeviceInfo* device = FindDeviceInfoById(it->second.id);
281 if (device)
282 return device->capabilities_;
283 }
284 return media::VideoCaptureCapabilities();
285 }
286
255 void VideoCaptureManager::DoStopDeviceOnDeviceThread(DeviceEntry* entry) { 287 void VideoCaptureManager::DoStopDeviceOnDeviceThread(DeviceEntry* entry) {
256 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime"); 288 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime");
257 DCHECK(IsOnDeviceThread()); 289 DCHECK(IsOnDeviceThread());
258 if (entry->video_capture_device) { 290 if (entry->video_capture_device) {
259 entry->video_capture_device->StopAndDeAllocate(); 291 entry->video_capture_device->StopAndDeAllocate();
260 } 292 }
261 entry->video_capture_device.reset(); 293 entry->video_capture_device.reset();
262 } 294 }
263 295
264 void VideoCaptureManager::OnOpened(MediaStreamType stream_type, 296 void VideoCaptureManager::OnOpened(MediaStreamType stream_type,
(...skipping 13 matching lines...) Expand all
278 // Listener has been removed. 310 // Listener has been removed.
279 return; 311 return;
280 } 312 }
281 listener_->Closed(stream_type, capture_session_id); 313 listener_->Closed(stream_type, capture_session_id);
282 } 314 }
283 315
284 void VideoCaptureManager::OnDevicesEnumerated( 316 void VideoCaptureManager::OnDevicesEnumerated(
285 MediaStreamType stream_type, 317 MediaStreamType stream_type,
286 const media::VideoCaptureDevice::Names& device_names) { 318 const media::VideoCaptureDevice::Names& device_names) {
287 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 319 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
288
289 if (!listener_) { 320 if (!listener_) {
290 // Listener has been removed. 321 // Listener has been removed.
291 return; 322 return;
292 } 323 }
293 324
294 // Transform from VCD::Name to StreamDeviceInfo. 325 // Walk the returned |device_names| do: a) transform from VCD::Name to
326 // StreamDeviceInfo, and b) at the same time retrieve device capture
327 // capabilities to create the |devices_info_cache_| - skipping known devices.
295 StreamDeviceInfoArray devices; 328 StreamDeviceInfoArray devices;
329 media::VideoCaptureCapabilities capabilities;
296 for (media::VideoCaptureDevice::Names::const_iterator it = 330 for (media::VideoCaptureDevice::Names::const_iterator it =
297 device_names.begin(); it != device_names.end(); ++it) { 331 device_names.begin(); it != device_names.end(); ++it) {
298 devices.push_back(StreamDeviceInfo( 332 devices.push_back(
299 stream_type, it->GetNameAndModel(), it->id())); 333 StreamDeviceInfo(stream_type, it->GetNameAndModel(), it->id()));
334 if (FindDeviceInfoById(it->id()))
335 continue;
336 if (!use_fake_device_) {
337 media::VideoCaptureDevice::GetDeviceSupportedFormats(*it, &capabilities);
perkj_chrome 2013/10/31 09:46:00 We do not want to actually call this function on t
mcasas 2013/10/31 14:25:23 Done.
338 } else {
339 media::FakeVideoCaptureDevice::GetDeviceSupportedFormats(*it,
340 &capabilities);
341 }
342 devices_info_cache_.push_back(new DeviceInfo(*it, capabilities));
300 } 343 }
301 344
302 listener_->DevicesEnumerated(stream_type, devices); 345 listener_->DevicesEnumerated(stream_type, devices);
303 } 346 }
304 347
305 bool VideoCaptureManager::IsOnDeviceThread() const { 348 bool VideoCaptureManager::IsOnDeviceThread() const {
306 return device_loop_->BelongsToCurrentThread(); 349 return device_loop_->BelongsToCurrentThread();
307 } 350 }
308 351
309 media::VideoCaptureDevice::Names 352 media::VideoCaptureDevice::Names
310 VideoCaptureManager::GetAvailableDevicesOnDeviceThread( 353 VideoCaptureManager::GetAvailableDevicesOnDeviceThread(
311 MediaStreamType stream_type) { 354 MediaStreamType stream_type) {
312 SCOPED_UMA_HISTOGRAM_TIMER( 355 SCOPED_UMA_HISTOGRAM_TIMER(
313 "Media.VideoCaptureManager.GetAvailableDevicesTime"); 356 "Media.VideoCaptureManager.GetAvailableDevicesTime");
314 DCHECK(IsOnDeviceThread()); 357 DCHECK(IsOnDeviceThread());
315 media::VideoCaptureDevice::Names result; 358 media::VideoCaptureDevice::Names names;
316 359
317 switch (stream_type) { 360 switch (stream_type) {
318 case MEDIA_DEVICE_VIDEO_CAPTURE: 361 case MEDIA_DEVICE_VIDEO_CAPTURE:
319 // Cache the latest enumeration of video capture devices. 362 if (!use_fake_device_)
320 // We'll refer to this list again in OnOpen to avoid having to 363 media::VideoCaptureDevice::GetDeviceNames(&names);
321 // enumerate the devices again. 364 else
322 if (!use_fake_device_) { 365 media::FakeVideoCaptureDevice::GetDeviceNames(&names);
323 media::VideoCaptureDevice::GetDeviceNames(&result);
324 } else {
325 media::FakeVideoCaptureDevice::GetDeviceNames(&result);
326 }
327
328 // TODO(nick): The correctness of device start depends on this cache being
329 // maintained, but it seems a little odd to keep a cache here. Can we
330 // eliminate it?
331 video_capture_devices_ = result;
332 break; 366 break;
333 367
334 case MEDIA_DESKTOP_VIDEO_CAPTURE: 368 case MEDIA_DESKTOP_VIDEO_CAPTURE:
335 // Do nothing. 369 // Do nothing.
336 break; 370 break;
337 371
338 default: 372 default:
339 NOTREACHED(); 373 NOTREACHED();
340 break; 374 break;
341 } 375 }
342 return result; 376 return names;
343 } 377 }
344 378
345 VideoCaptureManager::DeviceEntry* 379 VideoCaptureManager::DeviceEntry*
346 VideoCaptureManager::GetDeviceEntryForMediaStreamDevice( 380 VideoCaptureManager::GetDeviceEntryForMediaStreamDevice(
347 const MediaStreamDevice& device_info) { 381 const MediaStreamDevice& device_info) {
348 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 382 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
349 383
350 for (DeviceEntries::iterator it = devices_.begin(); 384 for (DeviceEntries::iterator it = devices_.begin();
351 it != devices_.end(); ++it) { 385 it != devices_.end(); ++it) {
352 DeviceEntry* device = *it; 386 DeviceEntry* device = *it;
(...skipping 26 matching lines...) Expand all
379 << entry->stream_type << ", id = " << entry->id << ")"; 413 << entry->stream_type << ", id = " << entry->id << ")";
380 414
381 // The DeviceEntry is removed from |devices_| immediately. The controller is 415 // The DeviceEntry is removed from |devices_| immediately. The controller is
382 // deleted immediately, and the device is freed asynchronously. After this 416 // deleted immediately, and the device is freed asynchronously. After this
383 // point, subsequent requests to open this same device ID will create a new 417 // point, subsequent requests to open this same device ID will create a new
384 // DeviceEntry, VideoCaptureController, and VideoCaptureDevice. 418 // DeviceEntry, VideoCaptureController, and VideoCaptureDevice.
385 devices_.erase(entry); 419 devices_.erase(entry);
386 entry->video_capture_controller.reset(); 420 entry->video_capture_controller.reset();
387 device_loop_->PostTask( 421 device_loop_->PostTask(
388 FROM_HERE, 422 FROM_HERE,
389 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, 423 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread,
424 this,
390 base::Owned(entry))); 425 base::Owned(entry)));
426 // When the device is closed, its capabilities are reread from the device
perkj_chrome 2013/10/31 09:46:00 ok I see. May I suggest a different strategy? Ins
mcasas 2013/10/31 14:25:23 Done.
427 // to reflect that all are possible.
428 DeviceInfo* device_info = FindDeviceInfoById(entry->id);
429 if (device_info) {
430 if (!use_fake_device_) {
431 media::VideoCaptureDevice::GetDeviceSupportedFormats(
432 device_info->name_, &(device_info->capabilities_));
433 } else {
434 media::FakeVideoCaptureDevice::GetDeviceSupportedFormats(
435 device_info->name_, &(device_info->capabilities_));
436 }
437 }
391 } 438 }
392 } 439 }
393 440
394 VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry( 441 VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry(
395 int capture_session_id) { 442 int capture_session_id) {
396 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 443 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
397 444
398 std::map<int, MediaStreamDevice>::iterator session_it = 445 std::map<int, MediaStreamDevice>::iterator session_it =
399 sessions_.find(capture_session_id); 446 sessions_.find(capture_session_id);
400 if (session_it == sessions_.end()) { 447 if (session_it == sessions_.end()) {
(...skipping 12 matching lines...) Expand all
413 460
414 scoped_ptr<VideoCaptureController> video_capture_controller( 461 scoped_ptr<VideoCaptureController> video_capture_controller(
415 new VideoCaptureController()); 462 new VideoCaptureController());
416 DeviceEntry* new_device = new DeviceEntry(device_info.type, 463 DeviceEntry* new_device = new DeviceEntry(device_info.type,
417 device_info.id, 464 device_info.id,
418 video_capture_controller.Pass()); 465 video_capture_controller.Pass());
419 devices_.insert(new_device); 466 devices_.insert(new_device);
420 return new_device; 467 return new_device;
421 } 468 }
422 469
470 VideoCaptureManager::DeviceInfo* VideoCaptureManager::FindDeviceInfoById(
471 const std::string& id) {
472 ScopedVector<DeviceInfo>::iterator it;
473 for (it = devices_info_cache_.begin();
474 it != devices_info_cache_.end();
475 ++it) {
476 if ((*it)->name_.id() == id)
477 return *it;
478 }
479 return NULL;
480 }
481
423 } // namespace content 482 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698