Chromium Code Reviews| Index: content/browser/renderer_host/media/media_stream_manager.cc |
| =================================================================== |
| --- content/browser/renderer_host/media/media_stream_manager.cc (revision 148913) |
| +++ content/browser/renderer_host/media/media_stream_manager.cc (working copy) |
| @@ -11,6 +11,8 @@ |
| #include "base/logging.h" |
| #include "base/rand_util.h" |
| #include "base/win/scoped_com_initializer.h" |
| +#include "content/browser/browser_main_loop.h" |
| +#include "content/browser/devices_monitor/devices_monitor.h" |
| #include "content/browser/renderer_host/media/audio_input_device_manager.h" |
| #include "content/browser/renderer_host/media/media_stream_device_settings.h" |
| #include "content/browser/renderer_host/media/media_stream_requester.h" |
| @@ -131,6 +133,10 @@ |
| StreamDeviceInfoArray video_devices; |
| }; |
| +MediaStreamManager::EnumerationCache::EnumerationCache() |
| + : valid(false) { |
| +} |
| + |
| MediaStreamManager::MediaStreamManager( |
| AudioInputDeviceManager* audio_input_device_manager, |
| VideoCaptureManager* video_capture_manager) |
| @@ -138,6 +144,7 @@ |
| device_settings_(new MediaStreamDeviceSettings(this))), |
| audio_input_device_manager_(audio_input_device_manager), |
| video_capture_manager_(video_capture_manager), |
| + monitoring_started_(false), |
| enumeration_in_progress_(content::NUM_MEDIA_STREAM_DEVICE_TYPES, false), |
|
tommi (sloooow) - chröme
2012/07/30 12:10:21
This array seems to be used in conjunction with th
wjia(left Chromium)
2012/08/01 01:28:59
This |enumeration_in_progress_| also include other
|
| io_loop_(NULL) { |
| } |
| @@ -176,6 +183,17 @@ |
| render_view_id, |
| security_origin); |
| StartEnumeration(&new_request, label); |
| + |
| + // Get user confirmation to use capture devices. |
| + // Need to make an asynchronous call to make sure the |requester| gets the |
| + // |label| before it would receive any event. |
| + BrowserThread::PostTask(BrowserThread::IO, |
| + FROM_HERE, |
| + base::Bind(&MediaStreamDeviceSettings::RequestCaptureDeviceUsage, |
| + base::Unretained(device_settings_.get()), |
| + *label, render_process_id, |
| + render_view_id, options, |
| + security_origin)); |
| } |
| void MediaStreamManager::CancelRequests(MediaStreamRequester* requester) { |
| @@ -246,6 +264,10 @@ |
| // Find the request and close all open devices for the request. |
| DeviceRequests::iterator it = requests_.find(label); |
| if (it != requests_.end()) { |
| + if (it->second.type == DeviceRequest::kEnumerateDevices) { |
|
tommi (sloooow) - chröme
2012/07/30 12:10:21
kEnumerateDevices -> ENUMERATE_DEVICES
wjia(left Chromium)
2012/08/01 01:28:59
Done.
|
| + StopEnumerateDevices(label); |
| + return; |
| + } |
| for (StreamDeviceInfoArray::iterator audio_it = |
| it->second.audio_devices.begin(); |
| audio_it != it->second.audio_devices.end(); ++audio_it) { |
| @@ -260,7 +282,6 @@ |
| NotifyObserverDevicesClosed(&(it->second)); |
| } |
| requests_.erase(it); |
| - return; |
| } |
| } |
| @@ -272,13 +293,19 @@ |
| const GURL& security_origin, |
| std::string* label) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + DCHECK(type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE || |
| + type == content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE); |
| // Create a new request. |
| StreamOptions options; |
| - if (type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) |
| + EnumerationCache* cache = NULL; |
| + if (type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) { |
| options.audio = true; |
| - else |
| + cache = &audio_enumeration_cache_; |
| + } else { |
| options.video = true; |
| + cache = &video_enumeration_cache_; |
| + } |
| DeviceRequest new_request(requester, options, |
| render_process_id, |
| @@ -286,9 +313,35 @@ |
| security_origin); |
| new_request.type = DeviceRequest::kEnumerateDevices; |
| - StartEnumeration(&new_request, label); |
| + if (cache->valid) { |
| + // Cached device list of this type exists. Just send it out. |
| + new_request.state[type] = DeviceRequest::kRequested; |
|
tommi (sloooow) - chröme
2012/07/30 12:10:21
kRequested -> REQUESTED
wjia(left Chromium)
2012/08/01 01:28:59
Done.
|
| + AddRequest(&new_request, label); |
| + // Need to post a task since the requester won't have label till |
| + // this function returns. |
| + BrowserThread::PostTask(BrowserThread::IO, |
| + FROM_HERE, |
| + base::Bind(&MediaStreamManager::SendCachedDeviceList, |
| + base::Unretained(this), cache, *label)); |
| + } else { |
| + StartEnumeration(&new_request, label); |
| + StartMonitoring(); |
| + } |
| } |
| +void MediaStreamManager::StopEnumerateDevices(const std::string& label) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + DeviceRequests::iterator it = requests_.find(label); |
| + if (it != requests_.end()) { |
| + DCHECK_EQ(it->second.type, DeviceRequest::kEnumerateDevices); |
| + requests_.erase(it); |
| + if (!HasEnumerationRequest()) { |
| + StopMonitoring(); |
| + } |
| + } |
| +} |
| + |
| void MediaStreamManager::OpenDevice( |
| MediaStreamRequester* requester, |
| int render_process_id, |
| @@ -316,6 +369,42 @@ |
| StartEnumeration(&new_request, label); |
| } |
| +void MediaStreamManager::SendCachedDeviceList( |
| + EnumerationCache* cache, |
| + const std::string& label) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + if (cache->valid && requests_.find(label) != requests_.end()) { |
| + requests_[label].requester->DevicesEnumerated(label, cache->devices); |
|
tommi (sloooow) - chröme
2012/07/30 12:10:21
nit: you've already looked up the label so you cou
wjia(left Chromium)
2012/08/01 01:28:59
Done.
|
| + } |
| +} |
| + |
| +void MediaStreamManager::StartMonitoring() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + if (!monitoring_started_) { |
| + monitoring_started_ = true; |
| + content::BrowserMainLoop::GetDevicesMonitor()->Start(this); |
| + base::SystemMonitor::Get()->AddDevicesChangedObserver(this); |
|
tommi (sloooow) - chröme
2012/07/30 12:10:21
What do you think about this:
* Remove:
- Start
wjia(left Chromium)
2012/08/01 01:28:59
The start/stop of DeviceMonitor has been removed b
tommi (sloooow) - chröme
2012/08/01 10:21:37
Great. Thanks.
|
| + } |
| +} |
| + |
| +void MediaStreamManager::StopMonitoring() { |
| + DCHECK_EQ(MessageLoop::current(), io_loop_); |
| + if (monitoring_started_ && !HasEnumerationRequest()) { |
| + content::BrowserMainLoop::GetDevicesMonitor()->Stop(this); |
| + base::SystemMonitor::Get()->RemoveDevicesChangedObserver(this); |
| + monitoring_started_ = false; |
| + ClearEnumerationCache(&audio_enumeration_cache_); |
| + ClearEnumerationCache(&video_enumeration_cache_); |
| + } |
| +} |
| + |
| +void MediaStreamManager::ClearEnumerationCache(EnumerationCache* cache) { |
|
tommi (sloooow) - chröme
2012/07/30 12:10:21
could an empty cache mean valid == false?
if so, w
wjia(left Chromium)
2012/08/01 01:28:59
Unfortunately, empty cache doesn't mean valid or i
tommi (sloooow) - chröme
2012/08/01 10:21:37
sgtm.
|
| + DCHECK_EQ(MessageLoop::current(), io_loop_); |
| + if (cache->valid) { |
|
tommi (sloooow) - chröme
2012/07/30 12:10:21
no need to check it first. just set valid to fals
wjia(left Chromium)
2012/08/01 01:28:59
Done.
|
| + cache->valid = false; |
| + } |
| +} |
| + |
| void MediaStreamManager::StartEnumeration( |
| DeviceRequest* new_request, |
| std::string* label) { |
| @@ -338,6 +427,14 @@ |
| } |
| } |
| + AddRequest(new_request, label); |
| +} |
| + |
| +void MediaStreamManager::AddRequest( |
| + DeviceRequest* new_request, |
| + std::string* label) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| // Create a label for this request and verify it is unique. |
| std::string request_label; |
| do { |
| @@ -346,19 +443,6 @@ |
| requests_.insert(std::make_pair(request_label, *new_request)); |
| - // Get user confirmation to use capture devices. |
| - // Need to make an asynchronous call to make sure the |requester| gets the |
| - // |label| before it would receive any event. |
| - if (new_request->type == DeviceRequest::kGenerateStream) { |
| - BrowserThread::PostTask(BrowserThread::IO, |
| - FROM_HERE, |
| - base::Bind(&MediaStreamDeviceSettings::RequestCaptureDeviceUsage, |
| - base::Unretained(device_settings_.get()), |
| - request_label, new_request->render_process_id, |
| - new_request->render_view_id, new_request->options, |
| - new_request->security_origin)); |
| - } |
| - |
| (*label) = request_label; |
| } |
| @@ -455,6 +539,19 @@ |
| MediaStreamType stream_type, const StreamDeviceInfoArray& devices) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + // Only cache device list when there is EnumerateDevices request, since |
| + // other requests don't turn on device monitoring. |
| + bool need_update_clients = false; |
| + EnumerationCache* cache = |
| + (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE ? |
| + &audio_enumeration_cache_ : &video_enumeration_cache_); |
| + if (HasEnumerationRequest(stream_type)) { |
| + if (!cache->valid || cache->devices != devices) { |
|
tommi (sloooow) - chröme
2012/07/30 12:10:21
I think this is a case for not needing the |valid|
wjia(left Chromium)
2012/08/01 01:28:59
Without |valid| flag, we have to keep cache always
tommi (sloooow) - chröme
2012/08/01 10:21:37
sgtm
|
| + cache->devices = devices; |
| + need_update_clients = true; |
| + } |
| + } |
| + |
| // Publish the result for all requests waiting for device list(s). |
| // Find the requests waiting for this device list, store their labels and |
| // release the iterator before calling device settings. We might get a call |
| @@ -464,7 +561,8 @@ |
| ++it) { |
| if (it->second.state[stream_type] == DeviceRequest::kRequested && |
| Requested(it->second.options, stream_type)) { |
| - it->second.state[stream_type] = DeviceRequest::kPendingApproval; |
| + if (it->second.type != DeviceRequest::kEnumerateDevices) |
| + it->second.state[stream_type] = DeviceRequest::kPendingApproval; |
| label_list.push_back(it->first); |
| } |
| } |
| @@ -473,8 +571,8 @@ |
| DeviceRequest& request = requests_[*it]; |
| switch (request.type) { |
| case DeviceRequest::kEnumerateDevices: |
| - request.requester->DevicesEnumerated(*it, devices); |
| - requests_.erase(*it); |
| + if (need_update_clients) |
| + request.requester->DevicesEnumerated(*it, devices); |
| break; |
| case DeviceRequest::kOpenDevice: |
| for (StreamDeviceInfoArray::const_iterator device_it = devices.begin(); |
| @@ -628,7 +726,10 @@ |
| void MediaStreamManager::WillDestroyCurrentMessageLoop() { |
| DCHECK_EQ(MessageLoop::current(), io_loop_); |
| + DCHECK(requests_.empty()); |
| if (device_thread_.get()) { |
| + StopMonitoring(); |
| + |
| video_capture_manager_->Unregister(); |
| audio_input_device_manager_->Unregister(); |
| device_thread_.reset(); |
| @@ -721,4 +822,55 @@ |
| return NULL; |
| } |
| +void MediaStreamManager::OnDevicesChanged( |
| + base::SystemMonitor::DeviceType device_type) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + MediaStreamType stream_type; |
| + EnumerationCache* cache; |
| + if (device_type == base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE) { |
| + stream_type = content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE; |
| + cache = &audio_enumeration_cache_; |
| + } else if (device_type == base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE) { |
| + stream_type = content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE; |
| + cache = &video_enumeration_cache_; |
| + } else { |
| + return; // Uninterested device change. |
|
tommi (sloooow) - chröme
2012/07/30 12:10:21
s/Uninterested/Uninteresting.
wjia(left Chromium)
2012/08/01 01:28:59
Done.
|
| + } |
| + |
| + if (!HasEnumerationRequest(stream_type)) { |
| + // There is no request for that type, No need to enumerate devices. |
| + // Therefore, invalidate the cache of that type. |
| + ClearEnumerationCache(cache); |
| + } else if (!enumeration_in_progress_[stream_type]) { |
| + enumeration_in_progress_[stream_type] = true; |
| + GetDeviceManager(stream_type)->EnumerateDevices(); |
| + } |
| +} |
| + |
| +bool MediaStreamManager::HasEnumerationRequest() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + for (DeviceRequests::iterator it = requests_.begin(); |
| + it != requests_.end(); ++it) { |
| + DeviceRequest& request = it->second; |
| + if (request.type == DeviceRequest::kEnumerateDevices) { |
| + return true; |
| + } |
| + } |
| + return false; |
| +} |
| + |
| +bool MediaStreamManager::HasEnumerationRequest( |
| + MediaStreamType stream_type) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + for (DeviceRequests::iterator it = requests_.begin(); |
| + it != requests_.end(); ++it) { |
| + DeviceRequest& request = it->second; |
| + if (request.type == DeviceRequest::kEnumerateDevices && |
| + Requested(request.options, stream_type)) { |
| + return true; |
| + } |
| + } |
| + return false; |
| +} |
| + |
| } // namespace media_stream |