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

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

Powered by Google App Engine
This is Rietveld 408576698