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

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

Issue 8480028: support video device enumeration from renderer process. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/media_stream_manager.h" 5 #include "content/browser/renderer_host/media/media_stream_manager.h"
6 6
7 #include <list> 7 #include <list>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 if (stream_type == kVideoCapture && 43 if (stream_type == kVideoCapture &&
44 (options.video_option != StreamOptions::kNoCamera)) { 44 (options.video_option != StreamOptions::kNoCamera)) {
45 return true; 45 return true;
46 } else if (stream_type == kAudioCapture && options.audio == true) { 46 } else if (stream_type == kAudioCapture && options.audio == true) {
47 return true; 47 return true;
48 } 48 }
49 return false; 49 return false;
50 } 50 }
51 51
52 struct MediaStreamManager::DeviceRequest { 52 struct MediaStreamManager::DeviceRequest {
53 DeviceRequest()
54 : requester(NULL),
55 state(kNumMediaStreamTypes, kNotRequested) {
56 options.audio = false;
57 options.video_option = StreamOptions::kNoCamera;
58 }
59 DeviceRequest(MediaStreamRequester* requester,
60 const StreamOptions& request_options)
61 : requester(requester),
62 options(request_options),
63 state(kNumMediaStreamTypes, kNotRequested) {
64 DCHECK(requester);
65 }
66 ~DeviceRequest() {}
67
68 enum RequestState { 53 enum RequestState {
69 kNotRequested = 0, 54 kNotRequested = 0,
70 kRequested, 55 kRequested,
71 kOpening, 56 kOpening,
72 kDone, 57 kDone,
73 kError 58 kError
74 }; 59 };
75 60
61 enum RequestType {
62 kGenerateStream = 0,
63 kEnumerateVideoDevices,
64 kOpenVideoDevice
65 };
66
67 DeviceRequest()
68 : requester(NULL),
69 state(kNumMediaStreamTypes, kNotRequested),
70 type(kGenerateStream) {
71 options.audio = false;
72 options.video_option = StreamOptions::kNoCamera;
73 }
74
75 DeviceRequest(MediaStreamRequester* requester,
76 const StreamOptions& request_options)
77 : requester(requester),
78 options(request_options),
79 state(kNumMediaStreamTypes, kNotRequested),
80 type(kGenerateStream) {
81 DCHECK(requester);
82 }
83
84 ~DeviceRequest() {}
85
76 MediaStreamRequester* requester; 86 MediaStreamRequester* requester;
77 StreamOptions options; 87 StreamOptions options;
78 std::vector<RequestState> state; 88 std::vector<RequestState> state;
89 RequestType type;
90 std::string requested_device_id;
79 StreamDeviceInfoArray audio_devices; 91 StreamDeviceInfoArray audio_devices;
80 StreamDeviceInfoArray video_devices; 92 StreamDeviceInfoArray video_devices;
81 }; 93 };
82 94
83 MediaStreamManager::MediaStreamManager() 95 MediaStreamManager::MediaStreamManager()
84 : ALLOW_THIS_IN_INITIALIZER_LIST( 96 : ALLOW_THIS_IN_INITIALIZER_LIST(
85 device_settings_(new MediaStreamDeviceSettings(this))), 97 device_settings_(new MediaStreamDeviceSettings(this))),
86 enumeration_in_progress_(kNumMediaStreamTypes, false) { 98 enumeration_in_progress_(kNumMediaStreamTypes, false) {
87 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 99 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
88 } 100 }
(...skipping 23 matching lines...) Expand all
112 void MediaStreamManager::GenerateStream(MediaStreamRequester* requester, 124 void MediaStreamManager::GenerateStream(MediaStreamRequester* requester,
113 int render_process_id, 125 int render_process_id,
114 int render_view_id, 126 int render_view_id,
115 const StreamOptions& options, 127 const StreamOptions& options,
116 const std::string& security_origin, 128 const std::string& security_origin,
117 std::string* label) { 129 std::string* label) {
118 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 130 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
119 131
120 // Create a new request based on options. 132 // Create a new request based on options.
121 DeviceRequest new_request = DeviceRequest(requester, options); 133 DeviceRequest new_request = DeviceRequest(requester, options);
122 if (Requested(new_request.options, kAudioCapture)) { 134 StartEnumeration(&new_request, render_process_id, render_view_id,
123 new_request.state[kAudioCapture] = DeviceRequest::kRequested; 135 security_origin, label);
124 }
125 if (Requested(new_request.options, kVideoCapture)) {
126 new_request.state[kVideoCapture] = DeviceRequest::kRequested;
127 }
128
129 // Create a label for this request and verify it is unique.
130 std::string request_label;
131 do {
132 request_label = RandomLabel();
133 } while (requests_.find(request_label) != requests_.end());
134
135 requests_.insert(std::make_pair(request_label, new_request));
136
137 // Get user confirmation to use capture devices.
138 // Need to make an asynchronous call to make sure the |requester| gets the
139 // |label| before it would receive any event.
140 BrowserThread::PostTask(
141 BrowserThread::IO,
142 FROM_HERE,
143 base::Bind(&MediaStreamDeviceSettings::RequestCaptureDeviceUsage,
144 base::Unretained(device_settings_.get()),
145 request_label, render_process_id,
146 render_view_id, options,
147 security_origin));
148
149 (*label) = request_label;
150 } 136 }
151 137
152 void MediaStreamManager::CancelRequests(MediaStreamRequester* requester) { 138 void MediaStreamManager::CancelRequests(MediaStreamRequester* requester) {
153 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
154 DeviceRequests::iterator it = requests_.begin(); 140 DeviceRequests::iterator it = requests_.begin();
155 while (it != requests_.end()) { 141 while (it != requests_.end()) {
156 if (it->second.requester == requester && !RequestDone(it->second)) { 142 if (it->second.requester == requester && !RequestDone(it->second)) {
157 // The request isn't complete, but there might be some devices already 143 // The request isn't complete, but there might be some devices already
158 // opened -> close them. 144 // opened -> close them.
159 DeviceRequest* request = &(it->second); 145 DeviceRequest* request = &(it->second);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 for (StreamDeviceInfoArray::iterator video_it = 181 for (StreamDeviceInfoArray::iterator video_it =
196 it->second.video_devices.begin(); 182 it->second.video_devices.begin();
197 video_it != it->second.video_devices.end(); ++video_it) { 183 video_it != it->second.video_devices.end(); ++video_it) {
198 video_capture_manager()->Close(video_it->session_id); 184 video_capture_manager()->Close(video_it->session_id);
199 } 185 }
200 requests_.erase(it); 186 requests_.erase(it);
201 return; 187 return;
202 } 188 }
203 } 189 }
204 190
191 void MediaStreamManager::EnumerateVideoDevices(
192 MediaStreamRequester* requester,
193 int render_process_id,
194 int render_view_id,
195 const std::string& security_origin,
196 std::string* label) {
197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
198
199 // Create a new request.
200 StreamOptions options(false, StreamOptions::kFacingUser);
201 DeviceRequest new_request = DeviceRequest(requester, options);
202 new_request.type = DeviceRequest::kEnumerateVideoDevices;
203
204 StartEnumeration(&new_request, render_process_id, render_view_id,
205 security_origin, label);
206 }
207
208 void MediaStreamManager::OpenVideoDevice(
209 MediaStreamRequester* requester,
210 int render_process_id,
211 int render_view_id,
212 const std::string& device_id,
213 const std::string& security_origin,
214 std::string* label) {
215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
216
217 // Create a new request.
218 StreamOptions options(false, StreamOptions::kFacingUser);
219 DeviceRequest new_request = DeviceRequest(requester, options);
220 new_request.type = DeviceRequest::kOpenVideoDevice;
221 new_request.requested_device_id = device_id;
222
223 StartEnumeration(&new_request, render_process_id, render_view_id,
224 security_origin, label);
225 }
226
227 void MediaStreamManager::StartEnumeration(
228 DeviceRequest* new_request,
229 int render_process_id,
230 int render_view_id,
231 const std::string& security_origin,
232 std::string* label) {
233 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
234
235 if (Requested(new_request->options, kAudioCapture)) {
236 new_request->state[kAudioCapture] = DeviceRequest::kRequested;
237 if (!enumeration_in_progress_[kAudioCapture]) {
238 enumeration_in_progress_[kAudioCapture] = true;
239 GetDeviceManager(kAudioCapture)->EnumerateDevices();
240 }
241 }
242 if (Requested(new_request->options, kVideoCapture)) {
243 new_request->state[kVideoCapture] = DeviceRequest::kRequested;
244 if (!enumeration_in_progress_[kVideoCapture]) {
245 enumeration_in_progress_[kVideoCapture] = true;
246 GetDeviceManager(kVideoCapture)->EnumerateDevices();
247 }
248 }
249
250 // Create a label for this request and verify it is unique.
251 std::string request_label;
252 do {
253 request_label = RandomLabel();
254 } while (requests_.find(request_label) != requests_.end());
255
256 requests_.insert(std::make_pair(request_label, *new_request));
257
258 // Get user confirmation to use capture devices.
259 // Need to make an asynchronous call to make sure the |requester| gets the
260 // |label| before it would receive any event.
261 if (new_request->type == DeviceRequest::kGenerateStream) {
262 BrowserThread::PostTask(BrowserThread::IO,
263 FROM_HERE,
264 base::Bind(&MediaStreamDeviceSettings::RequestCaptureDeviceUsage,
265 base::Unretained(device_settings_.get()),
266 request_label, render_process_id,
267 render_view_id, new_request->options,
268 security_origin));
269 }
270
271 (*label) = request_label;
272 }
273
205 void MediaStreamManager::Opened(MediaStreamType stream_type, 274 void MediaStreamManager::Opened(MediaStreamType stream_type,
206 int capture_session_id) { 275 int capture_session_id) {
207 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 276 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
208 277
209 // Find the request containing this device and mark it as used. 278 // Find the request containing this device and mark it as used.
210 DeviceRequest* request = NULL; 279 DeviceRequest* request = NULL;
211 StreamDeviceInfoArray* devices = NULL; 280 StreamDeviceInfoArray* devices = NULL;
212 std::string label; 281 std::string label;
213 for (DeviceRequests::iterator request_it = requests_.begin(); 282 for (DeviceRequests::iterator request_it = requests_.begin();
214 request_it != requests_.end() && request == NULL; ++request_it) { 283 request_it != requests_.end() && request == NULL; ++request_it) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 return; 316 return;
248 } 317 }
249 } 318 }
250 request->state[stream_type] = DeviceRequest::kDone; 319 request->state[stream_type] = DeviceRequest::kDone;
251 320
252 if (!RequestDone(*request)) { 321 if (!RequestDone(*request)) {
253 // This stream_type is done, but not the other type. 322 // This stream_type is done, but not the other type.
254 return; 323 return;
255 } 324 }
256 325
257 request->requester->StreamGenerated(label, request->audio_devices, 326 if (request->type == DeviceRequest::kOpenVideoDevice) {
258 request->video_devices); 327 DCHECK_NE(request->options.video_option, StreamOptions::kNoCamera);
328 request->requester->VideoDeviceOpened(label, request->video_devices[0]);
329 } else {
mflodman_chromium_OOO 2011/11/29 02:30:56 The else case will include DeviceRequest::kEnumera
wjia(left Chromium) 2011/11/30 00:14:23 Done.
330 request->requester->StreamGenerated(label, request->audio_devices,
331 request->video_devices);
332 }
259 } 333 }
260 334
261 void MediaStreamManager::Closed(MediaStreamType stream_type, 335 void MediaStreamManager::Closed(MediaStreamType stream_type,
262 int capture_session_id) { 336 int capture_session_id) {
263 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 337 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
264 } 338 }
265 339
266 void MediaStreamManager::DevicesEnumerated( 340 void MediaStreamManager::DevicesEnumerated(
267 MediaStreamType stream_type, const StreamDeviceInfoArray& devices) { 341 MediaStreamType stream_type, const StreamDeviceInfoArray& devices) {
268 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 342 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
269 343
270 // Publish the result for all requests waiting for device list(s). 344 // Publish the result for all requests waiting for device list(s).
271 // Find the requests waiting for this device list, store their labels and 345 // Find the requests waiting for this device list, store their labels and
272 // release the iterator before calling device settings. We might get a call 346 // release the iterator before calling device settings. We might get a call
273 // back from device_settings that will need to iterate through devices. 347 // back from device_settings that will need to iterate through devices.
274 std::list<std::string> label_list; 348 std::list<std::string> label_list;
275 for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end(); 349 for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end();
276 ++it) { 350 ++it) {
277 if (it->second.state[stream_type] == DeviceRequest::kRequested && 351 if (it->second.state[stream_type] == DeviceRequest::kRequested &&
278 Requested(it->second.options, stream_type)) { 352 Requested(it->second.options, stream_type)) {
279 label_list.push_back(it->first); 353 label_list.push_back(it->first);
280 } 354 }
281 } 355 }
282 for (std::list<std::string>::iterator it = label_list.begin(); 356 for (std::list<std::string>::iterator it = label_list.begin();
283 it != label_list.end(); ++it) { 357 it != label_list.end(); ++it) {
284 device_settings_->AvailableDevices(*it, stream_type, devices); 358 DeviceRequest& request = requests_[*it];
359 if (request.type == DeviceRequest::kEnumerateVideoDevices) {
360 DCHECK_NE(request.options.video_option, StreamOptions::kNoCamera);
361 request.requester->VideoDevicesEnumerated(*it, devices);
362 requests_.erase(*it);
363 } else if (request.type == DeviceRequest::kOpenVideoDevice) {
364 DCHECK_NE(request.options.video_option, StreamOptions::kNoCamera);
365 for (StreamDeviceInfoArray::const_iterator device_it = devices.begin();
366 device_it != devices.end(); device_it++) {
367 if (request.requested_device_id == device_it->device_id) {
368 StreamDeviceInfo device = *device_it;
369 device.in_use = false;
370 device.session_id =
371 GetDeviceManager(device_it->stream_type)->Open(device);
372 request.state[device_it->stream_type] = DeviceRequest::kOpening;
373 request.video_devices.push_back(device);
374 break;
375 }
376 }
377 } else {
378 BrowserThread::PostTask(BrowserThread::IO,
379 FROM_HERE,
380 base::Bind(&MediaStreamDeviceSettings::AvailableDevices,
381 base::Unretained(device_settings_.get()),
382 *it, stream_type, devices));
383 }
285 } 384 }
286 label_list.clear(); 385 label_list.clear();
287 enumeration_in_progress_[stream_type] = false; 386 enumeration_in_progress_[stream_type] = false;
288 } 387 }
289 388
290 void MediaStreamManager::Error(MediaStreamType stream_type, 389 void MediaStreamManager::Error(MediaStreamType stream_type,
291 int capture_session_id, 390 int capture_session_id,
292 MediaStreamProviderError error) { 391 MediaStreamProviderError error) {
293 // Find the device for the error call. 392 // Find the device for the error call.
294 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 393 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 // 3. Not opened but other devices exists for this request -> remove 428 // 3. Not opened but other devices exists for this request -> remove
330 // device from list, but don't signal an error. 429 // device from list, but don't signal an error.
331 devices->erase(device_it); 430 devices->erase(device_it);
332 } 431 }
333 return; 432 return;
334 } 433 }
335 } 434 }
336 } 435 }
337 } 436 }
338 437
339 void MediaStreamManager::GetDevices(const std::string& label,
340 MediaStreamType stream_type) {
341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
342 if (!enumeration_in_progress_[stream_type]) {
343 enumeration_in_progress_[stream_type] = true;
344 GetDeviceManager(stream_type)->EnumerateDevices();
345 }
346 }
347
348 void MediaStreamManager::DevicesAccepted(const std::string& label, 438 void MediaStreamManager::DevicesAccepted(const std::string& label,
349 const StreamDeviceInfoArray& devices) { 439 const StreamDeviceInfoArray& devices) {
350 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 440 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
351 DeviceRequests::iterator request_it = requests_.find(label); 441 DeviceRequests::iterator request_it = requests_.find(label);
352 if (request_it != requests_.end()) { 442 if (request_it != requests_.end()) {
353 if (devices.empty()) { 443 if (devices.empty()) {
354 // No available devices or user didn't accept device usage. 444 // No available devices or user didn't accept device usage.
355 request_it->second.requester->StreamGenerationFailed(request_it->first); 445 request_it->second.requester->StreamGenerationFailed(request_it->first);
356 requests_.erase(request_it); 446 requests_.erase(request_it);
357 return; 447 return;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 } 479 }
390 return; 480 return;
391 } 481 }
392 } 482 }
393 483
394 void MediaStreamManager::SettingsError(const std::string& label) { 484 void MediaStreamManager::SettingsError(const std::string& label) {
395 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 485 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
396 // Erase this request and report an error. 486 // Erase this request and report an error.
397 DeviceRequests::iterator it = requests_.find(label); 487 DeviceRequests::iterator it = requests_.find(label);
398 if (it != requests_.end()) { 488 if (it != requests_.end()) {
399 it->second.requester->StreamGenerationFailed(label); 489 if (it->second.type == DeviceRequest::kEnumerateVideoDevices) {
490 DCHECK_NE(it->second.options.video_option, StreamOptions::kNoCamera);
491 it->second.requester->VideoDevicesEnumerationFailed(label);
492 } else if (it->second.type == DeviceRequest::kOpenVideoDevice) {
493 DCHECK_NE(it->second.options.video_option, StreamOptions::kNoCamera);
494 it->second.requester->VideoDeviceOpenFailed(label);
495 } else {
496 it->second.requester->StreamGenerationFailed(label);
497 }
400 requests_.erase(it); 498 requests_.erase(it);
401 return; 499 return;
402 } 500 }
403 } 501 }
404 502
405 void MediaStreamManager::UseFakeDevice() { 503 void MediaStreamManager::UseFakeDevice() {
406 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 504 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
407 video_capture_manager()->UseFakeDevice(); 505 video_capture_manager()->UseFakeDevice();
408 device_settings_->UseFakeUI(); 506 device_settings_->UseFakeUI();
409 } 507 }
(...skipping 28 matching lines...) Expand all
438 if (stream_type == kVideoCapture) { 536 if (stream_type == kVideoCapture) {
439 return video_capture_manager(); 537 return video_capture_manager();
440 } else if (stream_type == kAudioCapture) { 538 } else if (stream_type == kAudioCapture) {
441 return audio_input_device_manager(); 539 return audio_input_device_manager();
442 } 540 }
443 NOTREACHED(); 541 NOTREACHED();
444 return NULL; 542 return NULL;
445 } 543 }
446 544
447 } // namespace media_stream 545 } // namespace media_stream
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698