Index: content/browser/renderer_host/media/media_stream_manager.cc |
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc |
index 8194fde724332595de1996e35f27e6c6f4aa7e41..b8a8eef32fcc39470a7015f253be75b1dc445846 100644 |
--- a/content/browser/renderer_host/media/media_stream_manager.cc |
+++ b/content/browser/renderer_host/media/media_stream_manager.cc |
@@ -11,6 +11,7 @@ |
#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/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" |
@@ -47,10 +48,8 @@ static std::string RandomLabel() { |
// Helper to verify if a media stream type is part of options or not. |
static bool Requested(const StreamOptions& options, |
MediaStreamType stream_type) { |
- return (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE && |
- options.video) || |
- (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE && |
- options.audio); |
+ return (options.audio_type == stream_type || |
+ options.video_type == stream_type); |
} |
DeviceThread::DeviceThread(const char* name) |
@@ -90,12 +89,10 @@ struct MediaStreamManager::DeviceRequest { |
DeviceRequest() |
: requester(NULL), |
- state(content::NUM_MEDIA_STREAM_DEVICE_TYPES, STATE_NOT_REQUESTED), |
+ state(content::NUM_MEDIA_TYPES, STATE_NOT_REQUESTED), |
type(GENERATE_STREAM), |
render_process_id(-1), |
render_view_id(-1) { |
- options.audio = false; |
- options.video = false; |
} |
DeviceRequest(MediaStreamRequester* requester, |
@@ -105,7 +102,7 @@ struct MediaStreamManager::DeviceRequest { |
const GURL& request_security_origin) |
: requester(requester), |
options(request_options), |
- state(content::NUM_MEDIA_STREAM_DEVICE_TYPES, STATE_NOT_REQUESTED), |
+ state(content::NUM_MEDIA_TYPES, STATE_NOT_REQUESTED), |
type(GENERATE_STREAM), |
render_process_id(render_process_id), |
render_view_id(render_view_id), |
@@ -123,8 +120,7 @@ struct MediaStreamManager::DeviceRequest { |
int render_view_id; |
GURL security_origin; |
std::string requested_device_id; |
- StreamDeviceInfoArray audio_devices; |
- StreamDeviceInfoArray video_devices; |
+ StreamDeviceInfoArray devices; |
}; |
MediaStreamManager::EnumerationCache::EnumerationCache() |
@@ -134,13 +130,10 @@ MediaStreamManager::EnumerationCache::EnumerationCache() |
MediaStreamManager::EnumerationCache::~EnumerationCache() { |
} |
-MediaStreamManager::MediaStreamManager( |
- AudioInputDeviceManager* audio_input_device_manager, |
- VideoCaptureManager* video_capture_manager) |
+MediaStreamManager::MediaStreamManager() |
: ALLOW_THIS_IN_INITIALIZER_LIST( |
device_settings_(new MediaStreamDeviceSettings(this))), |
- audio_input_device_manager_(audio_input_device_manager), |
- video_capture_manager_(video_capture_manager), |
+ audio_manager_(NULL), |
monitoring_started_(false), |
io_loop_(NULL) { |
memset(active_enumeration_ref_count_, 0, |
@@ -153,20 +146,6 @@ MediaStreamManager::~MediaStreamManager() { |
DCHECK(!io_loop_); |
} |
-VideoCaptureManager* MediaStreamManager::video_capture_manager() { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- DCHECK(video_capture_manager_); |
- EnsureDeviceThreadAndListener(); |
- return video_capture_manager_; |
-} |
- |
-AudioInputDeviceManager* MediaStreamManager::audio_input_device_manager() { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- DCHECK(audio_input_device_manager_); |
- EnsureDeviceThreadAndListener(); |
- return audio_input_device_manager_; |
-} |
- |
void MediaStreamManager::GenerateStream(MediaStreamRequester* requester, |
int render_process_id, |
int render_view_id, |
@@ -190,6 +169,45 @@ void MediaStreamManager::GenerateStream(MediaStreamRequester* requester, |
security_origin); |
} |
+void MediaStreamManager::GenerateStreamForDevice( |
+ MediaStreamRequester* requester, int render_process_id, int render_view_id, |
+ const StreamOptions& options, const std::string& device_id, |
+ const GURL& security_origin, std::string* label) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ |
+ // Create a new request based on options. |
+ AddRequest(DeviceRequest(requester, options, |
+ render_process_id, render_view_id, |
+ security_origin), |
+ label); |
+ DeviceRequest& request = requests_[*label]; |
+ |
+ // Get user confirmation to use the capture device. |
+ device_settings_->RequestCaptureDeviceUsage(*label, |
+ render_process_id, |
+ render_view_id, |
+ options, |
+ security_origin); |
+ // TODO(miu): We should ask the device manager whether a device with id |
+ // |device_id| actually exists. Note that no such MediaStreamProvider API for |
+ // this currently exists. Also, we don't have a user-friendly device name for |
+ // the infobar UI. |
+ if (content::IsAudioMediaType(options.audio_type)) { |
+ request.state[options.audio_type] = DeviceRequest::STATE_PENDING_APPROVAL; |
+ device_settings_->AvailableDevices( |
+ *label, options.audio_type, StreamDeviceInfoArray( |
+ 1, StreamDeviceInfo(options.audio_type, device_id, device_id, |
+ false))); |
+ } |
+ if (content::IsVideoMediaType(options.video_type)) { |
+ request.state[options.video_type] = DeviceRequest::STATE_PENDING_APPROVAL; |
+ device_settings_->AvailableDevices( |
+ *label, options.video_type, StreamDeviceInfoArray( |
+ 1, StreamDeviceInfo(options.video_type, device_id, device_id, |
+ false))); |
+ } |
+} |
+ |
void MediaStreamManager::CancelGenerateStream(const std::string& label) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
@@ -197,21 +215,19 @@ void MediaStreamManager::CancelGenerateStream(const std::string& label) { |
if (it != requests_.end()) { |
// The request isn't complete. |
if (!RequestDone(it->second)) { |
- DeviceRequest* request = &(it->second); |
- if (request->state[content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE] == |
- DeviceRequest::STATE_OPENING) { |
- for (StreamDeviceInfoArray::iterator it = |
- request->audio_devices.begin(); it != request->audio_devices.end(); |
- ++it) { |
- audio_input_device_manager()->Close(it->session_id); |
+ DeviceRequest& request = it->second; |
+ for (int i = content::MEDIA_NO_SERVICE + 1; i < content::NUM_MEDIA_TYPES; |
+ ++i) { |
+ const MediaStreamType stream_type = static_cast<MediaStreamType>(i); |
+ if (request.state[stream_type] != DeviceRequest::STATE_OPENING) { |
+ continue; |
} |
- } |
- if (request->state[content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE] == |
- DeviceRequest::STATE_OPENING) { |
- for (StreamDeviceInfoArray::iterator it = |
- request->video_devices.begin(); it != request->video_devices.end(); |
- ++it) { |
- video_capture_manager()->Close(it->session_id); |
+ for (StreamDeviceInfoArray::const_iterator device_it = |
+ request.devices.begin(); |
+ device_it != request.devices.end(); ++device_it) { |
+ if (device_it->stream_type == stream_type) { |
+ GetDeviceManager(stream_type)->Close(device_it->session_id); |
+ } |
} |
} |
requests_.erase(it); |
@@ -231,15 +247,10 @@ void MediaStreamManager::StopGeneratedStream(const std::string& label) { |
StopEnumerateDevices(label); |
return; |
} |
- for (StreamDeviceInfoArray::iterator audio_it = |
- it->second.audio_devices.begin(); |
- audio_it != it->second.audio_devices.end(); ++audio_it) { |
- audio_input_device_manager()->Close(audio_it->session_id); |
- } |
- for (StreamDeviceInfoArray::iterator video_it = |
- it->second.video_devices.begin(); |
- video_it != it->second.video_devices.end(); ++video_it) { |
- video_capture_manager()->Close(video_it->session_id); |
+ for (StreamDeviceInfoArray::const_iterator device_it = |
+ it->second.devices.begin(); |
+ device_it != it->second.devices.end(); ++device_it) { |
+ GetDeviceManager(device_it->stream_type)->Close(device_it->session_id); |
} |
if (it->second.type == DeviceRequest::GENERATE_STREAM && |
RequestDone(it->second)) { |
@@ -257,18 +268,20 @@ void MediaStreamManager::EnumerateDevices( |
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); |
+ DCHECK(type == content::MEDIA_AUDIO_DEVICE_CAPTURE || |
+ type == content::MEDIA_VIDEO_DEVICE_CAPTURE); |
// Create a new request. |
StreamOptions options; |
EnumerationCache* cache = NULL; |
- if (type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) { |
- options.audio = true; |
+ if (type == content::MEDIA_AUDIO_DEVICE_CAPTURE) { |
+ options.audio_type = type; |
cache = &audio_enumeration_cache_; |
- } else { |
- options.video = true; |
+ } else if (type == content::MEDIA_VIDEO_DEVICE_CAPTURE) { |
+ options.video_type = type; |
cache = &video_enumeration_cache_; |
+ } else { |
+ NOTREACHED(); |
} |
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
|
DeviceRequest new_request(requester, options, |
@@ -277,10 +290,10 @@ void MediaStreamManager::EnumerateDevices( |
security_origin); |
new_request.type = DeviceRequest::ENUMERATE_DEVICES; |
- if (cache->valid) { |
+ if (cache && cache->valid) { |
// Cached device list of this type exists. Just send it out. |
new_request.state[type] = DeviceRequest::STATE_REQUESTED; |
- AddRequest(&new_request, label); |
+ AddRequest(new_request, label); |
// Need to post a task since the requester won't have label till |
// this function returns. |
BrowserThread::PostTask(BrowserThread::IO, |
@@ -289,7 +302,9 @@ void MediaStreamManager::EnumerateDevices( |
base::Unretained(this), cache, *label)); |
} else { |
StartEnumeration(&new_request, label); |
- StartMonitoring(); |
+ if (cache) { |
+ StartMonitoring(); |
+ } |
} |
} |
@@ -315,13 +330,19 @@ void MediaStreamManager::OpenDevice( |
const GURL& security_origin, |
std::string* label) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ DCHECK(type == content::MEDIA_AUDIO_DEVICE_CAPTURE || |
+ type == content::MEDIA_VIDEO_DEVICE_CAPTURE); |
wjia(left Chromium)
2012/09/07 14:11:36
Thanks for adding DCHECK!
|
// Create a new request. |
StreamOptions options; |
- if (type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) |
- options.audio = true; |
- else |
- options.video = true; |
+ if (content::IsAudioMediaType(type)) { |
+ options.audio_type = type; |
+ } else if (content::IsVideoMediaType(type)) { |
+ options.video_type = type; |
+ } else { |
wjia(left Chromium)
2012/09/07 14:11:36
NOTREACHED() for this branch?
miu
2012/09/07 23:14:28
Done.
|
+ LOG(FATAL) << "Cannot handle request for MediaStreamType " << type; |
+ return; |
+ } |
DeviceRequest new_request(requester, options, |
render_process_id, |
@@ -373,30 +394,24 @@ void MediaStreamManager::StartEnumeration( |
std::string* label) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- MediaStreamType stream_type = content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE; |
- if (Requested(new_request->options, stream_type)) { |
- new_request->state[stream_type] = DeviceRequest::STATE_REQUESTED; |
- DCHECK_GE(active_enumeration_ref_count_[stream_type], 0); |
- if (!active_enumeration_ref_count_[stream_type]) { |
- ++active_enumeration_ref_count_[stream_type]; |
- GetDeviceManager(stream_type)->EnumerateDevices(); |
- } |
- } |
- stream_type = content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE; |
- if (Requested(new_request->options, stream_type)) { |
- new_request->state[stream_type] = DeviceRequest::STATE_REQUESTED; |
- DCHECK_GE(active_enumeration_ref_count_[stream_type], 0); |
- if (!active_enumeration_ref_count_[stream_type]) { |
- ++active_enumeration_ref_count_[stream_type]; |
- GetDeviceManager(stream_type)->EnumerateDevices(); |
+ for (int i = content::MEDIA_NO_SERVICE + 1; i < content::NUM_MEDIA_TYPES; |
+ ++i) { |
+ const MediaStreamType stream_type = static_cast<MediaStreamType>(i); |
+ if (Requested(new_request->options, stream_type)) { |
+ new_request->state[stream_type] = DeviceRequest::STATE_REQUESTED; |
+ DCHECK_GE(active_enumeration_ref_count_[stream_type], 0); |
+ if (active_enumeration_ref_count_[stream_type] == 0) { |
+ ++active_enumeration_ref_count_[stream_type]; |
+ GetDeviceManager(stream_type)->EnumerateDevices(); |
+ } |
} |
} |
- AddRequest(new_request, label); |
+ AddRequest(*new_request, label); |
} |
void MediaStreamManager::AddRequest( |
- DeviceRequest* new_request, |
+ const DeviceRequest& new_request, |
std::string* label) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
@@ -406,27 +421,51 @@ void MediaStreamManager::AddRequest( |
request_label = RandomLabel(); |
} while (requests_.find(request_label) != requests_.end()); |
- requests_.insert(std::make_pair(request_label, *new_request)); |
+ requests_.insert(std::make_pair(request_label, new_request)); |
(*label) = request_label; |
} |
-void MediaStreamManager::EnsureDeviceThreadAndListener() { |
+void MediaStreamManager::EnsureDeviceManagerStarted( |
+ MediaStreamType stream_type) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- if (device_thread_.get()) |
- return; |
- device_thread_.reset(new DeviceThread("MediaStreamDeviceThread")); |
- CHECK(device_thread_->Start()); |
+ if (!device_thread_.get()) { |
+ device_thread_.reset(new DeviceThread("MediaStreamDeviceThread")); |
+ CHECK(device_thread_->Start()); |
+ } |
- audio_input_device_manager_->Register(this, |
- device_thread_->message_loop_proxy()); |
- video_capture_manager_->Register(this, device_thread_->message_loop_proxy()); |
+ if (!device_manager_[stream_type]) { |
+ switch (stream_type) { |
+ case content::MEDIA_AUDIO_DEVICE_CAPTURE: |
+ case content::MEDIA_TAB_AUDIO_CAPTURE: |
+ if (!audio_manager_) { |
+ 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.
|
+ } |
+ device_manager_[stream_type] = |
+ new media_stream::AudioInputDeviceManager(audio_manager_, |
+ stream_type); |
+ break; |
+ case content::MEDIA_VIDEO_DEVICE_CAPTURE: |
+ case content::MEDIA_TAB_VIDEO_CAPTURE: |
+ device_manager_[stream_type] = |
+ new media_stream::VideoCaptureManager(stream_type); |
+ break; |
+ default: |
+ LOG(FATAL) << "Cannot create device manager for invalid or " |
+ << "unsupported MediaStreamType " << stream_type; |
+ return; |
+ } |
+ device_manager_[stream_type]->Register( |
+ this, device_thread_->message_loop_proxy()); |
+ } |
// We want to be notified of IO message loop destruction to delete the thread |
// and the device managers. |
- io_loop_ = MessageLoop::current(); |
- io_loop_->AddDestructionObserver(this); |
+ if (!io_loop_) { |
+ io_loop_ = MessageLoop::current(); |
+ io_loop_->AddDestructionObserver(this); |
+ } |
} |
void MediaStreamManager::Opened(MediaStreamType stream_type, |
@@ -439,17 +478,11 @@ void MediaStreamManager::Opened(MediaStreamType stream_type, |
std::string label; |
for (DeviceRequests::iterator request_it = requests_.begin(); |
request_it != requests_.end() && request == NULL; ++request_it) { |
- if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) { |
- devices = &(request_it->second.audio_devices); |
- } else if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) { |
- devices = &(request_it->second.video_devices); |
- } else { |
- NOTREACHED(); |
- } |
- |
+ devices = &(request_it->second.devices); |
for (StreamDeviceInfoArray::iterator device_it = devices->begin(); |
device_it != devices->end(); ++device_it) { |
- if (device_it->session_id == capture_session_id) { |
+ if (device_it->stream_type == stream_type && |
+ device_it->session_id == capture_session_id) { |
// We've found the request. |
device_it->in_use = true; |
label = request_it->first; |
@@ -469,6 +502,8 @@ void MediaStreamManager::Opened(MediaStreamType stream_type, |
// they are. |
for (StreamDeviceInfoArray::iterator device_it = devices->begin(); |
device_it != devices->end(); ++device_it) { |
+ if (device_it->stream_type != stream_type) |
+ continue; |
if (device_it->in_use == false) { |
// Wait for more devices to be opened before we're done. |
return; |
@@ -481,17 +516,36 @@ void MediaStreamManager::Opened(MediaStreamType stream_type, |
return; |
} |
+ // 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.
|
+ StreamDeviceInfoArray audio_devices, video_devices; |
+ for (StreamDeviceInfoArray::const_iterator device_it = devices->begin(); |
+ device_it != devices->end(); ++device_it) { |
+ if (content::IsAudioMediaType(device_it->stream_type)) { |
+ audio_devices.push_back(*device_it); |
+ } else if (content::IsVideoMediaType(device_it->stream_type)) { |
+ video_devices.push_back(*device_it); |
+ } else { |
+ NOTREACHED(); |
+ } |
+ } |
+ |
switch (request->type) { |
case DeviceRequest::OPEN_DEVICE: |
- request->requester->DeviceOpened(label, (*devices)[0]); |
+ if (content::IsAudioMediaType(stream_type)) { |
+ request->requester->DeviceOpened(label, audio_devices.front()); |
+ } else if (content::IsVideoMediaType(stream_type)) { |
+ request->requester->DeviceOpened(label, video_devices.front()); |
+ } else { |
+ NOTREACHED(); |
+ } |
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.
|
break; |
case DeviceRequest::GENERATE_STREAM: |
- request->requester->StreamGenerated(label, request->audio_devices, |
- request->video_devices); |
+ request->requester->StreamGenerated(label, audio_devices, video_devices); |
NotifyObserverDevicesOpened(request); |
break; |
default: |
NOTREACHED(); |
+ break; |
} |
} |
@@ -504,11 +558,11 @@ void MediaStreamManager::DevicesEnumerated( |
MediaStreamType stream_type, const StreamDeviceInfoArray& devices) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- // Only cache device list when there is EnumerateDevices request, since |
+ // Only cache the device list when there is an 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 ? |
+ (stream_type == content::MEDIA_AUDIO_DEVICE_CAPTURE ? |
&audio_enumeration_cache_ : &video_enumeration_cache_); |
if (HasEnumerationRequest(stream_type) && |
(!cache->valid || |
@@ -543,8 +597,9 @@ void MediaStreamManager::DevicesEnumerated( |
request.requester->DevicesEnumerated(*it, devices); |
break; |
case DeviceRequest::OPEN_DEVICE: |
+ DCHECK(!request.requested_device_id.empty()); |
for (StreamDeviceInfoArray::const_iterator device_it = devices.begin(); |
- device_it != devices.end(); device_it++) { |
+ device_it != devices.end(); ++device_it) { |
if (request.requested_device_id == device_it->device_id) { |
StreamDeviceInfo device = *device_it; |
device.in_use = false; |
@@ -552,16 +607,14 @@ void MediaStreamManager::DevicesEnumerated( |
GetDeviceManager(device_it->stream_type)->Open(device); |
request.state[device_it->stream_type] = |
DeviceRequest::STATE_OPENING; |
- if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) |
- request.audio_devices.push_back(device); |
- else |
- request.video_devices.push_back(device); |
+ request.devices.push_back(device); |
break; |
} |
} |
break; |
default: |
device_settings_->AvailableDevices(*it, stream_type, devices); |
+ break; |
} |
} |
label_list.clear(); |
@@ -574,52 +627,58 @@ void MediaStreamManager::Error(MediaStreamType stream_type, |
MediaStreamProviderError error) { |
// Find the device for the error call. |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ |
for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end(); |
++it) { |
- StreamDeviceInfoArray* devices = NULL; |
- if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) { |
- devices = &(it->second.audio_devices); |
- } else if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) { |
- devices = &(it->second.video_devices); |
- } else { |
- NOTREACHED(); |
- } |
+ StreamDeviceInfoArray& devices = it->second.devices; |
- int device_idx = 0; |
- for (StreamDeviceInfoArray::iterator device_it = devices->begin(); |
- device_it != devices->end(); ++device_it, ++device_idx) { |
- if (device_it->session_id == capture_session_id) { |
- // We've found the failing device. Find the error case: |
- if (it->second.state[stream_type] == DeviceRequest::STATE_DONE) { |
- // 1. Already opened -> signal device failure and close device. |
- // Use device_idx to signal which of the devices encountered an |
- // error. |
- if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) { |
- it->second.requester->AudioDeviceFailed(it->first, device_idx); |
- } else if (stream_type == |
- content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) { |
- it->second.requester->VideoDeviceFailed(it->first, device_idx); |
- } |
- GetDeviceManager(stream_type)->Close(capture_session_id); |
- // We don't erase the devices here so that we can update the UI |
- // properly in StopGeneratedStream(). |
- it->second.state[stream_type] = DeviceRequest::STATE_ERROR; |
+ int audio_device_idx = -1; |
+ int video_device_idx = -1; |
+ for (StreamDeviceInfoArray::iterator device_it = devices.begin(); |
+ device_it != devices.end(); ++device_it) { |
+ if (content::IsAudioMediaType(device_it->stream_type)) { |
+ ++audio_device_idx; |
+ } else if (content::IsVideoMediaType(device_it->stream_type)) { |
+ ++video_device_idx; |
+ } else { |
+ NOTREACHED(); |
+ continue; |
+ } |
+ if (device_it->stream_type != stream_type || |
+ device_it->session_id != capture_session_id) { |
+ continue; |
+ } |
+ // We've found the failing device. Find the error case: |
+ if (it->second.state[stream_type] == DeviceRequest::STATE_DONE) { |
+ // 1. Already opened -> signal device failure and close device. |
+ // Use device_idx to signal which of the devices encountered an |
+ // error. |
+ if (content::IsAudioMediaType(stream_type)) { |
+ it->second.requester->AudioDeviceFailed(it->first, audio_device_idx); |
+ } else if (content::IsVideoMediaType(stream_type)) { |
+ it->second.requester->VideoDeviceFailed(it->first, video_device_idx); |
} else { |
- // Request is not done, devices are not opened in this case. |
- if ((it->second.audio_devices.size() + |
- it->second.video_devices.size()) <= 1) { |
- // 2. Device not opened and no other devices for this request -> |
- // signal stream error and remove the request. |
- it->second.requester->StreamGenerationFailed(it->first); |
- requests_.erase(it); |
- } else { |
- // 3. Not opened but other devices exists for this request -> remove |
- // device from list, but don't signal an error. |
- devices->erase(device_it); |
- } |
+ NOTREACHED(); |
+ return; |
+ } |
+ GetDeviceManager(stream_type)->Close(capture_session_id); |
+ // We don't erase the devices here so that we can update the UI |
+ // properly in StopGeneratedStream(). |
+ it->second.state[stream_type] = DeviceRequest::STATE_ERROR; |
+ } else { |
+ // Request is not done, devices are not opened in this case. |
+ if (devices.size() <= 1) { |
+ // 2. Device not opened and no other devices for this request -> |
+ // signal stream error and remove the request. |
+ it->second.requester->StreamGenerationFailed(it->first); |
+ requests_.erase(it); |
+ } else { |
+ // 3. Not opened but other devices exists for this request -> remove |
+ // device from list, but don't signal an error. |
+ devices.erase(device_it); // NOTE: This invalidates device_it! |
} |
- return; |
} |
+ return; |
} |
} |
} |
@@ -628,53 +687,55 @@ void MediaStreamManager::DevicesAccepted(const std::string& label, |
const StreamDeviceInfoArray& devices) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
DeviceRequests::iterator request_it = requests_.find(label); |
- if (request_it != requests_.end()) { |
- if (devices.empty()) { |
- // No available devices or user didn't accept device usage. |
- request_it->second.requester->StreamGenerationFailed(request_it->first); |
- requests_.erase(request_it); |
- return; |
- } |
+ if (request_it == requests_.end()) |
+ return; |
- // Loop through all device types for this request. |
- for (StreamDeviceInfoArray::const_iterator device_it = devices.begin(); |
- device_it != devices.end(); ++device_it) { |
- StreamDeviceInfo device_info = *device_it; |
- |
- // Set in_use to false to be able to track if this device has been |
- // opened. in_use might be true if the device type can be used in more |
- // than one session. |
- DCHECK_EQ(request_it->second.state[device_it->stream_type], |
- DeviceRequest::STATE_PENDING_APPROVAL); |
- device_info.in_use = false; |
- device_info.session_id = |
- GetDeviceManager(device_info.stream_type)->Open(device_info); |
- request_it->second.state[device_it->stream_type] = |
- DeviceRequest::STATE_OPENING; |
- if (device_info.stream_type == |
- content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) { |
- request_it->second.audio_devices.push_back(device_info); |
- } else if (device_info.stream_type == |
- content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) { |
- request_it->second.video_devices.push_back(device_info); |
- } else { |
- NOTREACHED(); |
- } |
- } |
- // Check if we received all stream types requested. |
- MediaStreamType stream_type = |
- content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE; |
- if (Requested(request_it->second.options, stream_type) && |
- request_it->second.audio_devices.size() == 0) { |
- request_it->second.state[stream_type] = DeviceRequest::STATE_ERROR; |
- } |
- stream_type = content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE; |
- if (Requested(request_it->second.options, stream_type) && |
- request_it->second.video_devices.size() == 0) { |
- request_it->second.state[stream_type] = DeviceRequest::STATE_ERROR; |
- } |
+ DeviceRequest& request = request_it->second; |
+ |
+ if (devices.empty()) { |
+ // No available devices or user didn't accept device usage. |
+ request.requester->StreamGenerationFailed(request_it->first); |
+ requests_.erase(request_it); |
return; |
} |
+ |
+ // Process all newly-accepted devices for this request. |
+ for (StreamDeviceInfoArray::const_iterator device_it = devices.begin(); |
+ device_it != devices.end(); ++device_it) { |
+ StreamDeviceInfo device_info = *device_it; // Make a copy. |
+ |
+ // Set in_use to false to be able to track if this device has been |
+ // opened. in_use might be true if the device type can be used in more |
+ // than one session. |
+ DCHECK_EQ(request.state[device_it->stream_type], |
+ DeviceRequest::STATE_PENDING_APPROVAL); |
+ device_info.in_use = false; |
+ device_info.session_id = |
+ GetDeviceManager(device_info.stream_type)->Open(device_info); |
+ request.state[device_it->stream_type] = DeviceRequest::STATE_OPENING; |
+ request.devices.push_back(device_info); |
+ } |
+ |
+ // Check whether we've received all stream types requested. |
+ bool found_audio = false, found_video = false; |
+ for (StreamDeviceInfoArray::const_iterator i = request.devices.begin(); |
+ 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.
|
+ if (i->stream_type == request.options.audio_type) { |
+ found_audio = true; |
+ } else if (i->stream_type == request.options.video_type) { |
+ found_video = true; |
+ } else { |
+ NOTREACHED(); |
+ } |
+ } |
+ if (request.options.audio_type != content::MEDIA_NO_SERVICE && |
+ !found_audio) { |
+ request.state[request.options.audio_type] = DeviceRequest::STATE_ERROR; |
+ } |
+ if (request.options.video_type != content::MEDIA_NO_SERVICE && |
+ !found_video) { |
+ request.state[request.options.video_type] = DeviceRequest::STATE_ERROR; |
+ } |
} |
void MediaStreamManager::SettingsError(const std::string& label) { |
@@ -689,9 +750,21 @@ void MediaStreamManager::SettingsError(const std::string& label) { |
} |
} |
+void MediaStreamManager::SetAudioManager(media::AudioManager* audio_manager) { |
+ LOG_IF(FATAL, (audio_manager_ != NULL) && (audio_manager_ != audio_manager)) |
+ << "Cannot override AudioManager after it has been set."; |
+ audio_manager_ = audio_manager; |
+} |
+ |
void MediaStreamManager::UseFakeDevice() { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- video_capture_manager()->UseFakeDevice(); |
+ for (int i = content::MEDIA_NO_SERVICE + 1; i < content::NUM_MEDIA_TYPES; |
+ ++i) { |
+ const MediaStreamType stream_type = static_cast<MediaStreamType>(i); |
+ if (content::IsVideoMediaType(stream_type)) { |
+ GetVideoCaptureManager(stream_type)->UseFakeDevice(); |
+ } |
+ } |
device_settings_->UseFakeUI(); |
} |
@@ -701,13 +774,20 @@ void MediaStreamManager::WillDestroyCurrentMessageLoop() { |
if (device_thread_.get()) { |
StopMonitoring(); |
- video_capture_manager_->Unregister(); |
- audio_input_device_manager_->Unregister(); |
+ for (int i = content::MEDIA_NO_SERVICE + 1; i < content::NUM_MEDIA_TYPES; |
+ ++i) { |
+ if (device_manager_[i]) { |
+ device_manager_[i]->Unregister(); |
+ } |
+ } |
+ |
device_thread_.reset(); |
} |
- audio_input_device_manager_ = NULL; |
- video_capture_manager_ = NULL; |
+ for (int i = content::MEDIA_NO_SERVICE + 1; i < content::NUM_MEDIA_TYPES; |
+ ++i) { |
+ device_manager_[i] = NULL; |
+ } |
io_loop_ = NULL; |
device_settings_.reset(); |
} |
@@ -737,84 +817,85 @@ void MediaStreamManager::NotifyObserverDevicesClosed(DeviceRequest* request) { |
void MediaStreamManager::DevicesFromRequest( |
DeviceRequest* request, content::MediaStreamDevices* devices) { |
- StreamDeviceInfoArray::const_iterator it = request->audio_devices.begin(); |
- for (; it != request->audio_devices.end(); ++it) { |
- devices->push_back( |
- content::MediaStreamDevice( |
- content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE, |
- it->device_id, |
- it->name)); |
- } |
- for (it = request->video_devices.begin(); it != request->video_devices.end(); |
- ++it) { |
- devices->push_back( |
- content::MediaStreamDevice( |
- content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE, |
- it->device_id, |
- it->name)); |
+ for (StreamDeviceInfoArray::const_iterator it = request->devices.begin(); |
+ it != request->devices.end(); ++it) { |
+ devices->push_back(content::MediaStreamDevice( |
+ it->stream_type, it->device_id, it->name)); |
} |
} |
bool MediaStreamManager::RequestDone(const DeviceRequest& request) const { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- // Check if all devices are opened. |
- MediaStreamType stream_type = content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE; |
- if (Requested(request.options, stream_type)) { |
- if (request.state[stream_type] != DeviceRequest::STATE_DONE && |
- request.state[stream_type] != DeviceRequest::STATE_ERROR) { |
- return false; |
- } |
- for (StreamDeviceInfoArray::const_iterator it = |
- request.audio_devices.begin(); it != request.audio_devices.end(); |
- ++it) { |
- if (it->in_use == false) { |
- return false; |
- } |
- } |
+ const bool requested_audio = |
+ content::IsAudioMediaType(request.options.audio_type); |
+ const bool requested_video = |
+ content::IsVideoMediaType(request.options.video_type); |
+ |
+ const bool audio_done = |
+ !requested_audio || |
+ request.state[request.options.audio_type] == DeviceRequest::STATE_DONE || |
+ request.state[request.options.audio_type] == DeviceRequest::STATE_ERROR; |
+ if (!audio_done) { |
+ return false; |
} |
- stream_type = content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE; |
- if (Requested(request.options, stream_type)) { |
- if (request.state[stream_type] != DeviceRequest::STATE_DONE && |
- request.state[stream_type] != DeviceRequest::STATE_ERROR) { |
- return false; |
- } |
+ const bool video_done = |
+ !requested_video || |
+ request.state[request.options.video_type] == DeviceRequest::STATE_DONE || |
+ request.state[request.options.video_type] == DeviceRequest::STATE_ERROR; |
+ if (!video_done) { |
+ return false; |
+ } |
- for (StreamDeviceInfoArray::const_iterator it = |
- request.video_devices.begin(); it != request.video_devices.end(); |
- ++it) { |
- if (it->in_use == false) { |
- return false; |
- } |
+ for (StreamDeviceInfoArray::const_iterator it = request.devices.begin(); |
+ it != request.devices.end(); ++it) { |
+ if ((!requested_audio && content::IsAudioMediaType(it->stream_type)) || |
+ (!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.
|
+ continue; |
+ } |
+ if (it->in_use == false) { |
+ return false; |
} |
} |
return true; |
} |
-// Called to get media capture device manager of specified type. |
MediaStreamProvider* MediaStreamManager::GetDeviceManager( |
MediaStreamType stream_type) { |
- if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) { |
- return video_capture_manager(); |
- } else if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) { |
- return audio_input_device_manager(); |
- } |
- NOTREACHED(); |
- return NULL; |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ EnsureDeviceManagerStarted(stream_type); |
+ return device_manager_[stream_type]; |
+} |
+ |
+VideoCaptureManager* MediaStreamManager::GetVideoCaptureManager( |
+ MediaStreamType stream_type) { |
+ DCHECK(content::IsVideoMediaType(stream_type)); |
+ return reinterpret_cast<VideoCaptureManager*>(GetDeviceManager(stream_type)); |
+} |
+ |
+AudioInputDeviceManager* MediaStreamManager::GetAudioInputDeviceManager( |
+ MediaStreamType stream_type) { |
+ DCHECK(content::IsAudioMediaType(stream_type)); |
+ return reinterpret_cast<AudioInputDeviceManager*>( |
+ GetDeviceManager(stream_type)); |
} |
void MediaStreamManager::OnDevicesChanged( |
base::SystemMonitor::DeviceType device_type) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ |
+ // NOTE: This method is only called in response to physical audio/video device |
+ // changes (from the operating system). |
+ |
MediaStreamType stream_type; |
EnumerationCache* cache; |
if (device_type == base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE) { |
- stream_type = content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE; |
+ stream_type = content::MEDIA_AUDIO_DEVICE_CAPTURE; |
cache = &audio_enumeration_cache_; |
} else if (device_type == base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE) { |
- stream_type = content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE; |
+ stream_type = content::MEDIA_VIDEO_DEVICE_CAPTURE; |
cache = &video_enumeration_cache_; |
} else { |
return; // Uninteresting device change. |