| 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/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 #include "content/public/browser/media_observer.h" | 22 #include "content/public/browser/media_observer.h" |
| 23 #include "content/public/browser/media_request_state.h" | 23 #include "content/public/browser/media_request_state.h" |
| 24 #include "content/public/common/content_switches.h" | 24 #include "content/public/common/content_switches.h" |
| 25 #include "content/public/common/media_stream_request.h" | 25 #include "content/public/common/media_stream_request.h" |
| 26 #include "googleurl/src/gurl.h" | 26 #include "googleurl/src/gurl.h" |
| 27 | 27 |
| 28 #if defined(OS_WIN) | 28 #if defined(OS_WIN) |
| 29 #include "base/win/scoped_com_initializer.h" | 29 #include "base/win/scoped_com_initializer.h" |
| 30 #endif | 30 #endif |
| 31 | 31 |
| 32 using content::BrowserThread; | |
| 33 using content::MediaStreamRequest; | |
| 34 | |
| 35 namespace { | 32 namespace { |
| 36 const char kExtensionScheme[] = "chrome-extension"; | 33 const char kExtensionScheme[] = "chrome-extension"; |
| 37 } // namespace | 34 } // namespace |
| 38 | 35 |
| 39 namespace media_stream { | 36 namespace content { |
| 40 | 37 |
| 41 // Creates a random label used to identify requests. | 38 // Creates a random label used to identify requests. |
| 42 static std::string RandomLabel() { | 39 static std::string RandomLabel() { |
| 43 // An earlier PeerConnection spec, | 40 // An earlier PeerConnection spec, |
| 44 // http://dev.w3.org/2011/webrtc/editor/webrtc.html, specified the | 41 // http://dev.w3.org/2011/webrtc/editor/webrtc.html, specified the |
| 45 // MediaStream::label alphabet as containing 36 characters from | 42 // MediaStream::label alphabet as containing 36 characters from |
| 46 // range: U+0021, U+0023 to U+0027, U+002A to U+002B, U+002D to U+002E, | 43 // range: U+0021, U+0023 to U+0027, U+002A to U+002B, U+002D to U+002E, |
| 47 // U+0030 to U+0039, U+0041 to U+005A, U+005E to U+007E. | 44 // U+0030 to U+0039, U+0041 to U+005A, U+005E to U+007E. |
| 48 // Here we use a safe subset. | 45 // Here we use a safe subset. |
| 49 static const char kAlphabet[] = "0123456789" | 46 static const char kAlphabet[] = "0123456789" |
| (...skipping 22 matching lines...) Expand all Loading... |
| 72 GENERATE_STREAM, | 69 GENERATE_STREAM, |
| 73 ENUMERATE_DEVICES, | 70 ENUMERATE_DEVICES, |
| 74 OPEN_DEVICE | 71 OPEN_DEVICE |
| 75 }; | 72 }; |
| 76 | 73 |
| 77 DeviceRequest() | 74 DeviceRequest() |
| 78 : requester(NULL), | 75 : requester(NULL), |
| 79 type(GENERATE_STREAM), | 76 type(GENERATE_STREAM), |
| 80 render_process_id(-1), | 77 render_process_id(-1), |
| 81 render_view_id(-1), | 78 render_view_id(-1), |
| 82 state_(content::NUM_MEDIA_TYPES, | 79 state_(NUM_MEDIA_TYPES, MEDIA_REQUEST_STATE_NOT_REQUESTED) { |
| 83 content::MEDIA_REQUEST_STATE_NOT_REQUESTED) { | |
| 84 } | 80 } |
| 85 | 81 |
| 86 DeviceRequest(MediaStreamRequester* requester, | 82 DeviceRequest(MediaStreamRequester* requester, |
| 87 const StreamOptions& request_options, | 83 const StreamOptions& request_options, |
| 88 RequestType request_type, | 84 RequestType request_type, |
| 89 int render_process_id, | 85 int render_process_id, |
| 90 int render_view_id, | 86 int render_view_id, |
| 91 const GURL& request_security_origin) | 87 const GURL& request_security_origin) |
| 92 : requester(requester), | 88 : requester(requester), |
| 93 options(request_options), | 89 options(request_options), |
| 94 type(request_type), | 90 type(request_type), |
| 95 render_process_id(render_process_id), | 91 render_process_id(render_process_id), |
| 96 render_view_id(render_view_id), | 92 render_view_id(render_view_id), |
| 97 security_origin(request_security_origin), | 93 security_origin(request_security_origin), |
| 98 state_(content::NUM_MEDIA_TYPES, | 94 state_(NUM_MEDIA_TYPES, MEDIA_REQUEST_STATE_NOT_REQUESTED) { |
| 99 content::MEDIA_REQUEST_STATE_NOT_REQUESTED) { | |
| 100 } | 95 } |
| 101 | 96 |
| 102 ~DeviceRequest() {} | 97 ~DeviceRequest() {} |
| 103 | 98 |
| 104 // Update the request state and notify observers. | 99 // Update the request state and notify observers. |
| 105 void setState(MediaStreamType stream_type, | 100 void setState(MediaStreamType stream_type, MediaRequestState new_state) { |
| 106 content::MediaRequestState new_state) { | |
| 107 state_[stream_type] = new_state; | 101 state_[stream_type] = new_state; |
| 108 | 102 |
| 109 if (options.video_type != content::MEDIA_TAB_VIDEO_CAPTURE && | 103 if (options.video_type != MEDIA_TAB_VIDEO_CAPTURE && |
| 110 options.audio_type != content::MEDIA_TAB_AUDIO_CAPTURE) | 104 options.audio_type != MEDIA_TAB_AUDIO_CAPTURE) |
| 111 return; | 105 return; |
| 112 | 106 |
| 113 content::MediaObserver* media_observer = | 107 MediaObserver* media_observer = |
| 114 content::GetContentClient()->browser()->GetMediaObserver(); | 108 GetContentClient()->browser()->GetMediaObserver(); |
| 115 if (media_observer == NULL) | 109 if (media_observer == NULL) |
| 116 return; | 110 return; |
| 117 | 111 |
| 118 media_observer->OnMediaRequestStateChanged( | 112 media_observer->OnMediaRequestStateChanged( |
| 119 render_process_id, render_view_id, | 113 render_process_id, render_view_id, |
| 120 content::MediaStreamDevice(stream_type, | 114 MediaStreamDevice( |
| 121 requested_device_id, | 115 stream_type, requested_device_id, requested_device_id), new_state); |
| 122 requested_device_id), | |
| 123 new_state); | |
| 124 } | 116 } |
| 125 | 117 |
| 126 content::MediaRequestState getState(MediaStreamType stream_type) const { | 118 MediaRequestState getState(MediaStreamType stream_type) const { |
| 127 return state_[stream_type]; | 119 return state_[stream_type]; |
| 128 } | 120 } |
| 129 | 121 |
| 130 MediaStreamRequester* requester; // Can be NULL. | 122 MediaStreamRequester* requester; // Can be NULL. |
| 131 StreamOptions options; | 123 StreamOptions options; |
| 132 RequestType type; | 124 RequestType type; |
| 133 int render_process_id; | 125 int render_process_id; |
| 134 int render_view_id; | 126 int render_view_id; |
| 135 GURL security_origin; | 127 GURL security_origin; |
| 136 std::string requested_device_id; | 128 std::string requested_device_id; |
| 137 StreamDeviceInfoArray devices; | 129 StreamDeviceInfoArray devices; |
| 138 | 130 |
| 139 // Callback to the requester which audio/video devices have been selected. | 131 // Callback to the requester which audio/video devices have been selected. |
| 140 // It can be null if the requester has no interest to know the result. | 132 // It can be null if the requester has no interest to know the result. |
| 141 // Currently it is only used by |DEVICE_ACCESS| type. | 133 // Currently it is only used by |DEVICE_ACCESS| type. |
| 142 media_stream::MediaRequestResponseCallback callback; | 134 MediaRequestResponseCallback callback; |
| 143 | 135 |
| 144 private: | 136 private: |
| 145 std::vector<content::MediaRequestState> state_; | 137 std::vector<MediaRequestState> state_; |
| 146 }; | 138 }; |
| 147 | 139 |
| 148 MediaStreamManager::EnumerationCache::EnumerationCache() | 140 MediaStreamManager::EnumerationCache::EnumerationCache() |
| 149 : valid(false) { | 141 : valid(false) { |
| 150 } | 142 } |
| 151 | 143 |
| 152 MediaStreamManager::EnumerationCache::~EnumerationCache() { | 144 MediaStreamManager::EnumerationCache::~EnumerationCache() { |
| 153 } | 145 } |
| 154 | 146 |
| 155 MediaStreamManager::MediaStreamManager(media::AudioManager* audio_manager) | 147 MediaStreamManager::MediaStreamManager(media::AudioManager* audio_manager) |
| 156 : ALLOW_THIS_IN_INITIALIZER_LIST( | 148 : ALLOW_THIS_IN_INITIALIZER_LIST( |
| 157 ui_controller_(new content::MediaStreamUIController(this))), | 149 ui_controller_(new MediaStreamUIController(this))), |
| 158 audio_manager_(audio_manager), | 150 audio_manager_(audio_manager), |
| 159 monitoring_started_(false), | 151 monitoring_started_(false), |
| 160 io_loop_(NULL) { | 152 io_loop_(NULL) { |
| 161 DCHECK(audio_manager_); | 153 DCHECK(audio_manager_); |
| 162 memset(active_enumeration_ref_count_, 0, | 154 memset(active_enumeration_ref_count_, 0, |
| 163 sizeof(active_enumeration_ref_count_)); | 155 sizeof(active_enumeration_ref_count_)); |
| 164 } | 156 } |
| 165 | 157 |
| 166 MediaStreamManager::~MediaStreamManager() { | 158 MediaStreamManager::~MediaStreamManager() { |
| 167 DCHECK(requests_.empty()); | 159 DCHECK(requests_.empty()); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 render_process_id, render_view_id, | 236 render_process_id, render_view_id, |
| 245 security_origin), | 237 security_origin), |
| 246 label); | 238 label); |
| 247 DeviceRequest& request = requests_[*label]; | 239 DeviceRequest& request = requests_[*label]; |
| 248 request.requested_device_id = device_id; | 240 request.requested_device_id = device_id; |
| 249 | 241 |
| 250 // Get user confirmation to use the capture device. | 242 // Get user confirmation to use the capture device. |
| 251 PostRequestToUI(*label); | 243 PostRequestToUI(*label); |
| 252 | 244 |
| 253 if (!security_origin.SchemeIs(kExtensionScheme) || | 245 if (!security_origin.SchemeIs(kExtensionScheme) || |
| 254 (options.audio_type != content::MEDIA_TAB_AUDIO_CAPTURE && | 246 (options.audio_type != MEDIA_TAB_AUDIO_CAPTURE && |
| 255 options.audio_type != content::MEDIA_NO_SERVICE) || | 247 options.audio_type != MEDIA_NO_SERVICE) || |
| 256 (options.video_type != content::MEDIA_TAB_VIDEO_CAPTURE && | 248 (options.video_type != MEDIA_TAB_VIDEO_CAPTURE && |
| 257 options.video_type != content::MEDIA_NO_SERVICE)) { | 249 options.video_type != MEDIA_NO_SERVICE)) { |
| 258 LOG(ERROR) << "Invalid request or used tab capture outside extension API."; | 250 LOG(ERROR) << "Invalid request or used tab capture outside extension API."; |
| 259 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 251 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 260 base::Bind(&MediaStreamManager::CancelRequest, | 252 base::Bind(&MediaStreamManager::CancelRequest, |
| 261 base::Unretained(this), *label)); | 253 base::Unretained(this), *label)); |
| 262 return; | 254 return; |
| 263 } | 255 } |
| 264 | 256 |
| 265 // TODO(miu): We should ask the device manager whether a device with id | 257 // TODO(miu): We should ask the device manager whether a device with id |
| 266 // |device_id| actually exists. Note that no such MediaStreamProvider API for | 258 // |device_id| actually exists. Note that no such MediaStreamProvider API for |
| 267 // this currently exists. Also, we don't have a user-friendly device name for | 259 // this currently exists. Also, we don't have a user-friendly device name for |
| 268 // the infobar UI. | 260 // the infobar UI. |
| 269 if (content::IsAudioMediaType(options.audio_type)) { | 261 if (IsAudioMediaType(options.audio_type)) { |
| 270 // TODO(justinlin): Updating the state to requested and pending are no-ops | 262 // TODO(justinlin): Updating the state to requested and pending are no-ops |
| 271 // in terms of the media manager, but these are the state changes we want to | 263 // in terms of the media manager, but these are the state changes we want to |
| 272 // support in terms of extensions (which is registered as an observer). | 264 // support in terms of extensions (which is registered as an observer). |
| 273 request.setState(options.audio_type, | 265 request.setState(options.audio_type, MEDIA_REQUEST_STATE_REQUESTED); |
| 274 content::MEDIA_REQUEST_STATE_REQUESTED); | 266 request.setState(options.audio_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL); |
| 275 request.setState(options.audio_type, | |
| 276 content::MEDIA_REQUEST_STATE_PENDING_APPROVAL); | |
| 277 ui_controller_->AddAvailableDevicesToRequest( | 267 ui_controller_->AddAvailableDevicesToRequest( |
| 278 *label, options.audio_type, StreamDeviceInfoArray( | 268 *label, options.audio_type, StreamDeviceInfoArray( |
| 279 1, StreamDeviceInfo(options.audio_type, device_id, device_id, | 269 1, StreamDeviceInfo(options.audio_type, device_id, device_id, |
| 280 false))); | 270 false))); |
| 281 } | 271 } |
| 282 if (content::IsVideoMediaType(options.video_type)) { | 272 if (IsVideoMediaType(options.video_type)) { |
| 283 request.setState(options.video_type, | 273 request.setState(options.video_type, MEDIA_REQUEST_STATE_REQUESTED); |
| 284 content::MEDIA_REQUEST_STATE_REQUESTED); | 274 request.setState(options.video_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL); |
| 285 request.setState(options.video_type, | |
| 286 content::MEDIA_REQUEST_STATE_PENDING_APPROVAL); | |
| 287 ui_controller_->AddAvailableDevicesToRequest( | 275 ui_controller_->AddAvailableDevicesToRequest( |
| 288 *label, options.video_type, StreamDeviceInfoArray( | 276 *label, options.video_type, StreamDeviceInfoArray( |
| 289 1, StreamDeviceInfo(options.video_type, device_id, device_id, | 277 1, StreamDeviceInfo(options.video_type, device_id, device_id, |
| 290 false))); | 278 false))); |
| 291 } | 279 } |
| 292 } | 280 } |
| 293 | 281 |
| 294 void MediaStreamManager::CancelRequest(const std::string& label) { | 282 void MediaStreamManager::CancelRequest(const std::string& label) { |
| 295 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 283 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 296 | 284 |
| 297 DeviceRequests::iterator it = requests_.find(label); | 285 DeviceRequests::iterator it = requests_.find(label); |
| 298 if (it != requests_.end()) { | 286 if (it != requests_.end()) { |
| 299 // The request isn't complete, notify the UI immediately. | 287 // The request isn't complete, notify the UI immediately. |
| 300 ui_controller_->CancelUIRequest(label); | 288 ui_controller_->CancelUIRequest(label); |
| 301 | 289 |
| 302 if (!RequestDone(it->second)) { | 290 if (!RequestDone(it->second)) { |
| 303 // TODO(xians): update the |state| to STATE_DONE to trigger a state | 291 // TODO(xians): update the |state| to STATE_DONE to trigger a state |
| 304 // changed notification to UI before deleting the request? | 292 // changed notification to UI before deleting the request? |
| 305 DeviceRequest& request = it->second; | 293 DeviceRequest& request = it->second; |
| 306 for (int i = content::MEDIA_NO_SERVICE + 1; i < content::NUM_MEDIA_TYPES; | 294 for (int i = MEDIA_NO_SERVICE + 1; i < NUM_MEDIA_TYPES; |
| 307 ++i) { | 295 ++i) { |
| 308 const MediaStreamType stream_type = static_cast<MediaStreamType>(i); | 296 const MediaStreamType stream_type = static_cast<MediaStreamType>(i); |
| 309 if (request.getState(stream_type) != | 297 if (request.getState(stream_type) != MEDIA_REQUEST_STATE_OPENING) { |
| 310 content::MEDIA_REQUEST_STATE_OPENING) { | |
| 311 continue; | 298 continue; |
| 312 } | 299 } |
| 313 for (StreamDeviceInfoArray::const_iterator device_it = | 300 for (StreamDeviceInfoArray::const_iterator device_it = |
| 314 request.devices.begin(); | 301 request.devices.begin(); |
| 315 device_it != request.devices.end(); ++device_it) { | 302 device_it != request.devices.end(); ++device_it) { |
| 316 if (device_it->stream_type == stream_type) { | 303 if (device_it->stream_type == stream_type) { |
| 317 GetDeviceManager(stream_type)->Close(device_it->session_id); | 304 GetDeviceManager(stream_type)->Close(device_it->session_id); |
| 318 } | 305 } |
| 319 } | 306 } |
| 320 } | 307 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 337 return; | 324 return; |
| 338 } | 325 } |
| 339 for (StreamDeviceInfoArray::const_iterator device_it = | 326 for (StreamDeviceInfoArray::const_iterator device_it = |
| 340 it->second.devices.begin(); | 327 it->second.devices.begin(); |
| 341 device_it != it->second.devices.end(); ++device_it) { | 328 device_it != it->second.devices.end(); ++device_it) { |
| 342 GetDeviceManager(device_it->stream_type)->Close(device_it->session_id); | 329 GetDeviceManager(device_it->stream_type)->Close(device_it->session_id); |
| 343 } | 330 } |
| 344 if (it->second.type == DeviceRequest::GENERATE_STREAM && | 331 if (it->second.type == DeviceRequest::GENERATE_STREAM && |
| 345 RequestDone(it->second)) { | 332 RequestDone(it->second)) { |
| 346 // Notify observers that this device is being closed. | 333 // Notify observers that this device is being closed. |
| 347 for (int i = content::MEDIA_NO_SERVICE + 1; | 334 for (int i = MEDIA_NO_SERVICE + 1; i != NUM_MEDIA_TYPES; ++i) { |
| 348 i != content::NUM_MEDIA_TYPES; ++i) { | |
| 349 if (it->second.getState(static_cast<MediaStreamType>(i)) != | 335 if (it->second.getState(static_cast<MediaStreamType>(i)) != |
| 350 content::MEDIA_REQUEST_STATE_NOT_REQUESTED) | 336 MEDIA_REQUEST_STATE_NOT_REQUESTED) |
| 351 it->second.setState(static_cast<MediaStreamType>(i), | 337 it->second.setState(static_cast<MediaStreamType>(i), |
| 352 content::MEDIA_REQUEST_STATE_CLOSING); | 338 MEDIA_REQUEST_STATE_CLOSING); |
| 353 } | 339 } |
| 354 NotifyDevicesClosed(it->second); | 340 NotifyDevicesClosed(it->second); |
| 355 } | 341 } |
| 356 | 342 |
| 357 // If request isn't complete, notify the UI on the cancellation. And it | 343 // If request isn't complete, notify the UI on the cancellation. And it |
| 358 // is also safe to call CancelUIRequest if the request has been done. | 344 // is also safe to call CancelUIRequest if the request has been done. |
| 359 ui_controller_->CancelUIRequest(label); | 345 ui_controller_->CancelUIRequest(label); |
| 360 | 346 |
| 361 // Delete the request now. | 347 // Delete the request now. |
| 362 requests_.erase(it); | 348 requests_.erase(it); |
| 363 } | 349 } |
| 364 } | 350 } |
| 365 | 351 |
| 366 void MediaStreamManager::EnumerateDevices( | 352 void MediaStreamManager::EnumerateDevices( |
| 367 MediaStreamRequester* requester, | 353 MediaStreamRequester* requester, |
| 368 int render_process_id, | 354 int render_process_id, |
| 369 int render_view_id, | 355 int render_view_id, |
| 370 MediaStreamType type, | 356 MediaStreamType type, |
| 371 const GURL& security_origin, | 357 const GURL& security_origin, |
| 372 std::string* label) { | 358 std::string* label) { |
| 373 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 359 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 374 DCHECK(type == content::MEDIA_DEVICE_AUDIO_CAPTURE || | 360 DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE || |
| 375 type == content::MEDIA_DEVICE_VIDEO_CAPTURE); | 361 type == MEDIA_DEVICE_VIDEO_CAPTURE); |
| 376 | 362 |
| 377 // Create a new request. | 363 // Create a new request. |
| 378 StreamOptions options; | 364 StreamOptions options; |
| 379 EnumerationCache* cache = NULL; | 365 EnumerationCache* cache = NULL; |
| 380 if (type == content::MEDIA_DEVICE_AUDIO_CAPTURE) { | 366 if (type == MEDIA_DEVICE_AUDIO_CAPTURE) { |
| 381 options.audio_type = type; | 367 options.audio_type = type; |
| 382 cache = &audio_enumeration_cache_; | 368 cache = &audio_enumeration_cache_; |
| 383 } else if (type == content::MEDIA_DEVICE_VIDEO_CAPTURE) { | 369 } else if (type == MEDIA_DEVICE_VIDEO_CAPTURE) { |
| 384 options.video_type = type; | 370 options.video_type = type; |
| 385 cache = &video_enumeration_cache_; | 371 cache = &video_enumeration_cache_; |
| 386 } else { | 372 } else { |
| 387 NOTREACHED(); | 373 NOTREACHED(); |
| 388 return; | 374 return; |
| 389 } | 375 } |
| 390 | 376 |
| 391 DeviceRequest new_request(requester, options, | 377 DeviceRequest new_request(requester, options, |
| 392 DeviceRequest::ENUMERATE_DEVICES, | 378 DeviceRequest::ENUMERATE_DEVICES, |
| 393 render_process_id, | 379 render_process_id, |
| 394 render_view_id, | 380 render_view_id, |
| 395 security_origin); | 381 security_origin); |
| 396 | 382 |
| 397 if (cache->valid) { | 383 if (cache->valid) { |
| 398 // Cached device list of this type exists. Just send it out. | 384 // Cached device list of this type exists. Just send it out. |
| 399 new_request.setState(type, content::MEDIA_REQUEST_STATE_REQUESTED); | 385 new_request.setState(type, MEDIA_REQUEST_STATE_REQUESTED); |
| 400 AddRequest(new_request, label); | 386 AddRequest(new_request, label); |
| 401 // Need to post a task since the requester won't have label till | 387 // Need to post a task since the requester won't have label till |
| 402 // this function returns. | 388 // this function returns. |
| 403 BrowserThread::PostTask(BrowserThread::IO, | 389 BrowserThread::PostTask(BrowserThread::IO, |
| 404 FROM_HERE, | 390 FROM_HERE, |
| 405 base::Bind(&MediaStreamManager::SendCachedDeviceList, | 391 base::Bind(&MediaStreamManager::SendCachedDeviceList, |
| 406 base::Unretained(this), cache, *label)); | 392 base::Unretained(this), cache, *label)); |
| 407 } else { | 393 } else { |
| 408 StartEnumeration(&new_request, label); | 394 StartEnumeration(&new_request, label); |
| 409 StartMonitoring(); | 395 StartMonitoring(); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 425 | 411 |
| 426 void MediaStreamManager::OpenDevice( | 412 void MediaStreamManager::OpenDevice( |
| 427 MediaStreamRequester* requester, | 413 MediaStreamRequester* requester, |
| 428 int render_process_id, | 414 int render_process_id, |
| 429 int render_view_id, | 415 int render_view_id, |
| 430 const std::string& device_id, | 416 const std::string& device_id, |
| 431 MediaStreamType type, | 417 MediaStreamType type, |
| 432 const GURL& security_origin, | 418 const GURL& security_origin, |
| 433 std::string* label) { | 419 std::string* label) { |
| 434 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 420 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 435 DCHECK(type == content::MEDIA_DEVICE_AUDIO_CAPTURE || | 421 DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE || |
| 436 type == content::MEDIA_DEVICE_VIDEO_CAPTURE); | 422 type == MEDIA_DEVICE_VIDEO_CAPTURE); |
| 437 | 423 |
| 438 // Create a new request. | 424 // Create a new request. |
| 439 StreamOptions options; | 425 StreamOptions options; |
| 440 if (content::IsAudioMediaType(type)) { | 426 if (IsAudioMediaType(type)) { |
| 441 options.audio_type = type; | 427 options.audio_type = type; |
| 442 } else if (content::IsVideoMediaType(type)) { | 428 } else if (IsVideoMediaType(type)) { |
| 443 options.video_type = type; | 429 options.video_type = type; |
| 444 } else { | 430 } else { |
| 445 NOTREACHED(); | 431 NOTREACHED(); |
| 446 return; | 432 return; |
| 447 } | 433 } |
| 448 | 434 |
| 449 DeviceRequest new_request(requester, options, | 435 DeviceRequest new_request(requester, options, |
| 450 DeviceRequest::OPEN_DEVICE, | 436 DeviceRequest::OPEN_DEVICE, |
| 451 render_process_id, | 437 render_process_id, |
| 452 render_view_id, | 438 render_view_id, |
| 453 security_origin); | 439 security_origin); |
| 454 new_request.requested_device_id = device_id; | 440 new_request.requested_device_id = device_id; |
| 455 | 441 |
| 456 StartEnumeration(&new_request, label); | 442 StartEnumeration(&new_request, label); |
| 457 } | 443 } |
| 458 | 444 |
| 459 void MediaStreamManager::NotifyUIDevicesOpened( | 445 void MediaStreamManager::NotifyUIDevicesOpened( |
| 460 int render_process_id, | 446 int render_process_id, |
| 461 int render_view_id, | 447 int render_view_id, |
| 462 const content::MediaStreamDevices& devices) { | 448 const MediaStreamDevices& devices) { |
| 463 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 449 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 464 ui_controller_->NotifyUIIndicatorDevicesOpened(render_process_id, | 450 ui_controller_->NotifyUIIndicatorDevicesOpened(render_process_id, |
| 465 render_view_id, | 451 render_view_id, |
| 466 devices); | 452 devices); |
| 467 } | 453 } |
| 468 | 454 |
| 469 void MediaStreamManager::NotifyUIDevicesClosed( | 455 void MediaStreamManager::NotifyUIDevicesClosed( |
| 470 int render_process_id, | 456 int render_process_id, |
| 471 int render_view_id, | 457 int render_view_id, |
| 472 const content::MediaStreamDevices& devices) { | 458 const MediaStreamDevices& devices) { |
| 473 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 459 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 474 ui_controller_->NotifyUIIndicatorDevicesClosed(render_process_id, | 460 ui_controller_->NotifyUIIndicatorDevicesClosed(render_process_id, |
| 475 render_view_id, | 461 render_view_id, |
| 476 devices); | 462 devices); |
| 477 } | 463 } |
| 478 | 464 |
| 479 void MediaStreamManager::SendCachedDeviceList( | 465 void MediaStreamManager::SendCachedDeviceList( |
| 480 EnumerationCache* cache, | 466 EnumerationCache* cache, |
| 481 const std::string& label) { | 467 const std::string& label) { |
| 482 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 468 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 509 void MediaStreamManager::ClearEnumerationCache(EnumerationCache* cache) { | 495 void MediaStreamManager::ClearEnumerationCache(EnumerationCache* cache) { |
| 510 DCHECK_EQ(MessageLoop::current(), io_loop_); | 496 DCHECK_EQ(MessageLoop::current(), io_loop_); |
| 511 cache->valid = false; | 497 cache->valid = false; |
| 512 } | 498 } |
| 513 | 499 |
| 514 void MediaStreamManager::StartEnumeration( | 500 void MediaStreamManager::StartEnumeration( |
| 515 DeviceRequest* new_request, | 501 DeviceRequest* new_request, |
| 516 std::string* label) { | 502 std::string* label) { |
| 517 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 503 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 518 | 504 |
| 519 for (int i = content::MEDIA_NO_SERVICE + 1; i < content::NUM_MEDIA_TYPES; | 505 for (int i = MEDIA_NO_SERVICE + 1; i < NUM_MEDIA_TYPES; |
| 520 ++i) { | 506 ++i) { |
| 521 const MediaStreamType stream_type = static_cast<MediaStreamType>(i); | 507 const MediaStreamType stream_type = static_cast<MediaStreamType>(i); |
| 522 if (Requested(new_request->options, stream_type)) { | 508 if (Requested(new_request->options, stream_type)) { |
| 523 new_request->setState(stream_type, | 509 new_request->setState(stream_type, MEDIA_REQUEST_STATE_REQUESTED); |
| 524 content::MEDIA_REQUEST_STATE_REQUESTED); | |
| 525 DCHECK_GE(active_enumeration_ref_count_[stream_type], 0); | 510 DCHECK_GE(active_enumeration_ref_count_[stream_type], 0); |
| 526 if (active_enumeration_ref_count_[stream_type] == 0) { | 511 if (active_enumeration_ref_count_[stream_type] == 0) { |
| 527 ++active_enumeration_ref_count_[stream_type]; | 512 ++active_enumeration_ref_count_[stream_type]; |
| 528 GetDeviceManager(stream_type)->EnumerateDevices(); | 513 GetDeviceManager(stream_type)->EnumerateDevices(); |
| 529 } | 514 } |
| 530 } | 515 } |
| 531 } | 516 } |
| 532 | 517 |
| 533 AddRequest(*new_request, label); | 518 AddRequest(*new_request, label); |
| 534 } | 519 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 565 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 550 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 566 if (device_thread_.get()) | 551 if (device_thread_.get()) |
| 567 return; | 552 return; |
| 568 | 553 |
| 569 device_thread_.reset(new base::Thread("MediaStreamDeviceThread")); | 554 device_thread_.reset(new base::Thread("MediaStreamDeviceThread")); |
| 570 #if defined(OS_WIN) | 555 #if defined(OS_WIN) |
| 571 device_thread_->init_com_with_mta(true); | 556 device_thread_->init_com_with_mta(true); |
| 572 #endif | 557 #endif |
| 573 CHECK(device_thread_->Start()); | 558 CHECK(device_thread_->Start()); |
| 574 | 559 |
| 575 audio_input_device_manager_ = | 560 audio_input_device_manager_ = new AudioInputDeviceManager(audio_manager_); |
| 576 new media_stream::AudioInputDeviceManager(audio_manager_); | |
| 577 audio_input_device_manager_->Register(this, | 561 audio_input_device_manager_->Register(this, |
| 578 device_thread_->message_loop_proxy()); | 562 device_thread_->message_loop_proxy()); |
| 579 | 563 |
| 580 video_capture_manager_ = new media_stream::VideoCaptureManager(); | 564 video_capture_manager_ = new VideoCaptureManager(); |
| 581 video_capture_manager_->Register(this, | 565 video_capture_manager_->Register(this, device_thread_->message_loop_proxy()); |
| 582 device_thread_->message_loop_proxy()); | |
| 583 | 566 |
| 584 // We want to be notified of IO message loop destruction to delete the thread | 567 // We want to be notified of IO message loop destruction to delete the thread |
| 585 // and the device managers. | 568 // and the device managers. |
| 586 io_loop_ = MessageLoop::current(); | 569 io_loop_ = MessageLoop::current(); |
| 587 io_loop_->AddDestructionObserver(this); | 570 io_loop_->AddDestructionObserver(this); |
| 588 } | 571 } |
| 589 | 572 |
| 590 void MediaStreamManager::Opened(MediaStreamType stream_type, | 573 void MediaStreamManager::Opened(MediaStreamType stream_type, |
| 591 int capture_session_id) { | 574 int capture_session_id) { |
| 592 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 575 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 608 request = &(request_it->second); | 591 request = &(request_it->second); |
| 609 break; | 592 break; |
| 610 } | 593 } |
| 611 } | 594 } |
| 612 } | 595 } |
| 613 if (request == NULL) { | 596 if (request == NULL) { |
| 614 // The request doesn't exist. | 597 // The request doesn't exist. |
| 615 return; | 598 return; |
| 616 } | 599 } |
| 617 | 600 |
| 618 DCHECK_NE(request->getState(stream_type), | 601 DCHECK_NE(request->getState(stream_type), MEDIA_REQUEST_STATE_REQUESTED); |
| 619 content::MEDIA_REQUEST_STATE_REQUESTED); | |
| 620 | 602 |
| 621 // Check if all devices for this stream type are opened. Update the state if | 603 // Check if all devices for this stream type are opened. Update the state if |
| 622 // they are. | 604 // they are. |
| 623 for (StreamDeviceInfoArray::iterator device_it = devices->begin(); | 605 for (StreamDeviceInfoArray::iterator device_it = devices->begin(); |
| 624 device_it != devices->end(); ++device_it) { | 606 device_it != devices->end(); ++device_it) { |
| 625 if (device_it->stream_type != stream_type) { | 607 if (device_it->stream_type != stream_type) { |
| 626 continue; | 608 continue; |
| 627 } | 609 } |
| 628 if (device_it->in_use == false) { | 610 if (device_it->in_use == false) { |
| 629 // Wait for more devices to be opened before we're done. | 611 // Wait for more devices to be opened before we're done. |
| 630 return; | 612 return; |
| 631 } | 613 } |
| 632 } | 614 } |
| 633 | 615 |
| 634 request->setState(stream_type, content::MEDIA_REQUEST_STATE_DONE); | 616 request->setState(stream_type, MEDIA_REQUEST_STATE_DONE); |
| 635 | 617 |
| 636 if (!RequestDone(*request)) { | 618 if (!RequestDone(*request)) { |
| 637 // This stream_type is done, but not the other type. | 619 // This stream_type is done, but not the other type. |
| 638 return; | 620 return; |
| 639 } | 621 } |
| 640 | 622 |
| 641 switch (request->type) { | 623 switch (request->type) { |
| 642 case DeviceRequest::OPEN_DEVICE: | 624 case DeviceRequest::OPEN_DEVICE: |
| 643 request->requester->DeviceOpened(label, devices->front()); | 625 request->requester->DeviceOpened(label, devices->front()); |
| 644 break; | 626 break; |
| 645 case DeviceRequest::GENERATE_STREAM: { | 627 case DeviceRequest::GENERATE_STREAM: { |
| 646 // Partition the array of devices into audio vs video. | 628 // Partition the array of devices into audio vs video. |
| 647 StreamDeviceInfoArray audio_devices, video_devices; | 629 StreamDeviceInfoArray audio_devices, video_devices; |
| 648 for (StreamDeviceInfoArray::const_iterator device_it = devices->begin(); | 630 for (StreamDeviceInfoArray::const_iterator device_it = devices->begin(); |
| 649 device_it != devices->end(); ++device_it) { | 631 device_it != devices->end(); ++device_it) { |
| 650 if (content::IsAudioMediaType(device_it->stream_type)) { | 632 if (IsAudioMediaType(device_it->stream_type)) { |
| 651 audio_devices.push_back(*device_it); | 633 audio_devices.push_back(*device_it); |
| 652 } else if (content::IsVideoMediaType(device_it->stream_type)) { | 634 } else if (IsVideoMediaType(device_it->stream_type)) { |
| 653 video_devices.push_back(*device_it); | 635 video_devices.push_back(*device_it); |
| 654 } else { | 636 } else { |
| 655 NOTREACHED(); | 637 NOTREACHED(); |
| 656 } | 638 } |
| 657 } | 639 } |
| 658 | 640 |
| 659 request->requester->StreamGenerated(label, audio_devices, video_devices); | 641 request->requester->StreamGenerated(label, audio_devices, video_devices); |
| 660 NotifyDevicesOpened(*request); | 642 NotifyDevicesOpened(*request); |
| 661 break; | 643 break; |
| 662 } | 644 } |
| 663 default: | 645 default: |
| 664 NOTREACHED(); | 646 NOTREACHED(); |
| 665 break; | 647 break; |
| 666 } | 648 } |
| 667 } | 649 } |
| 668 | 650 |
| 669 void MediaStreamManager::Closed(MediaStreamType stream_type, | 651 void MediaStreamManager::Closed(MediaStreamType stream_type, |
| 670 int capture_session_id) { | 652 int capture_session_id) { |
| 671 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 653 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 672 } | 654 } |
| 673 | 655 |
| 674 void MediaStreamManager::DevicesEnumerated( | 656 void MediaStreamManager::DevicesEnumerated( |
| 675 MediaStreamType stream_type, const StreamDeviceInfoArray& devices) { | 657 MediaStreamType stream_type, const StreamDeviceInfoArray& devices) { |
| 676 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 658 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 677 | 659 |
| 678 // Only cache the device list when there is an EnumerateDevices request, since | 660 // Only cache the device list when there is an EnumerateDevices request, since |
| 679 // other requests don't turn on device monitoring. | 661 // other requests don't turn on device monitoring. |
| 680 bool need_update_clients = false; | 662 bool need_update_clients = false; |
| 681 EnumerationCache* cache = | 663 EnumerationCache* cache = (stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ? |
| 682 (stream_type == content::MEDIA_DEVICE_AUDIO_CAPTURE ? | |
| 683 &audio_enumeration_cache_ : &video_enumeration_cache_); | 664 &audio_enumeration_cache_ : &video_enumeration_cache_); |
| 684 if (HasEnumerationRequest(stream_type) && | 665 if (HasEnumerationRequest(stream_type) && |
| 685 (!cache->valid || | 666 (!cache->valid || |
| 686 devices.size() != cache->devices.size() || | 667 devices.size() != cache->devices.size() || |
| 687 !std::equal(devices.begin(), devices.end(), cache->devices.begin(), | 668 !std::equal(devices.begin(), devices.end(), cache->devices.begin(), |
| 688 media_stream::StreamDeviceInfo::IsEqual))) { | 669 StreamDeviceInfo::IsEqual))) { |
| 689 cache->valid = true; | 670 cache->valid = true; |
| 690 cache->devices = devices; | 671 cache->devices = devices; |
| 691 need_update_clients = true; | 672 need_update_clients = true; |
| 692 } | 673 } |
| 693 | 674 |
| 694 // Publish the result for all requests waiting for device list(s). | 675 // Publish the result for all requests waiting for device list(s). |
| 695 // Find the requests waiting for this device list, store their labels and | 676 // Find the requests waiting for this device list, store their labels and |
| 696 // release the iterator before calling device settings. We might get a call | 677 // release the iterator before calling device settings. We might get a call |
| 697 // back from device_settings that will need to iterate through devices. | 678 // back from device_settings that will need to iterate through devices. |
| 698 std::list<std::string> label_list; | 679 std::list<std::string> label_list; |
| 699 for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end(); | 680 for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end(); |
| 700 ++it) { | 681 ++it) { |
| 701 if (it->second.getState(stream_type) == | 682 if (it->second.getState(stream_type) == |
| 702 content::MEDIA_REQUEST_STATE_REQUESTED && | 683 MEDIA_REQUEST_STATE_REQUESTED && |
| 703 Requested(it->second.options, stream_type)) { | 684 Requested(it->second.options, stream_type)) { |
| 704 if (it->second.type != DeviceRequest::ENUMERATE_DEVICES) | 685 if (it->second.type != DeviceRequest::ENUMERATE_DEVICES) |
| 705 it->second.setState(stream_type, | 686 it->second.setState(stream_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL); |
| 706 content::MEDIA_REQUEST_STATE_PENDING_APPROVAL); | |
| 707 label_list.push_back(it->first); | 687 label_list.push_back(it->first); |
| 708 } | 688 } |
| 709 } | 689 } |
| 710 for (std::list<std::string>::iterator it = label_list.begin(); | 690 for (std::list<std::string>::iterator it = label_list.begin(); |
| 711 it != label_list.end(); ++it) { | 691 it != label_list.end(); ++it) { |
| 712 DeviceRequest& request = requests_[*it]; | 692 DeviceRequest& request = requests_[*it]; |
| 713 switch (request.type) { | 693 switch (request.type) { |
| 714 case DeviceRequest::ENUMERATE_DEVICES: | 694 case DeviceRequest::ENUMERATE_DEVICES: |
| 715 if (need_update_clients) | 695 if (need_update_clients) |
| 716 request.requester->DevicesEnumerated(*it, devices); | 696 request.requester->DevicesEnumerated(*it, devices); |
| 717 break; | 697 break; |
| 718 case DeviceRequest::OPEN_DEVICE: | 698 case DeviceRequest::OPEN_DEVICE: |
| 719 DCHECK(!request.requested_device_id.empty()); | 699 DCHECK(!request.requested_device_id.empty()); |
| 720 for (StreamDeviceInfoArray::const_iterator device_it = devices.begin(); | 700 for (StreamDeviceInfoArray::const_iterator device_it = devices.begin(); |
| 721 device_it != devices.end(); ++device_it) { | 701 device_it != devices.end(); ++device_it) { |
| 722 if (request.requested_device_id == device_it->device_id) { | 702 if (request.requested_device_id == device_it->device_id) { |
| 723 StreamDeviceInfo device = *device_it; | 703 StreamDeviceInfo device = *device_it; |
| 724 device.in_use = false; | 704 device.in_use = false; |
| 725 device.session_id = | 705 device.session_id = |
| 726 GetDeviceManager(device_it->stream_type)->Open(device); | 706 GetDeviceManager(device_it->stream_type)->Open(device); |
| 727 request.setState(device_it->stream_type, | 707 request.setState(device_it->stream_type, |
| 728 content::MEDIA_REQUEST_STATE_OPENING); | 708 MEDIA_REQUEST_STATE_OPENING); |
| 729 request.devices.push_back(device); | 709 request.devices.push_back(device); |
| 730 break; | 710 break; |
| 731 } | 711 } |
| 732 } | 712 } |
| 733 break; | 713 break; |
| 734 default: | 714 default: |
| 735 ui_controller_->AddAvailableDevicesToRequest(*it, stream_type, | 715 ui_controller_->AddAvailableDevicesToRequest(*it, stream_type, |
| 736 devices); | 716 devices); |
| 737 break; | 717 break; |
| 738 } | 718 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 752 ++it) { | 732 ++it) { |
| 753 StreamDeviceInfoArray& devices = it->second.devices; | 733 StreamDeviceInfoArray& devices = it->second.devices; |
| 754 | 734 |
| 755 // TODO(miu): BUG. It's possible for the audio (or video) device array in | 735 // TODO(miu): BUG. It's possible for the audio (or video) device array in |
| 756 // the "requester" to become out-of-sync with the order of devices we have | 736 // the "requester" to become out-of-sync with the order of devices we have |
| 757 // here. See http://crbug.com/147650 | 737 // here. See http://crbug.com/147650 |
| 758 int audio_device_idx = -1; | 738 int audio_device_idx = -1; |
| 759 int video_device_idx = -1; | 739 int video_device_idx = -1; |
| 760 for (StreamDeviceInfoArray::iterator device_it = devices.begin(); | 740 for (StreamDeviceInfoArray::iterator device_it = devices.begin(); |
| 761 device_it != devices.end(); ++device_it) { | 741 device_it != devices.end(); ++device_it) { |
| 762 if (content::IsAudioMediaType(device_it->stream_type)) { | 742 if (IsAudioMediaType(device_it->stream_type)) { |
| 763 ++audio_device_idx; | 743 ++audio_device_idx; |
| 764 } else if (content::IsVideoMediaType(device_it->stream_type)) { | 744 } else if (IsVideoMediaType(device_it->stream_type)) { |
| 765 ++video_device_idx; | 745 ++video_device_idx; |
| 766 } else { | 746 } else { |
| 767 NOTREACHED(); | 747 NOTREACHED(); |
| 768 continue; | 748 continue; |
| 769 } | 749 } |
| 770 if (device_it->stream_type != stream_type || | 750 if (device_it->stream_type != stream_type || |
| 771 device_it->session_id != capture_session_id) { | 751 device_it->session_id != capture_session_id) { |
| 772 continue; | 752 continue; |
| 773 } | 753 } |
| 774 // We've found the failing device. Find the error case: | 754 // We've found the failing device. Find the error case: |
| 775 // An error should only be reported to the MediaStreamManager if | 755 // An error should only be reported to the MediaStreamManager if |
| 776 // the request has not been fulfilled yet. | 756 // the request has not been fulfilled yet. |
| 777 DCHECK(it->second.getState(stream_type) != | 757 DCHECK(it->second.getState(stream_type) != MEDIA_REQUEST_STATE_DONE); |
| 778 content::MEDIA_REQUEST_STATE_DONE); | 758 if (it->second.getState(stream_type) != MEDIA_REQUEST_STATE_DONE) { |
| 779 if (it->second.getState(stream_type) != | |
| 780 content::MEDIA_REQUEST_STATE_DONE) { | |
| 781 // Request is not done, devices are not opened in this case. | 759 // Request is not done, devices are not opened in this case. |
| 782 if (devices.size() <= 1) { | 760 if (devices.size() <= 1) { |
| 783 // 1. Device not opened and no other devices for this request -> | 761 // 1. Device not opened and no other devices for this request -> |
| 784 // signal stream error and remove the request. | 762 // signal stream error and remove the request. |
| 785 if (it->second.requester) | 763 if (it->second.requester) |
| 786 it->second.requester->StreamGenerationFailed(it->first); | 764 it->second.requester->StreamGenerationFailed(it->first); |
| 787 | 765 |
| 788 requests_.erase(it); | 766 requests_.erase(it); |
| 789 } else { | 767 } else { |
| 790 // 2. Not opened but other devices exists for this request -> remove | 768 // 2. Not opened but other devices exists for this request -> remove |
| (...skipping 13 matching lines...) Expand all Loading... |
| 804 DeviceRequests::iterator request_it = requests_.find(label); | 782 DeviceRequests::iterator request_it = requests_.find(label); |
| 805 if (request_it == requests_.end()) { | 783 if (request_it == requests_.end()) { |
| 806 return; | 784 return; |
| 807 } | 785 } |
| 808 | 786 |
| 809 DeviceRequest& request = request_it->second; | 787 DeviceRequest& request = request_it->second; |
| 810 | 788 |
| 811 if (request.type == DeviceRequest::DEVICE_ACCESS) { | 789 if (request.type == DeviceRequest::DEVICE_ACCESS) { |
| 812 if (!request.callback.is_null()) { | 790 if (!request.callback.is_null()) { |
| 813 // Map the devices to MediaStreamDevices. | 791 // Map the devices to MediaStreamDevices. |
| 814 content::MediaStreamDevices selected_devices; | 792 MediaStreamDevices selected_devices; |
| 815 for (StreamDeviceInfoArray::const_iterator it = devices.begin(); | 793 for (StreamDeviceInfoArray::const_iterator it = devices.begin(); |
| 816 it != devices.end(); ++it) { | 794 it != devices.end(); ++it) { |
| 817 selected_devices.push_back(content::MediaStreamDevice( | 795 selected_devices.push_back(MediaStreamDevice( |
| 818 it->stream_type, it->device_id, it->name)); | 796 it->stream_type, it->device_id, it->name)); |
| 819 } | 797 } |
| 820 | 798 |
| 821 request.callback.Run(label, selected_devices); | 799 request.callback.Run(label, selected_devices); |
| 822 } | 800 } |
| 823 | 801 |
| 824 // Delete the request since it is done. | 802 // Delete the request since it is done. |
| 825 requests_.erase(request_it); | 803 requests_.erase(request_it); |
| 826 return; | 804 return; |
| 827 } | 805 } |
| 828 | 806 |
| 829 // Process all newly-accepted devices for this request. | 807 // Process all newly-accepted devices for this request. |
| 830 bool found_audio = false, found_video = false; | 808 bool found_audio = false, found_video = false; |
| 831 for (StreamDeviceInfoArray::const_iterator device_it = devices.begin(); | 809 for (StreamDeviceInfoArray::const_iterator device_it = devices.begin(); |
| 832 device_it != devices.end(); ++device_it) { | 810 device_it != devices.end(); ++device_it) { |
| 833 StreamDeviceInfo device_info = *device_it; // Make a copy. | 811 StreamDeviceInfo device_info = *device_it; // Make a copy. |
| 834 | 812 |
| 835 // Set in_use to false to be able to track if this device has been | 813 // Set in_use to false to be able to track if this device has been |
| 836 // opened. in_use might be true if the device type can be used in more | 814 // opened. in_use might be true if the device type can be used in more |
| 837 // than one session. | 815 // than one session. |
| 838 DCHECK_EQ(request.getState(device_it->stream_type), | 816 DCHECK_EQ(request.getState(device_it->stream_type), |
| 839 content::MEDIA_REQUEST_STATE_PENDING_APPROVAL); | 817 MEDIA_REQUEST_STATE_PENDING_APPROVAL); |
| 840 device_info.in_use = false; | 818 device_info.in_use = false; |
| 841 | 819 |
| 842 device_info.session_id = | 820 device_info.session_id = |
| 843 GetDeviceManager(device_info.stream_type)->Open(device_info); | 821 GetDeviceManager(device_info.stream_type)->Open(device_info); |
| 844 request.setState(device_it->stream_type, | 822 request.setState(device_it->stream_type, MEDIA_REQUEST_STATE_OPENING); |
| 845 content::MEDIA_REQUEST_STATE_OPENING); | |
| 846 request.devices.push_back(device_info); | 823 request.devices.push_back(device_info); |
| 847 | 824 |
| 848 if (device_info.stream_type == request.options.audio_type) { | 825 if (device_info.stream_type == request.options.audio_type) { |
| 849 found_audio = true; | 826 found_audio = true; |
| 850 } else if (device_info.stream_type == request.options.video_type) { | 827 } else if (device_info.stream_type == request.options.video_type) { |
| 851 found_video = true; | 828 found_video = true; |
| 852 } | 829 } |
| 853 } | 830 } |
| 854 | 831 |
| 855 // Check whether we've received all stream types requested. | 832 // Check whether we've received all stream types requested. |
| 856 if (!found_audio && content::IsAudioMediaType(request.options.audio_type)) { | 833 if (!found_audio && IsAudioMediaType(request.options.audio_type)) { |
| 857 request.setState(request.options.audio_type, | 834 request.setState(request.options.audio_type, MEDIA_REQUEST_STATE_ERROR); |
| 858 content::MEDIA_REQUEST_STATE_ERROR); | |
| 859 } | 835 } |
| 860 if (!found_video && content::IsVideoMediaType(request.options.video_type)) { | 836 if (!found_video && IsVideoMediaType(request.options.video_type)) { |
| 861 request.setState(request.options.video_type, | 837 request.setState(request.options.video_type, MEDIA_REQUEST_STATE_ERROR); |
| 862 content::MEDIA_REQUEST_STATE_ERROR); | |
| 863 } | 838 } |
| 864 } | 839 } |
| 865 | 840 |
| 866 void MediaStreamManager::SettingsError(const std::string& label) { | 841 void MediaStreamManager::SettingsError(const std::string& label) { |
| 867 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 842 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 868 // Erase this request and report an error. | 843 // Erase this request and report an error. |
| 869 DeviceRequests::iterator it = requests_.find(label); | 844 DeviceRequests::iterator it = requests_.find(label); |
| 870 if (it == requests_.end()) | 845 if (it == requests_.end()) |
| 871 return; | 846 return; |
| 872 | 847 |
| 873 // Notify the users about the request result. | 848 // Notify the users about the request result. |
| 874 DeviceRequest& request = it->second; | 849 DeviceRequest& request = it->second; |
| 875 if (request.requester) | 850 if (request.requester) |
| 876 it->second.requester->StreamGenerationFailed(label); | 851 it->second.requester->StreamGenerationFailed(label); |
| 877 | 852 |
| 878 if (request.type == DeviceRequest::DEVICE_ACCESS) | 853 if (request.type == DeviceRequest::DEVICE_ACCESS) |
| 879 request.callback.Run(label, content::MediaStreamDevices()); | 854 request.callback.Run(label, MediaStreamDevices()); |
| 880 | 855 |
| 881 requests_.erase(it); | 856 requests_.erase(it); |
| 882 } | 857 } |
| 883 | 858 |
| 884 void MediaStreamManager::UseFakeDevice() { | 859 void MediaStreamManager::UseFakeDevice() { |
| 885 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 860 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 886 video_capture_manager()->UseFakeDevice(); | 861 video_capture_manager()->UseFakeDevice(); |
| 887 ui_controller_->UseFakeUI(); | 862 ui_controller_->UseFakeUI(); |
| 888 } | 863 } |
| 889 | 864 |
| 890 void MediaStreamManager::WillDestroyCurrentMessageLoop() { | 865 void MediaStreamManager::WillDestroyCurrentMessageLoop() { |
| 891 DCHECK_EQ(MessageLoop::current(), io_loop_); | 866 DCHECK_EQ(MessageLoop::current(), io_loop_); |
| 892 DCHECK(requests_.empty()); | 867 DCHECK(requests_.empty()); |
| 893 if (device_thread_.get()) { | 868 if (device_thread_.get()) { |
| 894 StopMonitoring(); | 869 StopMonitoring(); |
| 895 | 870 |
| 896 video_capture_manager_->Unregister(); | 871 video_capture_manager_->Unregister(); |
| 897 audio_input_device_manager_->Unregister(); | 872 audio_input_device_manager_->Unregister(); |
| 898 device_thread_.reset(); | 873 device_thread_.reset(); |
| 899 } | 874 } |
| 900 | 875 |
| 901 audio_input_device_manager_ = NULL; | 876 audio_input_device_manager_ = NULL; |
| 902 video_capture_manager_ = NULL; | 877 video_capture_manager_ = NULL; |
| 903 io_loop_ = NULL; | 878 io_loop_ = NULL; |
| 904 ui_controller_.reset(); | 879 ui_controller_.reset(); |
| 905 } | 880 } |
| 906 | 881 |
| 907 void MediaStreamManager::NotifyDevicesOpened(const DeviceRequest& request) { | 882 void MediaStreamManager::NotifyDevicesOpened(const DeviceRequest& request) { |
| 908 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 883 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 909 content::MediaStreamDevices opened_devices; | 884 MediaStreamDevices opened_devices; |
| 910 DevicesFromRequest(request, &opened_devices); | 885 DevicesFromRequest(request, &opened_devices); |
| 911 if (opened_devices.empty()) | 886 if (opened_devices.empty()) |
| 912 return; | 887 return; |
| 913 | 888 |
| 914 NotifyUIDevicesOpened(request.render_process_id, | 889 NotifyUIDevicesOpened(request.render_process_id, |
| 915 request.render_view_id, | 890 request.render_view_id, |
| 916 opened_devices); | 891 opened_devices); |
| 917 } | 892 } |
| 918 | 893 |
| 919 void MediaStreamManager::NotifyDevicesClosed(const DeviceRequest& request) { | 894 void MediaStreamManager::NotifyDevicesClosed(const DeviceRequest& request) { |
| 920 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 895 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 921 content::MediaStreamDevices closed_devices; | 896 MediaStreamDevices closed_devices; |
| 922 DevicesFromRequest(request, &closed_devices); | 897 DevicesFromRequest(request, &closed_devices); |
| 923 if (closed_devices.empty()) | 898 if (closed_devices.empty()) |
| 924 return; | 899 return; |
| 925 | 900 |
| 926 NotifyUIDevicesClosed(request.render_process_id, | 901 NotifyUIDevicesClosed(request.render_process_id, |
| 927 request.render_view_id, | 902 request.render_view_id, |
| 928 closed_devices); | 903 closed_devices); |
| 929 } | 904 } |
| 930 | 905 |
| 931 void MediaStreamManager::DevicesFromRequest( | 906 void MediaStreamManager::DevicesFromRequest( |
| 932 const DeviceRequest& request, content::MediaStreamDevices* devices) { | 907 const DeviceRequest& request, MediaStreamDevices* devices) { |
| 933 for (StreamDeviceInfoArray::const_iterator it = request.devices.begin(); | 908 for (StreamDeviceInfoArray::const_iterator it = request.devices.begin(); |
| 934 it != request.devices.end(); ++it) { | 909 it != request.devices.end(); ++it) { |
| 935 devices->push_back(content::MediaStreamDevice( | 910 devices->push_back(MediaStreamDevice( |
| 936 it->stream_type, it->device_id, it->name)); | 911 it->stream_type, it->device_id, it->name)); |
| 937 } | 912 } |
| 938 } | 913 } |
| 939 | 914 |
| 940 bool MediaStreamManager::RequestDone(const DeviceRequest& request) const { | 915 bool MediaStreamManager::RequestDone(const DeviceRequest& request) const { |
| 941 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 916 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 942 | 917 |
| 943 const bool requested_audio = | 918 const bool requested_audio = IsAudioMediaType(request.options.audio_type); |
| 944 content::IsAudioMediaType(request.options.audio_type); | 919 const bool requested_video = IsVideoMediaType(request.options.video_type); |
| 945 const bool requested_video = | |
| 946 content::IsVideoMediaType(request.options.video_type); | |
| 947 | 920 |
| 948 const bool audio_done = | 921 const bool audio_done = |
| 949 !requested_audio || | 922 !requested_audio || |
| 950 request.getState(request.options.audio_type) == | 923 request.getState(request.options.audio_type) == |
| 951 content::MEDIA_REQUEST_STATE_DONE || | 924 MEDIA_REQUEST_STATE_DONE || |
| 952 request.getState(request.options.audio_type) == | 925 request.getState(request.options.audio_type) == |
| 953 content::MEDIA_REQUEST_STATE_ERROR; | 926 MEDIA_REQUEST_STATE_ERROR; |
| 954 if (!audio_done) { | 927 if (!audio_done) { |
| 955 return false; | 928 return false; |
| 956 } | 929 } |
| 957 | 930 |
| 958 const bool video_done = | 931 const bool video_done = |
| 959 !requested_video || | 932 !requested_video || |
| 960 request.getState(request.options.video_type) == | 933 request.getState(request.options.video_type) == |
| 961 content::MEDIA_REQUEST_STATE_DONE || | 934 MEDIA_REQUEST_STATE_DONE || |
| 962 request.getState(request.options.video_type) == | 935 request.getState(request.options.video_type) == |
| 963 content::MEDIA_REQUEST_STATE_ERROR; | 936 MEDIA_REQUEST_STATE_ERROR; |
| 964 if (!video_done) { | 937 if (!video_done) { |
| 965 return false; | 938 return false; |
| 966 } | 939 } |
| 967 | 940 |
| 968 for (StreamDeviceInfoArray::const_iterator it = request.devices.begin(); | 941 for (StreamDeviceInfoArray::const_iterator it = request.devices.begin(); |
| 969 it != request.devices.end(); ++it) { | 942 it != request.devices.end(); ++it) { |
| 970 if (it->in_use == false) { | 943 if (it->in_use == false) { |
| 971 return false; | 944 return false; |
| 972 } | 945 } |
| 973 } | 946 } |
| 974 | 947 |
| 975 return true; | 948 return true; |
| 976 } | 949 } |
| 977 | 950 |
| 978 MediaStreamProvider* MediaStreamManager::GetDeviceManager( | 951 MediaStreamProvider* MediaStreamManager::GetDeviceManager( |
| 979 MediaStreamType stream_type) { | 952 MediaStreamType stream_type) { |
| 980 if (content::IsVideoMediaType(stream_type)) { | 953 if (IsVideoMediaType(stream_type)) { |
| 981 return video_capture_manager(); | 954 return video_capture_manager(); |
| 982 } else if (content::IsAudioMediaType(stream_type)) { | 955 } else if (IsAudioMediaType(stream_type)) { |
| 983 return audio_input_device_manager(); | 956 return audio_input_device_manager(); |
| 984 } | 957 } |
| 985 NOTREACHED(); | 958 NOTREACHED(); |
| 986 return NULL; | 959 return NULL; |
| 987 } | 960 } |
| 988 | 961 |
| 989 void MediaStreamManager::OnDevicesChanged( | 962 void MediaStreamManager::OnDevicesChanged( |
| 990 base::SystemMonitor::DeviceType device_type) { | 963 base::SystemMonitor::DeviceType device_type) { |
| 991 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 964 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 992 | 965 |
| 993 // NOTE: This method is only called in response to physical audio/video device | 966 // NOTE: This method is only called in response to physical audio/video device |
| 994 // changes (from the operating system). | 967 // changes (from the operating system). |
| 995 | 968 |
| 996 MediaStreamType stream_type; | 969 MediaStreamType stream_type; |
| 997 EnumerationCache* cache; | 970 EnumerationCache* cache; |
| 998 if (device_type == base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE) { | 971 if (device_type == base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE) { |
| 999 stream_type = content::MEDIA_DEVICE_AUDIO_CAPTURE; | 972 stream_type = MEDIA_DEVICE_AUDIO_CAPTURE; |
| 1000 cache = &audio_enumeration_cache_; | 973 cache = &audio_enumeration_cache_; |
| 1001 } else if (device_type == base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE) { | 974 } else if (device_type == base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE) { |
| 1002 stream_type = content::MEDIA_DEVICE_VIDEO_CAPTURE; | 975 stream_type = MEDIA_DEVICE_VIDEO_CAPTURE; |
| 1003 cache = &video_enumeration_cache_; | 976 cache = &video_enumeration_cache_; |
| 1004 } else { | 977 } else { |
| 1005 return; // Uninteresting device change. | 978 return; // Uninteresting device change. |
| 1006 } | 979 } |
| 1007 | 980 |
| 1008 if (!HasEnumerationRequest(stream_type)) { | 981 if (!HasEnumerationRequest(stream_type)) { |
| 1009 // There is no request for that type, No need to enumerate devices. | 982 // There is no request for that type, No need to enumerate devices. |
| 1010 // Therefore, invalidate the cache of that type. | 983 // Therefore, invalidate the cache of that type. |
| 1011 ClearEnumerationCache(cache); | 984 ClearEnumerationCache(cache); |
| 1012 return; | 985 return; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1036 for (DeviceRequests::iterator it = requests_.begin(); | 1009 for (DeviceRequests::iterator it = requests_.begin(); |
| 1037 it != requests_.end(); ++it) { | 1010 it != requests_.end(); ++it) { |
| 1038 if (it->second.type == DeviceRequest::ENUMERATE_DEVICES && | 1011 if (it->second.type == DeviceRequest::ENUMERATE_DEVICES && |
| 1039 Requested(it->second.options, stream_type)) { | 1012 Requested(it->second.options, stream_type)) { |
| 1040 return true; | 1013 return true; |
| 1041 } | 1014 } |
| 1042 } | 1015 } |
| 1043 return false; | 1016 return false; |
| 1044 } | 1017 } |
| 1045 | 1018 |
| 1046 } // namespace media_stream | 1019 } // namespace content |
| OLD | NEW |