OLD | NEW |
---|---|
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" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/rand_util.h" | 12 #include "base/rand_util.h" |
13 #include "base/win/scoped_com_initializer.h" | 13 #include "base/win/scoped_com_initializer.h" |
14 #include "content/browser/browser_main_loop.h" | |
14 #include "content/browser/renderer_host/media/audio_input_device_manager.h" | 15 #include "content/browser/renderer_host/media/audio_input_device_manager.h" |
15 #include "content/browser/renderer_host/media/media_stream_device_settings.h" | 16 #include "content/browser/renderer_host/media/media_stream_device_settings.h" |
16 #include "content/browser/renderer_host/media/media_stream_requester.h" | 17 #include "content/browser/renderer_host/media/media_stream_requester.h" |
17 #include "content/browser/renderer_host/media/video_capture_manager.h" | 18 #include "content/browser/renderer_host/media/video_capture_manager.h" |
18 #include "content/common/media/media_stream_options.h" | 19 #include "content/common/media/media_stream_options.h" |
19 #include "content/public/browser/browser_thread.h" | 20 #include "content/public/browser/browser_thread.h" |
20 #include "content/public/browser/content_browser_client.h" | 21 #include "content/public/browser/content_browser_client.h" |
21 #include "content/public/browser/media_observer.h" | 22 #include "content/public/browser/media_observer.h" |
22 #include "googleurl/src/gurl.h" | 23 #include "googleurl/src/gurl.h" |
23 | 24 |
(...skipping 16 matching lines...) Expand all Loading... | |
40 for (size_t i = 0; i < label.size(); ++i) { | 41 for (size_t i = 0; i < label.size(); ++i) { |
41 int random_char = base::RandGenerator(sizeof(kAlphabet) - 1); | 42 int random_char = base::RandGenerator(sizeof(kAlphabet) - 1); |
42 label[i] = kAlphabet[random_char]; | 43 label[i] = kAlphabet[random_char]; |
43 } | 44 } |
44 return label; | 45 return label; |
45 } | 46 } |
46 | 47 |
47 // Helper to verify if a media stream type is part of options or not. | 48 // Helper to verify if a media stream type is part of options or not. |
48 static bool Requested(const StreamOptions& options, | 49 static bool Requested(const StreamOptions& options, |
49 MediaStreamType stream_type) { | 50 MediaStreamType stream_type) { |
50 return (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE && | 51 return (options.audio_type == stream_type || |
51 options.video) || | 52 options.video_type == stream_type); |
52 (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE && | |
53 options.audio); | |
54 } | 53 } |
55 | 54 |
56 DeviceThread::DeviceThread(const char* name) | 55 DeviceThread::DeviceThread(const char* name) |
57 : base::Thread(name) { | 56 : base::Thread(name) { |
58 } | 57 } |
59 | 58 |
60 DeviceThread::~DeviceThread() { | 59 DeviceThread::~DeviceThread() { |
61 Stop(); | 60 Stop(); |
62 } | 61 } |
63 | 62 |
(...skipping 19 matching lines...) Expand all Loading... | |
83 }; | 82 }; |
84 | 83 |
85 enum RequestType { | 84 enum RequestType { |
86 GENERATE_STREAM = 0, | 85 GENERATE_STREAM = 0, |
87 ENUMERATE_DEVICES, | 86 ENUMERATE_DEVICES, |
88 OPEN_DEVICE | 87 OPEN_DEVICE |
89 }; | 88 }; |
90 | 89 |
91 DeviceRequest() | 90 DeviceRequest() |
92 : requester(NULL), | 91 : requester(NULL), |
93 state(content::NUM_MEDIA_STREAM_DEVICE_TYPES, STATE_NOT_REQUESTED), | 92 state(content::NUM_MEDIA_TYPES, STATE_NOT_REQUESTED), |
94 type(GENERATE_STREAM), | 93 type(GENERATE_STREAM), |
95 render_process_id(-1), | 94 render_process_id(-1), |
96 render_view_id(-1) { | 95 render_view_id(-1) { |
97 options.audio = false; | |
98 options.video = false; | |
99 } | 96 } |
100 | 97 |
101 DeviceRequest(MediaStreamRequester* requester, | 98 DeviceRequest(MediaStreamRequester* requester, |
102 const StreamOptions& request_options, | 99 const StreamOptions& request_options, |
103 int render_process_id, | 100 int render_process_id, |
104 int render_view_id, | 101 int render_view_id, |
105 const GURL& request_security_origin) | 102 const GURL& request_security_origin) |
106 : requester(requester), | 103 : requester(requester), |
107 options(request_options), | 104 options(request_options), |
108 state(content::NUM_MEDIA_STREAM_DEVICE_TYPES, STATE_NOT_REQUESTED), | 105 state(content::NUM_MEDIA_TYPES, STATE_NOT_REQUESTED), |
109 type(GENERATE_STREAM), | 106 type(GENERATE_STREAM), |
110 render_process_id(render_process_id), | 107 render_process_id(render_process_id), |
111 render_view_id(render_view_id), | 108 render_view_id(render_view_id), |
112 security_origin(request_security_origin) { | 109 security_origin(request_security_origin) { |
113 DCHECK(requester); | 110 DCHECK(requester); |
114 } | 111 } |
115 | 112 |
116 ~DeviceRequest() {} | 113 ~DeviceRequest() {} |
117 | 114 |
118 MediaStreamRequester* requester; | 115 MediaStreamRequester* requester; |
119 StreamOptions options; | 116 StreamOptions options; |
120 std::vector<RequestState> state; | 117 std::vector<RequestState> state; |
121 RequestType type; | 118 RequestType type; |
122 int render_process_id; | 119 int render_process_id; |
123 int render_view_id; | 120 int render_view_id; |
124 GURL security_origin; | 121 GURL security_origin; |
125 std::string requested_device_id; | 122 StreamDeviceInfoArray devices; |
126 StreamDeviceInfoArray audio_devices; | |
127 StreamDeviceInfoArray video_devices; | |
128 }; | 123 }; |
129 | 124 |
130 MediaStreamManager::EnumerationCache::EnumerationCache() | 125 MediaStreamManager::EnumerationCache::EnumerationCache() |
131 : valid(false) { | 126 : valid(false) { |
132 } | 127 } |
133 | 128 |
134 MediaStreamManager::EnumerationCache::~EnumerationCache() { | 129 MediaStreamManager::EnumerationCache::~EnumerationCache() { |
135 } | 130 } |
136 | 131 |
137 MediaStreamManager::MediaStreamManager( | 132 MediaStreamManager::MediaStreamManager() |
138 AudioInputDeviceManager* audio_input_device_manager, | |
139 VideoCaptureManager* video_capture_manager) | |
140 : ALLOW_THIS_IN_INITIALIZER_LIST( | 133 : ALLOW_THIS_IN_INITIALIZER_LIST( |
141 device_settings_(new MediaStreamDeviceSettings(this))), | 134 device_settings_(new MediaStreamDeviceSettings(this))), |
142 audio_input_device_manager_(audio_input_device_manager), | 135 audio_manager_(NULL), |
143 video_capture_manager_(video_capture_manager), | |
144 monitoring_started_(false), | 136 monitoring_started_(false), |
145 io_loop_(NULL) { | 137 io_loop_(NULL) { |
146 memset(active_enumeration_ref_count_, 0, | 138 memset(active_enumeration_ref_count_, 0, |
147 sizeof(active_enumeration_ref_count_)); | 139 sizeof(active_enumeration_ref_count_)); |
148 } | 140 } |
149 | 141 |
150 MediaStreamManager::~MediaStreamManager() { | 142 MediaStreamManager::~MediaStreamManager() { |
151 DCHECK(requests_.empty()); | 143 DCHECK(requests_.empty()); |
152 DCHECK(!device_thread_.get()); | 144 DCHECK(!device_thread_.get()); |
153 DCHECK(!io_loop_); | 145 DCHECK(!io_loop_); |
154 } | 146 } |
155 | 147 |
156 VideoCaptureManager* MediaStreamManager::video_capture_manager() { | |
157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
158 DCHECK(video_capture_manager_); | |
159 EnsureDeviceThreadAndListener(); | |
160 return video_capture_manager_; | |
161 } | |
162 | |
163 AudioInputDeviceManager* MediaStreamManager::audio_input_device_manager() { | |
164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
165 DCHECK(audio_input_device_manager_); | |
166 EnsureDeviceThreadAndListener(); | |
167 return audio_input_device_manager_; | |
168 } | |
169 | |
170 void MediaStreamManager::GenerateStream(MediaStreamRequester* requester, | 148 void MediaStreamManager::GenerateStream(MediaStreamRequester* requester, |
171 int render_process_id, | 149 int render_process_id, |
172 int render_view_id, | 150 int render_view_id, |
173 const StreamOptions& options, | 151 const StreamOptions& options, |
174 const GURL& security_origin, | 152 const GURL& security_origin, |
175 std::string* label) { | 153 std::string* label) { |
176 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 154 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
177 | 155 |
178 // Create a new request based on options. | 156 // Create a new request based on options. |
179 DeviceRequest new_request(requester, options, | 157 DeviceRequest new_request(requester, options, |
(...skipping 10 matching lines...) Expand all Loading... | |
190 security_origin); | 168 security_origin); |
191 } | 169 } |
192 | 170 |
193 void MediaStreamManager::CancelGenerateStream(const std::string& label) { | 171 void MediaStreamManager::CancelGenerateStream(const std::string& label) { |
194 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
195 | 173 |
196 DeviceRequests::iterator it = requests_.find(label); | 174 DeviceRequests::iterator it = requests_.find(label); |
197 if (it != requests_.end()) { | 175 if (it != requests_.end()) { |
198 // The request isn't complete. | 176 // The request isn't complete. |
199 if (!RequestDone(it->second)) { | 177 if (!RequestDone(it->second)) { |
200 DeviceRequest* request = &(it->second); | 178 DeviceRequest& request = it->second; |
201 if (request->state[content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE] == | 179 for (int i = content::MEDIA_NO_SERVICE + 1; i < content::NUM_MEDIA_TYPES; |
202 DeviceRequest::STATE_OPENING) { | 180 ++i) { |
203 for (StreamDeviceInfoArray::iterator it = | 181 const MediaStreamType stream_type = static_cast<MediaStreamType>(i); |
204 request->audio_devices.begin(); it != request->audio_devices.end(); | 182 if (request.state[stream_type] != DeviceRequest::STATE_OPENING) { |
205 ++it) { | 183 continue; |
206 audio_input_device_manager()->Close(it->session_id); | |
207 } | 184 } |
208 } | 185 for (StreamDeviceInfoArray::const_iterator device_it = |
209 if (request->state[content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE] == | 186 request.devices.begin(); |
210 DeviceRequest::STATE_OPENING) { | 187 device_it != request.devices.end(); ++device_it) { |
211 for (StreamDeviceInfoArray::iterator it = | 188 if (device_it->stream_type == stream_type) { |
212 request->video_devices.begin(); it != request->video_devices.end(); | 189 GetDeviceManager(stream_type)->Close(device_it->session_id); |
213 ++it) { | 190 } |
214 video_capture_manager()->Close(it->session_id); | |
215 } | 191 } |
216 } | 192 } |
217 requests_.erase(it); | 193 requests_.erase(it); |
218 } else { | 194 } else { |
219 StopGeneratedStream(label); | 195 StopGeneratedStream(label); |
220 } | 196 } |
221 device_settings_->RemovePendingCaptureRequest(label); | 197 device_settings_->RemovePendingCaptureRequest(label); |
222 } | 198 } |
223 } | 199 } |
224 | 200 |
225 void MediaStreamManager::StopGeneratedStream(const std::string& label) { | 201 void MediaStreamManager::StopGeneratedStream(const std::string& label) { |
226 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 202 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
227 // Find the request and close all open devices for the request. | 203 // Find the request and close all open devices for the request. |
228 DeviceRequests::iterator it = requests_.find(label); | 204 DeviceRequests::iterator it = requests_.find(label); |
229 if (it != requests_.end()) { | 205 if (it != requests_.end()) { |
230 if (it->second.type == DeviceRequest::ENUMERATE_DEVICES) { | 206 if (it->second.type == DeviceRequest::ENUMERATE_DEVICES) { |
231 StopEnumerateDevices(label); | 207 StopEnumerateDevices(label); |
232 return; | 208 return; |
233 } | 209 } |
234 for (StreamDeviceInfoArray::iterator audio_it = | 210 for (StreamDeviceInfoArray::const_iterator device_it = |
235 it->second.audio_devices.begin(); | 211 it->second.devices.begin(); |
236 audio_it != it->second.audio_devices.end(); ++audio_it) { | 212 device_it != it->second.devices.end(); ++device_it) { |
237 audio_input_device_manager()->Close(audio_it->session_id); | 213 GetDeviceManager(device_it->stream_type)->Close(device_it->session_id); |
238 } | |
239 for (StreamDeviceInfoArray::iterator video_it = | |
240 it->second.video_devices.begin(); | |
241 video_it != it->second.video_devices.end(); ++video_it) { | |
242 video_capture_manager()->Close(video_it->session_id); | |
243 } | 214 } |
244 if (it->second.type == DeviceRequest::GENERATE_STREAM && | 215 if (it->second.type == DeviceRequest::GENERATE_STREAM && |
245 RequestDone(it->second)) { | 216 RequestDone(it->second)) { |
246 NotifyObserverDevicesClosed(&(it->second)); | 217 NotifyObserverDevicesClosed(&(it->second)); |
247 } | 218 } |
248 requests_.erase(it); | 219 requests_.erase(it); |
249 } | 220 } |
250 } | 221 } |
251 | 222 |
252 void MediaStreamManager::EnumerateDevices( | 223 void MediaStreamManager::EnumerateDevices( |
253 MediaStreamRequester* requester, | 224 MediaStreamRequester* requester, |
254 int render_process_id, | 225 int render_process_id, |
255 int render_view_id, | 226 int render_view_id, |
256 MediaStreamType type, | 227 MediaStreamType type, |
257 const GURL& security_origin, | 228 const GURL& security_origin, |
258 std::string* label) { | 229 std::string* label) { |
259 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 230 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
260 DCHECK(type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE || | 231 DCHECK_LT(content::MEDIA_NO_SERVICE, type); |
261 type == content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE); | 232 DCHECK_GT(content::NUM_MEDIA_TYPES, type); |
262 | 233 |
263 // Create a new request. | 234 // Create a new request. |
264 StreamOptions options; | 235 StreamOptions options; |
265 EnumerationCache* cache = NULL; | 236 EnumerationCache* cache; |
no longer working on chromium
2012/09/05 14:19:41
why not keep initializing it to NULL?
miu
2012/09/06 04:40:35
Done.
| |
266 if (type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) { | 237 if (type == content::MEDIA_AUDIO_DEVICE_CAPTURE) { |
267 options.audio = true; | 238 options.audio_type = type; |
268 cache = &audio_enumeration_cache_; | 239 cache = &audio_enumeration_cache_; |
240 } else if (type == content::MEDIA_VIDEO_DEVICE_CAPTURE) { | |
241 options.video_type = type; | |
242 cache = &video_enumeration_cache_; | |
269 } else { | 243 } else { |
270 options.video = true; | 244 if (content::IsAudioMediaType(type)) { |
no longer working on chromium
2012/09/05 14:19:41
tab monitoring is only using the GenerateStream(),
miu
2012/09/06 04:40:35
Done.
| |
271 cache = &video_enumeration_cache_; | 245 options.audio_type = type; |
246 } else if (content::IsVideoMediaType(type)) { | |
247 options.video_type = type; | |
248 } | |
249 cache = NULL; | |
272 } | 250 } |
273 | 251 |
274 DeviceRequest new_request(requester, options, | 252 DeviceRequest new_request(requester, options, |
275 render_process_id, | 253 render_process_id, |
276 render_view_id, | 254 render_view_id, |
277 security_origin); | 255 security_origin); |
278 new_request.type = DeviceRequest::ENUMERATE_DEVICES; | 256 new_request.type = DeviceRequest::ENUMERATE_DEVICES; |
279 | 257 |
280 if (cache->valid) { | 258 if (cache && cache->valid) { |
281 // Cached device list of this type exists. Just send it out. | 259 // Cached device list of this type exists. Just send it out. |
282 new_request.state[type] = DeviceRequest::STATE_REQUESTED; | 260 new_request.state[type] = DeviceRequest::STATE_REQUESTED; |
283 AddRequest(&new_request, label); | 261 AddRequest(&new_request, label); |
284 // Need to post a task since the requester won't have label till | 262 // Need to post a task since the requester won't have label till |
285 // this function returns. | 263 // this function returns. |
286 BrowserThread::PostTask(BrowserThread::IO, | 264 BrowserThread::PostTask(BrowserThread::IO, |
287 FROM_HERE, | 265 FROM_HERE, |
288 base::Bind(&MediaStreamManager::SendCachedDeviceList, | 266 base::Bind(&MediaStreamManager::SendCachedDeviceList, |
289 base::Unretained(this), cache, *label)); | 267 base::Unretained(this), cache, *label)); |
290 } else { | 268 } else { |
291 StartEnumeration(&new_request, label); | 269 StartEnumeration(&new_request, label); |
292 StartMonitoring(); | 270 if (cache) { |
271 StartMonitoring(); | |
272 } | |
293 } | 273 } |
294 } | 274 } |
295 | 275 |
296 void MediaStreamManager::StopEnumerateDevices(const std::string& label) { | 276 void MediaStreamManager::StopEnumerateDevices(const std::string& label) { |
297 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 277 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
298 | 278 |
299 DeviceRequests::iterator it = requests_.find(label); | 279 DeviceRequests::iterator it = requests_.find(label); |
300 if (it != requests_.end()) { | 280 if (it != requests_.end()) { |
301 DCHECK_EQ(it->second.type, DeviceRequest::ENUMERATE_DEVICES); | 281 DCHECK_EQ(it->second.type, DeviceRequest::ENUMERATE_DEVICES); |
302 requests_.erase(it); | 282 requests_.erase(it); |
303 if (!HasEnumerationRequest()) { | 283 if (!HasEnumerationRequest()) { |
304 StopMonitoring(); | 284 StopMonitoring(); |
305 } | 285 } |
306 } | 286 } |
307 } | 287 } |
308 | 288 |
309 void MediaStreamManager::OpenDevice( | 289 void MediaStreamManager::OpenDevice( |
310 MediaStreamRequester* requester, | 290 MediaStreamRequester* requester, |
311 int render_process_id, | 291 int render_process_id, |
312 int render_view_id, | 292 int render_view_id, |
313 const std::string& device_id, | 293 const std::string& device_id, |
314 MediaStreamType type, | 294 MediaStreamType type, |
315 const GURL& security_origin, | 295 const GURL& security_origin, |
316 std::string* label) { | 296 std::string* label) { |
317 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 297 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
318 | 298 |
319 // Create a new request. | 299 // Create a new request. |
320 StreamOptions options; | 300 StreamOptions options; |
321 if (type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) | 301 if (content::IsAudioMediaType(type)) { |
322 options.audio = true; | 302 options.audio_type = type; |
323 else | 303 } else if (content::IsVideoMediaType(type)) { |
324 options.video = true; | 304 options.video_type = type; |
305 } else { | |
306 LOG(FATAL) << "Cannot handle request for MediaStreamType " << type; | |
307 return; | |
308 } | |
309 options.opt_device_id = device_id; | |
325 | 310 |
326 DeviceRequest new_request(requester, options, | 311 DeviceRequest new_request(requester, options, |
327 render_process_id, | 312 render_process_id, |
328 render_view_id, | 313 render_view_id, |
329 security_origin); | 314 security_origin); |
330 new_request.type = DeviceRequest::OPEN_DEVICE; | 315 new_request.type = DeviceRequest::OPEN_DEVICE; |
331 new_request.requested_device_id = device_id; | |
332 | 316 |
333 StartEnumeration(&new_request, label); | 317 StartEnumeration(&new_request, label); |
334 } | 318 } |
335 | 319 |
336 void MediaStreamManager::SendCachedDeviceList( | 320 void MediaStreamManager::SendCachedDeviceList( |
337 EnumerationCache* cache, | 321 EnumerationCache* cache, |
338 const std::string& label) { | 322 const std::string& label) { |
339 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 323 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
340 if (cache->valid) { | 324 if (cache->valid) { |
341 DeviceRequests::iterator it = requests_.find(label); | 325 DeviceRequests::iterator it = requests_.find(label); |
(...skipping 24 matching lines...) Expand all Loading... | |
366 void MediaStreamManager::ClearEnumerationCache(EnumerationCache* cache) { | 350 void MediaStreamManager::ClearEnumerationCache(EnumerationCache* cache) { |
367 DCHECK_EQ(MessageLoop::current(), io_loop_); | 351 DCHECK_EQ(MessageLoop::current(), io_loop_); |
368 cache->valid = false; | 352 cache->valid = false; |
369 } | 353 } |
370 | 354 |
371 void MediaStreamManager::StartEnumeration( | 355 void MediaStreamManager::StartEnumeration( |
372 DeviceRequest* new_request, | 356 DeviceRequest* new_request, |
373 std::string* label) { | 357 std::string* label) { |
374 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 358 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
375 | 359 |
376 MediaStreamType stream_type = content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE; | 360 for (int i = content::MEDIA_NO_SERVICE + 1; i < content::NUM_MEDIA_TYPES; |
377 if (Requested(new_request->options, stream_type)) { | 361 ++i) { |
378 new_request->state[stream_type] = DeviceRequest::STATE_REQUESTED; | 362 const MediaStreamType stream_type = static_cast<MediaStreamType>(i); |
379 DCHECK_GE(active_enumeration_ref_count_[stream_type], 0); | 363 if (Requested(new_request->options, stream_type)) { |
380 if (!active_enumeration_ref_count_[stream_type]) { | 364 new_request->state[stream_type] = DeviceRequest::STATE_REQUESTED; |
381 ++active_enumeration_ref_count_[stream_type]; | 365 DCHECK_GE(active_enumeration_ref_count_[stream_type], 0); |
382 GetDeviceManager(stream_type)->EnumerateDevices(); | 366 if (active_enumeration_ref_count_[stream_type] == 0) { |
383 } | 367 ++active_enumeration_ref_count_[stream_type]; |
384 } | 368 GetDeviceManager(stream_type)->EnumerateDevices(); |
385 stream_type = content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE; | 369 } |
386 if (Requested(new_request->options, stream_type)) { | |
387 new_request->state[stream_type] = DeviceRequest::STATE_REQUESTED; | |
388 DCHECK_GE(active_enumeration_ref_count_[stream_type], 0); | |
389 if (!active_enumeration_ref_count_[stream_type]) { | |
390 ++active_enumeration_ref_count_[stream_type]; | |
391 GetDeviceManager(stream_type)->EnumerateDevices(); | |
392 } | 370 } |
393 } | 371 } |
394 | 372 |
395 AddRequest(new_request, label); | 373 AddRequest(new_request, label); |
396 } | 374 } |
397 | 375 |
398 void MediaStreamManager::AddRequest( | 376 void MediaStreamManager::AddRequest( |
399 DeviceRequest* new_request, | 377 DeviceRequest* new_request, |
400 std::string* label) { | 378 std::string* label) { |
401 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 379 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
402 | 380 |
403 // Create a label for this request and verify it is unique. | 381 // Create a label for this request and verify it is unique. |
404 std::string request_label; | 382 std::string request_label; |
405 do { | 383 do { |
406 request_label = RandomLabel(); | 384 request_label = RandomLabel(); |
407 } while (requests_.find(request_label) != requests_.end()); | 385 } while (requests_.find(request_label) != requests_.end()); |
408 | 386 |
409 requests_.insert(std::make_pair(request_label, *new_request)); | 387 requests_.insert(std::make_pair(request_label, *new_request)); |
410 | 388 |
411 (*label) = request_label; | 389 (*label) = request_label; |
412 } | 390 } |
413 | 391 |
414 void MediaStreamManager::EnsureDeviceThreadAndListener() { | 392 void MediaStreamManager::EnsureDeviceManagerStarted( |
393 MediaStreamType stream_type) { | |
415 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 394 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
416 if (device_thread_.get()) | |
417 return; | |
418 | 395 |
419 device_thread_.reset(new DeviceThread("MediaStreamDeviceThread")); | 396 if (!device_thread_.get()) { |
420 CHECK(device_thread_->Start()); | 397 device_thread_.reset(new DeviceThread("MediaStreamDeviceThread")); |
398 CHECK(device_thread_->Start()); | |
399 } | |
421 | 400 |
422 audio_input_device_manager_->Register(this, | 401 if (!device_manager_[stream_type]) { |
423 device_thread_->message_loop_proxy()); | 402 switch (stream_type) { |
424 video_capture_manager_->Register(this, device_thread_->message_loop_proxy()); | 403 case content::MEDIA_AUDIO_DEVICE_CAPTURE: |
404 case content::MEDIA_TAB_AUDIO_CAPTURE: | |
405 if (!audio_manager_) { | |
406 audio_manager_ = content::BrowserMainLoop::GetAudioManager(); | |
407 } | |
408 device_manager_[stream_type] = | |
409 new media_stream::AudioInputDeviceManager(audio_manager_, | |
no longer working on chromium
2012/09/05 14:19:41
Why do we use different AudioInputDeviceManager fo
miu
2012/09/06 04:40:35
Each is instantiated for a different stream_type.
| |
410 stream_type); | |
411 break; | |
412 case content::MEDIA_VIDEO_DEVICE_CAPTURE: | |
413 case content::MEDIA_TAB_VIDEO_CAPTURE: | |
414 device_manager_[stream_type] = | |
415 new media_stream::VideoCaptureManager(stream_type); | |
no longer working on chromium
2012/09/05 14:19:41
same question for video?
| |
416 break; | |
417 default: | |
418 LOG(FATAL) << "Cannot create device manager for invalid or " | |
419 << "unsupported MediaStreamType " << stream_type; | |
420 return; | |
421 } | |
422 device_manager_[stream_type]->Register( | |
423 this, device_thread_->message_loop_proxy()); | |
424 } | |
425 | 425 |
426 // We want to be notified of IO message loop destruction to delete the thread | 426 // We want to be notified of IO message loop destruction to delete the thread |
427 // and the device managers. | 427 // and the device managers. |
428 io_loop_ = MessageLoop::current(); | 428 if (!io_loop_) { |
429 io_loop_->AddDestructionObserver(this); | 429 io_loop_ = MessageLoop::current(); |
430 io_loop_->AddDestructionObserver(this); | |
431 } | |
430 } | 432 } |
431 | 433 |
432 void MediaStreamManager::Opened(MediaStreamType stream_type, | 434 void MediaStreamManager::Opened(MediaStreamType stream_type, |
433 int capture_session_id) { | 435 int capture_session_id) { |
434 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 436 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
435 | 437 |
436 // Find the request containing this device and mark it as used. | 438 // Find the request containing this device and mark it as used. |
437 DeviceRequest* request = NULL; | 439 DeviceRequest* request = NULL; |
438 StreamDeviceInfoArray* devices = NULL; | 440 StreamDeviceInfoArray* devices = NULL; |
439 std::string label; | 441 std::string label; |
440 for (DeviceRequests::iterator request_it = requests_.begin(); | 442 for (DeviceRequests::iterator request_it = requests_.begin(); |
441 request_it != requests_.end() && request == NULL; ++request_it) { | 443 request_it != requests_.end() && request == NULL; ++request_it) { |
442 if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) { | 444 devices = &(request_it->second.devices); |
443 devices = &(request_it->second.audio_devices); | |
444 } else if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) { | |
445 devices = &(request_it->second.video_devices); | |
446 } else { | |
447 NOTREACHED(); | |
448 } | |
449 | |
450 for (StreamDeviceInfoArray::iterator device_it = devices->begin(); | 445 for (StreamDeviceInfoArray::iterator device_it = devices->begin(); |
451 device_it != devices->end(); ++device_it) { | 446 device_it != devices->end(); ++device_it) { |
452 if (device_it->session_id == capture_session_id) { | 447 if (device_it->stream_type == stream_type && |
448 device_it->session_id == capture_session_id) { | |
453 // We've found the request. | 449 // We've found the request. |
454 device_it->in_use = true; | 450 device_it->in_use = true; |
455 label = request_it->first; | 451 label = request_it->first; |
456 request = &(request_it->second); | 452 request = &(request_it->second); |
457 break; | 453 break; |
458 } | 454 } |
459 } | 455 } |
460 } | 456 } |
461 if (request == NULL) { | 457 if (request == NULL) { |
462 // The request doesn't exist. | 458 // The request doesn't exist. |
463 return; | 459 return; |
464 } | 460 } |
465 | 461 |
466 DCHECK_NE(request->state[stream_type], DeviceRequest::STATE_REQUESTED); | 462 DCHECK_NE(request->state[stream_type], DeviceRequest::STATE_REQUESTED); |
467 | 463 |
468 // Check if all devices for this stream type are opened. Update the state if | 464 // Check if all devices for this stream type are opened. Update the state if |
469 // they are. | 465 // they are. |
470 for (StreamDeviceInfoArray::iterator device_it = devices->begin(); | 466 for (StreamDeviceInfoArray::iterator device_it = devices->begin(); |
471 device_it != devices->end(); ++device_it) { | 467 device_it != devices->end(); ++device_it) { |
468 if (device_it->stream_type != stream_type) { | |
no longer working on chromium
2012/09/05 14:19:41
nit, remove the {}
miu
2012/09/06 04:40:35
Done.
| |
469 continue; | |
470 } | |
472 if (device_it->in_use == false) { | 471 if (device_it->in_use == false) { |
473 // Wait for more devices to be opened before we're done. | 472 // Wait for more devices to be opened before we're done. |
474 return; | 473 return; |
475 } | 474 } |
476 } | 475 } |
477 request->state[stream_type] = DeviceRequest::STATE_DONE; | 476 request->state[stream_type] = DeviceRequest::STATE_DONE; |
478 | 477 |
479 if (!RequestDone(*request)) { | 478 if (!RequestDone(*request)) { |
480 // This stream_type is done, but not the other type. | 479 // This stream_type is done, but not the other type. |
481 return; | 480 return; |
482 } | 481 } |
483 | 482 |
483 // Partition the array of devices into audio vs video. | |
484 StreamDeviceInfoArray audio_devices, video_devices; | |
485 for (StreamDeviceInfoArray::const_iterator device_it = devices->begin(); | |
486 device_it != devices->end(); ++device_it) { | |
487 if (content::IsAudioMediaType(device_it->stream_type)) { | |
488 audio_devices.push_back(*device_it); | |
489 } else if (content::IsVideoMediaType(device_it->stream_type)) { | |
490 video_devices.push_back(*device_it); | |
491 } else { | |
492 NOTREACHED(); | |
493 } | |
494 } | |
495 | |
484 switch (request->type) { | 496 switch (request->type) { |
485 case DeviceRequest::OPEN_DEVICE: | 497 case DeviceRequest::OPEN_DEVICE: |
486 request->requester->DeviceOpened(label, (*devices)[0]); | 498 if (content::IsAudioMediaType(stream_type)) { |
499 request->requester->DeviceOpened(label, audio_devices.front()); | |
500 } else if (content::IsVideoMediaType(stream_type)) { | |
501 request->requester->DeviceOpened(label, video_devices.front()); | |
502 } else { | |
503 NOTREACHED(); | |
504 } | |
487 break; | 505 break; |
488 case DeviceRequest::GENERATE_STREAM: | 506 case DeviceRequest::GENERATE_STREAM: |
489 request->requester->StreamGenerated(label, request->audio_devices, | 507 request->requester->StreamGenerated(label, audio_devices, video_devices); |
490 request->video_devices); | |
491 NotifyObserverDevicesOpened(request); | 508 NotifyObserverDevicesOpened(request); |
492 break; | 509 break; |
493 default: | 510 default: |
494 NOTREACHED(); | 511 NOTREACHED(); |
512 break; | |
495 } | 513 } |
496 } | 514 } |
497 | 515 |
498 void MediaStreamManager::Closed(MediaStreamType stream_type, | 516 void MediaStreamManager::Closed(MediaStreamType stream_type, |
499 int capture_session_id) { | 517 int capture_session_id) { |
500 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 518 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
501 } | 519 } |
502 | 520 |
503 void MediaStreamManager::DevicesEnumerated( | 521 void MediaStreamManager::DevicesEnumerated( |
504 MediaStreamType stream_type, const StreamDeviceInfoArray& devices) { | 522 MediaStreamType stream_type, const StreamDeviceInfoArray& devices) { |
505 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 523 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
506 | 524 |
507 // Only cache device list when there is EnumerateDevices request, since | 525 // Only cache the device list when there is an EnumerateDevices request, since |
508 // other requests don't turn on device monitoring. | 526 // other requests don't turn on device monitoring. |
527 // NOTE: Caching only applies to the physical audio/video capture devices. | |
528 EnumerationCache* cache; | |
529 if (stream_type == content::MEDIA_AUDIO_DEVICE_CAPTURE) { | |
530 cache = &audio_enumeration_cache_; | |
531 } else if (stream_type == content::MEDIA_VIDEO_DEVICE_CAPTURE) { | |
532 cache = &video_enumeration_cache_; | |
533 } else { | |
534 cache = NULL; | |
535 } | |
509 bool need_update_clients = false; | 536 bool need_update_clients = false; |
510 EnumerationCache* cache = | 537 if (cache && |
511 (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE ? | 538 HasEnumerationRequest(stream_type) && |
512 &audio_enumeration_cache_ : &video_enumeration_cache_); | |
513 if (HasEnumerationRequest(stream_type) && | |
514 (!cache->valid || | 539 (!cache->valid || |
515 devices.size() != cache->devices.size() || | 540 devices.size() != cache->devices.size() || |
516 !std::equal(devices.begin(), devices.end(), cache->devices.begin(), | 541 !std::equal(devices.begin(), devices.end(), cache->devices.begin(), |
517 media_stream::StreamDeviceInfo::IsEqual))) { | 542 media_stream::StreamDeviceInfo::IsEqual))) { |
518 cache->valid = true; | 543 cache->valid = true; |
519 cache->devices = devices; | 544 cache->devices = devices; |
520 need_update_clients = true; | 545 need_update_clients = true; |
546 } else { | |
547 // If stream_type is not a physical device type, there is no caching. In | |
548 // such cases, we assume we always need to update the clients. | |
549 need_update_clients = (cache == NULL); | |
521 } | 550 } |
522 | 551 |
523 // Publish the result for all requests waiting for device list(s). | 552 // Publish the result for all requests waiting for device list(s). |
524 // Find the requests waiting for this device list, store their labels and | 553 // Find the requests waiting for this device list, store their labels and |
525 // release the iterator before calling device settings. We might get a call | 554 // release the iterator before calling device settings. We might get a call |
526 // back from device_settings that will need to iterate through devices. | 555 // back from device_settings that will need to iterate through devices. |
527 std::list<std::string> label_list; | 556 std::list<std::string> label_list; |
528 for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end(); | 557 for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end(); |
529 ++it) { | 558 ++it) { |
530 if (it->second.state[stream_type] == DeviceRequest::STATE_REQUESTED && | 559 if (it->second.state[stream_type] == DeviceRequest::STATE_REQUESTED && |
531 Requested(it->second.options, stream_type)) { | 560 Requested(it->second.options, stream_type)) { |
532 if (it->second.type != DeviceRequest::ENUMERATE_DEVICES) | 561 if (it->second.type != DeviceRequest::ENUMERATE_DEVICES) |
533 it->second.state[stream_type] = DeviceRequest::STATE_PENDING_APPROVAL; | 562 it->second.state[stream_type] = DeviceRequest::STATE_PENDING_APPROVAL; |
534 label_list.push_back(it->first); | 563 label_list.push_back(it->first); |
535 } | 564 } |
536 } | 565 } |
537 for (std::list<std::string>::iterator it = label_list.begin(); | 566 for (std::list<std::string>::iterator it = label_list.begin(); |
538 it != label_list.end(); ++it) { | 567 it != label_list.end(); ++it) { |
539 DeviceRequest& request = requests_[*it]; | 568 DeviceRequest& request = requests_[*it]; |
569 | |
570 // If one specific device has been requested, prune all other devices out. | |
571 StreamDeviceInfoArray tmp; | |
572 const StreamDeviceInfoArray* pruned_devices; | |
573 if (request.options.opt_device_id.empty()) { | |
574 pruned_devices = &devices; | |
575 } else { | |
576 for (StreamDeviceInfoArray::const_iterator device_it = devices.begin(); | |
577 device_it != devices.end(); ++device_it) { | |
578 if (device_it->device_id == request.options.opt_device_id) { | |
579 tmp.push_back(*device_it); | |
580 } | |
581 } | |
582 pruned_devices = &tmp; | |
583 } | |
584 | |
540 switch (request.type) { | 585 switch (request.type) { |
541 case DeviceRequest::ENUMERATE_DEVICES: | 586 case DeviceRequest::ENUMERATE_DEVICES: |
542 if (need_update_clients) | 587 if (need_update_clients) |
543 request.requester->DevicesEnumerated(*it, devices); | 588 request.requester->DevicesEnumerated(*it, *pruned_devices); |
544 break; | 589 break; |
545 case DeviceRequest::OPEN_DEVICE: | 590 case DeviceRequest::OPEN_DEVICE: |
546 for (StreamDeviceInfoArray::const_iterator device_it = devices.begin(); | 591 if (!pruned_devices->empty()) { |
547 device_it != devices.end(); device_it++) { | 592 StreamDeviceInfo device = pruned_devices->front(); |
548 if (request.requested_device_id == device_it->device_id) { | 593 // For OPEN_DEVICE requests, it is mandatory for the opt_device_id |
549 StreamDeviceInfo device = *device_it; | 594 // field to be provided. See MediaStreamManager::OpenDevice(). |
550 device.in_use = false; | 595 DCHECK(!request.options.opt_device_id.empty()); |
551 device.session_id = | 596 DCHECK_EQ(request.options.opt_device_id, device.device_id); |
552 GetDeviceManager(device_it->stream_type)->Open(device); | 597 device.in_use = false; |
553 request.state[device_it->stream_type] = | 598 device.session_id = |
554 DeviceRequest::STATE_OPENING; | 599 GetDeviceManager(device.stream_type)->Open(device); |
555 if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) | 600 request.state[device.stream_type] = DeviceRequest::STATE_OPENING; |
556 request.audio_devices.push_back(device); | 601 request.devices.push_back(device); |
557 else | |
558 request.video_devices.push_back(device); | |
559 break; | |
560 } | |
561 } | 602 } |
562 break; | 603 break; |
563 default: | 604 default: |
564 device_settings_->AvailableDevices(*it, stream_type, devices); | 605 device_settings_->AvailableDevices(*it, stream_type, *pruned_devices); |
606 break; | |
565 } | 607 } |
566 } | 608 } |
567 label_list.clear(); | 609 label_list.clear(); |
568 --active_enumeration_ref_count_[stream_type]; | 610 --active_enumeration_ref_count_[stream_type]; |
569 DCHECK_GE(active_enumeration_ref_count_[stream_type], 0); | 611 DCHECK_GE(active_enumeration_ref_count_[stream_type], 0); |
570 } | 612 } |
571 | 613 |
572 void MediaStreamManager::Error(MediaStreamType stream_type, | 614 void MediaStreamManager::Error(MediaStreamType stream_type, |
573 int capture_session_id, | 615 int capture_session_id, |
574 MediaStreamProviderError error) { | 616 MediaStreamProviderError error) { |
575 // Find the device for the error call. | 617 // Find the device for the error call. |
576 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 618 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
619 | |
577 for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end(); | 620 for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end(); |
578 ++it) { | 621 ++it) { |
579 StreamDeviceInfoArray* devices = NULL; | 622 StreamDeviceInfoArray& devices = it->second.devices; |
580 if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) { | |
581 devices = &(it->second.audio_devices); | |
582 } else if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) { | |
583 devices = &(it->second.video_devices); | |
584 } else { | |
585 NOTREACHED(); | |
586 } | |
587 | 623 |
588 int device_idx = 0; | 624 int audio_device_idx = -1; |
589 for (StreamDeviceInfoArray::iterator device_it = devices->begin(); | 625 int video_device_idx = -1; |
590 device_it != devices->end(); ++device_it, ++device_idx) { | 626 for (StreamDeviceInfoArray::iterator device_it = devices.begin(); |
591 if (device_it->session_id == capture_session_id) { | 627 device_it != devices.end(); ++device_it) { |
592 // We've found the failing device. Find the error case: | 628 if (content::IsAudioMediaType(device_it->stream_type)) { |
593 if (it->second.state[stream_type] == DeviceRequest::STATE_DONE) { | 629 ++audio_device_idx; |
594 // 1. Already opened -> signal device failure and close device. | 630 } else if (content::IsVideoMediaType(device_it->stream_type)) { |
595 // Use device_idx to signal which of the devices encountered an | 631 ++video_device_idx; |
596 // error. | 632 } else { |
597 if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) { | 633 NOTREACHED(); |
598 it->second.requester->AudioDeviceFailed(it->first, device_idx); | 634 continue; |
599 } else if (stream_type == | 635 } |
600 content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) { | 636 if (device_it->stream_type != stream_type || |
601 it->second.requester->VideoDeviceFailed(it->first, device_idx); | 637 device_it->session_id != capture_session_id) { |
602 } | 638 continue; |
603 GetDeviceManager(stream_type)->Close(capture_session_id); | 639 } |
604 // We don't erase the devices here so that we can update the UI | 640 // We've found the failing device. Find the error case: |
605 // properly in StopGeneratedStream(). | 641 if (it->second.state[stream_type] == DeviceRequest::STATE_DONE) { |
606 it->second.state[stream_type] = DeviceRequest::STATE_ERROR; | 642 // 1. Already opened -> signal device failure and close device. |
643 // Use device_idx to signal which of the devices encountered an | |
644 // error. | |
645 if (content::IsAudioMediaType(stream_type)) { | |
646 it->second.requester->AudioDeviceFailed(it->first, audio_device_idx); | |
647 } else if (content::IsVideoMediaType(stream_type)) { | |
648 it->second.requester->VideoDeviceFailed(it->first, video_device_idx); | |
607 } else { | 649 } else { |
608 // Request is not done, devices are not opened in this case. | 650 NOTREACHED(); |
609 if ((it->second.audio_devices.size() + | 651 return; |
610 it->second.video_devices.size()) <= 1) { | |
611 // 2. Device not opened and no other devices for this request -> | |
612 // signal stream error and remove the request. | |
613 it->second.requester->StreamGenerationFailed(it->first); | |
614 requests_.erase(it); | |
615 } else { | |
616 // 3. Not opened but other devices exists for this request -> remove | |
617 // device from list, but don't signal an error. | |
618 devices->erase(device_it); | |
619 } | |
620 } | 652 } |
621 return; | 653 GetDeviceManager(stream_type)->Close(capture_session_id); |
654 // We don't erase the devices here so that we can update the UI | |
655 // properly in StopGeneratedStream(). | |
656 it->second.state[stream_type] = DeviceRequest::STATE_ERROR; | |
657 } else { | |
658 // Request is not done, devices are not opened in this case. | |
659 if (devices.size() <= 1) { | |
660 // 2. Device not opened and no other devices for this request -> | |
661 // signal stream error and remove the request. | |
662 it->second.requester->StreamGenerationFailed(it->first); | |
663 requests_.erase(it); | |
664 } else { | |
665 // 3. Not opened but other devices exists for this request -> remove | |
666 // device from list, but don't signal an error. | |
667 devices.erase(device_it); // NOTE: This invalidates device_it! | |
668 } | |
622 } | 669 } |
670 return; | |
623 } | 671 } |
624 } | 672 } |
625 } | 673 } |
626 | 674 |
627 void MediaStreamManager::DevicesAccepted(const std::string& label, | 675 void MediaStreamManager::DevicesAccepted(const std::string& label, |
628 const StreamDeviceInfoArray& devices) { | 676 const StreamDeviceInfoArray& devices) { |
629 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 677 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
630 DeviceRequests::iterator request_it = requests_.find(label); | 678 DeviceRequests::iterator request_it = requests_.find(label); |
631 if (request_it != requests_.end()) { | 679 if (request_it == requests_.end()) { |
no longer working on chromium
2012/09/05 14:19:41
nit, no need for {}
miu
2012/09/06 04:40:35
Done.
| |
632 if (devices.empty()) { | 680 return; |
633 // No available devices or user didn't accept device usage. | 681 } |
634 request_it->second.requester->StreamGenerationFailed(request_it->first); | 682 |
635 requests_.erase(request_it); | 683 DeviceRequest& request = request_it->second; |
636 return; | 684 |
685 if (devices.empty()) { | |
686 // No available devices or user didn't accept device usage. | |
687 request.requester->StreamGenerationFailed(request_it->first); | |
688 requests_.erase(request_it); | |
689 return; | |
690 } | |
691 | |
692 // Process all newly-accepted devices for this request. | |
693 for (StreamDeviceInfoArray::const_iterator device_it = devices.begin(); | |
694 device_it != devices.end(); ++device_it) { | |
695 StreamDeviceInfo device_info = *device_it; // make a copy | |
no longer working on chromium
2012/09/05 14:19:41
I saw both cases in chrome. But not sure if it is
miu
2012/09/06 04:40:35
Done.
| |
696 | |
697 // Set in_use to false to be able to track if this device has been | |
698 // opened. in_use might be true if the device type can be used in more | |
699 // than one session. | |
700 DCHECK_EQ(request.state[device_it->stream_type], | |
701 DeviceRequest::STATE_PENDING_APPROVAL); | |
702 device_info.in_use = false; | |
703 device_info.session_id = | |
704 GetDeviceManager(device_info.stream_type)->Open(device_info); | |
705 request.state[device_it->stream_type] = DeviceRequest::STATE_OPENING; | |
706 request.devices.push_back(device_info); | |
707 } | |
708 | |
709 // Check whether we've received all stream types requested. | |
710 bool found_audio = false, found_video = false; | |
711 for (StreamDeviceInfoArray::const_iterator i = request.devices.begin(); | |
712 i != request.devices.end(); ++i) { | |
713 if (i->stream_type == request.options.audio_type) { | |
714 found_audio = true; | |
715 } else if (i->stream_type == request.options.video_type) { | |
716 found_video = true; | |
717 } else { | |
718 NOTREACHED(); | |
637 } | 719 } |
638 | 720 } |
639 // Loop through all device types for this request. | 721 if (request.options.audio_type != content::MEDIA_NO_SERVICE && |
640 for (StreamDeviceInfoArray::const_iterator device_it = devices.begin(); | 722 !found_audio) { |
641 device_it != devices.end(); ++device_it) { | 723 request.state[request.options.audio_type] = DeviceRequest::STATE_ERROR; |
642 StreamDeviceInfo device_info = *device_it; | 724 } |
643 | 725 if (request.options.video_type != content::MEDIA_NO_SERVICE && |
644 // Set in_use to false to be able to track if this device has been | 726 !found_video) { |
645 // opened. in_use might be true if the device type can be used in more | 727 request.state[request.options.video_type] = DeviceRequest::STATE_ERROR; |
646 // than one session. | |
647 DCHECK_EQ(request_it->second.state[device_it->stream_type], | |
648 DeviceRequest::STATE_PENDING_APPROVAL); | |
649 device_info.in_use = false; | |
650 device_info.session_id = | |
651 GetDeviceManager(device_info.stream_type)->Open(device_info); | |
652 request_it->second.state[device_it->stream_type] = | |
653 DeviceRequest::STATE_OPENING; | |
654 if (device_info.stream_type == | |
655 content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) { | |
656 request_it->second.audio_devices.push_back(device_info); | |
657 } else if (device_info.stream_type == | |
658 content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) { | |
659 request_it->second.video_devices.push_back(device_info); | |
660 } else { | |
661 NOTREACHED(); | |
662 } | |
663 } | |
664 // Check if we received all stream types requested. | |
665 MediaStreamType stream_type = | |
666 content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE; | |
667 if (Requested(request_it->second.options, stream_type) && | |
668 request_it->second.audio_devices.size() == 0) { | |
669 request_it->second.state[stream_type] = DeviceRequest::STATE_ERROR; | |
670 } | |
671 stream_type = content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE; | |
672 if (Requested(request_it->second.options, stream_type) && | |
673 request_it->second.video_devices.size() == 0) { | |
674 request_it->second.state[stream_type] = DeviceRequest::STATE_ERROR; | |
675 } | |
676 return; | |
677 } | 728 } |
678 } | 729 } |
679 | 730 |
680 void MediaStreamManager::SettingsError(const std::string& label) { | 731 void MediaStreamManager::SettingsError(const std::string& label) { |
681 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 732 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
682 // Erase this request and report an error. | 733 // Erase this request and report an error. |
683 DeviceRequests::iterator it = requests_.find(label); | 734 DeviceRequests::iterator it = requests_.find(label); |
684 if (it != requests_.end()) { | 735 if (it != requests_.end()) { |
685 DCHECK_EQ(it->second.type, DeviceRequest::GENERATE_STREAM); | 736 DCHECK_EQ(it->second.type, DeviceRequest::GENERATE_STREAM); |
686 it->second.requester->StreamGenerationFailed(label); | 737 it->second.requester->StreamGenerationFailed(label); |
687 requests_.erase(it); | 738 requests_.erase(it); |
688 return; | 739 return; |
689 } | 740 } |
690 } | 741 } |
691 | 742 |
743 void MediaStreamManager::SetAudioManager(media::AudioManager* audio_manager) { | |
744 LOG_IF(FATAL, (audio_manager_ != NULL) && (audio_manager_ != audio_manager)) | |
745 << "Cannot override AudioManager after it has been set."; | |
746 audio_manager_ = audio_manager; | |
747 } | |
748 | |
692 void MediaStreamManager::UseFakeDevice() { | 749 void MediaStreamManager::UseFakeDevice() { |
693 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 750 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
694 video_capture_manager()->UseFakeDevice(); | 751 for (int i = content::MEDIA_NO_SERVICE + 1; i < content::NUM_MEDIA_TYPES; |
752 ++i) { | |
753 const MediaStreamType stream_type = static_cast<MediaStreamType>(i); | |
754 if (content::IsVideoMediaType(stream_type)) { | |
755 GetVideoCaptureManager(stream_type)->UseFakeDevice(); | |
756 } | |
757 } | |
695 device_settings_->UseFakeUI(); | 758 device_settings_->UseFakeUI(); |
696 } | 759 } |
697 | 760 |
698 void MediaStreamManager::WillDestroyCurrentMessageLoop() { | 761 void MediaStreamManager::WillDestroyCurrentMessageLoop() { |
699 DCHECK_EQ(MessageLoop::current(), io_loop_); | 762 DCHECK_EQ(MessageLoop::current(), io_loop_); |
700 DCHECK(requests_.empty()); | 763 DCHECK(requests_.empty()); |
701 if (device_thread_.get()) { | 764 if (device_thread_.get()) { |
702 StopMonitoring(); | 765 StopMonitoring(); |
703 | 766 |
704 video_capture_manager_->Unregister(); | 767 for (int i = content::MEDIA_NO_SERVICE + 1; i < content::NUM_MEDIA_TYPES; |
705 audio_input_device_manager_->Unregister(); | 768 ++i) { |
769 if (device_manager_[i]) { | |
770 device_manager_[i]->Unregister(); | |
771 } | |
772 } | |
773 | |
706 device_thread_.reset(); | 774 device_thread_.reset(); |
707 } | 775 } |
708 | 776 |
709 audio_input_device_manager_ = NULL; | 777 for (int i = content::MEDIA_NO_SERVICE + 1; i < content::NUM_MEDIA_TYPES; |
710 video_capture_manager_ = NULL; | 778 ++i) { |
779 device_manager_[i] = NULL; | |
780 } | |
711 io_loop_ = NULL; | 781 io_loop_ = NULL; |
712 device_settings_.reset(); | 782 device_settings_.reset(); |
713 } | 783 } |
714 | 784 |
715 void MediaStreamManager::NotifyObserverDevicesOpened(DeviceRequest* request) { | 785 void MediaStreamManager::NotifyObserverDevicesOpened(DeviceRequest* request) { |
716 content::MediaObserver* media_observer = | 786 content::MediaObserver* media_observer = |
717 content::GetContentClient()->browser()->GetMediaObserver(); | 787 content::GetContentClient()->browser()->GetMediaObserver(); |
718 content::MediaStreamDevices opened_devices; | 788 content::MediaStreamDevices opened_devices; |
719 DevicesFromRequest(request, &opened_devices); | 789 DevicesFromRequest(request, &opened_devices); |
720 DCHECK(!opened_devices.empty()); | 790 DCHECK(!opened_devices.empty()); |
721 media_observer->OnCaptureDevicesOpened(request->render_process_id, | 791 media_observer->OnCaptureDevicesOpened(request->render_process_id, |
722 request->render_view_id, | 792 request->render_view_id, |
723 opened_devices); | 793 opened_devices); |
724 } | 794 } |
725 | 795 |
726 void MediaStreamManager::NotifyObserverDevicesClosed(DeviceRequest* request) { | 796 void MediaStreamManager::NotifyObserverDevicesClosed(DeviceRequest* request) { |
727 content::MediaObserver* media_observer = | 797 content::MediaObserver* media_observer = |
728 content::GetContentClient()->browser()->GetMediaObserver(); | 798 content::GetContentClient()->browser()->GetMediaObserver(); |
729 content::MediaStreamDevices closed_devices; | 799 content::MediaStreamDevices closed_devices; |
730 DevicesFromRequest(request, &closed_devices); | 800 DevicesFromRequest(request, &closed_devices); |
731 if (closed_devices.empty()) | 801 if (closed_devices.empty()) |
732 return; | 802 return; |
733 media_observer->OnCaptureDevicesClosed(request->render_process_id, | 803 media_observer->OnCaptureDevicesClosed(request->render_process_id, |
734 request->render_view_id, | 804 request->render_view_id, |
735 closed_devices); | 805 closed_devices); |
736 } | 806 } |
737 | 807 |
738 void MediaStreamManager::DevicesFromRequest( | 808 void MediaStreamManager::DevicesFromRequest( |
739 DeviceRequest* request, content::MediaStreamDevices* devices) { | 809 DeviceRequest* request, content::MediaStreamDevices* devices) { |
740 StreamDeviceInfoArray::const_iterator it = request->audio_devices.begin(); | 810 for (StreamDeviceInfoArray::const_iterator it = request->devices.begin(); |
741 for (; it != request->audio_devices.end(); ++it) { | 811 it != request->devices.end(); ++it) { |
742 devices->push_back( | 812 devices->push_back(content::MediaStreamDevice( |
743 content::MediaStreamDevice( | 813 it->stream_type, it->device_id, it->name)); |
744 content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE, | |
745 it->device_id, | |
746 it->name)); | |
747 } | |
748 for (it = request->video_devices.begin(); it != request->video_devices.end(); | |
749 ++it) { | |
750 devices->push_back( | |
751 content::MediaStreamDevice( | |
752 content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE, | |
753 it->device_id, | |
754 it->name)); | |
755 } | 814 } |
756 } | 815 } |
757 | 816 |
758 bool MediaStreamManager::RequestDone(const DeviceRequest& request) const { | 817 bool MediaStreamManager::RequestDone(const DeviceRequest& request) const { |
759 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 818 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
760 // Check if all devices are opened. | |
761 MediaStreamType stream_type = content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE; | |
762 if (Requested(request.options, stream_type)) { | |
763 if (request.state[stream_type] != DeviceRequest::STATE_DONE && | |
764 request.state[stream_type] != DeviceRequest::STATE_ERROR) { | |
765 return false; | |
766 } | |
767 | 819 |
768 for (StreamDeviceInfoArray::const_iterator it = | 820 const bool requested_audio = |
769 request.audio_devices.begin(); it != request.audio_devices.end(); | 821 content::IsAudioMediaType(request.options.audio_type); |
770 ++it) { | 822 const bool requested_video = |
771 if (it->in_use == false) { | 823 content::IsVideoMediaType(request.options.video_type); |
772 return false; | 824 |
773 } | 825 const bool audio_done = |
774 } | 826 !requested_audio || |
827 request.state[request.options.audio_type] == DeviceRequest::STATE_DONE || | |
828 request.state[request.options.audio_type] == DeviceRequest::STATE_ERROR; | |
829 if (!audio_done) { | |
830 return false; | |
775 } | 831 } |
776 | 832 |
777 stream_type = content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE; | 833 const bool video_done = |
778 if (Requested(request.options, stream_type)) { | 834 !requested_video || |
779 if (request.state[stream_type] != DeviceRequest::STATE_DONE && | 835 request.state[request.options.video_type] == DeviceRequest::STATE_DONE || |
780 request.state[stream_type] != DeviceRequest::STATE_ERROR) { | 836 request.state[request.options.video_type] == DeviceRequest::STATE_ERROR; |
837 if (!video_done) { | |
838 return false; | |
839 } | |
840 | |
841 for (StreamDeviceInfoArray::const_iterator it = request.devices.begin(); | |
842 it != request.devices.end(); ++it) { | |
843 if ((!requested_audio && content::IsAudioMediaType(it->stream_type)) || | |
844 (!requested_video && content::IsVideoMediaType(it->stream_type))) { | |
845 continue; | |
846 } | |
847 if (it->in_use == false) { | |
781 return false; | 848 return false; |
782 } | 849 } |
783 | |
784 for (StreamDeviceInfoArray::const_iterator it = | |
785 request.video_devices.begin(); it != request.video_devices.end(); | |
786 ++it) { | |
787 if (it->in_use == false) { | |
788 return false; | |
789 } | |
790 } | |
791 } | 850 } |
792 | 851 |
793 return true; | 852 return true; |
794 } | 853 } |
795 | 854 |
796 // Called to get media capture device manager of specified type. | |
797 MediaStreamProvider* MediaStreamManager::GetDeviceManager( | 855 MediaStreamProvider* MediaStreamManager::GetDeviceManager( |
798 MediaStreamType stream_type) { | 856 MediaStreamType stream_type) { |
799 if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) { | 857 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
800 return video_capture_manager(); | 858 EnsureDeviceManagerStarted(stream_type); |
801 } else if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) { | 859 return device_manager_[stream_type]; |
802 return audio_input_device_manager(); | 860 } |
803 } | 861 |
804 NOTREACHED(); | 862 VideoCaptureManager* MediaStreamManager::GetVideoCaptureManager( |
805 return NULL; | 863 MediaStreamType stream_type) { |
864 DCHECK(content::IsVideoMediaType(stream_type)); | |
865 return reinterpret_cast<VideoCaptureManager*>(GetDeviceManager(stream_type)); | |
866 } | |
867 | |
868 AudioInputDeviceManager* MediaStreamManager::GetAudioInputDeviceManager( | |
869 MediaStreamType stream_type) { | |
870 DCHECK(content::IsAudioMediaType(stream_type)); | |
871 return reinterpret_cast<AudioInputDeviceManager*>( | |
872 GetDeviceManager(stream_type)); | |
806 } | 873 } |
807 | 874 |
808 void MediaStreamManager::OnDevicesChanged( | 875 void MediaStreamManager::OnDevicesChanged( |
809 base::SystemMonitor::DeviceType device_type) { | 876 base::SystemMonitor::DeviceType device_type) { |
810 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 877 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
878 | |
879 // NOTE: This method is only called in response to physical audio/video device | |
880 // changes (from the operating system). | |
881 | |
811 MediaStreamType stream_type; | 882 MediaStreamType stream_type; |
812 EnumerationCache* cache; | 883 EnumerationCache* cache; |
813 if (device_type == base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE) { | 884 if (device_type == base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE) { |
814 stream_type = content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE; | 885 stream_type = content::MEDIA_AUDIO_DEVICE_CAPTURE; |
815 cache = &audio_enumeration_cache_; | 886 cache = &audio_enumeration_cache_; |
816 } else if (device_type == base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE) { | 887 } else if (device_type == base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE) { |
817 stream_type = content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE; | 888 stream_type = content::MEDIA_VIDEO_DEVICE_CAPTURE; |
818 cache = &video_enumeration_cache_; | 889 cache = &video_enumeration_cache_; |
819 } else { | 890 } else { |
820 return; // Uninteresting device change. | 891 return; // Uninteresting device change. |
821 } | 892 } |
822 | 893 |
823 if (!HasEnumerationRequest(stream_type)) { | 894 if (!HasEnumerationRequest(stream_type)) { |
824 // There is no request for that type, No need to enumerate devices. | 895 // There is no request for that type, No need to enumerate devices. |
825 // Therefore, invalidate the cache of that type. | 896 // Therefore, invalidate the cache of that type. |
826 ClearEnumerationCache(cache); | 897 ClearEnumerationCache(cache); |
827 return; | 898 return; |
(...skipping 24 matching lines...) Expand all Loading... | |
852 it != requests_.end(); ++it) { | 923 it != requests_.end(); ++it) { |
853 if (it->second.type == DeviceRequest::ENUMERATE_DEVICES && | 924 if (it->second.type == DeviceRequest::ENUMERATE_DEVICES && |
854 Requested(it->second.options, stream_type)) { | 925 Requested(it->second.options, stream_type)) { |
855 return true; | 926 return true; |
856 } | 927 } |
857 } | 928 } |
858 return false; | 929 return false; |
859 } | 930 } |
860 | 931 |
861 } // namespace media_stream | 932 } // namespace media_stream |
OLD | NEW |