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