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 std::string requested_device_id; |
126 StreamDeviceInfoArray audio_devices; | 123 StreamDeviceInfoArray devices; |
127 StreamDeviceInfoArray video_devices; | |
128 }; | 124 }; |
129 | 125 |
130 MediaStreamManager::EnumerationCache::EnumerationCache() | 126 MediaStreamManager::EnumerationCache::EnumerationCache() |
131 : valid(false) { | 127 : valid(false) { |
132 } | 128 } |
133 | 129 |
134 MediaStreamManager::EnumerationCache::~EnumerationCache() { | 130 MediaStreamManager::EnumerationCache::~EnumerationCache() { |
135 } | 131 } |
136 | 132 |
137 MediaStreamManager::MediaStreamManager( | 133 MediaStreamManager::MediaStreamManager() |
138 AudioInputDeviceManager* audio_input_device_manager, | |
139 VideoCaptureManager* video_capture_manager) | |
140 : ALLOW_THIS_IN_INITIALIZER_LIST( | 134 : ALLOW_THIS_IN_INITIALIZER_LIST( |
141 device_settings_(new MediaStreamDeviceSettings(this))), | 135 device_settings_(new MediaStreamDeviceSettings(this))), |
142 audio_input_device_manager_(audio_input_device_manager), | 136 audio_manager_(NULL), |
143 video_capture_manager_(video_capture_manager), | |
144 monitoring_started_(false), | 137 monitoring_started_(false), |
145 io_loop_(NULL) { | 138 io_loop_(NULL) { |
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_AUDIO_DEVICE_CAPTURE || |
261 type == content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE); | 272 type == content::MEDIA_VIDEO_DEVICE_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_AUDIO_DEVICE_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_VIDEO_DEVICE_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_; | |
272 } | 285 } |
wjia(left Chromium)
2012/09/07 14:11:36
Based on the DCHECK at the beginning of this funct
miu
2012/09/07 23:14:28
(This was just left over from an earlier revision
| |
273 | 286 |
274 DeviceRequest new_request(requester, options, | 287 DeviceRequest new_request(requester, options, |
275 render_process_id, | 288 render_process_id, |
276 render_view_id, | 289 render_view_id, |
277 security_origin); | 290 security_origin); |
278 new_request.type = DeviceRequest::ENUMERATE_DEVICES; | 291 new_request.type = DeviceRequest::ENUMERATE_DEVICES; |
279 | 292 |
280 if (cache->valid) { | 293 if (cache && cache->valid) { |
281 // Cached device list of this type exists. Just send it out. | 294 // Cached device list of this type exists. Just send it out. |
282 new_request.state[type] = DeviceRequest::STATE_REQUESTED; | 295 new_request.state[type] = DeviceRequest::STATE_REQUESTED; |
283 AddRequest(&new_request, label); | 296 AddRequest(new_request, label); |
284 // Need to post a task since the requester won't have label till | 297 // Need to post a task since the requester won't have label till |
285 // this function returns. | 298 // this function returns. |
286 BrowserThread::PostTask(BrowserThread::IO, | 299 BrowserThread::PostTask(BrowserThread::IO, |
287 FROM_HERE, | 300 FROM_HERE, |
288 base::Bind(&MediaStreamManager::SendCachedDeviceList, | 301 base::Bind(&MediaStreamManager::SendCachedDeviceList, |
289 base::Unretained(this), cache, *label)); | 302 base::Unretained(this), cache, *label)); |
290 } else { | 303 } else { |
291 StartEnumeration(&new_request, label); | 304 StartEnumeration(&new_request, label); |
292 StartMonitoring(); | 305 if (cache) { |
306 StartMonitoring(); | |
307 } | |
293 } | 308 } |
294 } | 309 } |
295 | 310 |
296 void MediaStreamManager::StopEnumerateDevices(const std::string& label) { | 311 void MediaStreamManager::StopEnumerateDevices(const std::string& label) { |
297 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 312 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
298 | 313 |
299 DeviceRequests::iterator it = requests_.find(label); | 314 DeviceRequests::iterator it = requests_.find(label); |
300 if (it != requests_.end()) { | 315 if (it != requests_.end()) { |
301 DCHECK_EQ(it->second.type, DeviceRequest::ENUMERATE_DEVICES); | 316 DCHECK_EQ(it->second.type, DeviceRequest::ENUMERATE_DEVICES); |
302 requests_.erase(it); | 317 requests_.erase(it); |
303 if (!HasEnumerationRequest()) { | 318 if (!HasEnumerationRequest()) { |
304 StopMonitoring(); | 319 StopMonitoring(); |
305 } | 320 } |
306 } | 321 } |
307 } | 322 } |
308 | 323 |
309 void MediaStreamManager::OpenDevice( | 324 void MediaStreamManager::OpenDevice( |
310 MediaStreamRequester* requester, | 325 MediaStreamRequester* requester, |
311 int render_process_id, | 326 int render_process_id, |
312 int render_view_id, | 327 int render_view_id, |
313 const std::string& device_id, | 328 const std::string& device_id, |
314 MediaStreamType type, | 329 MediaStreamType type, |
315 const GURL& security_origin, | 330 const GURL& security_origin, |
316 std::string* label) { | 331 std::string* label) { |
317 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 332 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
333 DCHECK(type == content::MEDIA_AUDIO_DEVICE_CAPTURE || | |
334 type == content::MEDIA_VIDEO_DEVICE_CAPTURE); | |
wjia(left Chromium)
2012/09/07 14:11:36
Thanks for adding DCHECK!
| |
318 | 335 |
319 // Create a new request. | 336 // Create a new request. |
320 StreamOptions options; | 337 StreamOptions options; |
321 if (type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) | 338 if (content::IsAudioMediaType(type)) { |
322 options.audio = true; | 339 options.audio_type = type; |
323 else | 340 } else if (content::IsVideoMediaType(type)) { |
324 options.video = true; | 341 options.video_type = type; |
342 } else { | |
wjia(left Chromium)
2012/09/07 14:11:36
NOTREACHED() for this branch?
miu
2012/09/07 23:14:28
Done.
| |
343 LOG(FATAL) << "Cannot handle request for MediaStreamType " << type; | |
344 return; | |
345 } | |
325 | 346 |
326 DeviceRequest new_request(requester, options, | 347 DeviceRequest new_request(requester, options, |
327 render_process_id, | 348 render_process_id, |
328 render_view_id, | 349 render_view_id, |
329 security_origin); | 350 security_origin); |
330 new_request.type = DeviceRequest::OPEN_DEVICE; | 351 new_request.type = DeviceRequest::OPEN_DEVICE; |
331 new_request.requested_device_id = device_id; | 352 new_request.requested_device_id = device_id; |
332 | 353 |
333 StartEnumeration(&new_request, label); | 354 StartEnumeration(&new_request, label); |
334 } | 355 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
366 void MediaStreamManager::ClearEnumerationCache(EnumerationCache* cache) { | 387 void MediaStreamManager::ClearEnumerationCache(EnumerationCache* cache) { |
367 DCHECK_EQ(MessageLoop::current(), io_loop_); | 388 DCHECK_EQ(MessageLoop::current(), io_loop_); |
368 cache->valid = false; | 389 cache->valid = false; |
369 } | 390 } |
370 | 391 |
371 void MediaStreamManager::StartEnumeration( | 392 void MediaStreamManager::StartEnumeration( |
372 DeviceRequest* new_request, | 393 DeviceRequest* new_request, |
373 std::string* label) { | 394 std::string* label) { |
374 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 395 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
375 | 396 |
376 MediaStreamType stream_type = content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE; | 397 for (int i = content::MEDIA_NO_SERVICE + 1; i < content::NUM_MEDIA_TYPES; |
377 if (Requested(new_request->options, stream_type)) { | 398 ++i) { |
378 new_request->state[stream_type] = DeviceRequest::STATE_REQUESTED; | 399 const MediaStreamType stream_type = static_cast<MediaStreamType>(i); |
379 DCHECK_GE(active_enumeration_ref_count_[stream_type], 0); | 400 if (Requested(new_request->options, stream_type)) { |
380 if (!active_enumeration_ref_count_[stream_type]) { | 401 new_request->state[stream_type] = DeviceRequest::STATE_REQUESTED; |
381 ++active_enumeration_ref_count_[stream_type]; | 402 DCHECK_GE(active_enumeration_ref_count_[stream_type], 0); |
382 GetDeviceManager(stream_type)->EnumerateDevices(); | 403 if (active_enumeration_ref_count_[stream_type] == 0) { |
383 } | 404 ++active_enumeration_ref_count_[stream_type]; |
384 } | 405 GetDeviceManager(stream_type)->EnumerateDevices(); |
385 stream_type = content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE; | 406 } |
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 } | 407 } |
393 } | 408 } |
394 | 409 |
395 AddRequest(new_request, label); | 410 AddRequest(*new_request, label); |
396 } | 411 } |
397 | 412 |
398 void MediaStreamManager::AddRequest( | 413 void MediaStreamManager::AddRequest( |
399 DeviceRequest* new_request, | 414 const DeviceRequest& new_request, |
400 std::string* label) { | 415 std::string* label) { |
401 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 416 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
402 | 417 |
403 // Create a label for this request and verify it is unique. | 418 // Create a label for this request and verify it is unique. |
404 std::string request_label; | 419 std::string request_label; |
405 do { | 420 do { |
406 request_label = RandomLabel(); | 421 request_label = RandomLabel(); |
407 } while (requests_.find(request_label) != requests_.end()); | 422 } while (requests_.find(request_label) != requests_.end()); |
408 | 423 |
409 requests_.insert(std::make_pair(request_label, *new_request)); | 424 requests_.insert(std::make_pair(request_label, new_request)); |
410 | 425 |
411 (*label) = request_label; | 426 (*label) = request_label; |
412 } | 427 } |
413 | 428 |
414 void MediaStreamManager::EnsureDeviceThreadAndListener() { | 429 void MediaStreamManager::EnsureDeviceManagerStarted( |
430 MediaStreamType stream_type) { | |
415 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 431 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
416 if (device_thread_.get()) | |
417 return; | |
418 | 432 |
419 device_thread_.reset(new DeviceThread("MediaStreamDeviceThread")); | 433 if (!device_thread_.get()) { |
420 CHECK(device_thread_->Start()); | 434 device_thread_.reset(new DeviceThread("MediaStreamDeviceThread")); |
435 CHECK(device_thread_->Start()); | |
436 } | |
421 | 437 |
422 audio_input_device_manager_->Register(this, | 438 if (!device_manager_[stream_type]) { |
423 device_thread_->message_loop_proxy()); | 439 switch (stream_type) { |
424 video_capture_manager_->Register(this, device_thread_->message_loop_proxy()); | 440 case content::MEDIA_AUDIO_DEVICE_CAPTURE: |
441 case content::MEDIA_TAB_AUDIO_CAPTURE: | |
442 if (!audio_manager_) { | |
443 audio_manager_ = content::BrowserMainLoop::GetAudioManager(); | |
wjia(left Chromium)
2012/09/07 14:11:36
Injecting an audio_manager in ctor can remove the
miu
2012/09/07 23:14:28
Done.
| |
444 } | |
445 device_manager_[stream_type] = | |
446 new media_stream::AudioInputDeviceManager(audio_manager_, | |
447 stream_type); | |
448 break; | |
449 case content::MEDIA_VIDEO_DEVICE_CAPTURE: | |
450 case content::MEDIA_TAB_VIDEO_CAPTURE: | |
451 device_manager_[stream_type] = | |
452 new media_stream::VideoCaptureManager(stream_type); | |
453 break; | |
454 default: | |
455 LOG(FATAL) << "Cannot create device manager for invalid or " | |
456 << "unsupported MediaStreamType " << stream_type; | |
457 return; | |
458 } | |
459 device_manager_[stream_type]->Register( | |
460 this, device_thread_->message_loop_proxy()); | |
461 } | |
425 | 462 |
426 // We want to be notified of IO message loop destruction to delete the thread | 463 // We want to be notified of IO message loop destruction to delete the thread |
427 // and the device managers. | 464 // and the device managers. |
428 io_loop_ = MessageLoop::current(); | 465 if (!io_loop_) { |
429 io_loop_->AddDestructionObserver(this); | 466 io_loop_ = MessageLoop::current(); |
467 io_loop_->AddDestructionObserver(this); | |
468 } | |
430 } | 469 } |
431 | 470 |
432 void MediaStreamManager::Opened(MediaStreamType stream_type, | 471 void MediaStreamManager::Opened(MediaStreamType stream_type, |
433 int capture_session_id) { | 472 int capture_session_id) { |
434 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 473 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
435 | 474 |
436 // Find the request containing this device and mark it as used. | 475 // Find the request containing this device and mark it as used. |
437 DeviceRequest* request = NULL; | 476 DeviceRequest* request = NULL; |
438 StreamDeviceInfoArray* devices = NULL; | 477 StreamDeviceInfoArray* devices = NULL; |
439 std::string label; | 478 std::string label; |
440 for (DeviceRequests::iterator request_it = requests_.begin(); | 479 for (DeviceRequests::iterator request_it = requests_.begin(); |
441 request_it != requests_.end() && request == NULL; ++request_it) { | 480 request_it != requests_.end() && request == NULL; ++request_it) { |
442 if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) { | 481 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(); | 482 for (StreamDeviceInfoArray::iterator device_it = devices->begin(); |
451 device_it != devices->end(); ++device_it) { | 483 device_it != devices->end(); ++device_it) { |
452 if (device_it->session_id == capture_session_id) { | 484 if (device_it->stream_type == stream_type && |
485 device_it->session_id == capture_session_id) { | |
453 // We've found the request. | 486 // We've found the request. |
454 device_it->in_use = true; | 487 device_it->in_use = true; |
455 label = request_it->first; | 488 label = request_it->first; |
456 request = &(request_it->second); | 489 request = &(request_it->second); |
457 break; | 490 break; |
458 } | 491 } |
459 } | 492 } |
460 } | 493 } |
461 if (request == NULL) { | 494 if (request == NULL) { |
462 // The request doesn't exist. | 495 // The request doesn't exist. |
463 return; | 496 return; |
464 } | 497 } |
465 | 498 |
466 DCHECK_NE(request->state[stream_type], DeviceRequest::STATE_REQUESTED); | 499 DCHECK_NE(request->state[stream_type], DeviceRequest::STATE_REQUESTED); |
467 | 500 |
468 // Check if all devices for this stream type are opened. Update the state if | 501 // Check if all devices for this stream type are opened. Update the state if |
469 // they are. | 502 // they are. |
470 for (StreamDeviceInfoArray::iterator device_it = devices->begin(); | 503 for (StreamDeviceInfoArray::iterator device_it = devices->begin(); |
471 device_it != devices->end(); ++device_it) { | 504 device_it != devices->end(); ++device_it) { |
505 if (device_it->stream_type != stream_type) | |
506 continue; | |
472 if (device_it->in_use == false) { | 507 if (device_it->in_use == false) { |
473 // Wait for more devices to be opened before we're done. | 508 // Wait for more devices to be opened before we're done. |
474 return; | 509 return; |
475 } | 510 } |
476 } | 511 } |
477 request->state[stream_type] = DeviceRequest::STATE_DONE; | 512 request->state[stream_type] = DeviceRequest::STATE_DONE; |
478 | 513 |
479 if (!RequestDone(*request)) { | 514 if (!RequestDone(*request)) { |
480 // This stream_type is done, but not the other type. | 515 // This stream_type is done, but not the other type. |
481 return; | 516 return; |
482 } | 517 } |
483 | 518 |
519 // Partition the array of devices into audio vs video. | |
wjia(left Chromium)
2012/09/07 14:11:36
This portion of code (partitioning the devices int
miu
2012/09/07 23:14:28
Done.
| |
520 StreamDeviceInfoArray audio_devices, video_devices; | |
521 for (StreamDeviceInfoArray::const_iterator device_it = devices->begin(); | |
522 device_it != devices->end(); ++device_it) { | |
523 if (content::IsAudioMediaType(device_it->stream_type)) { | |
524 audio_devices.push_back(*device_it); | |
525 } else if (content::IsVideoMediaType(device_it->stream_type)) { | |
526 video_devices.push_back(*device_it); | |
527 } else { | |
528 NOTREACHED(); | |
529 } | |
530 } | |
531 | |
484 switch (request->type) { | 532 switch (request->type) { |
485 case DeviceRequest::OPEN_DEVICE: | 533 case DeviceRequest::OPEN_DEVICE: |
486 request->requester->DeviceOpened(label, (*devices)[0]); | 534 if (content::IsAudioMediaType(stream_type)) { |
535 request->requester->DeviceOpened(label, audio_devices.front()); | |
536 } else if (content::IsVideoMediaType(stream_type)) { | |
537 request->requester->DeviceOpened(label, video_devices.front()); | |
538 } else { | |
539 NOTREACHED(); | |
540 } | |
wjia(left Chromium)
2012/09/07 14:11:36
This change is not needed for DeviceRequest::OPEN_
miu
2012/09/07 23:14:28
Done.
| |
487 break; | 541 break; |
488 case DeviceRequest::GENERATE_STREAM: | 542 case DeviceRequest::GENERATE_STREAM: |
489 request->requester->StreamGenerated(label, request->audio_devices, | 543 request->requester->StreamGenerated(label, audio_devices, video_devices); |
490 request->video_devices); | |
491 NotifyObserverDevicesOpened(request); | 544 NotifyObserverDevicesOpened(request); |
492 break; | 545 break; |
493 default: | 546 default: |
494 NOTREACHED(); | 547 NOTREACHED(); |
548 break; | |
495 } | 549 } |
496 } | 550 } |
497 | 551 |
498 void MediaStreamManager::Closed(MediaStreamType stream_type, | 552 void MediaStreamManager::Closed(MediaStreamType stream_type, |
499 int capture_session_id) { | 553 int capture_session_id) { |
500 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 554 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
501 } | 555 } |
502 | 556 |
503 void MediaStreamManager::DevicesEnumerated( | 557 void MediaStreamManager::DevicesEnumerated( |
504 MediaStreamType stream_type, const StreamDeviceInfoArray& devices) { | 558 MediaStreamType stream_type, const StreamDeviceInfoArray& devices) { |
505 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 559 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
506 | 560 |
507 // Only cache device list when there is EnumerateDevices request, since | 561 // Only cache the device list when there is an EnumerateDevices request, since |
508 // other requests don't turn on device monitoring. | 562 // other requests don't turn on device monitoring. |
509 bool need_update_clients = false; | 563 bool need_update_clients = false; |
510 EnumerationCache* cache = | 564 EnumerationCache* cache = |
511 (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE ? | 565 (stream_type == content::MEDIA_AUDIO_DEVICE_CAPTURE ? |
512 &audio_enumeration_cache_ : &video_enumeration_cache_); | 566 &audio_enumeration_cache_ : &video_enumeration_cache_); |
513 if (HasEnumerationRequest(stream_type) && | 567 if (HasEnumerationRequest(stream_type) && |
514 (!cache->valid || | 568 (!cache->valid || |
515 devices.size() != cache->devices.size() || | 569 devices.size() != cache->devices.size() || |
516 !std::equal(devices.begin(), devices.end(), cache->devices.begin(), | 570 !std::equal(devices.begin(), devices.end(), cache->devices.begin(), |
517 media_stream::StreamDeviceInfo::IsEqual))) { | 571 media_stream::StreamDeviceInfo::IsEqual))) { |
518 cache->valid = true; | 572 cache->valid = true; |
519 cache->devices = devices; | 573 cache->devices = devices; |
520 need_update_clients = true; | 574 need_update_clients = true; |
521 } | 575 } |
(...skipping 14 matching lines...) Expand all Loading... | |
536 } | 590 } |
537 for (std::list<std::string>::iterator it = label_list.begin(); | 591 for (std::list<std::string>::iterator it = label_list.begin(); |
538 it != label_list.end(); ++it) { | 592 it != label_list.end(); ++it) { |
539 DeviceRequest& request = requests_[*it]; | 593 DeviceRequest& request = requests_[*it]; |
540 switch (request.type) { | 594 switch (request.type) { |
541 case DeviceRequest::ENUMERATE_DEVICES: | 595 case DeviceRequest::ENUMERATE_DEVICES: |
542 if (need_update_clients) | 596 if (need_update_clients) |
543 request.requester->DevicesEnumerated(*it, devices); | 597 request.requester->DevicesEnumerated(*it, devices); |
544 break; | 598 break; |
545 case DeviceRequest::OPEN_DEVICE: | 599 case DeviceRequest::OPEN_DEVICE: |
600 DCHECK(!request.requested_device_id.empty()); | |
546 for (StreamDeviceInfoArray::const_iterator device_it = devices.begin(); | 601 for (StreamDeviceInfoArray::const_iterator device_it = devices.begin(); |
547 device_it != devices.end(); device_it++) { | 602 device_it != devices.end(); ++device_it) { |
548 if (request.requested_device_id == device_it->device_id) { | 603 if (request.requested_device_id == device_it->device_id) { |
549 StreamDeviceInfo device = *device_it; | 604 StreamDeviceInfo device = *device_it; |
550 device.in_use = false; | 605 device.in_use = false; |
551 device.session_id = | 606 device.session_id = |
552 GetDeviceManager(device_it->stream_type)->Open(device); | 607 GetDeviceManager(device_it->stream_type)->Open(device); |
553 request.state[device_it->stream_type] = | 608 request.state[device_it->stream_type] = |
554 DeviceRequest::STATE_OPENING; | 609 DeviceRequest::STATE_OPENING; |
555 if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) | 610 request.devices.push_back(device); |
556 request.audio_devices.push_back(device); | |
557 else | |
558 request.video_devices.push_back(device); | |
559 break; | 611 break; |
560 } | 612 } |
561 } | 613 } |
562 break; | 614 break; |
563 default: | 615 default: |
564 device_settings_->AvailableDevices(*it, stream_type, devices); | 616 device_settings_->AvailableDevices(*it, stream_type, devices); |
617 break; | |
565 } | 618 } |
566 } | 619 } |
567 label_list.clear(); | 620 label_list.clear(); |
568 --active_enumeration_ref_count_[stream_type]; | 621 --active_enumeration_ref_count_[stream_type]; |
569 DCHECK_GE(active_enumeration_ref_count_[stream_type], 0); | 622 DCHECK_GE(active_enumeration_ref_count_[stream_type], 0); |
570 } | 623 } |
571 | 624 |
572 void MediaStreamManager::Error(MediaStreamType stream_type, | 625 void MediaStreamManager::Error(MediaStreamType stream_type, |
573 int capture_session_id, | 626 int capture_session_id, |
574 MediaStreamProviderError error) { | 627 MediaStreamProviderError error) { |
575 // Find the device for the error call. | 628 // Find the device for the error call. |
576 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 629 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
630 | |
577 for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end(); | 631 for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end(); |
578 ++it) { | 632 ++it) { |
579 StreamDeviceInfoArray* devices = NULL; | 633 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 | 634 |
588 int device_idx = 0; | 635 int audio_device_idx = -1; |
589 for (StreamDeviceInfoArray::iterator device_it = devices->begin(); | 636 int video_device_idx = -1; |
590 device_it != devices->end(); ++device_it, ++device_idx) { | 637 for (StreamDeviceInfoArray::iterator device_it = devices.begin(); |
591 if (device_it->session_id == capture_session_id) { | 638 device_it != devices.end(); ++device_it) { |
592 // We've found the failing device. Find the error case: | 639 if (content::IsAudioMediaType(device_it->stream_type)) { |
593 if (it->second.state[stream_type] == DeviceRequest::STATE_DONE) { | 640 ++audio_device_idx; |
594 // 1. Already opened -> signal device failure and close device. | 641 } else if (content::IsVideoMediaType(device_it->stream_type)) { |
595 // Use device_idx to signal which of the devices encountered an | 642 ++video_device_idx; |
596 // error. | 643 } else { |
597 if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) { | 644 NOTREACHED(); |
598 it->second.requester->AudioDeviceFailed(it->first, device_idx); | 645 continue; |
599 } else if (stream_type == | 646 } |
600 content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) { | 647 if (device_it->stream_type != stream_type || |
601 it->second.requester->VideoDeviceFailed(it->first, device_idx); | 648 device_it->session_id != capture_session_id) { |
602 } | 649 continue; |
603 GetDeviceManager(stream_type)->Close(capture_session_id); | 650 } |
604 // We don't erase the devices here so that we can update the UI | 651 // We've found the failing device. Find the error case: |
605 // properly in StopGeneratedStream(). | 652 if (it->second.state[stream_type] == DeviceRequest::STATE_DONE) { |
606 it->second.state[stream_type] = DeviceRequest::STATE_ERROR; | 653 // 1. Already opened -> signal device failure and close device. |
654 // Use device_idx to signal which of the devices encountered an | |
655 // error. | |
656 if (content::IsAudioMediaType(stream_type)) { | |
657 it->second.requester->AudioDeviceFailed(it->first, audio_device_idx); | |
658 } else if (content::IsVideoMediaType(stream_type)) { | |
659 it->second.requester->VideoDeviceFailed(it->first, video_device_idx); | |
607 } else { | 660 } else { |
608 // Request is not done, devices are not opened in this case. | 661 NOTREACHED(); |
609 if ((it->second.audio_devices.size() + | 662 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 } | 663 } |
621 return; | 664 GetDeviceManager(stream_type)->Close(capture_session_id); |
665 // We don't erase the devices here so that we can update the UI | |
666 // properly in StopGeneratedStream(). | |
667 it->second.state[stream_type] = DeviceRequest::STATE_ERROR; | |
668 } else { | |
669 // Request is not done, devices are not opened in this case. | |
670 if (devices.size() <= 1) { | |
671 // 2. Device not opened and no other devices for this request -> | |
672 // signal stream error and remove the request. | |
673 it->second.requester->StreamGenerationFailed(it->first); | |
674 requests_.erase(it); | |
675 } else { | |
676 // 3. Not opened but other devices exists for this request -> remove | |
677 // device from list, but don't signal an error. | |
678 devices.erase(device_it); // NOTE: This invalidates device_it! | |
679 } | |
622 } | 680 } |
681 return; | |
623 } | 682 } |
624 } | 683 } |
625 } | 684 } |
626 | 685 |
627 void MediaStreamManager::DevicesAccepted(const std::string& label, | 686 void MediaStreamManager::DevicesAccepted(const std::string& label, |
628 const StreamDeviceInfoArray& devices) { | 687 const StreamDeviceInfoArray& devices) { |
629 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 688 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
630 DeviceRequests::iterator request_it = requests_.find(label); | 689 DeviceRequests::iterator request_it = requests_.find(label); |
631 if (request_it != requests_.end()) { | 690 if (request_it == requests_.end()) |
632 if (devices.empty()) { | 691 return; |
633 // No available devices or user didn't accept device usage. | 692 |
634 request_it->second.requester->StreamGenerationFailed(request_it->first); | 693 DeviceRequest& request = request_it->second; |
635 requests_.erase(request_it); | 694 |
636 return; | 695 if (devices.empty()) { |
696 // No available devices or user didn't accept device usage. | |
697 request.requester->StreamGenerationFailed(request_it->first); | |
698 requests_.erase(request_it); | |
699 return; | |
700 } | |
701 | |
702 // Process all newly-accepted devices for this request. | |
703 for (StreamDeviceInfoArray::const_iterator device_it = devices.begin(); | |
704 device_it != devices.end(); ++device_it) { | |
705 StreamDeviceInfo device_info = *device_it; // Make a copy. | |
706 | |
707 // Set in_use to false to be able to track if this device has been | |
708 // opened. in_use might be true if the device type can be used in more | |
709 // than one session. | |
710 DCHECK_EQ(request.state[device_it->stream_type], | |
711 DeviceRequest::STATE_PENDING_APPROVAL); | |
712 device_info.in_use = false; | |
713 device_info.session_id = | |
714 GetDeviceManager(device_info.stream_type)->Open(device_info); | |
715 request.state[device_it->stream_type] = DeviceRequest::STATE_OPENING; | |
716 request.devices.push_back(device_info); | |
717 } | |
718 | |
719 // Check whether we've received all stream types requested. | |
720 bool found_audio = false, found_video = false; | |
721 for (StreamDeviceInfoArray::const_iterator i = request.devices.begin(); | |
722 i != request.devices.end(); ++i) { | |
wjia(left Chromium)
2012/09/07 14:11:36
This for loop can be merged with for loop above.
miu
2012/09/07 23:14:28
Done.
| |
723 if (i->stream_type == request.options.audio_type) { | |
724 found_audio = true; | |
725 } else if (i->stream_type == request.options.video_type) { | |
726 found_video = true; | |
727 } else { | |
728 NOTREACHED(); | |
637 } | 729 } |
638 | 730 } |
639 // Loop through all device types for this request. | 731 if (request.options.audio_type != content::MEDIA_NO_SERVICE && |
640 for (StreamDeviceInfoArray::const_iterator device_it = devices.begin(); | 732 !found_audio) { |
641 device_it != devices.end(); ++device_it) { | 733 request.state[request.options.audio_type] = DeviceRequest::STATE_ERROR; |
642 StreamDeviceInfo device_info = *device_it; | 734 } |
643 | 735 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 | 736 !found_video) { |
645 // opened. in_use might be true if the device type can be used in more | 737 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 } | 738 } |
678 } | 739 } |
679 | 740 |
680 void MediaStreamManager::SettingsError(const std::string& label) { | 741 void MediaStreamManager::SettingsError(const std::string& label) { |
681 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 742 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
682 // Erase this request and report an error. | 743 // Erase this request and report an error. |
683 DeviceRequests::iterator it = requests_.find(label); | 744 DeviceRequests::iterator it = requests_.find(label); |
684 if (it != requests_.end()) { | 745 if (it != requests_.end()) { |
685 DCHECK_EQ(it->second.type, DeviceRequest::GENERATE_STREAM); | 746 DCHECK_EQ(it->second.type, DeviceRequest::GENERATE_STREAM); |
686 it->second.requester->StreamGenerationFailed(label); | 747 it->second.requester->StreamGenerationFailed(label); |
687 requests_.erase(it); | 748 requests_.erase(it); |
688 return; | 749 return; |
689 } | 750 } |
690 } | 751 } |
691 | 752 |
753 void MediaStreamManager::SetAudioManager(media::AudioManager* audio_manager) { | |
754 LOG_IF(FATAL, (audio_manager_ != NULL) && (audio_manager_ != audio_manager)) | |
755 << "Cannot override AudioManager after it has been set."; | |
756 audio_manager_ = audio_manager; | |
757 } | |
758 | |
692 void MediaStreamManager::UseFakeDevice() { | 759 void MediaStreamManager::UseFakeDevice() { |
693 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 760 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
694 video_capture_manager()->UseFakeDevice(); | 761 for (int i = content::MEDIA_NO_SERVICE + 1; i < content::NUM_MEDIA_TYPES; |
762 ++i) { | |
763 const MediaStreamType stream_type = static_cast<MediaStreamType>(i); | |
764 if (content::IsVideoMediaType(stream_type)) { | |
765 GetVideoCaptureManager(stream_type)->UseFakeDevice(); | |
766 } | |
767 } | |
695 device_settings_->UseFakeUI(); | 768 device_settings_->UseFakeUI(); |
696 } | 769 } |
697 | 770 |
698 void MediaStreamManager::WillDestroyCurrentMessageLoop() { | 771 void MediaStreamManager::WillDestroyCurrentMessageLoop() { |
699 DCHECK_EQ(MessageLoop::current(), io_loop_); | 772 DCHECK_EQ(MessageLoop::current(), io_loop_); |
700 DCHECK(requests_.empty()); | 773 DCHECK(requests_.empty()); |
701 if (device_thread_.get()) { | 774 if (device_thread_.get()) { |
702 StopMonitoring(); | 775 StopMonitoring(); |
703 | 776 |
704 video_capture_manager_->Unregister(); | 777 for (int i = content::MEDIA_NO_SERVICE + 1; i < content::NUM_MEDIA_TYPES; |
705 audio_input_device_manager_->Unregister(); | 778 ++i) { |
779 if (device_manager_[i]) { | |
780 device_manager_[i]->Unregister(); | |
781 } | |
782 } | |
783 | |
706 device_thread_.reset(); | 784 device_thread_.reset(); |
707 } | 785 } |
708 | 786 |
709 audio_input_device_manager_ = NULL; | 787 for (int i = content::MEDIA_NO_SERVICE + 1; i < content::NUM_MEDIA_TYPES; |
710 video_capture_manager_ = NULL; | 788 ++i) { |
789 device_manager_[i] = NULL; | |
790 } | |
711 io_loop_ = NULL; | 791 io_loop_ = NULL; |
712 device_settings_.reset(); | 792 device_settings_.reset(); |
713 } | 793 } |
714 | 794 |
715 void MediaStreamManager::NotifyObserverDevicesOpened(DeviceRequest* request) { | 795 void MediaStreamManager::NotifyObserverDevicesOpened(DeviceRequest* request) { |
716 content::MediaObserver* media_observer = | 796 content::MediaObserver* media_observer = |
717 content::GetContentClient()->browser()->GetMediaObserver(); | 797 content::GetContentClient()->browser()->GetMediaObserver(); |
718 content::MediaStreamDevices opened_devices; | 798 content::MediaStreamDevices opened_devices; |
719 DevicesFromRequest(request, &opened_devices); | 799 DevicesFromRequest(request, &opened_devices); |
720 DCHECK(!opened_devices.empty()); | 800 DCHECK(!opened_devices.empty()); |
721 media_observer->OnCaptureDevicesOpened(request->render_process_id, | 801 media_observer->OnCaptureDevicesOpened(request->render_process_id, |
722 request->render_view_id, | 802 request->render_view_id, |
723 opened_devices); | 803 opened_devices); |
724 } | 804 } |
725 | 805 |
726 void MediaStreamManager::NotifyObserverDevicesClosed(DeviceRequest* request) { | 806 void MediaStreamManager::NotifyObserverDevicesClosed(DeviceRequest* request) { |
727 content::MediaObserver* media_observer = | 807 content::MediaObserver* media_observer = |
728 content::GetContentClient()->browser()->GetMediaObserver(); | 808 content::GetContentClient()->browser()->GetMediaObserver(); |
729 content::MediaStreamDevices closed_devices; | 809 content::MediaStreamDevices closed_devices; |
730 DevicesFromRequest(request, &closed_devices); | 810 DevicesFromRequest(request, &closed_devices); |
731 if (closed_devices.empty()) | 811 if (closed_devices.empty()) |
732 return; | 812 return; |
733 media_observer->OnCaptureDevicesClosed(request->render_process_id, | 813 media_observer->OnCaptureDevicesClosed(request->render_process_id, |
734 request->render_view_id, | 814 request->render_view_id, |
735 closed_devices); | 815 closed_devices); |
736 } | 816 } |
737 | 817 |
738 void MediaStreamManager::DevicesFromRequest( | 818 void MediaStreamManager::DevicesFromRequest( |
739 DeviceRequest* request, content::MediaStreamDevices* devices) { | 819 DeviceRequest* request, content::MediaStreamDevices* devices) { |
740 StreamDeviceInfoArray::const_iterator it = request->audio_devices.begin(); | 820 for (StreamDeviceInfoArray::const_iterator it = request->devices.begin(); |
741 for (; it != request->audio_devices.end(); ++it) { | 821 it != request->devices.end(); ++it) { |
742 devices->push_back( | 822 devices->push_back(content::MediaStreamDevice( |
743 content::MediaStreamDevice( | 823 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 } | 824 } |
756 } | 825 } |
757 | 826 |
758 bool MediaStreamManager::RequestDone(const DeviceRequest& request) const { | 827 bool MediaStreamManager::RequestDone(const DeviceRequest& request) const { |
759 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 828 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 | 829 |
768 for (StreamDeviceInfoArray::const_iterator it = | 830 const bool requested_audio = |
769 request.audio_devices.begin(); it != request.audio_devices.end(); | 831 content::IsAudioMediaType(request.options.audio_type); |
770 ++it) { | 832 const bool requested_video = |
771 if (it->in_use == false) { | 833 content::IsVideoMediaType(request.options.video_type); |
772 return false; | 834 |
773 } | 835 const bool audio_done = |
774 } | 836 !requested_audio || |
837 request.state[request.options.audio_type] == DeviceRequest::STATE_DONE || | |
838 request.state[request.options.audio_type] == DeviceRequest::STATE_ERROR; | |
839 if (!audio_done) { | |
840 return false; | |
775 } | 841 } |
776 | 842 |
777 stream_type = content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE; | 843 const bool video_done = |
778 if (Requested(request.options, stream_type)) { | 844 !requested_video || |
779 if (request.state[stream_type] != DeviceRequest::STATE_DONE && | 845 request.state[request.options.video_type] == DeviceRequest::STATE_DONE || |
780 request.state[stream_type] != DeviceRequest::STATE_ERROR) { | 846 request.state[request.options.video_type] == DeviceRequest::STATE_ERROR; |
847 if (!video_done) { | |
848 return false; | |
849 } | |
850 | |
851 for (StreamDeviceInfoArray::const_iterator it = request.devices.begin(); | |
852 it != request.devices.end(); ++it) { | |
853 if ((!requested_audio && content::IsAudioMediaType(it->stream_type)) || | |
854 (!requested_video && content::IsVideoMediaType(it->stream_type))) { | |
wjia(left Chromium)
2012/09/07 14:11:36
This won't happen since the "request" only accepts
miu
2012/09/07 23:14:28
Done.
| |
855 continue; | |
856 } | |
857 if (it->in_use == false) { | |
781 return false; | 858 return false; |
782 } | 859 } |
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 } | 860 } |
792 | 861 |
793 return true; | 862 return true; |
794 } | 863 } |
795 | 864 |
796 // Called to get media capture device manager of specified type. | |
797 MediaStreamProvider* MediaStreamManager::GetDeviceManager( | 865 MediaStreamProvider* MediaStreamManager::GetDeviceManager( |
798 MediaStreamType stream_type) { | 866 MediaStreamType stream_type) { |
799 if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) { | 867 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
800 return video_capture_manager(); | 868 EnsureDeviceManagerStarted(stream_type); |
801 } else if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) { | 869 return device_manager_[stream_type]; |
802 return audio_input_device_manager(); | 870 } |
803 } | 871 |
804 NOTREACHED(); | 872 VideoCaptureManager* MediaStreamManager::GetVideoCaptureManager( |
805 return NULL; | 873 MediaStreamType stream_type) { |
874 DCHECK(content::IsVideoMediaType(stream_type)); | |
875 return reinterpret_cast<VideoCaptureManager*>(GetDeviceManager(stream_type)); | |
876 } | |
877 | |
878 AudioInputDeviceManager* MediaStreamManager::GetAudioInputDeviceManager( | |
879 MediaStreamType stream_type) { | |
880 DCHECK(content::IsAudioMediaType(stream_type)); | |
881 return reinterpret_cast<AudioInputDeviceManager*>( | |
882 GetDeviceManager(stream_type)); | |
806 } | 883 } |
807 | 884 |
808 void MediaStreamManager::OnDevicesChanged( | 885 void MediaStreamManager::OnDevicesChanged( |
809 base::SystemMonitor::DeviceType device_type) { | 886 base::SystemMonitor::DeviceType device_type) { |
810 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 887 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
888 | |
889 // NOTE: This method is only called in response to physical audio/video device | |
890 // changes (from the operating system). | |
891 | |
811 MediaStreamType stream_type; | 892 MediaStreamType stream_type; |
812 EnumerationCache* cache; | 893 EnumerationCache* cache; |
813 if (device_type == base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE) { | 894 if (device_type == base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE) { |
814 stream_type = content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE; | 895 stream_type = content::MEDIA_AUDIO_DEVICE_CAPTURE; |
815 cache = &audio_enumeration_cache_; | 896 cache = &audio_enumeration_cache_; |
816 } else if (device_type == base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE) { | 897 } else if (device_type == base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE) { |
817 stream_type = content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE; | 898 stream_type = content::MEDIA_VIDEO_DEVICE_CAPTURE; |
818 cache = &video_enumeration_cache_; | 899 cache = &video_enumeration_cache_; |
819 } else { | 900 } else { |
820 return; // Uninteresting device change. | 901 return; // Uninteresting device change. |
821 } | 902 } |
822 | 903 |
823 if (!HasEnumerationRequest(stream_type)) { | 904 if (!HasEnumerationRequest(stream_type)) { |
824 // There is no request for that type, No need to enumerate devices. | 905 // There is no request for that type, No need to enumerate devices. |
825 // Therefore, invalidate the cache of that type. | 906 // Therefore, invalidate the cache of that type. |
826 ClearEnumerationCache(cache); | 907 ClearEnumerationCache(cache); |
827 return; | 908 return; |
(...skipping 24 matching lines...) Expand all Loading... | |
852 it != requests_.end(); ++it) { | 933 it != requests_.end(); ++it) { |
853 if (it->second.type == DeviceRequest::ENUMERATE_DEVICES && | 934 if (it->second.type == DeviceRequest::ENUMERATE_DEVICES && |
854 Requested(it->second.options, stream_type)) { | 935 Requested(it->second.options, stream_type)) { |
855 return true; | 936 return true; |
856 } | 937 } |
857 } | 938 } |
858 return false; | 939 return false; |
859 } | 940 } |
860 | 941 |
861 } // namespace media_stream | 942 } // namespace media_stream |
OLD | NEW |