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/media_stream_manager.cc

Issue 8480028: support video device enumeration from renderer process. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: update unittest Created 8 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 | 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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 if (stream_type == kVideoCapture && 44 if (stream_type == kVideoCapture &&
45 (options.video_option != StreamOptions::kNoCamera)) { 45 (options.video_option != StreamOptions::kNoCamera)) {
46 return true; 46 return true;
47 } else if (stream_type == kAudioCapture && options.audio == true) { 47 } else if (stream_type == kAudioCapture && options.audio == true) {
48 return true; 48 return true;
49 } 49 }
50 return false; 50 return false;
51 } 51 }
52 52
53 struct MediaStreamManager::DeviceRequest { 53 struct MediaStreamManager::DeviceRequest {
54 DeviceRequest()
55 : requester(NULL),
56 state(kNumMediaStreamTypes, kNotRequested) {
57 options.audio = false;
58 options.video_option = StreamOptions::kNoCamera;
59 }
60 DeviceRequest(MediaStreamRequester* requester,
61 const StreamOptions& request_options)
62 : requester(requester),
63 options(request_options),
64 state(kNumMediaStreamTypes, kNotRequested) {
65 DCHECK(requester);
66 }
67 ~DeviceRequest() {}
68
69 enum RequestState { 54 enum RequestState {
70 kNotRequested = 0, 55 kNotRequested = 0,
71 kRequested, 56 kRequested,
72 kOpening, 57 kOpening,
73 kDone, 58 kDone,
74 kError 59 kError
75 }; 60 };
76 61
62 enum RequestType {
63 kGenerateStream = 0,
64 kEnumerateDevices,
65 kOpenDevice
66 };
67
68 DeviceRequest()
69 : requester(NULL),
70 state(kNumMediaStreamTypes, kNotRequested),
71 type(kGenerateStream) {
72 options.audio = false;
73 options.video_option = StreamOptions::kNoCamera;
74 }
75
76 DeviceRequest(MediaStreamRequester* requester,
77 const StreamOptions& request_options)
78 : requester(requester),
79 options(request_options),
80 state(kNumMediaStreamTypes, kNotRequested),
81 type(kGenerateStream) {
82 DCHECK(requester);
83 }
84
85 ~DeviceRequest() {}
86
77 MediaStreamRequester* requester; 87 MediaStreamRequester* requester;
78 StreamOptions options; 88 StreamOptions options;
79 std::vector<RequestState> state; 89 std::vector<RequestState> state;
90 RequestType type;
91 std::string requested_device_id;
80 StreamDeviceInfoArray audio_devices; 92 StreamDeviceInfoArray audio_devices;
81 StreamDeviceInfoArray video_devices; 93 StreamDeviceInfoArray video_devices;
82 }; 94 };
83 95
84 MediaStreamManager::MediaStreamManager(AudioManager* audio_manager) 96 MediaStreamManager::MediaStreamManager(AudioManager* audio_manager)
85 : ALLOW_THIS_IN_INITIALIZER_LIST( 97 : ALLOW_THIS_IN_INITIALIZER_LIST(
86 device_settings_(new MediaStreamDeviceSettings(this))), 98 device_settings_(new MediaStreamDeviceSettings(this))),
87 enumeration_in_progress_(kNumMediaStreamTypes, false), 99 enumeration_in_progress_(kNumMediaStreamTypes, false),
88 audio_manager_(audio_manager) { 100 audio_manager_(audio_manager) {
89 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 101 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
(...skipping 25 matching lines...) Expand all
115 void MediaStreamManager::GenerateStream(MediaStreamRequester* requester, 127 void MediaStreamManager::GenerateStream(MediaStreamRequester* requester,
116 int render_process_id, 128 int render_process_id,
117 int render_view_id, 129 int render_view_id,
118 const StreamOptions& options, 130 const StreamOptions& options,
119 const std::string& security_origin, 131 const std::string& security_origin,
120 std::string* label) { 132 std::string* label) {
121 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 133 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
122 134
123 // Create a new request based on options. 135 // Create a new request based on options.
124 DeviceRequest new_request = DeviceRequest(requester, options); 136 DeviceRequest new_request = DeviceRequest(requester, options);
125 if (Requested(new_request.options, kAudioCapture)) { 137 StartEnumeration(&new_request, render_process_id, render_view_id,
126 new_request.state[kAudioCapture] = DeviceRequest::kRequested; 138 security_origin, label);
127 }
128 if (Requested(new_request.options, kVideoCapture)) {
129 new_request.state[kVideoCapture] = DeviceRequest::kRequested;
130 }
131
132 // Create a label for this request and verify it is unique.
133 std::string request_label;
134 do {
135 request_label = RandomLabel();
136 } while (requests_.find(request_label) != requests_.end());
137
138 requests_.insert(std::make_pair(request_label, new_request));
139
140 // Get user confirmation to use capture devices.
141 // Need to make an asynchronous call to make sure the |requester| gets the
142 // |label| before it would receive any event.
143 BrowserThread::PostTask(
144 BrowserThread::IO,
145 FROM_HERE,
146 base::Bind(&MediaStreamDeviceSettings::RequestCaptureDeviceUsage,
147 base::Unretained(device_settings_.get()),
148 request_label, render_process_id,
149 render_view_id, options,
150 security_origin));
151
152 (*label) = request_label;
153 } 139 }
154 140
155 void MediaStreamManager::CancelRequests(MediaStreamRequester* requester) { 141 void MediaStreamManager::CancelRequests(MediaStreamRequester* requester) {
156 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 142 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
157 DeviceRequests::iterator it = requests_.begin(); 143 DeviceRequests::iterator it = requests_.begin();
158 while (it != requests_.end()) { 144 while (it != requests_.end()) {
159 if (it->second.requester == requester && !RequestDone(it->second)) { 145 if (it->second.requester == requester && !RequestDone(it->second)) {
160 // The request isn't complete, but there might be some devices already 146 // The request isn't complete, but there might be some devices already
161 // opened -> close them. 147 // opened -> close them.
162 DeviceRequest* request = &(it->second); 148 DeviceRequest* request = &(it->second);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 for (StreamDeviceInfoArray::iterator video_it = 184 for (StreamDeviceInfoArray::iterator video_it =
199 it->second.video_devices.begin(); 185 it->second.video_devices.begin();
200 video_it != it->second.video_devices.end(); ++video_it) { 186 video_it != it->second.video_devices.end(); ++video_it) {
201 video_capture_manager()->Close(video_it->session_id); 187 video_capture_manager()->Close(video_it->session_id);
202 } 188 }
203 requests_.erase(it); 189 requests_.erase(it);
204 return; 190 return;
205 } 191 }
206 } 192 }
207 193
194 void MediaStreamManager::EnumerateDevices(
195 MediaStreamRequester* requester,
196 int render_process_id,
197 int render_view_id,
198 MediaStreamType type,
199 const std::string& security_origin,
200 std::string* label) {
201 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
202
203 // Create a new request.
204 StreamOptions options;
205 if (type == media_stream::kAudioCapture)
206 options.audio = true;
207 else
208 options.video_option = StreamOptions::kFacingUser;
209
210 DeviceRequest new_request = DeviceRequest(requester, options);
211 new_request.type = DeviceRequest::kEnumerateDevices;
212
213 StartEnumeration(&new_request, render_process_id, render_view_id,
214 security_origin, label);
215 }
216
217 void MediaStreamManager::OpenDevice(
218 MediaStreamRequester* requester,
219 int render_process_id,
220 int render_view_id,
221 const std::string& device_id,
222 MediaStreamType type,
223 const std::string& security_origin,
224 std::string* label) {
225 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
226
227 // Create a new request.
228 StreamOptions options;
229 if (type == media_stream::kAudioCapture)
230 options.audio = true;
231 else
232 options.video_option = StreamOptions::kFacingUser;
233
234 DeviceRequest new_request = DeviceRequest(requester, options);
235 new_request.type = DeviceRequest::kOpenDevice;
236 new_request.requested_device_id = device_id;
237
238 StartEnumeration(&new_request, render_process_id, render_view_id,
239 security_origin, label);
240 }
241
242 void MediaStreamManager::StartEnumeration(
243 DeviceRequest* new_request,
244 int render_process_id,
245 int render_view_id,
246 const std::string& security_origin,
247 std::string* label) {
248 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
249
250 if (Requested(new_request->options, kAudioCapture)) {
251 new_request->state[kAudioCapture] = DeviceRequest::kRequested;
252 if (!enumeration_in_progress_[kAudioCapture]) {
253 enumeration_in_progress_[kAudioCapture] = true;
254 GetDeviceManager(kAudioCapture)->EnumerateDevices();
255 }
256 }
257 if (Requested(new_request->options, kVideoCapture)) {
258 new_request->state[kVideoCapture] = DeviceRequest::kRequested;
259 if (!enumeration_in_progress_[kVideoCapture]) {
260 enumeration_in_progress_[kVideoCapture] = true;
261 GetDeviceManager(kVideoCapture)->EnumerateDevices();
262 }
263 }
264
265 // Create a label for this request and verify it is unique.
266 std::string request_label;
267 do {
268 request_label = RandomLabel();
269 } while (requests_.find(request_label) != requests_.end());
270
271 requests_.insert(std::make_pair(request_label, *new_request));
272
273 // Get user confirmation to use capture devices.
274 // Need to make an asynchronous call to make sure the |requester| gets the
275 // |label| before it would receive any event.
276 if (new_request->type == DeviceRequest::kGenerateStream) {
277 BrowserThread::PostTask(BrowserThread::IO,
278 FROM_HERE,
279 base::Bind(&MediaStreamDeviceSettings::RequestCaptureDeviceUsage,
280 base::Unretained(device_settings_.get()),
281 request_label, render_process_id,
282 render_view_id, new_request->options,
283 security_origin));
284 }
285
286 (*label) = request_label;
287 }
288
208 void MediaStreamManager::Opened(MediaStreamType stream_type, 289 void MediaStreamManager::Opened(MediaStreamType stream_type,
209 int capture_session_id) { 290 int capture_session_id) {
210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 291 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
211 292
212 // Find the request containing this device and mark it as used. 293 // Find the request containing this device and mark it as used.
213 DeviceRequest* request = NULL; 294 DeviceRequest* request = NULL;
214 StreamDeviceInfoArray* devices = NULL; 295 StreamDeviceInfoArray* devices = NULL;
215 std::string label; 296 std::string label;
216 for (DeviceRequests::iterator request_it = requests_.begin(); 297 for (DeviceRequests::iterator request_it = requests_.begin();
217 request_it != requests_.end() && request == NULL; ++request_it) { 298 request_it != requests_.end() && request == NULL; ++request_it) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 return; 331 return;
251 } 332 }
252 } 333 }
253 request->state[stream_type] = DeviceRequest::kDone; 334 request->state[stream_type] = DeviceRequest::kDone;
254 335
255 if (!RequestDone(*request)) { 336 if (!RequestDone(*request)) {
256 // This stream_type is done, but not the other type. 337 // This stream_type is done, but not the other type.
257 return; 338 return;
258 } 339 }
259 340
260 request->requester->StreamGenerated(label, request->audio_devices, 341 if (request->type == DeviceRequest::kOpenDevice) {
scherkus (not reviewing) 2012/01/25 03:19:42 use switch statement?
wjia(left Chromium) 2012/01/25 22:50:44 Done.
261 request->video_devices); 342 request->requester->DeviceOpened(label, (*devices)[0]);
343 } else if (request->type == DeviceRequest::kGenerateStream) {
344 request->requester->StreamGenerated(label, request->audio_devices,
345 request->video_devices);
346 } else {
347 NOTREACHED();
348 }
262 } 349 }
263 350
264 void MediaStreamManager::Closed(MediaStreamType stream_type, 351 void MediaStreamManager::Closed(MediaStreamType stream_type,
265 int capture_session_id) { 352 int capture_session_id) {
266 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 353 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
267 } 354 }
268 355
269 void MediaStreamManager::DevicesEnumerated( 356 void MediaStreamManager::DevicesEnumerated(
270 MediaStreamType stream_type, const StreamDeviceInfoArray& devices) { 357 MediaStreamType stream_type, const StreamDeviceInfoArray& devices) {
271 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 358 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
272 359
273 // Publish the result for all requests waiting for device list(s). 360 // Publish the result for all requests waiting for device list(s).
274 // Find the requests waiting for this device list, store their labels and 361 // Find the requests waiting for this device list, store their labels and
275 // release the iterator before calling device settings. We might get a call 362 // release the iterator before calling device settings. We might get a call
276 // back from device_settings that will need to iterate through devices. 363 // back from device_settings that will need to iterate through devices.
277 std::list<std::string> label_list; 364 std::list<std::string> label_list;
278 for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end(); 365 for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end();
279 ++it) { 366 ++it) {
280 if (it->second.state[stream_type] == DeviceRequest::kRequested && 367 if (it->second.state[stream_type] == DeviceRequest::kRequested &&
281 Requested(it->second.options, stream_type)) { 368 Requested(it->second.options, stream_type)) {
282 label_list.push_back(it->first); 369 label_list.push_back(it->first);
283 } 370 }
284 } 371 }
285 for (std::list<std::string>::iterator it = label_list.begin(); 372 for (std::list<std::string>::iterator it = label_list.begin();
286 it != label_list.end(); ++it) { 373 it != label_list.end(); ++it) {
287 device_settings_->AvailableDevices(*it, stream_type, devices); 374 DeviceRequest& request = requests_[*it];
375 if (request.type == DeviceRequest::kEnumerateDevices) {
scherkus (not reviewing) 2012/01/25 03:19:42 use switch statement?
wjia(left Chromium) 2012/01/25 22:50:44 Done.
376 request.requester->DevicesEnumerated(*it, devices);
377 requests_.erase(*it);
378 } else if (request.type == DeviceRequest::kOpenDevice) {
379 for (StreamDeviceInfoArray::const_iterator device_it = devices.begin();
380 device_it != devices.end(); device_it++) {
381 if (request.requested_device_id == device_it->device_id) {
382 StreamDeviceInfo device = *device_it;
383 device.in_use = false;
384 device.session_id =
385 GetDeviceManager(device_it->stream_type)->Open(device);
386 request.state[device_it->stream_type] = DeviceRequest::kOpening;
387 if (stream_type == kAudioCapture)
388 request.audio_devices.push_back(device);
389 else
390 request.video_devices.push_back(device);
391 break;
392 }
393 }
394 } else {
395 BrowserThread::PostTask(BrowserThread::IO,
396 FROM_HERE,
397 base::Bind(&MediaStreamDeviceSettings::AvailableDevices,
398 base::Unretained(device_settings_.get()),
399 *it, stream_type, devices));
400 }
288 } 401 }
289 label_list.clear(); 402 label_list.clear();
290 enumeration_in_progress_[stream_type] = false; 403 enumeration_in_progress_[stream_type] = false;
291 } 404 }
292 405
293 void MediaStreamManager::Error(MediaStreamType stream_type, 406 void MediaStreamManager::Error(MediaStreamType stream_type,
294 int capture_session_id, 407 int capture_session_id,
295 MediaStreamProviderError error) { 408 MediaStreamProviderError error) {
296 // Find the device for the error call. 409 // Find the device for the error call.
297 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 410 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 // 3. Not opened but other devices exists for this request -> remove 445 // 3. Not opened but other devices exists for this request -> remove
333 // device from list, but don't signal an error. 446 // device from list, but don't signal an error.
334 devices->erase(device_it); 447 devices->erase(device_it);
335 } 448 }
336 return; 449 return;
337 } 450 }
338 } 451 }
339 } 452 }
340 } 453 }
341 454
342 void MediaStreamManager::GetDevices(const std::string& label,
343 MediaStreamType stream_type) {
344 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
345 if (!enumeration_in_progress_[stream_type]) {
346 enumeration_in_progress_[stream_type] = true;
347 GetDeviceManager(stream_type)->EnumerateDevices();
348 }
349 }
350
351 void MediaStreamManager::DevicesAccepted(const std::string& label, 455 void MediaStreamManager::DevicesAccepted(const std::string& label,
352 const StreamDeviceInfoArray& devices) { 456 const StreamDeviceInfoArray& devices) {
353 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 457 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
354 DeviceRequests::iterator request_it = requests_.find(label); 458 DeviceRequests::iterator request_it = requests_.find(label);
355 if (request_it != requests_.end()) { 459 if (request_it != requests_.end()) {
356 if (devices.empty()) { 460 if (devices.empty()) {
357 // No available devices or user didn't accept device usage. 461 // No available devices or user didn't accept device usage.
358 request_it->second.requester->StreamGenerationFailed(request_it->first); 462 request_it->second.requester->StreamGenerationFailed(request_it->first);
359 requests_.erase(request_it); 463 requests_.erase(request_it);
360 return; 464 return;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 } 496 }
393 return; 497 return;
394 } 498 }
395 } 499 }
396 500
397 void MediaStreamManager::SettingsError(const std::string& label) { 501 void MediaStreamManager::SettingsError(const std::string& label) {
398 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 502 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
399 // Erase this request and report an error. 503 // Erase this request and report an error.
400 DeviceRequests::iterator it = requests_.find(label); 504 DeviceRequests::iterator it = requests_.find(label);
401 if (it != requests_.end()) { 505 if (it != requests_.end()) {
506 DCHECK_EQ(it->second.type, DeviceRequest::kGenerateStream);
402 it->second.requester->StreamGenerationFailed(label); 507 it->second.requester->StreamGenerationFailed(label);
403 requests_.erase(it); 508 requests_.erase(it);
404 return; 509 return;
405 } 510 }
406 } 511 }
407 512
408 void MediaStreamManager::UseFakeDevice() { 513 void MediaStreamManager::UseFakeDevice() {
409 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 514 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
410 video_capture_manager()->UseFakeDevice(); 515 video_capture_manager()->UseFakeDevice();
411 device_settings_->UseFakeUI(); 516 device_settings_->UseFakeUI();
(...skipping 29 matching lines...) Expand all
441 if (stream_type == kVideoCapture) { 546 if (stream_type == kVideoCapture) {
442 return video_capture_manager(); 547 return video_capture_manager();
443 } else if (stream_type == kAudioCapture) { 548 } else if (stream_type == kAudioCapture) {
444 return audio_input_device_manager(); 549 return audio_input_device_manager();
445 } 550 }
446 NOTREACHED(); 551 NOTREACHED();
447 return NULL; 552 return NULL;
448 } 553 }
449 554
450 } // namespace media_stream 555 } // namespace media_stream
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698