| 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 3a0f6172374ea7012e2d2acb9582601ce995793c..94b703d59813fa61f8138ba21f122befeb4fc8e5 100644
|
| --- a/content/browser/renderer_host/media/media_stream_manager.cc
|
| +++ b/content/browser/renderer_host/media/media_stream_manager.cc
|
| @@ -47,10 +47,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 +88,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 +101,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 +119,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()
|
| @@ -141,15 +136,13 @@ void MediaStreamManager::AlwaysUseFakeDevice() {
|
| always_use_fake_devices_ = true;
|
| }
|
|
|
| -MediaStreamManager::MediaStreamManager(
|
| - AudioInputDeviceManager* audio_input_device_manager,
|
| - VideoCaptureManager* video_capture_manager)
|
| +MediaStreamManager::MediaStreamManager(media::AudioManager* audio_manager)
|
| : 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_(audio_manager),
|
| monitoring_started_(false),
|
| io_loop_(NULL) {
|
| + DCHECK(audio_manager_);
|
| memset(active_enumeration_ref_count_, 0,
|
| sizeof(active_enumeration_ref_count_));
|
| }
|
| @@ -162,15 +155,15 @@ MediaStreamManager::~MediaStreamManager() {
|
|
|
| VideoCaptureManager* MediaStreamManager::video_capture_manager() {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + EnsureDeviceManagersStarted();
|
| DCHECK(video_capture_manager_);
|
| - EnsureDeviceThreadAndListener();
|
| return video_capture_manager_;
|
| }
|
|
|
| AudioInputDeviceManager* MediaStreamManager::audio_input_device_manager() {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + EnsureDeviceManagersStarted();
|
| DCHECK(audio_input_device_manager_);
|
| - EnsureDeviceThreadAndListener();
|
| return audio_input_device_manager_;
|
| }
|
|
|
| @@ -199,6 +192,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));
|
|
|
| @@ -206,21 +238,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);
|
| @@ -240,15 +270,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)) {
|
| @@ -266,18 +291,21 @@ 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_DEVICE_AUDIO_CAPTURE ||
|
| + type == content::MEDIA_DEVICE_VIDEO_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_DEVICE_AUDIO_CAPTURE) {
|
| + options.audio_type = type;
|
| cache = &audio_enumeration_cache_;
|
| - } else {
|
| - options.video = true;
|
| + } else if (type == content::MEDIA_DEVICE_VIDEO_CAPTURE) {
|
| + options.video_type = type;
|
| cache = &video_enumeration_cache_;
|
| + } else {
|
| + NOTREACHED();
|
| + return;
|
| }
|
|
|
| DeviceRequest new_request(requester, options,
|
| @@ -289,7 +317,7 @@ void MediaStreamManager::EnumerateDevices(
|
| if (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,
|
| @@ -324,13 +352,19 @@ void MediaStreamManager::OpenDevice(
|
| const GURL& security_origin,
|
| std::string* label) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + DCHECK(type == content::MEDIA_DEVICE_AUDIO_CAPTURE ||
|
| + type == content::MEDIA_DEVICE_VIDEO_CAPTURE);
|
|
|
| // 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 {
|
| + NOTREACHED();
|
| + return;
|
| + }
|
|
|
| DeviceRequest new_request(requester, options,
|
| render_process_id,
|
| @@ -382,30 +416,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));
|
|
|
| @@ -415,12 +443,12 @@ 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::EnsureDeviceManagersStarted() {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| if (device_thread_.get())
|
| return;
|
| @@ -428,9 +456,14 @@ void MediaStreamManager::EnsureDeviceThreadAndListener() {
|
| device_thread_.reset(new DeviceThread("MediaStreamDeviceThread"));
|
| CHECK(device_thread_->Start());
|
|
|
| + audio_input_device_manager_ =
|
| + new media_stream::AudioInputDeviceManager(audio_manager_);
|
| audio_input_device_manager_->Register(this,
|
| device_thread_->message_loop_proxy());
|
| - video_capture_manager_->Register(this, device_thread_->message_loop_proxy());
|
| +
|
| + video_capture_manager_ = new media_stream::VideoCaptureManager();
|
| + video_capture_manager_->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.
|
| @@ -448,17 +481,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;
|
| @@ -478,6 +505,9 @@ 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;
|
| @@ -492,15 +522,29 @@ void MediaStreamManager::Opened(MediaStreamType stream_type,
|
|
|
| switch (request->type) {
|
| case DeviceRequest::OPEN_DEVICE:
|
| - request->requester->DeviceOpened(label, (*devices)[0]);
|
| + request->requester->DeviceOpened(label, devices->front());
|
| break;
|
| - case DeviceRequest::GENERATE_STREAM:
|
| - request->requester->StreamGenerated(label, request->audio_devices,
|
| - request->video_devices);
|
| + case DeviceRequest::GENERATE_STREAM: {
|
| + // Partition the array of devices into audio vs video.
|
| + 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();
|
| + }
|
| + }
|
| +
|
| + request->requester->StreamGenerated(label, audio_devices, video_devices);
|
| NotifyObserverDevicesOpened(request);
|
| break;
|
| + }
|
| default:
|
| NOTREACHED();
|
| + break;
|
| }
|
| }
|
|
|
| @@ -513,11 +557,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_DEVICE_AUDIO_CAPTURE ?
|
| &audio_enumeration_cache_ : &video_enumeration_cache_);
|
| if (HasEnumerationRequest(stream_type) &&
|
| (!cache->valid ||
|
| @@ -552,8 +596,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;
|
| @@ -561,16 +606,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();
|
| @@ -583,52 +626,61 @@ 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();
|
| - }
|
| -
|
| - 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;
|
| + StreamDeviceInfoArray& devices = it->second.devices;
|
| +
|
| + // TODO(miu): BUG. It's possible for the audio (or video) device array in
|
| + // the "requester" to become out-of-sync with the order of devices we have
|
| + // here. See http://crbug.com/147650
|
| + 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;
|
| }
|
| }
|
| }
|
| @@ -637,53 +689,50 @@ 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.
|
| + bool found_audio = false, found_video = false;
|
| + 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);
|
| +
|
| + if (device_info.stream_type == request.options.audio_type) {
|
| + found_audio = true;
|
| + } else if (device_info.stream_type == request.options.video_type) {
|
| + found_video = true;
|
| + }
|
| + }
|
| +
|
| + // Check whether we've received all stream types requested.
|
| + if (!found_audio && content::IsAudioMediaType(request.options.audio_type)) {
|
| + request.state[request.options.audio_type] = DeviceRequest::STATE_ERROR;
|
| + }
|
| + if (!found_video && content::IsVideoMediaType(request.options.video_type)) {
|
| + request.state[request.options.video_type] = DeviceRequest::STATE_ERROR;
|
| + }
|
| }
|
|
|
| void MediaStreamManager::SettingsError(const std::string& label) {
|
| @@ -750,68 +799,52 @@ 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 (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) {
|
| + if (content::IsVideoMediaType(stream_type)) {
|
| return video_capture_manager();
|
| - } else if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) {
|
| + } else if (content::IsAudioMediaType(stream_type)) {
|
| return audio_input_device_manager();
|
| }
|
| NOTREACHED();
|
| @@ -821,13 +854,17 @@ MediaStreamProvider* MediaStreamManager::GetDeviceManager(
|
| 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_DEVICE_AUDIO_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_DEVICE_VIDEO_CAPTURE;
|
| cache = &video_enumeration_cache_;
|
| } else {
|
| return; // Uninteresting device change.
|
|
|