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

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: code review 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 kEnumerateDevices,
64 kOpenDevice
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::EnumerateDevices(
192 MediaStreamRequester* requester,
193 int render_process_id,
194 int render_view_id,
195 MediaStreamType type,
196 const std::string& security_origin,
197 std::string* label) {
198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
199
200 // Create a new request.
201 StreamOptions options;
202 if (type == media_stream::kAudioCapture)
203 options.audio = true;
204 else
205 options.video_option = StreamOptions::kFacingUser;
206
207 DeviceRequest new_request = DeviceRequest(requester, options);
208 new_request.type = DeviceRequest::kEnumerateDevices;
209
210 StartEnumeration(&new_request, render_process_id, render_view_id,
211 security_origin, label);
212 }
213
214 void MediaStreamManager::OpenDevice(
215 MediaStreamRequester* requester,
216 int render_process_id,
217 int render_view_id,
218 const std::string& device_id,
219 MediaStreamType type,
220 const std::string& security_origin,
221 std::string* label) {
222 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
223
224 // Create a new request.
225 StreamOptions options;
226 if (type == media_stream::kAudioCapture)
227 options.audio = true;
228 else
229 options.video_option = StreamOptions::kFacingUser;
230
231 DeviceRequest new_request = DeviceRequest(requester, options);
232 new_request.type = DeviceRequest::kOpenDevice;
233 new_request.requested_device_id = device_id;
234
235 StartEnumeration(&new_request, render_process_id, render_view_id,
mflodman_chromium_OOO 2011/12/02 18:44:02 I was thinking of calling Open directly from here,
236 security_origin, label);
237 }
238
239 void MediaStreamManager::StartEnumeration(
240 DeviceRequest* new_request,
241 int render_process_id,
242 int render_view_id,
243 const std::string& security_origin,
244 std::string* label) {
245 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
246
247 if (Requested(new_request->options, kAudioCapture)) {
248 new_request->state[kAudioCapture] = DeviceRequest::kRequested;
249 if (!enumeration_in_progress_[kAudioCapture]) {
250 enumeration_in_progress_[kAudioCapture] = true;
251 GetDeviceManager(kAudioCapture)->EnumerateDevices();
252 }
253 }
254 if (Requested(new_request->options, kVideoCapture)) {
255 new_request->state[kVideoCapture] = DeviceRequest::kRequested;
256 if (!enumeration_in_progress_[kVideoCapture]) {
257 enumeration_in_progress_[kVideoCapture] = true;
258 GetDeviceManager(kVideoCapture)->EnumerateDevices();
259 }
260 }
261
262 // Create a label for this request and verify it is unique.
263 std::string request_label;
264 do {
265 request_label = RandomLabel();
266 } while (requests_.find(request_label) != requests_.end());
267
268 requests_.insert(std::make_pair(request_label, *new_request));
269
270 // Get user confirmation to use capture devices.
271 // Need to make an asynchronous call to make sure the |requester| gets the
272 // |label| before it would receive any event.
273 if (new_request->type == DeviceRequest::kGenerateStream) {
274 BrowserThread::PostTask(BrowserThread::IO,
275 FROM_HERE,
276 base::Bind(&MediaStreamDeviceSettings::RequestCaptureDeviceUsage,
277 base::Unretained(device_settings_.get()),
278 request_label, render_process_id,
279 render_view_id, new_request->options,
280 security_origin));
281 }
282
283 (*label) = request_label;
284 }
285
205 void MediaStreamManager::Opened(MediaStreamType stream_type, 286 void MediaStreamManager::Opened(MediaStreamType stream_type,
206 int capture_session_id) { 287 int capture_session_id) {
207 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 288 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
208 289
209 // Find the request containing this device and mark it as used. 290 // Find the request containing this device and mark it as used.
210 DeviceRequest* request = NULL; 291 DeviceRequest* request = NULL;
211 StreamDeviceInfoArray* devices = NULL; 292 StreamDeviceInfoArray* devices = NULL;
212 std::string label; 293 std::string label;
213 for (DeviceRequests::iterator request_it = requests_.begin(); 294 for (DeviceRequests::iterator request_it = requests_.begin();
214 request_it != requests_.end() && request == NULL; ++request_it) { 295 request_it != requests_.end() && request == NULL; ++request_it) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 return; 328 return;
248 } 329 }
249 } 330 }
250 request->state[stream_type] = DeviceRequest::kDone; 331 request->state[stream_type] = DeviceRequest::kDone;
251 332
252 if (!RequestDone(*request)) { 333 if (!RequestDone(*request)) {
253 // This stream_type is done, but not the other type. 334 // This stream_type is done, but not the other type.
254 return; 335 return;
255 } 336 }
256 337
257 request->requester->StreamGenerated(label, request->audio_devices, 338 if (request->type == DeviceRequest::kOpenDevice) {
258 request->video_devices); 339 request->requester->DeviceOpened(label, (*devices)[0]);
340 } else if (request->type == DeviceRequest::kGenerateStream) {
341 request->requester->StreamGenerated(label, request->audio_devices,
342 request->video_devices);
343 } else {
344 NOTREACHED();
345 }
259 } 346 }
260 347
261 void MediaStreamManager::Closed(MediaStreamType stream_type, 348 void MediaStreamManager::Closed(MediaStreamType stream_type,
262 int capture_session_id) { 349 int capture_session_id) {
263 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 350 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
264 } 351 }
265 352
266 void MediaStreamManager::DevicesEnumerated( 353 void MediaStreamManager::DevicesEnumerated(
267 MediaStreamType stream_type, const StreamDeviceInfoArray& devices) { 354 MediaStreamType stream_type, const StreamDeviceInfoArray& devices) {
268 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 355 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
269 356
270 // Publish the result for all requests waiting for device list(s). 357 // Publish the result for all requests waiting for device list(s).
271 // Find the requests waiting for this device list, store their labels and 358 // 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 359 // release the iterator before calling device settings. We might get a call
273 // back from device_settings that will need to iterate through devices. 360 // back from device_settings that will need to iterate through devices.
274 std::list<std::string> label_list; 361 std::list<std::string> label_list;
275 for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end(); 362 for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end();
276 ++it) { 363 ++it) {
277 if (it->second.state[stream_type] == DeviceRequest::kRequested && 364 if (it->second.state[stream_type] == DeviceRequest::kRequested &&
278 Requested(it->second.options, stream_type)) { 365 Requested(it->second.options, stream_type)) {
279 label_list.push_back(it->first); 366 label_list.push_back(it->first);
280 } 367 }
281 } 368 }
282 for (std::list<std::string>::iterator it = label_list.begin(); 369 for (std::list<std::string>::iterator it = label_list.begin();
283 it != label_list.end(); ++it) { 370 it != label_list.end(); ++it) {
284 device_settings_->AvailableDevices(*it, stream_type, devices); 371 DeviceRequest& request = requests_[*it];
372 if (request.type == DeviceRequest::kEnumerateDevices) {
373 request.requester->DevicesEnumerated(*it, devices);
374 requests_.erase(*it);
375 } else if (request.type == DeviceRequest::kOpenDevice) {
376 for (StreamDeviceInfoArray::const_iterator device_it = devices.begin();
377 device_it != devices.end(); device_it++) {
378 if (request.requested_device_id == device_it->device_id) {
379 StreamDeviceInfo device = *device_it;
380 device.in_use = false;
381 device.session_id =
382 GetDeviceManager(device_it->stream_type)->Open(device);
383 request.state[device_it->stream_type] = DeviceRequest::kOpening;
384 if (stream_type == kAudioCapture)
385 request.audio_devices.push_back(device);
386 else
387 request.video_devices.push_back(device);
388 break;
389 }
390 }
391 } else {
392 BrowserThread::PostTask(BrowserThread::IO,
393 FROM_HERE,
394 base::Bind(&MediaStreamDeviceSettings::AvailableDevices,
395 base::Unretained(device_settings_.get()),
396 *it, stream_type, devices));
397 }
285 } 398 }
286 label_list.clear(); 399 label_list.clear();
287 enumeration_in_progress_[stream_type] = false; 400 enumeration_in_progress_[stream_type] = false;
288 } 401 }
289 402
290 void MediaStreamManager::Error(MediaStreamType stream_type, 403 void MediaStreamManager::Error(MediaStreamType stream_type,
291 int capture_session_id, 404 int capture_session_id,
292 MediaStreamProviderError error) { 405 MediaStreamProviderError error) {
293 // Find the device for the error call. 406 // Find the device for the error call.
294 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 407 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 442 // 3. Not opened but other devices exists for this request -> remove
330 // device from list, but don't signal an error. 443 // device from list, but don't signal an error.
331 devices->erase(device_it); 444 devices->erase(device_it);
332 } 445 }
333 return; 446 return;
334 } 447 }
335 } 448 }
336 } 449 }
337 } 450 }
338 451
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, 452 void MediaStreamManager::DevicesAccepted(const std::string& label,
349 const StreamDeviceInfoArray& devices) { 453 const StreamDeviceInfoArray& devices) {
350 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 454 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
351 DeviceRequests::iterator request_it = requests_.find(label); 455 DeviceRequests::iterator request_it = requests_.find(label);
352 if (request_it != requests_.end()) { 456 if (request_it != requests_.end()) {
353 if (devices.empty()) { 457 if (devices.empty()) {
354 // No available devices or user didn't accept device usage. 458 // No available devices or user didn't accept device usage.
355 request_it->second.requester->StreamGenerationFailed(request_it->first); 459 request_it->second.requester->StreamGenerationFailed(request_it->first);
356 requests_.erase(request_it); 460 requests_.erase(request_it);
357 return; 461 return;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 } 493 }
390 return; 494 return;
391 } 495 }
392 } 496 }
393 497
394 void MediaStreamManager::SettingsError(const std::string& label) { 498 void MediaStreamManager::SettingsError(const std::string& label) {
395 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 499 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
396 // Erase this request and report an error. 500 // Erase this request and report an error.
397 DeviceRequests::iterator it = requests_.find(label); 501 DeviceRequests::iterator it = requests_.find(label);
398 if (it != requests_.end()) { 502 if (it != requests_.end()) {
503 DCHECK_EQ(it->second.type, DeviceRequest::kGenerateStream);
399 it->second.requester->StreamGenerationFailed(label); 504 it->second.requester->StreamGenerationFailed(label);
400 requests_.erase(it); 505 requests_.erase(it);
401 return; 506 return;
402 } 507 }
403 } 508 }
404 509
405 void MediaStreamManager::UseFakeDevice() { 510 void MediaStreamManager::UseFakeDevice() {
406 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 511 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
407 video_capture_manager()->UseFakeDevice(); 512 video_capture_manager()->UseFakeDevice();
408 device_settings_->UseFakeUI(); 513 device_settings_->UseFakeUI();
(...skipping 29 matching lines...) Expand all
438 if (stream_type == kVideoCapture) { 543 if (stream_type == kVideoCapture) {
439 return video_capture_manager(); 544 return video_capture_manager();
440 } else if (stream_type == kAudioCapture) { 545 } else if (stream_type == kAudioCapture) {
441 return audio_input_device_manager(); 546 return audio_input_device_manager();
442 } 547 }
443 NOTREACHED(); 548 NOTREACHED();
444 return NULL; 549 return NULL;
445 } 550 }
446 551
447 } // namespace media_stream 552 } // namespace media_stream
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698