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

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

Issue 2350693002: Remove device enumeration, caching and monitoring from MediaStreamManager. (Closed)
Patch Set: latest hta@ comments Created 4 years, 3 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 81f4162377f7b5e4d58fd0c2560c96bd51221654..74018626f842f0464bff8ec79f2c434650f28ccb 100644
--- a/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -6,12 +6,10 @@
#include <stddef.h>
#include <stdint.h>
-#include <string.h>
+
#include <algorithm>
#include <cctype>
#include <list>
-#include <utility>
-#include <vector>
#include "base/bind.h"
#include "base/command_line.h"
@@ -21,7 +19,6 @@
#include "base/power_monitor/power_monitor.h"
#include "base/profiler/scoped_tracker.h"
#include "base/rand_util.h"
-#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -29,11 +26,10 @@
#include "base/threading/thread.h"
#include "base/threading/thread_local.h"
#include "build/build_config.h"
-#include "content/browser/browser_main_loop.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/renderer_host/media/audio_input_device_manager.h"
-#include "content/browser/renderer_host/media/audio_output_device_enumerator.h"
#include "content/browser/renderer_host/media/media_capture_devices_impl.h"
+#include "content/browser/renderer_host/media/media_devices_manager.h"
#include "content/browser/renderer_host/media/media_stream_requester.h"
#include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
@@ -42,7 +38,6 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/desktop_media_id.h"
#include "content/public/browser/media_observer.h"
-#include "content/public/browser/media_request_state.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents_media_capture_id.h"
#include "content/public/common/content_client.h"
@@ -66,10 +61,6 @@
#include "chromeos/audio/cras_audio_handler.h"
#endif
-#if defined(OS_MACOSX)
-#include "media/device_monitors/device_monitor_mac.h"
-#endif
-
namespace content {
base::LazyInstance<base::ThreadLocalPointer<MediaStreamManager>>::Leaky
@@ -164,19 +155,6 @@ void EnableHotwordEffect(const StreamControls& controls, int* effects) {
}
}
-// Private helper method to generate a string for the log message that lists the
-// human readable names of |devices|.
-std::string GetLogMessageString(MediaStreamType stream_type,
- const StreamDeviceInfoArray& device_infos) {
- std::string output_string =
- base::StringPrintf("Getting devices for stream type %d:\n", stream_type);
- if (device_infos.empty())
- return output_string + "No devices found.";
- for (const content::StreamDeviceInfo& device_info : device_infos)
- output_string += " " + device_info.device.name + "\n";
- return output_string;
-}
-
// Clears the MediaStreamDevice.name from all devices in |devices|.
void ClearDeviceLabels(content::StreamDeviceInfoArray* devices) {
for (content::StreamDeviceInfo& device_info : *devices)
@@ -194,6 +172,79 @@ GURL ConvertToGURL(const url::Origin& origin) {
return origin.unique() ? GURL() : GURL(origin.Serialize());
}
+bool GetDeviceIDFromHMAC(const std::string& salt,
+ const url::Origin& security_origin,
+ const std::string& hmac_device_id,
+ const MediaDeviceInfoArray& devices,
+ std::string* device_id) {
+ // The source_id can be empty if the constraint is set but empty.
+ if (hmac_device_id.empty())
+ return false;
+
+ for (const auto& device_info : devices) {
+ if (MediaStreamManager::DoesMediaDeviceIDMatchHMAC(
+ salt, security_origin, hmac_device_id, device_info.device_id)) {
+ *device_id = device_info.device_id;
+ return true;
+ }
+ }
+ return false;
+}
+
+MediaStreamType ConvertToMediaStreamType(MediaDeviceType type) {
+ switch (type) {
+ case MEDIA_DEVICE_TYPE_AUDIO_INPUT:
+ return MEDIA_DEVICE_AUDIO_CAPTURE;
+ case MEDIA_DEVICE_TYPE_VIDEO_INPUT:
+ return MEDIA_DEVICE_VIDEO_CAPTURE;
+ case MEDIA_DEVICE_TYPE_AUDIO_OUTPUT:
+ return MEDIA_DEVICE_AUDIO_OUTPUT;
+ default:
+ NOTREACHED();
+ }
+
+ return MEDIA_NO_SERVICE;
+}
+
+MediaDeviceType ConvertToMediaDeviceType(MediaStreamType stream_type) {
+ switch (stream_type) {
+ case MEDIA_DEVICE_AUDIO_CAPTURE:
+ return MEDIA_DEVICE_TYPE_AUDIO_INPUT;
+ case MEDIA_DEVICE_VIDEO_CAPTURE:
+ return MEDIA_DEVICE_TYPE_VIDEO_INPUT;
+ case MEDIA_DEVICE_AUDIO_OUTPUT:
+ return MEDIA_DEVICE_TYPE_AUDIO_OUTPUT;
+ default:
+ NOTREACHED();
+ }
+
+ return NUM_MEDIA_DEVICE_TYPES;
+}
+
+StreamDeviceInfoArray ConvertToStreamDeviceInfoArray(
+ MediaStreamType stream_type,
+ const MediaDeviceInfoArray& device_infos) {
+ StreamDeviceInfoArray stream_devices;
+ for (const auto& info : device_infos) {
+ stream_devices.emplace_back(stream_type, info.label, info.device_id,
+ info.group_id);
+ }
+
+ return stream_devices;
+}
+
+MediaStreamDevices ConvertToMediaStreamDevices(
+ MediaStreamType stream_type,
+ const MediaDeviceInfoArray& device_infos) {
+ MediaStreamDevices devices;
+ for (const auto& info : device_infos) {
+ devices.emplace_back(stream_type, info.device_id, info.label,
+ info.group_id);
+ }
+
+ return devices;
+}
+
} // namespace
@@ -363,13 +414,6 @@ class MediaStreamManager::DeviceRequest {
int target_frame_id_;
};
-MediaStreamManager::EnumerationCache::EnumerationCache()
- : valid(false) {
-}
-
-MediaStreamManager::EnumerationCache::~EnumerationCache() {
-}
-
// static
void MediaStreamManager::SendMessageToNativeLog(const std::string& message) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
@@ -392,12 +436,9 @@ MediaStreamManager::MediaStreamManager(media::AudioManager* audio_manager)
#if defined(OS_WIN)
video_capture_thread_("VideoCaptureThread"),
#endif
- monitoring_started_(false),
use_fake_ui_(base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseFakeUIForMediaStream)) {
DCHECK(audio_manager_);
- memset(active_enumeration_ref_count_, 0,
- sizeof(active_enumeration_ref_count_));
// Some unit tests create the MSM in the IO thread and assumes the
// initialization is done synchronously.
@@ -450,6 +491,12 @@ MediaStreamManager::audio_output_device_enumerator() {
return audio_output_device_enumerator_.get();
}
+MediaDevicesManager* MediaStreamManager::media_devices_manager() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(media_devices_manager_.get());
+ return media_devices_manager_.get();
+}
+
std::string MediaStreamManager::MakeMediaAccessRequest(
int render_process_id,
int render_frame_id,
@@ -721,75 +768,37 @@ void MediaStreamManager::DoEnumerateDevices(const std::string& label) {
if (request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT) {
DCHECK_EQ(MEDIA_NO_SERVICE, request->video_type());
- DCHECK_GE(active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_OUTPUT], 0);
request->SetState(MEDIA_DEVICE_AUDIO_OUTPUT, MEDIA_REQUEST_STATE_REQUESTED);
- if (active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_OUTPUT] == 0) {
- ++active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_OUTPUT];
- DCHECK(audio_output_device_enumerator_);
- audio_output_device_enumerator_->Enumerate(
- base::Bind(&MediaStreamManager::AudioOutputDevicesEnumerated,
- base::Unretained(this)));
- }
+ media_devices_manager_->EnumerateDevices(
+ {{false /* audio input */, false /* video input*/,
+ true /* audio output */}},
+ base::Bind(&MediaStreamManager::AudioOutputDevicesEnumerated,
+ base::Unretained(this), label));
return;
}
- MediaStreamType type;
- EnumerationCache* cache;
- if (request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE) {
- DCHECK_EQ(MEDIA_NO_SERVICE, request->video_type());
- type = MEDIA_DEVICE_AUDIO_CAPTURE;
- cache = &audio_enumeration_cache_;
- } else {
- DCHECK_EQ(MEDIA_DEVICE_VIDEO_CAPTURE, request->video_type());
- DCHECK_EQ(MEDIA_NO_SERVICE, request->audio_type());
- type = MEDIA_DEVICE_VIDEO_CAPTURE;
- cache = &video_enumeration_cache_;
- }
-
- if (!EnumerationRequired(cache, type)) {
- // Cached device list of this type exists. Just send it out.
- request->SetState(type, MEDIA_REQUEST_STATE_REQUESTED);
- request->devices = cache->devices;
- FinalizeEnumerateDevices(label, request);
- } else {
- StartEnumeration(request);
- }
+ StartEnumeration(request, label);
DVLOG(1) << "Enumerate Devices ({label = " << label << "})";
}
void MediaStreamManager::AudioOutputDevicesEnumerated(
- const AudioOutputDeviceEnumeration& device_enumeration) {
+ const std::string& label,
+ const MediaDeviceEnumeration& enumeration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DVLOG(1) << "AudioOutputDevicesEnumerated()";
- StreamDeviceInfoArray device_infos;
- if (device_enumeration.has_actual_devices) {
- for (const auto& entry : device_enumeration.devices) {
- device_infos.emplace_back(MEDIA_DEVICE_AUDIO_OUTPUT, entry.device_name,
- entry.unique_id, entry.group_id);
- }
- }
-
- const std::string log_message =
- "New device enumeration result:\n" +
- GetLogMessageString(MEDIA_DEVICE_AUDIO_OUTPUT, device_infos);
- SendMessageToNativeLog(log_message);
-
- // Publish the result for all requests waiting for device list(s).
- for (const LabeledDeviceRequest& request : requests_) {
- if (request.second->state(MEDIA_DEVICE_AUDIO_OUTPUT) ==
- MEDIA_REQUEST_STATE_REQUESTED &&
- request.second->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT) {
- DCHECK_EQ(MEDIA_ENUMERATE_DEVICES, request.second->request_type);
- request.second->SetState(MEDIA_DEVICE_AUDIO_OUTPUT,
- MEDIA_REQUEST_STATE_PENDING_APPROVAL);
- request.second->devices = device_infos;
- FinalizeEnumerateDevices(request.first, request.second);
- }
- }
+ DeviceRequest* request = FindRequest(label);
+ if (!request)
+ return;
- --active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_OUTPUT];
- DCHECK_GE(active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_OUTPUT], 0);
+ DCHECK_EQ(MEDIA_DEVICE_AUDIO_OUTPUT, request->audio_type());
+ DCHECK_EQ(MEDIA_REQUEST_STATE_REQUESTED,
+ request->state(MEDIA_DEVICE_AUDIO_OUTPUT));
+ DCHECK_EQ(MEDIA_ENUMERATE_DEVICES, request->request_type);
+ DCHECK(!request->ui_proxy.get());
+ StreamDeviceInfoArray device_infos = ConvertToStreamDeviceInfoArray(
+ MEDIA_DEVICE_AUDIO_OUTPUT, enumeration[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT]);
+ request->devices = device_infos;
+ FinalizeEnumerateDevices(label, request);
}
void MediaStreamManager::OpenDevice(MediaStreamRequester* requester,
@@ -844,61 +853,33 @@ bool MediaStreamManager::TranslateSourceIdToDeviceId(
if (source_id.empty())
return false;
- const EnumerationCache* cache =
- stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ?
- &audio_enumeration_cache_ : &video_enumeration_cache_;
-
- // If device monitoring hasn't started, the |device_guid| is not valid.
- if (!cache->valid)
- return false;
-
- for (const StreamDeviceInfo& device_info : cache->devices) {
- if (DoesMediaDeviceIDMatchHMAC(salt, security_origin, source_id,
- device_info.device.id)) {
- *device_id = device_info.device.id;
- return true;
- }
- }
- return false;
+ // TODO(guidou): Change to use MediaDevicesManager::EnumerateDevices.
+ // See http://crbug.com/648155.
+ MediaDeviceInfoArray cached_devices =
+ media_devices_manager_->GetCachedDeviceInfo(
+ ConvertToMediaDeviceType(stream_type));
+ return GetDeviceIDFromHMAC(salt, security_origin, source_id, cached_devices,
+ device_id);
}
void MediaStreamManager::EnsureDeviceMonitorStarted() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- StartMonitoring();
-}
-
-void MediaStreamManager::StopRemovedDevices(
- const StreamDeviceInfoArray& old_devices,
- const StreamDeviceInfoArray& new_devices) {
- DVLOG(1) << "StopRemovedDevices("
- << "{#old_devices = " << old_devices.size() << "} "
- << "{#new_devices = " << new_devices.size() << "})";
- for (const StreamDeviceInfo& old_device_info : old_devices) {
- bool device_found = false;
- for (const StreamDeviceInfo& new_device_info : new_devices) {
- if (old_device_info.device.id == new_device_info.device.id) {
- device_found = true;
- break;
- }
- }
-
- if (!device_found) {
- // A device has been removed. We need to check if it is used by a
- // MediaStream and in that case cleanup and notify the render process.
- StopRemovedDevice(old_device_info.device);
- }
- }
+ media_devices_manager_->StartMonitoring();
}
-void MediaStreamManager::StopRemovedDevice(const MediaStreamDevice& device) {
+void MediaStreamManager::StopRemovedDevice(MediaDeviceType type,
+ const MediaDeviceInfo& device) {
+ DCHECK(type == MEDIA_DEVICE_TYPE_AUDIO_INPUT ||
+ type == MEDIA_DEVICE_TYPE_VIDEO_INPUT);
+ MediaStreamType stream_type = ConvertToMediaStreamType(type);
std::vector<int> session_ids;
for (const LabeledDeviceRequest& labeled_request : requests_) {
const DeviceRequest* request = labeled_request.second;
for (const StreamDeviceInfo& device_info : request->devices) {
const std::string source_id = GetHMACForMediaDeviceID(
- request->salt, request->security_origin, device.id);
+ request->salt, request->security_origin, device.device_id);
if (device_info.device.id == source_id &&
- device_info.device.type == device.type) {
+ device_info.device.type == stream_type) {
session_ids.push_back(device_info.session_id);
if (labeled_request.second->requester) {
labeled_request.second->requester->DeviceStopped(
@@ -909,86 +890,20 @@ void MediaStreamManager::StopRemovedDevice(const MediaStreamDevice& device) {
}
}
for (const int session_id : session_ids)
- StopDevice(device.type, session_id);
+ StopDevice(stream_type, session_id);
AddLogMessageOnIOThread(
base::StringPrintf(
- "Media input device removed: type = %s, id = %s, name = %s ",
- (device.type == MEDIA_DEVICE_AUDIO_CAPTURE ? "audio" : "video"),
- device.id.c_str(), device.name.c_str()).c_str());
-}
-
-void MediaStreamManager::StartMonitoring() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (monitoring_started_)
- return;
-
- if (!base::SystemMonitor::Get())
- return;
-
- monitoring_started_ = true;
- base::SystemMonitor::Get()->AddDevicesChangedObserver(this);
-
- // Enumerate both the audio and video input devices to cache the device lists
- // and send them to media observer.
- ++active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_CAPTURE];
- audio_input_device_manager_->EnumerateDevices(MEDIA_DEVICE_AUDIO_CAPTURE);
- ++active_enumeration_ref_count_[MEDIA_DEVICE_VIDEO_CAPTURE];
- video_capture_manager_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
-
-#if defined(OS_MACOSX)
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&MediaStreamManager::StartMonitoringOnUIThread,
- base::Unretained(this)));
-#endif
-}
-
-void MediaStreamManager::StopMonitoring() {
- DCHECK(CalledOnIOThread());
- if (!monitoring_started_)
- return;
- base::SystemMonitor::Get()->RemoveDevicesChangedObserver(this);
- monitoring_started_ = false;
- ClearEnumerationCache(&audio_enumeration_cache_);
- ClearEnumerationCache(&video_enumeration_cache_);
- audio_output_device_enumerator_->SetCachePolicy(
- AudioOutputDeviceEnumerator::CACHE_POLICY_NO_CACHING);
-}
-
-#if defined(OS_MACOSX)
-void MediaStreamManager::StartMonitoringOnUIThread() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- // TODO(erikchen): Remove ScopedTracker below once crbug.com/458404 is fixed.
- tracked_objects::ScopedTracker tracking_profile1(
- FROM_HERE_WITH_EXPLICIT_FUNCTION(
- "458404 MediaStreamManager::GetBrowserMainLoop"));
- BrowserMainLoop* browser_main_loop = content::BrowserMainLoop::GetInstance();
- if (!browser_main_loop)
- return;
-
- // TODO(erikchen): Remove ScopedTracker below once crbug.com/458404 is
- // fixed.
- tracked_objects::ScopedTracker tracking_profile2(
- FROM_HERE_WITH_EXPLICIT_FUNCTION(
- "458404 MediaStreamManager::GetTaskRunner"));
- const scoped_refptr<base::SingleThreadTaskRunner> task_runner =
- audio_manager_->GetTaskRunner();
- // TODO(erikchen): Remove ScopedTracker below once crbug.com/458404 is
- // fixed.
- tracked_objects::ScopedTracker tracking_profile3(
- FROM_HERE_WITH_EXPLICIT_FUNCTION(
- "458404 MediaStreamManager::DeviceMonitorMac::StartMonitoring"));
- browser_main_loop->device_monitor_mac()->StartMonitoring(task_runner);
+ "Media input device removed: type=%s, id=%s, name=%s ",
+ (stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ? "audio" : "video"),
+ device.device_id.c_str(), device.label.c_str())
+ .c_str());
}
-#endif
-// Pick the first valid (translatable) device ID from lists of required
-// and optional IDs.
-bool MediaStreamManager::PickDeviceId(MediaStreamType type,
- const std::string& salt,
+bool MediaStreamManager::PickDeviceId(const std::string& salt,
const url::Origin& security_origin,
const TrackControls& controls,
+ const MediaDeviceInfoArray& devices,
std::string* device_id) const {
if (!controls.device_ids.empty()) {
if (controls.device_ids.size() > 1) {
@@ -996,8 +911,8 @@ bool MediaStreamManager::PickDeviceId(MediaStreamType type,
return false;
}
const std::string& candidate_id = controls.device_ids[0];
- if (!TranslateSourceIdToDeviceId(type, salt, security_origin, candidate_id,
- device_id)) {
+ if (!GetDeviceIDFromHMAC(salt, security_origin, candidate_id, devices,
+ device_id)) {
LOG(WARNING) << "Invalid mandatory capture ID = " << candidate_id;
return false;
}
@@ -1005,8 +920,8 @@ bool MediaStreamManager::PickDeviceId(MediaStreamType type,
}
// We don't have a required ID. Look at the alternates.
for (const std::string& candidate_id : controls.alternate_device_ids) {
- if (TranslateSourceIdToDeviceId(type, salt, security_origin, candidate_id,
- device_id)) {
+ if (GetDeviceIDFromHMAC(salt, security_origin, candidate_id, devices,
+ device_id)) {
return true;
} else {
LOG(WARNING) << "Invalid optional capture ID = " << candidate_id;
@@ -1018,13 +933,14 @@ bool MediaStreamManager::PickDeviceId(MediaStreamType type,
bool MediaStreamManager::GetRequestedDeviceCaptureId(
const DeviceRequest* request,
MediaStreamType type,
+ const MediaDeviceInfoArray& devices,
std::string* device_id) const {
if (type == MEDIA_DEVICE_AUDIO_CAPTURE) {
- return PickDeviceId(type, request->salt, request->security_origin,
- request->controls.audio, device_id);
+ return PickDeviceId(request->salt, request->security_origin,
+ request->controls.audio, devices, device_id);
} else if (type == MEDIA_DEVICE_VIDEO_CAPTURE) {
- return PickDeviceId(type, request->salt, request->security_origin,
- request->controls.video, device_id);
+ return PickDeviceId(request->salt, request->security_origin,
+ request->controls.video, devices, device_id);
} else {
NOTREACHED();
}
@@ -1045,55 +961,29 @@ void MediaStreamManager::TranslateDeviceIdToSourceId(
}
}
-void MediaStreamManager::ClearEnumerationCache(EnumerationCache* cache) {
- DCHECK(CalledOnIOThread());
- cache->valid = false;
-}
-
-bool MediaStreamManager::EnumerationRequired(EnumerationCache* cache,
- MediaStreamType stream_type) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (stream_type == MEDIA_NO_SERVICE)
- return false;
-
- DCHECK(stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ||
- stream_type == MEDIA_DEVICE_VIDEO_CAPTURE);
-
-#if defined(OS_ANDROID)
- // There's no SystemMonitor on Android that notifies us when devices are
- // added or removed, so we need to populate the cache on every request.
- // Fortunately, there is an already up-to-date cache in the browser side
- // audio manager that we can rely on, so the performance impact of
- // invalidating the cache like this, is minimal.
- if (stream_type == MEDIA_DEVICE_AUDIO_CAPTURE) {
- // Make sure the cache is marked as invalid so that FinalizeEnumerateDevices
- // will be called at the end of the enumeration.
- ClearEnumerationCache(cache);
- }
-#endif
- // If the cache isn't valid, we need to start a full enumeration.
- return !cache->valid;
-}
-
-void MediaStreamManager::StartEnumeration(DeviceRequest* request) {
+void MediaStreamManager::StartEnumeration(DeviceRequest* request,
+ const std::string& label) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// Start monitoring the devices when doing the first enumeration.
- StartMonitoring();
+ media_devices_manager_->StartMonitoring();
// Start enumeration for devices of all requested device types.
- const MediaStreamType stream_types[] = {request->audio_type(),
- request->video_type()};
- for (const MediaStreamType stream_type : stream_types) {
- if (stream_type == MEDIA_NO_SERVICE)
- continue;
- request->SetState(stream_type, MEDIA_REQUEST_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(stream_type);
- }
- }
+ bool request_audio_input = request->audio_type() != MEDIA_NO_SERVICE;
+ if (request_audio_input)
+ request->SetState(request->audio_type(), MEDIA_REQUEST_STATE_REQUESTED);
+
+ bool request_video_input = request->video_type() != MEDIA_NO_SERVICE;
+ if (request_video_input)
+ request->SetState(request->video_type(), MEDIA_REQUEST_STATE_REQUESTED);
+
+ // base::Unretained is safe here because MediaStreamManager is deleted on the
+ // UI thread, after the IO thread has been stopped.
+ DCHECK(request_audio_input || request_video_input);
+ media_devices_manager_->EnumerateDevices(
+ {{request_audio_input, request_video_input, false /* no audio output */}},
+ base::Bind(&MediaStreamManager::DevicesEnumerated, base::Unretained(this),
+ request_audio_input, request_video_input, label));
}
std::string MediaStreamManager::AddRequest(DeviceRequest* request) {
@@ -1134,7 +1024,8 @@ void MediaStreamManager::DeleteRequest(const std::string& label) {
void MediaStreamManager::ReadOutputParamsAndPostRequestToUI(
const std::string& label,
- DeviceRequest* request) {
+ DeviceRequest* request,
+ const MediaDeviceEnumeration& enumeration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// Actual audio parameters are required only for MEDIA_TAB_AUDIO_CAPTURE.
@@ -1150,15 +1041,16 @@ void MediaStreamManager::ReadOutputParamsAndPostRequestToUI(
base::Bind(&media::AudioManager::GetDefaultOutputStreamParameters,
base::Unretained(audio_manager_)),
base::Bind(&MediaStreamManager::PostRequestToUI, base::Unretained(this),
- label, request));
+ label, request, enumeration));
} else {
- PostRequestToUI(label, request, media::AudioParameters());
+ PostRequestToUI(label, request, enumeration, media::AudioParameters());
}
}
void MediaStreamManager::PostRequestToUI(
const std::string& label,
DeviceRequest* request,
+ const MediaDeviceEnumeration& enumeration,
const media::AudioParameters& output_parameters) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(request->HasUIRequest());
@@ -1181,17 +1073,13 @@ void MediaStreamManager::PostRequestToUI(
fake_ui_.reset(new FakeMediaStreamUIProxy());
MediaStreamDevices devices;
- if (audio_enumeration_cache_.valid) {
- for (const StreamDeviceInfo& device_info :
- audio_enumeration_cache_.devices) {
- devices.push_back(device_info.device);
- }
+ for (const auto& info : enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT]) {
+ devices.emplace_back(audio_type, info.device_id, info.label,
+ info.group_id);
}
- if (video_enumeration_cache_.valid) {
- for (const StreamDeviceInfo& device_info :
- video_enumeration_cache_.devices) {
- devices.push_back(device_info.device);
- }
+ for (const auto& info : enumeration[MEDIA_DEVICE_TYPE_VIDEO_INPUT]) {
+ devices.emplace_back(video_type, info.device_id, info.label,
+ info.group_id);
}
fake_ui_->SetAvailableDevices(devices);
@@ -1239,36 +1127,24 @@ void MediaStreamManager::SetupRequest(const std::string& label) {
}
if (!is_web_contents_capture && !is_screen_capture) {
- if (EnumerationRequired(&audio_enumeration_cache_, audio_type) ||
- EnumerationRequired(&video_enumeration_cache_, video_type)) {
- // Enumerate the devices if there is no valid device lists to be used.
- StartEnumeration(request);
+ if (audio_type == MEDIA_DEVICE_AUDIO_CAPTURE ||
+ video_type == MEDIA_DEVICE_VIDEO_CAPTURE) {
+ StartEnumeration(request, label);
return;
- } else {
- // Cache is valid, so log the cached devices for MediaStream requests.
- if (request->request_type == MEDIA_GENERATE_STREAM) {
- std::string log_message("Using cached devices for request.\n");
- if (audio_type != MEDIA_NO_SERVICE) {
- log_message +=
- GetLogMessageString(audio_type, audio_enumeration_cache_.devices);
- }
- if (video_type != MEDIA_NO_SERVICE) {
- log_message +=
- GetLogMessageString(video_type, video_enumeration_cache_.devices);
- }
- SendMessageToNativeLog(log_message);
- }
}
-
- if (!SetupDeviceCaptureRequest(request)) {
+ // If no actual device capture is requested, set up the request with an
+ // empty device list.
+ if (!SetupDeviceCaptureRequest(request, MediaDeviceEnumeration())) {
FinalizeRequestFailed(label, request, MEDIA_DEVICE_NO_HARDWARE);
return;
}
}
- ReadOutputParamsAndPostRequestToUI(label, request);
+ ReadOutputParamsAndPostRequestToUI(label, request, MediaDeviceEnumeration());
}
-bool MediaStreamManager::SetupDeviceCaptureRequest(DeviceRequest* request) {
+bool MediaStreamManager::SetupDeviceCaptureRequest(
+ DeviceRequest* request,
+ const MediaDeviceEnumeration& enumeration) {
DCHECK((request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE ||
request->audio_type() == MEDIA_NO_SERVICE) &&
(request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE ||
@@ -1276,6 +1152,7 @@ bool MediaStreamManager::SetupDeviceCaptureRequest(DeviceRequest* request) {
std::string audio_device_id;
if (request->controls.audio.requested &&
!GetRequestedDeviceCaptureId(request, request->audio_type(),
+ enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT],
&audio_device_id)) {
return false;
}
@@ -1283,6 +1160,7 @@ bool MediaStreamManager::SetupDeviceCaptureRequest(DeviceRequest* request) {
std::string video_device_id;
if (request->controls.video.requested &&
!GetRequestedDeviceCaptureId(request, request->video_type(),
+ enumeration[MEDIA_DEVICE_TYPE_VIDEO_INPUT],
&video_device_id)) {
return false;
}
@@ -1472,6 +1350,7 @@ void MediaStreamManager::FinalizeEnumerateDevices(const std::string& label,
fake_ui_.reset(new FakeMediaStreamUIProxy());
request->ui_proxy = std::move(fake_ui_);
} else {
+ DCHECK(!request->ui_proxy);
request->ui_proxy = MediaStreamUIProxy::Create();
}
@@ -1513,7 +1392,7 @@ void MediaStreamManager::HandleCheckMediaAccessResponse(
label,
request->devices);
- // TODO(tommi):
+ // TODO(guidou):
// Ideally enumeration requests should be deleted once they have been served
// (as any request). However, this implementation mixes requests and
// notifications together so enumeration requests are kept open by some
@@ -1589,11 +1468,6 @@ void MediaStreamManager::InitializeDeviceManagersOnIOThread() {
// and the device managers.
base::MessageLoop::current()->AddDestructionObserver(this);
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kUseFakeDeviceForMediaStream)) {
- audio_input_device_manager()->UseFakeDevice();
- }
-
// TODO(dalecurtis): Remove ScopedTracker below once crbug.com/457525 is
// fixed.
tracked_objects::ScopedTracker tracking_profile4(
@@ -1614,6 +1488,9 @@ void MediaStreamManager::InitializeDeviceManagersOnIOThread() {
audio_output_device_enumerator_.reset(new AudioOutputDeviceEnumerator(
audio_manager_, AudioOutputDeviceEnumerator::CACHE_POLICY_NO_CACHING));
+
+ media_devices_manager_.reset(
+ new MediaDevicesManager(audio_manager_, video_capture_manager_, this));
}
void MediaStreamManager::Opened(MediaStreamType stream_type,
@@ -1702,91 +1579,45 @@ void MediaStreamManager::Closed(MediaStreamType stream_type,
}
void MediaStreamManager::DevicesEnumerated(
- MediaStreamType stream_type, const StreamDeviceInfoArray& devices) {
+ bool requested_audio_input,
+ bool requested_video_input,
+ const std::string& label,
+ const MediaDeviceEnumeration& enumeration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DVLOG(1) << "DevicesEnumerated("
- << "{stream_type = " << stream_type << "})";
-
- std::string log_message = "New device enumeration result:\n" +
- GetLogMessageString(stream_type, devices);
- SendMessageToNativeLog(log_message);
-
- // Only cache the device list when the device list has been changed.
- bool need_update_clients = false;
- bool need_update_device_change_subscribers = false;
- EnumerationCache* cache = stream_type == MEDIA_DEVICE_AUDIO_CAPTURE
- ? &audio_enumeration_cache_
- : &video_enumeration_cache_;
- if (!cache->valid || devices.size() != cache->devices.size() ||
- !std::equal(devices.begin(), devices.end(), cache->devices.begin(),
- StreamDeviceInfo::IsEqual)) {
- StopRemovedDevices(cache->devices, devices);
- need_update_clients = true;
- // Device-change subscribers should not be notified the first time the cache
- // is loaded , as this is not a change in the set of devices. The same
- // applies to enumerations listing no devices when the cache is empty.
- need_update_device_change_subscribers =
- cache->valid && (devices.size() != 0 || cache->devices.size() != 0);
- cache->devices = devices;
-
- // The device might not be able to be enumerated when it is not warmed up,
- // for example, when the machine just wakes up from sleep. We set the cache
- // to be invalid so that the next media request will trigger the
- // enumeration again. See issue/317673.
- cache->valid = !devices.empty();
- }
-
- if (need_update_clients && monitoring_started_)
- NotifyDevicesChanged(stream_type, devices);
-
- if (need_update_device_change_subscribers)
- NotifyDeviceChangeSubscribers(stream_type);
-
- // Publish the result for all requests waiting for device list(s).
- // Find the requests waiting for this device list, store their labels and
- // release the iterator before calling device settings. We might get a call
- // back from device_settings that will need to iterate through devices.
- std::list<std::string> label_list;
- for (const LabeledDeviceRequest& labeled_request : requests_) {
- DeviceRequest* const request = labeled_request.second;
- if (request->state(stream_type) == MEDIA_REQUEST_STATE_REQUESTED &&
- (request->audio_type() == stream_type ||
- request->video_type() == stream_type)) {
- if (request->request_type != MEDIA_ENUMERATE_DEVICES)
- request->SetState(stream_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
- label_list.push_back(labeled_request.first);
- }
- }
- for (const std::string& label : label_list) {
- DeviceRequest* const request = FindRequest(label);
- switch (request->request_type) {
- case MEDIA_ENUMERATE_DEVICES:
- if (need_update_clients && request->requester) {
- request->devices = devices;
- FinalizeEnumerateDevices(label, request);
- }
- break;
- default:
- if (request->state(request->audio_type()) ==
- MEDIA_REQUEST_STATE_REQUESTED ||
- request->state(request->video_type()) ==
- MEDIA_REQUEST_STATE_REQUESTED) {
- // We are doing enumeration for other type of media, wait until it is
- // all done before posting the request to UI because UI needs
- // the device lists to handle the request.
- break;
- }
- if (!SetupDeviceCaptureRequest(request))
- FinalizeRequestFailed(label, request, MEDIA_DEVICE_NO_HARDWARE);
- else
- ReadOutputParamsAndPostRequestToUI(label, request);
- break;
+ DeviceRequest* request = FindRequest(label);
+ if (!request)
+ return;
+
+ bool requested[] = {requested_audio_input, requested_video_input};
+ MediaStreamType stream_types[] = {MEDIA_DEVICE_AUDIO_CAPTURE,
+ MEDIA_DEVICE_VIDEO_CAPTURE};
+ MediaDeviceType device_types[] = {MEDIA_DEVICE_TYPE_AUDIO_INPUT,
+ MEDIA_DEVICE_TYPE_VIDEO_INPUT};
+
+ for (size_t i = 0; i < arraysize(requested); ++i) {
+ if (!requested[i])
+ continue;
+
+ DCHECK(request->audio_type() == stream_types[i] ||
+ request->video_type() == stream_types[i]);
+ if (request->state(stream_types[i]) == MEDIA_REQUEST_STATE_REQUESTED) {
+ if (request->request_type == MEDIA_ENUMERATE_DEVICES) {
+ // MEDIA_ENUMERATE_DEVICES requests are always for a single type, so it
+ // is OK to ignore any remaining iteration in this loop.
+ ProcessEnumerationRequest(label, request, stream_types[i],
+ enumeration[device_types[i]]);
+ return;
+ }
+ // Not a MEDIA_ENUMERATE_DEVICES request.
+ request->SetState(stream_types[i], MEDIA_REQUEST_STATE_PENDING_APPROVAL);
}
}
- label_list.clear();
- --active_enumeration_ref_count_[stream_type];
- DCHECK_GE(active_enumeration_ref_count_[stream_type], 0);
+
+ if (!SetupDeviceCaptureRequest(request, enumeration))
+ FinalizeRequestFailed(label, request, MEDIA_DEVICE_NO_HARDWARE);
+ else
+ ReadOutputParamsAndPostRequestToUI(label, request, enumeration);
}
void MediaStreamManager::Aborted(MediaStreamType stream_type,
@@ -1957,7 +1788,7 @@ void MediaStreamManager::WillDestroyCurrentMessageLoop() {
DCHECK(CalledOnIOThread());
DCHECK(requests_.empty());
if (device_task_runner_.get()) {
- StopMonitoring();
+ media_devices_manager_->StopMonitoring();
video_capture_manager_->Unregister();
audio_input_device_manager_->Unregister();
@@ -1967,20 +1798,20 @@ void MediaStreamManager::WillDestroyCurrentMessageLoop() {
audio_input_device_manager_ = NULL;
video_capture_manager_ = NULL;
audio_output_device_enumerator_ = NULL;
+ media_devices_manager_ = NULL;
g_media_stream_manager_tls_ptr.Pointer()->Set(NULL);
}
void MediaStreamManager::NotifyDevicesChanged(
- MediaStreamType stream_type,
- const StreamDeviceInfoArray& devices) {
+ MediaDeviceType device_type,
+ const MediaDeviceInfoArray& devices) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
MediaObserver* media_observer =
GetContentClient()->browser()->GetMediaObserver();
- // Map the devices to MediaStreamDevices.
- MediaStreamDevices new_devices;
- for (const StreamDeviceInfo& device_info : devices)
- new_devices.push_back(device_info.device);
+ MediaStreamType stream_type = ConvertToMediaStreamType(device_type);
+ MediaStreamDevices new_devices =
+ ConvertToMediaStreamDevices(stream_type, devices);
if (IsAudioInputMediaType(stream_type)) {
MediaCaptureDevicesImpl::GetInstance()->OnAudioCaptureDevicesChanged(
@@ -1995,6 +1826,8 @@ void MediaStreamManager::NotifyDevicesChanged(
} else {
NOTREACHED();
}
+
+ ProcessOpenEnumerationRequests(stream_type, devices);
}
bool MediaStreamManager::RequestDone(const DeviceRequest& request) const {
@@ -2030,28 +1863,6 @@ MediaStreamProvider* MediaStreamManager::GetDeviceManager(
return NULL;
}
-void MediaStreamManager::OnDevicesChanged(
- base::SystemMonitor::DeviceType device_type) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // NOTE: This method is only called in response to physical audio/video device
- // changes (from the operating system).
-
- MediaStreamType stream_type;
- if (device_type == base::SystemMonitor::DEVTYPE_AUDIO) {
- stream_type = MEDIA_DEVICE_AUDIO_CAPTURE;
- } else if (device_type == base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE) {
- stream_type = MEDIA_DEVICE_VIDEO_CAPTURE;
- } else {
- return; // Uninteresting device change.
- }
-
- // Always do enumeration even though some enumeration is in progress, because
- // those enumeration commands could be sent before these devices change.
- ++active_enumeration_ref_count_[stream_type];
- GetDeviceManager(stream_type)->EnumerateDevices(stream_type);
-}
-
void MediaStreamManager::OnMediaStreamUIWindowId(MediaStreamType video_type,
StreamDeviceInfoArray devices,
gfx::NativeViewId window_id) {
@@ -2173,7 +1984,6 @@ void MediaStreamManager::SetCapturingLinkSecured(int render_process_id,
content::MediaStreamType type,
bool is_secure) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
for (LabeledDeviceRequest& labeled_request : requests_) {
DeviceRequest* request = labeled_request.second;
if (request->requesting_process_id != render_process_id)
@@ -2189,4 +1999,47 @@ void MediaStreamManager::SetCapturingLinkSecured(int render_process_id,
}
}
+void MediaStreamManager::ProcessEnumerationRequest(
+ const std::string& label,
+ DeviceRequest* request,
+ MediaStreamType stream_type,
+ const MediaDeviceInfoArray& device_infos) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_EQ(MEDIA_REQUEST_STATE_REQUESTED, request->state(stream_type));
+ DCHECK(request->audio_type() == stream_type ||
+ request->video_type() == stream_type);
+ DCHECK(request->audio_type() == MEDIA_NO_SERVICE ||
+ request->video_type() == MEDIA_NO_SERVICE);
+ DCHECK_EQ(MEDIA_ENUMERATE_DEVICES, request->request_type);
+
+ if (request->requester && !request->ui_proxy) {
+ request->devices =
+ ConvertToStreamDeviceInfoArray(stream_type, device_infos);
+ FinalizeEnumerateDevices(label, request);
+ }
+}
+
+// This function is intended to support subscription-style device enumerations.
+// It is only supported for media capture devices and will be removed once
+// handling of enumeration requests and device-change notifications is migrated
+// out of MediaStreamManager.
+void MediaStreamManager::ProcessOpenEnumerationRequests(
+ MediaStreamType stream_type,
+ const MediaDeviceInfoArray& device_infos) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ||
+ stream_type == MEDIA_DEVICE_VIDEO_CAPTURE);
+
+ for (const LabeledDeviceRequest& labeled_request : requests_) {
+ DeviceRequest* request = labeled_request.second;
+ if (request->request_type == MEDIA_ENUMERATE_DEVICES &&
+ request->state(stream_type) == MEDIA_REQUEST_STATE_REQUESTED &&
+ (request->audio_type() == stream_type ||
+ request->video_type() == stream_type)) {
+ ProcessEnumerationRequest(labeled_request.first, request, stream_type,
+ device_infos);
+ }
+ }
+}
+
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698