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

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

Powered by Google App Engine
This is Rietveld 408576698