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

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

Issue 10830063: refactor EnumerateDevices to make it a persistent request. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: code review Created 8 years, 4 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) 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/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 29 matching lines...) Expand all
40 for (size_t i = 0; i < label.size(); ++i) { 40 for (size_t i = 0; i < label.size(); ++i) {
41 int random_char = base::RandGenerator(sizeof(kAlphabet) - 1); 41 int random_char = base::RandGenerator(sizeof(kAlphabet) - 1);
42 label[i] = kAlphabet[random_char]; 42 label[i] = kAlphabet[random_char];
43 } 43 }
44 return label; 44 return label;
45 } 45 }
46 46
47 // Helper to verify if a media stream type is part of options or not. 47 // Helper to verify if a media stream type is part of options or not.
48 static bool Requested(const StreamOptions& options, 48 static bool Requested(const StreamOptions& options,
49 MediaStreamType stream_type) { 49 MediaStreamType stream_type) {
50 if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE && 50 return (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE &&
51 options.video) { 51 options.video) ||
52 return true; 52 (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE &&
53 } else if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE && 53 options.audio);
54 options.audio) {
55 return true;
56 }
57 return false;
58 } 54 }
59 55
60 DeviceThread::DeviceThread(const char* name) 56 DeviceThread::DeviceThread(const char* name)
61 : base::Thread(name) { 57 : base::Thread(name) {
62 } 58 }
63 59
64 DeviceThread::~DeviceThread() { 60 DeviceThread::~DeviceThread() {
65 Stop(); 61 Stop();
66 } 62 }
67 63
68 void DeviceThread::Init() { 64 void DeviceThread::Init() {
69 using base::win::ScopedCOMInitializer; 65 using base::win::ScopedCOMInitializer;
70 // Enter the multi-threaded apartment. 66 // Enter the multi-threaded apartment.
71 com_initializer_.reset(new ScopedCOMInitializer(ScopedCOMInitializer::kMTA)); 67 com_initializer_.reset(new ScopedCOMInitializer(ScopedCOMInitializer::kMTA));
72 } 68 }
73 69
74 void DeviceThread::CleanUp() { 70 void DeviceThread::CleanUp() {
75 com_initializer_.reset(); 71 com_initializer_.reset();
76 } 72 }
77 73
78 // TODO(xians): Merge DeviceRequest with MediaStreamRequest. 74 // TODO(xians): Merge DeviceRequest with MediaStreamRequest.
79 struct MediaStreamManager::DeviceRequest { 75 struct MediaStreamManager::DeviceRequest {
80 enum RequestState { 76 enum RequestState {
81 kNotRequested = 0, 77 STATE_NOT_REQUESTED = 0,
82 kRequested, 78 STATE_REQUESTED,
83 kPendingApproval, 79 STATE_PENDING_APPROVAL,
84 kOpening, 80 STATE_OPENING,
85 kDone, 81 STATE_DONE,
86 kError 82 STATE_ERROR
87 }; 83 };
88 84
89 enum RequestType { 85 enum RequestType {
90 kGenerateStream = 0, 86 GENERATE_STREAM = 0,
91 kEnumerateDevices, 87 ENUMERATE_DEVICES,
92 kOpenDevice 88 OPEN_DEVICE
93 }; 89 };
94 90
95 DeviceRequest() 91 DeviceRequest()
96 : requester(NULL), 92 : requester(NULL),
97 state(content::NUM_MEDIA_STREAM_DEVICE_TYPES, kNotRequested), 93 state(content::NUM_MEDIA_STREAM_DEVICE_TYPES, STATE_NOT_REQUESTED),
98 type(kGenerateStream), 94 type(GENERATE_STREAM),
99 render_process_id(-1), 95 render_process_id(-1),
100 render_view_id(-1) { 96 render_view_id(-1) {
101 options.audio = false; 97 options.audio = false;
102 options.video = false; 98 options.video = false;
103 } 99 }
104 100
105 DeviceRequest(MediaStreamRequester* requester, 101 DeviceRequest(MediaStreamRequester* requester,
106 const StreamOptions& request_options, 102 const StreamOptions& request_options,
107 int render_process_id, 103 int render_process_id,
108 int render_view_id, 104 int render_view_id,
109 const GURL& request_security_origin) 105 const GURL& request_security_origin)
110 : requester(requester), 106 : requester(requester),
111 options(request_options), 107 options(request_options),
112 state(content::NUM_MEDIA_STREAM_DEVICE_TYPES, kNotRequested), 108 state(content::NUM_MEDIA_STREAM_DEVICE_TYPES, STATE_NOT_REQUESTED),
113 type(kGenerateStream), 109 type(GENERATE_STREAM),
114 render_process_id(render_process_id), 110 render_process_id(render_process_id),
115 render_view_id(render_view_id), 111 render_view_id(render_view_id),
116 security_origin(request_security_origin) { 112 security_origin(request_security_origin) {
117 DCHECK(requester); 113 DCHECK(requester);
118 } 114 }
119 115
120 ~DeviceRequest() {} 116 ~DeviceRequest() {}
121 117
122 MediaStreamRequester* requester; 118 MediaStreamRequester* requester;
123 StreamOptions options; 119 StreamOptions options;
124 std::vector<RequestState> state; 120 std::vector<RequestState> state;
125 RequestType type; 121 RequestType type;
126 int render_process_id; 122 int render_process_id;
127 int render_view_id; 123 int render_view_id;
128 GURL security_origin; 124 GURL security_origin;
129 std::string requested_device_id; 125 std::string requested_device_id;
130 StreamDeviceInfoArray audio_devices; 126 StreamDeviceInfoArray audio_devices;
131 StreamDeviceInfoArray video_devices; 127 StreamDeviceInfoArray video_devices;
132 }; 128 };
133 129
130 MediaStreamManager::EnumerationCache::EnumerationCache()
131 : valid(false) {
132 }
133
134 MediaStreamManager::EnumerationCache::~EnumerationCache() {
135 }
136
134 MediaStreamManager::MediaStreamManager( 137 MediaStreamManager::MediaStreamManager(
135 AudioInputDeviceManager* audio_input_device_manager, 138 AudioInputDeviceManager* audio_input_device_manager,
136 VideoCaptureManager* video_capture_manager) 139 VideoCaptureManager* video_capture_manager)
137 : ALLOW_THIS_IN_INITIALIZER_LIST( 140 : ALLOW_THIS_IN_INITIALIZER_LIST(
138 device_settings_(new MediaStreamDeviceSettings(this))), 141 device_settings_(new MediaStreamDeviceSettings(this))),
139 audio_input_device_manager_(audio_input_device_manager), 142 audio_input_device_manager_(audio_input_device_manager),
140 video_capture_manager_(video_capture_manager), 143 video_capture_manager_(video_capture_manager),
141 enumeration_in_progress_(content::NUM_MEDIA_STREAM_DEVICE_TYPES, false), 144 monitoring_started_(false),
145 active_enumeration_ref_count_(),
scherkus (not reviewing) 2012/08/02 22:45:18 does this need to get initialized at all?
wjia(left Chromium) 2012/08/03 21:53:45 yes, it's needed since active_enumeration_ref_coun
142 io_loop_(NULL) { 146 io_loop_(NULL) {
143 } 147 }
144 148
145 MediaStreamManager::~MediaStreamManager() { 149 MediaStreamManager::~MediaStreamManager() {
146 DCHECK(requests_.empty()); 150 DCHECK(requests_.empty());
147 DCHECK(!device_thread_.get()); 151 DCHECK(!device_thread_.get());
148 DCHECK(!io_loop_); 152 DCHECK(!io_loop_);
149 } 153 }
150 154
151 VideoCaptureManager* MediaStreamManager::video_capture_manager() { 155 VideoCaptureManager* MediaStreamManager::video_capture_manager() {
(...skipping 17 matching lines...) Expand all
169 const GURL& security_origin, 173 const GURL& security_origin,
170 std::string* label) { 174 std::string* label) {
171 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 175 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
172 176
173 // Create a new request based on options. 177 // Create a new request based on options.
174 DeviceRequest new_request(requester, options, 178 DeviceRequest new_request(requester, options,
175 render_process_id, 179 render_process_id,
176 render_view_id, 180 render_view_id,
177 security_origin); 181 security_origin);
178 StartEnumeration(&new_request, label); 182 StartEnumeration(&new_request, label);
183
184 // Get user confirmation to use capture devices.
185 // Need to make an asynchronous call to make sure the |requester| gets the
186 // |label| before it would receive any event.
187 BrowserThread::PostTask(BrowserThread::IO,
188 FROM_HERE,
189 base::Bind(&MediaStreamDeviceSettings::RequestCaptureDeviceUsage,
190 base::Unretained(device_settings_.get()),
191 *label, render_process_id,
192 render_view_id, options,
193 security_origin));
179 } 194 }
180 195
181 void MediaStreamManager::CancelRequests(MediaStreamRequester* requester) { 196 void MediaStreamManager::CancelRequests(MediaStreamRequester* requester) {
182 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
183 DeviceRequests::iterator it = requests_.begin(); 198 DeviceRequests::iterator it = requests_.begin();
184 while (it != requests_.end()) { 199 while (it != requests_.end()) {
185 if (it->second.requester == requester && !RequestDone(it->second)) { 200 if (it->second.requester == requester && !RequestDone(it->second)) {
186 // The request isn't complete, but there might be some devices already 201 // The request isn't complete, but there might be some devices already
187 // opened -> close them. 202 // opened -> close them.
188 DeviceRequest* request = &(it->second); 203 DeviceRequest* request = &(it->second);
189 if (request->state[content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE] == 204 if (request->state[content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE] ==
190 DeviceRequest::kOpening) { 205 DeviceRequest::STATE_OPENING) {
191 for (StreamDeviceInfoArray::iterator it = 206 for (StreamDeviceInfoArray::iterator it =
192 request->audio_devices.begin(); it != request->audio_devices.end(); 207 request->audio_devices.begin(); it != request->audio_devices.end();
193 ++it) { 208 ++it) {
194 audio_input_device_manager()->Close(it->session_id); 209 audio_input_device_manager()->Close(it->session_id);
195 } 210 }
196 } 211 }
197 if (request->state[content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE] == 212 if (request->state[content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE] ==
198 DeviceRequest::kOpening) { 213 DeviceRequest::STATE_OPENING) {
199 for (StreamDeviceInfoArray::iterator it = 214 for (StreamDeviceInfoArray::iterator it =
200 request->video_devices.begin(); it != request->video_devices.end(); 215 request->video_devices.begin(); it != request->video_devices.end();
201 ++it) { 216 ++it) {
202 video_capture_manager()->Close(it->session_id); 217 video_capture_manager()->Close(it->session_id);
203 } 218 }
204 } 219 }
205 requests_.erase(it++); 220 requests_.erase(it++);
206 } else { 221 } else {
207 ++it; 222 ++it;
208 } 223 }
209 } 224 }
210 } 225 }
211 226
212 void MediaStreamManager::CancelGenerateStream(const std::string& label) { 227 void MediaStreamManager::CancelGenerateStream(const std::string& label) {
213 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
214 229
215 DeviceRequests::iterator it = requests_.find(label); 230 DeviceRequests::iterator it = requests_.find(label);
216 if (it != requests_.end()) { 231 if (it != requests_.end()) {
217 // The request isn't complete. 232 // The request isn't complete.
218 if (!RequestDone(it->second)) { 233 if (!RequestDone(it->second)) {
219 DeviceRequest* request = &(it->second); 234 DeviceRequest* request = &(it->second);
220 if (request->state[content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE] == 235 if (request->state[content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE] ==
221 DeviceRequest::kOpening) { 236 DeviceRequest::STATE_OPENING) {
222 for (StreamDeviceInfoArray::iterator it = 237 for (StreamDeviceInfoArray::iterator it =
223 request->audio_devices.begin(); it != request->audio_devices.end(); 238 request->audio_devices.begin(); it != request->audio_devices.end();
224 ++it) { 239 ++it) {
225 audio_input_device_manager()->Close(it->session_id); 240 audio_input_device_manager()->Close(it->session_id);
226 } 241 }
227 } 242 }
228 if (request->state[content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE] == 243 if (request->state[content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE] ==
229 DeviceRequest::kOpening) { 244 DeviceRequest::STATE_OPENING) {
230 for (StreamDeviceInfoArray::iterator it = 245 for (StreamDeviceInfoArray::iterator it =
231 request->video_devices.begin(); it != request->video_devices.end(); 246 request->video_devices.begin(); it != request->video_devices.end();
232 ++it) { 247 ++it) {
233 video_capture_manager()->Close(it->session_id); 248 video_capture_manager()->Close(it->session_id);
234 } 249 }
235 } 250 }
236 requests_.erase(it); 251 requests_.erase(it);
237 } else { 252 } else {
238 StopGeneratedStream(label); 253 StopGeneratedStream(label);
239 } 254 }
240 device_settings_->RemovePendingCaptureRequest(label); 255 device_settings_->RemovePendingCaptureRequest(label);
241 } 256 }
242 } 257 }
243 258
244 void MediaStreamManager::StopGeneratedStream(const std::string& label) { 259 void MediaStreamManager::StopGeneratedStream(const std::string& label) {
245 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 260 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
246 // Find the request and close all open devices for the request. 261 // Find the request and close all open devices for the request.
247 DeviceRequests::iterator it = requests_.find(label); 262 DeviceRequests::iterator it = requests_.find(label);
248 if (it != requests_.end()) { 263 if (it != requests_.end()) {
264 if (it->second.type == DeviceRequest::ENUMERATE_DEVICES) {
265 StopEnumerateDevices(label);
266 return;
267 }
249 for (StreamDeviceInfoArray::iterator audio_it = 268 for (StreamDeviceInfoArray::iterator audio_it =
250 it->second.audio_devices.begin(); 269 it->second.audio_devices.begin();
251 audio_it != it->second.audio_devices.end(); ++audio_it) { 270 audio_it != it->second.audio_devices.end(); ++audio_it) {
252 audio_input_device_manager()->Close(audio_it->session_id); 271 audio_input_device_manager()->Close(audio_it->session_id);
253 } 272 }
254 for (StreamDeviceInfoArray::iterator video_it = 273 for (StreamDeviceInfoArray::iterator video_it =
255 it->second.video_devices.begin(); 274 it->second.video_devices.begin();
256 video_it != it->second.video_devices.end(); ++video_it) { 275 video_it != it->second.video_devices.end(); ++video_it) {
257 video_capture_manager()->Close(video_it->session_id); 276 video_capture_manager()->Close(video_it->session_id);
258 } 277 }
259 if (it->second.type == DeviceRequest::kGenerateStream) { 278 if (it->second.type == DeviceRequest::GENERATE_STREAM) {
260 NotifyObserverDevicesClosed(&(it->second)); 279 NotifyObserverDevicesClosed(&(it->second));
261 } 280 }
262 requests_.erase(it); 281 requests_.erase(it);
263 return;
264 } 282 }
265 } 283 }
266 284
267 void MediaStreamManager::EnumerateDevices( 285 void MediaStreamManager::EnumerateDevices(
268 MediaStreamRequester* requester, 286 MediaStreamRequester* requester,
269 int render_process_id, 287 int render_process_id,
270 int render_view_id, 288 int render_view_id,
271 MediaStreamType type, 289 MediaStreamType type,
272 const GURL& security_origin, 290 const GURL& security_origin,
273 std::string* label) { 291 std::string* label) {
274 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 292 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
293 DCHECK(type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE ||
294 type == content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE);
275 295
276 // Create a new request. 296 // Create a new request.
277 StreamOptions options; 297 StreamOptions options;
278 if (type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) 298 EnumerationCache* cache = NULL;
299 if (type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) {
279 options.audio = true; 300 options.audio = true;
280 else 301 cache = &audio_enumeration_cache_;
302 } else {
281 options.video = true; 303 options.video = true;
304 cache = &video_enumeration_cache_;
305 }
282 306
283 DeviceRequest new_request(requester, options, 307 DeviceRequest new_request(requester, options,
284 render_process_id, 308 render_process_id,
285 render_view_id, 309 render_view_id,
286 security_origin); 310 security_origin);
287 new_request.type = DeviceRequest::kEnumerateDevices; 311 new_request.type = DeviceRequest::ENUMERATE_DEVICES;
288 312
289 StartEnumeration(&new_request, label); 313 if (cache->valid) {
314 // Cached device list of this type exists. Just send it out.
315 new_request.state[type] = DeviceRequest::STATE_REQUESTED;
316 AddRequest(&new_request, label);
317 // Need to post a task since the requester won't have label till
318 // this function returns.
319 BrowserThread::PostTask(BrowserThread::IO,
320 FROM_HERE,
321 base::Bind(&MediaStreamManager::SendCachedDeviceList,
322 base::Unretained(this), cache, *label));
323 } else {
324 StartEnumeration(&new_request, label);
325 StartMonitoring();
326 }
327 }
328
329 void MediaStreamManager::StopEnumerateDevices(const std::string& label) {
330 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
331
332 DeviceRequests::iterator it = requests_.find(label);
333 if (it != requests_.end()) {
334 DCHECK_EQ(it->second.type, DeviceRequest::ENUMERATE_DEVICES);
335 requests_.erase(it);
336 if (!HasEnumerationRequest()) {
337 StopMonitoring();
338 }
339 }
290 } 340 }
291 341
292 void MediaStreamManager::OpenDevice( 342 void MediaStreamManager::OpenDevice(
293 MediaStreamRequester* requester, 343 MediaStreamRequester* requester,
294 int render_process_id, 344 int render_process_id,
295 int render_view_id, 345 int render_view_id,
296 const std::string& device_id, 346 const std::string& device_id,
297 MediaStreamType type, 347 MediaStreamType type,
298 const GURL& security_origin, 348 const GURL& security_origin,
299 std::string* label) { 349 std::string* label) {
300 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 350 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
301 351
302 // Create a new request. 352 // Create a new request.
303 StreamOptions options; 353 StreamOptions options;
304 if (type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) 354 if (type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE)
305 options.audio = true; 355 options.audio = true;
306 else 356 else
307 options.video = true; 357 options.video = true;
308 358
309 DeviceRequest new_request(requester, options, 359 DeviceRequest new_request(requester, options,
310 render_process_id, 360 render_process_id,
311 render_view_id, 361 render_view_id,
312 security_origin); 362 security_origin);
313 new_request.type = DeviceRequest::kOpenDevice; 363 new_request.type = DeviceRequest::OPEN_DEVICE;
314 new_request.requested_device_id = device_id; 364 new_request.requested_device_id = device_id;
315 365
316 StartEnumeration(&new_request, label); 366 StartEnumeration(&new_request, label);
317 } 367 }
318 368
369 void MediaStreamManager::SendCachedDeviceList(
370 EnumerationCache* cache,
371 const std::string& label) {
372 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
373 if (cache->valid) {
374 DeviceRequests::iterator it = requests_.find(label);
375 if (it != requests_.end()) {
376 it->second.requester->DevicesEnumerated(label, cache->devices);
377 }
378 }
379 }
380
381 void MediaStreamManager::StartMonitoring() {
382 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
383 if (!monitoring_started_) {
384 monitoring_started_ = true;
385 base::SystemMonitor::Get()->AddDevicesChangedObserver(this);
386 }
387 }
388
389 void MediaStreamManager::StopMonitoring() {
390 DCHECK_EQ(MessageLoop::current(), io_loop_);
391 if (monitoring_started_ && !HasEnumerationRequest()) {
392 base::SystemMonitor::Get()->RemoveDevicesChangedObserver(this);
393 monitoring_started_ = false;
394 ClearEnumerationCache(&audio_enumeration_cache_);
395 ClearEnumerationCache(&video_enumeration_cache_);
396 }
397 }
398
399 void MediaStreamManager::ClearEnumerationCache(EnumerationCache* cache) {
400 DCHECK_EQ(MessageLoop::current(), io_loop_);
401 cache->valid = false;
402 }
403
319 void MediaStreamManager::StartEnumeration( 404 void MediaStreamManager::StartEnumeration(
320 DeviceRequest* new_request, 405 DeviceRequest* new_request,
321 std::string* label) { 406 std::string* label) {
322 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 407 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
323 408
324 MediaStreamType stream_type = content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE; 409 MediaStreamType stream_type = content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE;
325 if (Requested(new_request->options, stream_type)) { 410 if (Requested(new_request->options, stream_type)) {
326 new_request->state[stream_type] = DeviceRequest::kRequested; 411 new_request->state[stream_type] = DeviceRequest::STATE_REQUESTED;
327 if (!enumeration_in_progress_[stream_type]) { 412 DCHECK_GE(active_enumeration_ref_count_[stream_type], 0);
328 enumeration_in_progress_[stream_type] = true; 413 if (!active_enumeration_ref_count_[stream_type]) {
414 ++active_enumeration_ref_count_[stream_type];
329 GetDeviceManager(stream_type)->EnumerateDevices(); 415 GetDeviceManager(stream_type)->EnumerateDevices();
330 } 416 }
331 } 417 }
332 stream_type = content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE; 418 stream_type = content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE;
333 if (Requested(new_request->options, stream_type)) { 419 if (Requested(new_request->options, stream_type)) {
334 new_request->state[stream_type] = DeviceRequest::kRequested; 420 new_request->state[stream_type] = DeviceRequest::STATE_REQUESTED;
335 if (!enumeration_in_progress_[stream_type]) { 421 DCHECK_GE(active_enumeration_ref_count_[stream_type], 0);
336 enumeration_in_progress_[stream_type] = true; 422 if (!active_enumeration_ref_count_[stream_type]) {
423 ++active_enumeration_ref_count_[stream_type];
337 GetDeviceManager(stream_type)->EnumerateDevices(); 424 GetDeviceManager(stream_type)->EnumerateDevices();
338 } 425 }
339 } 426 }
340 427
428 AddRequest(new_request, label);
429 }
430
431 void MediaStreamManager::AddRequest(
432 DeviceRequest* new_request,
433 std::string* label) {
434 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
435
341 // Create a label for this request and verify it is unique. 436 // Create a label for this request and verify it is unique.
342 std::string request_label; 437 std::string request_label;
343 do { 438 do {
344 request_label = RandomLabel(); 439 request_label = RandomLabel();
345 } while (requests_.find(request_label) != requests_.end()); 440 } while (requests_.find(request_label) != requests_.end());
346 441
347 requests_.insert(std::make_pair(request_label, *new_request)); 442 requests_.insert(std::make_pair(request_label, *new_request));
348 443
349 // Get user confirmation to use capture devices.
350 // Need to make an asynchronous call to make sure the |requester| gets the
351 // |label| before it would receive any event.
352 if (new_request->type == DeviceRequest::kGenerateStream) {
353 BrowserThread::PostTask(BrowserThread::IO,
354 FROM_HERE,
355 base::Bind(&MediaStreamDeviceSettings::RequestCaptureDeviceUsage,
356 base::Unretained(device_settings_.get()),
357 request_label, new_request->render_process_id,
358 new_request->render_view_id, new_request->options,
359 new_request->security_origin));
360 }
361
362 (*label) = request_label; 444 (*label) = request_label;
363 } 445 }
364 446
365 void MediaStreamManager::EnsureDeviceThreadAndListener() { 447 void MediaStreamManager::EnsureDeviceThreadAndListener() {
366 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 448 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
367 if (device_thread_.get()) 449 if (device_thread_.get())
368 return; 450 return;
369 451
370 device_thread_.reset(new DeviceThread("MediaStreamDeviceThread")); 452 device_thread_.reset(new DeviceThread("MediaStreamDeviceThread"));
371 CHECK(device_thread_->Start()); 453 CHECK(device_thread_->Start());
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 request = &(request_it->second); 489 request = &(request_it->second);
408 break; 490 break;
409 } 491 }
410 } 492 }
411 } 493 }
412 if (request == NULL) { 494 if (request == NULL) {
413 // The request doesn't exist. 495 // The request doesn't exist.
414 return; 496 return;
415 } 497 }
416 498
417 DCHECK_NE(request->state[stream_type], DeviceRequest::kRequested); 499 DCHECK_NE(request->state[stream_type], DeviceRequest::STATE_REQUESTED);
418 500
419 // Check if all devices for this stream type are opened. Update the state if 501 // Check if all devices for this stream type are opened. Update the state if
420 // they are. 502 // they are.
421 for (StreamDeviceInfoArray::iterator device_it = devices->begin(); 503 for (StreamDeviceInfoArray::iterator device_it = devices->begin();
422 device_it != devices->end(); ++device_it) { 504 device_it != devices->end(); ++device_it) {
423 if (device_it->in_use == false) { 505 if (device_it->in_use == false) {
424 // Wait for more devices to be opened before we're done. 506 // Wait for more devices to be opened before we're done.
425 return; 507 return;
426 } 508 }
427 } 509 }
428 request->state[stream_type] = DeviceRequest::kDone; 510 request->state[stream_type] = DeviceRequest::STATE_DONE;
429 511
430 if (!RequestDone(*request)) { 512 if (!RequestDone(*request)) {
431 // This stream_type is done, but not the other type. 513 // This stream_type is done, but not the other type.
432 return; 514 return;
433 } 515 }
434 516
435 switch (request->type) { 517 switch (request->type) {
436 case DeviceRequest::kOpenDevice: 518 case DeviceRequest::OPEN_DEVICE:
437 request->requester->DeviceOpened(label, (*devices)[0]); 519 request->requester->DeviceOpened(label, (*devices)[0]);
438 break; 520 break;
439 case DeviceRequest::kGenerateStream: 521 case DeviceRequest::GENERATE_STREAM:
440 request->requester->StreamGenerated(label, request->audio_devices, 522 request->requester->StreamGenerated(label, request->audio_devices,
441 request->video_devices); 523 request->video_devices);
442 NotifyObserverDevicesOpened(request); 524 NotifyObserverDevicesOpened(request);
443 break; 525 break;
444 default: 526 default:
445 NOTREACHED(); 527 NOTREACHED();
446 } 528 }
447 } 529 }
448 530
449 void MediaStreamManager::Closed(MediaStreamType stream_type, 531 void MediaStreamManager::Closed(MediaStreamType stream_type,
450 int capture_session_id) { 532 int capture_session_id) {
451 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 533 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
452 } 534 }
453 535
454 void MediaStreamManager::DevicesEnumerated( 536 void MediaStreamManager::DevicesEnumerated(
455 MediaStreamType stream_type, const StreamDeviceInfoArray& devices) { 537 MediaStreamType stream_type, const StreamDeviceInfoArray& devices) {
456 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 538 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
457 539
540 // Only cache device list when there is EnumerateDevices request, since
541 // other requests don't turn on device monitoring.
542 bool need_update_clients = false;
543 EnumerationCache* cache =
544 (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE ?
545 &audio_enumeration_cache_ : &video_enumeration_cache_);
546 if (HasEnumerationRequest(stream_type) &&
547 (!cache->valid || cache->devices != devices)) {
548 cache->valid = true;
549 cache->devices = devices;
550 need_update_clients = true;
551 }
552
458 // Publish the result for all requests waiting for device list(s). 553 // Publish the result for all requests waiting for device list(s).
459 // Find the requests waiting for this device list, store their labels and 554 // Find the requests waiting for this device list, store their labels and
460 // release the iterator before calling device settings. We might get a call 555 // release the iterator before calling device settings. We might get a call
461 // back from device_settings that will need to iterate through devices. 556 // back from device_settings that will need to iterate through devices.
462 std::list<std::string> label_list; 557 std::list<std::string> label_list;
463 for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end(); 558 for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end();
464 ++it) { 559 ++it) {
465 if (it->second.state[stream_type] == DeviceRequest::kRequested && 560 if (it->second.state[stream_type] == DeviceRequest::STATE_REQUESTED &&
466 Requested(it->second.options, stream_type)) { 561 Requested(it->second.options, stream_type)) {
467 it->second.state[stream_type] = DeviceRequest::kPendingApproval; 562 if (it->second.type != DeviceRequest::ENUMERATE_DEVICES)
563 it->second.state[stream_type] = DeviceRequest::STATE_PENDING_APPROVAL;
468 label_list.push_back(it->first); 564 label_list.push_back(it->first);
469 } 565 }
470 } 566 }
471 for (std::list<std::string>::iterator it = label_list.begin(); 567 for (std::list<std::string>::iterator it = label_list.begin();
472 it != label_list.end(); ++it) { 568 it != label_list.end(); ++it) {
473 DeviceRequest& request = requests_[*it]; 569 DeviceRequest& request = requests_[*it];
474 switch (request.type) { 570 switch (request.type) {
475 case DeviceRequest::kEnumerateDevices: 571 case DeviceRequest::ENUMERATE_DEVICES:
476 request.requester->DevicesEnumerated(*it, devices); 572 if (need_update_clients)
477 requests_.erase(*it); 573 request.requester->DevicesEnumerated(*it, devices);
478 break; 574 break;
479 case DeviceRequest::kOpenDevice: 575 case DeviceRequest::OPEN_DEVICE:
480 for (StreamDeviceInfoArray::const_iterator device_it = devices.begin(); 576 for (StreamDeviceInfoArray::const_iterator device_it = devices.begin();
481 device_it != devices.end(); device_it++) { 577 device_it != devices.end(); device_it++) {
482 if (request.requested_device_id == device_it->device_id) { 578 if (request.requested_device_id == device_it->device_id) {
483 StreamDeviceInfo device = *device_it; 579 StreamDeviceInfo device = *device_it;
484 device.in_use = false; 580 device.in_use = false;
485 device.session_id = 581 device.session_id =
486 GetDeviceManager(device_it->stream_type)->Open(device); 582 GetDeviceManager(device_it->stream_type)->Open(device);
487 request.state[device_it->stream_type] = DeviceRequest::kOpening; 583 request.state[device_it->stream_type] =
584 DeviceRequest::STATE_OPENING;
488 if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) 585 if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE)
489 request.audio_devices.push_back(device); 586 request.audio_devices.push_back(device);
490 else 587 else
491 request.video_devices.push_back(device); 588 request.video_devices.push_back(device);
492 break; 589 break;
493 } 590 }
494 } 591 }
495 break; 592 break;
496 default: 593 default:
497 BrowserThread::PostTask(BrowserThread::IO, 594 BrowserThread::PostTask(BrowserThread::IO,
498 FROM_HERE, 595 FROM_HERE,
499 base::Bind(&MediaStreamDeviceSettings::AvailableDevices, 596 base::Bind(&MediaStreamDeviceSettings::AvailableDevices,
500 base::Unretained(device_settings_.get()), 597 base::Unretained(device_settings_.get()),
501 *it, stream_type, devices)); 598 *it, stream_type, devices));
502 } 599 }
503 } 600 }
504 label_list.clear(); 601 label_list.clear();
505 enumeration_in_progress_[stream_type] = false; 602 --active_enumeration_ref_count_[stream_type];
603 DCHECK_GE(active_enumeration_ref_count_[stream_type], 0);
506 } 604 }
507 605
508 void MediaStreamManager::Error(MediaStreamType stream_type, 606 void MediaStreamManager::Error(MediaStreamType stream_type,
509 int capture_session_id, 607 int capture_session_id,
510 MediaStreamProviderError error) { 608 MediaStreamProviderError error) {
511 // Find the device for the error call. 609 // Find the device for the error call.
512 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 610 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
513 for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end(); 611 for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end();
514 ++it) { 612 ++it) {
515 StreamDeviceInfoArray* devices = NULL; 613 StreamDeviceInfoArray* devices = NULL;
516 if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) { 614 if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) {
517 devices = &(it->second.audio_devices); 615 devices = &(it->second.audio_devices);
518 } else if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) { 616 } else if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) {
519 devices = &(it->second.video_devices); 617 devices = &(it->second.video_devices);
520 } else { 618 } else {
521 NOTREACHED(); 619 NOTREACHED();
522 } 620 }
523 621
524 int device_idx = 0; 622 int device_idx = 0;
525 for (StreamDeviceInfoArray::iterator device_it = devices->begin(); 623 for (StreamDeviceInfoArray::iterator device_it = devices->begin();
526 device_it != devices->end(); ++device_it, ++device_idx) { 624 device_it != devices->end(); ++device_it, ++device_idx) {
527 if (device_it->session_id == capture_session_id) { 625 if (device_it->session_id == capture_session_id) {
528 // We've found the failing device. Find the error case: 626 // We've found the failing device. Find the error case:
529 if (it->second.state[stream_type] == DeviceRequest::kDone) { 627 if (it->second.state[stream_type] == DeviceRequest::STATE_DONE) {
530 // 1. Already opened -> signal device failure and close device. 628 // 1. Already opened -> signal device failure and close device.
531 // Use device_idx to signal which of the devices encountered an 629 // Use device_idx to signal which of the devices encountered an
532 // error. 630 // error.
533 if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) { 631 if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) {
534 it->second.requester->AudioDeviceFailed(it->first, device_idx); 632 it->second.requester->AudioDeviceFailed(it->first, device_idx);
535 } else if (stream_type == 633 } else if (stream_type ==
536 content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) { 634 content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) {
537 it->second.requester->VideoDeviceFailed(it->first, device_idx); 635 it->second.requester->VideoDeviceFailed(it->first, device_idx);
538 } 636 }
539 GetDeviceManager(stream_type)->Close(capture_session_id); 637 GetDeviceManager(stream_type)->Close(capture_session_id);
(...skipping 29 matching lines...) Expand all
569 667
570 // Loop through all device types for this request. 668 // Loop through all device types for this request.
571 for (StreamDeviceInfoArray::const_iterator device_it = devices.begin(); 669 for (StreamDeviceInfoArray::const_iterator device_it = devices.begin();
572 device_it != devices.end(); ++device_it) { 670 device_it != devices.end(); ++device_it) {
573 StreamDeviceInfo device_info = *device_it; 671 StreamDeviceInfo device_info = *device_it;
574 672
575 // Set in_use to false to be able to track if this device has been 673 // Set in_use to false to be able to track if this device has been
576 // opened. in_use might be true if the device type can be used in more 674 // opened. in_use might be true if the device type can be used in more
577 // than one session. 675 // than one session.
578 DCHECK_EQ(request_it->second.state[device_it->stream_type], 676 DCHECK_EQ(request_it->second.state[device_it->stream_type],
579 DeviceRequest::kPendingApproval); 677 DeviceRequest::STATE_PENDING_APPROVAL);
580 device_info.in_use = false; 678 device_info.in_use = false;
581 device_info.session_id = 679 device_info.session_id =
582 GetDeviceManager(device_info.stream_type)->Open(device_info); 680 GetDeviceManager(device_info.stream_type)->Open(device_info);
583 request_it->second.state[device_it->stream_type] = 681 request_it->second.state[device_it->stream_type] =
584 DeviceRequest::kOpening; 682 DeviceRequest::STATE_OPENING;
585 if (device_info.stream_type == 683 if (device_info.stream_type ==
586 content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) { 684 content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) {
587 request_it->second.audio_devices.push_back(device_info); 685 request_it->second.audio_devices.push_back(device_info);
588 } else if (device_info.stream_type == 686 } else if (device_info.stream_type ==
589 content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) { 687 content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) {
590 request_it->second.video_devices.push_back(device_info); 688 request_it->second.video_devices.push_back(device_info);
591 } else { 689 } else {
592 NOTREACHED(); 690 NOTREACHED();
593 } 691 }
594 } 692 }
595 // Check if we received all stream types requested. 693 // Check if we received all stream types requested.
596 MediaStreamType stream_type = 694 MediaStreamType stream_type =
597 content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE; 695 content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE;
598 if (Requested(request_it->second.options, stream_type) && 696 if (Requested(request_it->second.options, stream_type) &&
599 request_it->second.audio_devices.size() == 0) { 697 request_it->second.audio_devices.size() == 0) {
600 request_it->second.state[stream_type] = DeviceRequest::kError; 698 request_it->second.state[stream_type] = DeviceRequest::STATE_ERROR;
601 } 699 }
602 stream_type = content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE; 700 stream_type = content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE;
603 if (Requested(request_it->second.options, stream_type) && 701 if (Requested(request_it->second.options, stream_type) &&
604 request_it->second.video_devices.size() == 0) { 702 request_it->second.video_devices.size() == 0) {
605 request_it->second.state[stream_type] = DeviceRequest::kError; 703 request_it->second.state[stream_type] = DeviceRequest::STATE_ERROR;
606 } 704 }
607 return; 705 return;
608 } 706 }
609 } 707 }
610 708
611 void MediaStreamManager::SettingsError(const std::string& label) { 709 void MediaStreamManager::SettingsError(const std::string& label) {
612 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 710 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
613 // Erase this request and report an error. 711 // Erase this request and report an error.
614 DeviceRequests::iterator it = requests_.find(label); 712 DeviceRequests::iterator it = requests_.find(label);
615 if (it != requests_.end()) { 713 if (it != requests_.end()) {
616 DCHECK_EQ(it->second.type, DeviceRequest::kGenerateStream); 714 DCHECK_EQ(it->second.type, DeviceRequest::GENERATE_STREAM);
617 it->second.requester->StreamGenerationFailed(label); 715 it->second.requester->StreamGenerationFailed(label);
618 requests_.erase(it); 716 requests_.erase(it);
619 return; 717 return;
620 } 718 }
621 } 719 }
622 720
623 void MediaStreamManager::UseFakeDevice() { 721 void MediaStreamManager::UseFakeDevice() {
624 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 722 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
625 video_capture_manager()->UseFakeDevice(); 723 video_capture_manager()->UseFakeDevice();
626 device_settings_->UseFakeUI(); 724 device_settings_->UseFakeUI();
627 } 725 }
628 726
629 void MediaStreamManager::WillDestroyCurrentMessageLoop() { 727 void MediaStreamManager::WillDestroyCurrentMessageLoop() {
630 DCHECK_EQ(MessageLoop::current(), io_loop_); 728 DCHECK_EQ(MessageLoop::current(), io_loop_);
729 DCHECK(requests_.empty());
631 if (device_thread_.get()) { 730 if (device_thread_.get()) {
731 StopMonitoring();
732
632 video_capture_manager_->Unregister(); 733 video_capture_manager_->Unregister();
633 audio_input_device_manager_->Unregister(); 734 audio_input_device_manager_->Unregister();
634 device_thread_.reset(); 735 device_thread_.reset();
635 } 736 }
636 737
637 audio_input_device_manager_ = NULL; 738 audio_input_device_manager_ = NULL;
638 video_capture_manager_ = NULL; 739 video_capture_manager_ = NULL;
639 io_loop_ = NULL; 740 io_loop_ = NULL;
640 device_settings_.reset(); 741 device_settings_.reset();
641 } 742 }
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
714 MediaStreamType stream_type) { 815 MediaStreamType stream_type) {
715 if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) { 816 if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) {
716 return video_capture_manager(); 817 return video_capture_manager();
717 } else if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) { 818 } else if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) {
718 return audio_input_device_manager(); 819 return audio_input_device_manager();
719 } 820 }
720 NOTREACHED(); 821 NOTREACHED();
721 return NULL; 822 return NULL;
722 } 823 }
723 824
825 void MediaStreamManager::OnDevicesChanged(
826 base::SystemMonitor::DeviceType device_type) {
827 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
828 MediaStreamType stream_type;
829 EnumerationCache* cache;
830 if (device_type == base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE) {
831 stream_type = content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE;
832 cache = &audio_enumeration_cache_;
833 } else if (device_type == base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE) {
834 stream_type = content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE;
835 cache = &video_enumeration_cache_;
836 } else {
837 return; // Uninteresting device change.
838 }
839
840 if (!HasEnumerationRequest(stream_type)) {
841 // There is no request for that type, No need to enumerate devices.
842 // Therefore, invalidate the cache of that type.
843 ClearEnumerationCache(cache);
scherkus (not reviewing) 2012/08/02 22:45:18 nit: early return where possible
wjia(left Chromium) 2012/08/03 21:53:45 Done.
844 } else {
845 // Always do enumeration even though some enumeration is in progress,
846 // because those enumeration commands could be sent before this devices
scherkus (not reviewing) 2012/08/02 22:45:18 s/this/these
wjia(left Chromium) 2012/08/03 21:53:45 Done.
847 // change.
848 ++active_enumeration_ref_count_[stream_type];
849 GetDeviceManager(stream_type)->EnumerateDevices();
850 }
851 }
852
853 bool MediaStreamManager::HasEnumerationRequest() {
854 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
855 for (DeviceRequests::iterator it = requests_.begin();
856 it != requests_.end(); ++it) {
857 if (it->second.type == DeviceRequest::ENUMERATE_DEVICES) {
858 return true;
859 }
860 }
861 return false;
862 }
863
864 bool MediaStreamManager::HasEnumerationRequest(
865 MediaStreamType stream_type) {
866 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
867 for (DeviceRequests::iterator it = requests_.begin();
868 it != requests_.end(); ++it) {
869 if (it->second.type == DeviceRequest::ENUMERATE_DEVICES &&
870 Requested(it->second.options, stream_type)) {
871 return true;
872 }
873 }
874 return false;
875 }
876
724 } // namespace media_stream 877 } // namespace media_stream
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698