Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(804)

Unified Diff: content/browser/renderer_host/media/media_stream_manager.cc

Issue 10912004: Begin adding support for tab mirroring via the MediaStream audio/video capturing (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Changes after review by xians@. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..26bb149cdda5d2fb58c575552a76a1415643008a 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),
@@ -122,9 +119,7 @@ struct MediaStreamManager::DeviceRequest {
int render_process_id;
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 +129,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 +145,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,
@@ -197,21 +175,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 +207,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 +228,25 @@ 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_LT(content::MEDIA_NO_SERVICE, type);
+ DCHECK_GT(content::NUM_MEDIA_TYPES, type);
// Create a new request.
StreamOptions options;
- EnumerationCache* cache = NULL;
- if (type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) {
- options.audio = true;
- cache = &audio_enumeration_cache_;
+ EnumerationCache* cache;
+ if (type == content::MEDIA_USER_AUDIO_CAPTURE) {
+ options.audio_type = type;
+ cache = &user_audio_enumeration_cache_;
+ } else if (type == content::MEDIA_USER_VIDEO_CAPTURE) {
+ options.video_type = type;
+ cache = &user_video_enumeration_cache_;
} else {
- options.video = true;
- cache = &video_enumeration_cache_;
+ if (content::IsAudioMediaType(type)) {
+ options.audio_type = type;
+ } else if (content::IsVideoMediaType(type)) {
+ options.video_type = type;
+ }
+ cache = NULL;
}
DeviceRequest new_request(requester, options,
@@ -277,7 +255,7 @@ 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);
@@ -289,7 +267,9 @@ void MediaStreamManager::EnumerateDevices(
base::Unretained(this), cache, *label));
} else {
StartEnumeration(&new_request, label);
- StartMonitoring();
+ if (cache) {
+ StartMonitoring();
+ }
}
}
@@ -318,17 +298,21 @@ void MediaStreamManager::OpenDevice(
// 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 {
+ LOG(FATAL) << "Cannot handle request for MediaStreamType " << type;
+ return;
+ }
+ options.opt_device_id = device_id;
wjia(left Chromium) 2012/09/03 15:54:17 device_id doesn't belong to here. It should be in
miu 2012/09/04 20:42:19 Actually, I didn't move it from here into StreamOp
DeviceRequest new_request(requester, options,
render_process_id,
render_view_id,
security_origin);
new_request.type = DeviceRequest::OPEN_DEVICE;
- new_request.requested_device_id = device_id;
StartEnumeration(&new_request, label);
}
@@ -358,8 +342,8 @@ void MediaStreamManager::StopMonitoring() {
if (monitoring_started_ && !HasEnumerationRequest()) {
base::SystemMonitor::Get()->RemoveDevicesChangedObserver(this);
monitoring_started_ = false;
- ClearEnumerationCache(&audio_enumeration_cache_);
- ClearEnumerationCache(&video_enumeration_cache_);
+ ClearEnumerationCache(&user_audio_enumeration_cache_);
+ ClearEnumerationCache(&user_video_enumeration_cache_);
}
}
@@ -373,22 +357,16 @@ 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();
+ }
}
}
@@ -411,22 +389,46 @@ void MediaStreamManager::AddRequest(
(*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_USER_AUDIO_CAPTURE:
+ case content::MEDIA_TAB_AUDIO_CAPTURE:
+ if (!audio_manager_) {
+ audio_manager_ = content::BrowserMainLoop::GetAudioManager();
+ }
+ device_manager_[stream_type] =
+ new media_stream::AudioInputDeviceManager(audio_manager_,
+ stream_type);
+ break;
+ case content::MEDIA_USER_VIDEO_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 +441,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 +465,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;
@@ -481,17 +480,36 @@ void MediaStreamManager::Opened(MediaStreamType stream_type,
return;
}
+ // 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();
+ }
+ }
+
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();
+ }
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,13 +522,20 @@ 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.
+ // NOTE: Caching only applies to the user audio/video capture devices.
+ EnumerationCache* cache;
+ if (stream_type == content::MEDIA_USER_AUDIO_CAPTURE) {
+ cache = &user_audio_enumeration_cache_;
+ } else if (stream_type == content::MEDIA_USER_VIDEO_CAPTURE) {
+ cache = &user_video_enumeration_cache_;
+ } else {
+ cache = NULL;
+ }
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 &&
+ HasEnumerationRequest(stream_type) &&
(!cache->valid ||
devices.size() != cache->devices.size() ||
!std::equal(devices.begin(), devices.end(), cache->devices.begin(),
@@ -518,6 +543,10 @@ void MediaStreamManager::DevicesEnumerated(
cache->valid = true;
cache->devices = devices;
need_update_clients = true;
+ } else {
+ // If stream_type is not a user type, there is no caching. In such cases,
+ // we assume we always need to update the clients.
+ need_update_clients = (cache == NULL);
}
// Publish the result for all requests waiting for device list(s).
@@ -537,31 +566,44 @@ void MediaStreamManager::DevicesEnumerated(
for (std::list<std::string>::iterator it = label_list.begin();
it != label_list.end(); ++it) {
DeviceRequest& request = requests_[*it];
+
+ // If one specific device has been requested, prune all other devices out.
+ StreamDeviceInfoArray tmp;
+ const StreamDeviceInfoArray* pruned_devices;
+ if (request.options.opt_device_id.empty()) {
+ pruned_devices = &devices;
+ } else {
+ for (StreamDeviceInfoArray::const_iterator device_it = devices.begin();
+ device_it != devices.end(); ++device_it) {
+ if (device_it->device_id == request.options.opt_device_id) {
+ tmp.push_back(*device_it);
+ }
+ }
+ pruned_devices = &tmp;
+ }
+
switch (request.type) {
case DeviceRequest::ENUMERATE_DEVICES:
if (need_update_clients)
- request.requester->DevicesEnumerated(*it, devices);
+ request.requester->DevicesEnumerated(*it, *pruned_devices);
break;
case DeviceRequest::OPEN_DEVICE:
- for (StreamDeviceInfoArray::const_iterator device_it = devices.begin();
- device_it != devices.end(); device_it++) {
- if (request.requested_device_id == device_it->device_id) {
- StreamDeviceInfo device = *device_it;
- device.in_use = false;
- device.session_id =
- 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);
- break;
- }
+ if (!pruned_devices->empty()) {
+ StreamDeviceInfo device = pruned_devices->front();
+ // For OPEN_DEVICE requests, it is mandatory for the opt_device_id
+ // field to be provided. See MediaStreamManager::OpenDevice().
+ DCHECK(!request.options.opt_device_id.empty());
+ DCHECK_EQ(request.options.opt_device_id, device.device_id);
+ device.in_use = false;
+ device.session_id =
+ GetDeviceManager(device.stream_type)->Open(device);
+ request.state[device.stream_type] = DeviceRequest::STATE_OPENING;
+ request.devices.push_back(device);
}
break;
default:
- device_settings_->AvailableDevices(*it, stream_type, devices);
+ device_settings_->AvailableDevices(*it, stream_type, *pruned_devices);
+ break;
}
}
label_list.clear();
@@ -574,52 +616,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 +676,56 @@ 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) {
+ 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 +740,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 +764,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,85 +807,86 @@ 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))) {
+ 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 user 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;
- cache = &audio_enumeration_cache_;
+ stream_type = content::MEDIA_USER_AUDIO_CAPTURE;
+ cache = &user_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_;
+ stream_type = content::MEDIA_USER_VIDEO_CAPTURE;
+ cache = &user_video_enumeration_cache_;
} else {
return; // Uninteresting device change.
}

Powered by Google App Engine
This is Rietveld 408576698