Commit cc6d460e authored by guidou's avatar guidou Committed by Commit bot

Remove device enumeration, caching and monitoring from MediaStreamManager.

This CL introduces MediaDevicesManager, which is now responsible for low-level
device enumerations, including using device monitoring to maintain updated
caches.

This CL also removes the enumeration functionality from the MediaStreamProvider
interface, as MediaDevicesManager is the new class resnposible for providing
enumeration results to be used to handle renderer-generated enumeration requests
and device-change notifications. Due to this, relatively minor changes are made
to AudioInputDeviceManager and VideoCaptureManager.

BUG=647660

Review-Url: https://codereview.chromium.org/2350693002
Cr-Commit-Position: refs/heads/master@{#420735}
parent ded470a3
......@@ -1058,6 +1058,8 @@ source_set("browser") {
"renderer_host/media/gpu_memory_buffer_tracker.h",
"renderer_host/media/media_capture_devices_impl.cc",
"renderer_host/media/media_capture_devices_impl.h",
"renderer_host/media/media_devices_manager.cc",
"renderer_host/media/media_devices_manager.h",
"renderer_host/media/media_stream_dispatcher_host.cc",
"renderer_host/media/media_stream_dispatcher_host.h",
"renderer_host/media/media_stream_manager.cc",
......
......@@ -7,6 +7,7 @@
#include <memory>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/metrics/histogram_macros.h"
#include "build/build_config.h"
#include "content/public/browser/browser_thread.h"
......@@ -15,6 +16,7 @@
#include "media/audio/audio_manager_base.h"
#include "media/base/audio_parameters.h"
#include "media/base/channel_layout.h"
#include "media/base/media_switches.h"
#if defined(OS_CHROMEOS)
#include "chromeos/audio/cras_audio_handler.h"
......@@ -33,7 +35,6 @@ AudioInputDeviceManager::AudioInputDeviceManager(
media::AudioManager* audio_manager)
: listener_(NULL),
next_capture_session_id_(kFirstSessionId),
use_fake_device_(false),
#if defined(OS_CHROMEOS)
keyboard_mic_streams_count_(0),
#endif
......@@ -68,16 +69,6 @@ void AudioInputDeviceManager::Unregister() {
listener_ = NULL;
}
void AudioInputDeviceManager::EnumerateDevices(MediaStreamType stream_type) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(listener_);
device_task_runner_->PostTask(
FROM_HERE,
base::Bind(&AudioInputDeviceManager::EnumerateOnDeviceThread,
this, stream_type));
}
int AudioInputDeviceManager::Open(const StreamDeviceInfo& device) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// Generate a new id for this device.
......@@ -108,16 +99,6 @@ void AudioInputDeviceManager::Close(int session_id) {
this, stream_type, session_id));
}
void AudioInputDeviceManager::UseFakeDevice() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
use_fake_device_ = true;
}
bool AudioInputDeviceManager::ShouldUseFakeDevice() const {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
return use_fake_device_;
}
#if defined(OS_CHROMEOS)
void AudioInputDeviceManager::RegisterKeyboardMicStream(
const base::Closure& callback) {
......@@ -155,41 +136,6 @@ void AudioInputDeviceManager::UnregisterKeyboardMicStream() {
}
#endif
void AudioInputDeviceManager::EnumerateOnDeviceThread(
MediaStreamType stream_type) {
SCOPED_UMA_HISTOGRAM_TIMER(
"Media.AudioInputDeviceManager.EnumerateOnDeviceThreadTime");
DCHECK(IsOnDeviceThread());
DCHECK_EQ(MEDIA_DEVICE_AUDIO_CAPTURE, stream_type);
media::AudioDeviceNames device_names;
if (use_fake_device_) {
// Use the fake devices.
GetFakeDeviceNames(&device_names);
} else {
// Enumerate the devices on the OS.
// AudioManager is guaranteed to outlive MediaStreamManager in
// BrowserMainloop.
audio_manager_->GetAudioInputDeviceNames(&device_names);
}
std::unique_ptr<StreamDeviceInfoArray> devices(new StreamDeviceInfoArray());
for (media::AudioDeviceNames::iterator it = device_names.begin();
it != device_names.end(); ++it) {
// Add device information to device vector.
devices->emplace_back(stream_type, it->device_name, it->unique_id,
audio_manager_->GetGroupIDInput(it->unique_id));
}
// Return the device list through the listener by posting a task on
// IO thread since MediaStreamManager handles the callback asynchronously.
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
base::Bind(&AudioInputDeviceManager::DevicesEnumeratedOnIOThread,
this, stream_type, base::Passed(&devices)));
}
void AudioInputDeviceManager::OpenOnDeviceThread(
int session_id, const StreamDeviceInfo& info) {
SCOPED_UMA_HISTOGRAM_TIMER(
......@@ -202,7 +148,8 @@ void AudioInputDeviceManager::OpenOnDeviceThread(
MediaStreamDevice::AudioDeviceParameters& input_params = out.device.input;
if (use_fake_device_) {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseFakeDeviceForMediaStream)) {
// Don't need to query the hardware information if using fake device.
input_params.sample_rate = 44100;
input_params.channel_layout = media::CHANNEL_LAYOUT_STEREO;
......@@ -240,15 +187,6 @@ void AudioInputDeviceManager::OpenOnDeviceThread(
this, session_id, out));
}
void AudioInputDeviceManager::DevicesEnumeratedOnIOThread(
MediaStreamType stream_type,
std::unique_ptr<StreamDeviceInfoArray> devices) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// Ensure that |devices| gets deleted on exit.
if (listener_)
listener_->DevicesEnumerated(stream_type, *devices);
}
void AudioInputDeviceManager::OpenedOnIOThread(int session_id,
const StreamDeviceInfo& info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
......@@ -283,20 +221,6 @@ AudioInputDeviceManager::GetDevice(int session_id) {
return devices_.end();
}
void AudioInputDeviceManager::GetFakeDeviceNames(
media::AudioDeviceNames* device_names) {
static const char kFakeDeviceName1[] = "Fake Audio 1";
static const char kFakeDeviceId1[] = "fake_audio_1";
static const char kFakeDeviceName2[] = "Fake Audio 2";
static const char kFakeDeviceId2[] = "fake_audio_2";
DCHECK(device_names->empty());
DCHECK(use_fake_device_);
device_names->push_back(media::AudioDeviceName(kFakeDeviceName1,
kFakeDeviceId1));
device_names->push_back(media::AudioDeviceName(kFakeDeviceName2,
kFakeDeviceId2));
}
#if defined(OS_CHROMEOS)
void AudioInputDeviceManager::SetKeyboardMicStreamActiveOnUIThread(
bool active) {
......
......@@ -14,6 +14,7 @@
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_INPUT_DEVICE_MANAGER_H_
#include <map>
#include <vector>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
......@@ -23,7 +24,6 @@
#include "content/common/content_export.h"
#include "content/common/media/media_stream_options.h"
#include "content/public/common/media_stream_request.h"
#include "media/audio/audio_device_name.h"
namespace media {
class AudioManager;
......@@ -51,13 +51,9 @@ class CONTENT_EXPORT AudioInputDeviceManager : public MediaStreamProvider {
void Register(MediaStreamProviderListener* listener,
const scoped_refptr<base::SingleThreadTaskRunner>&
device_task_runner) override;
void EnumerateDevices(MediaStreamType stream_type) override;
int Open(const StreamDeviceInfo& device) override;
void Close(int session_id) override;
void UseFakeDevice();
bool ShouldUseFakeDevice() const;
#if defined(OS_CHROMEOS)
// Registers and unregisters that a stream using keyboard mic has been opened
// or closed. Keeps count of how many such streams are open and activates and
......@@ -70,23 +66,12 @@ class CONTENT_EXPORT AudioInputDeviceManager : public MediaStreamProvider {
#endif
private:
// Used by the unittests to get a list of fake devices.
friend class MediaStreamDispatcherHostTest;
void GetFakeDeviceNames(media::AudioDeviceNames* device_names);
typedef std::vector<StreamDeviceInfo> StreamDeviceList;
~AudioInputDeviceManager() override;
// Enumerates audio input devices on media stream device thread.
void EnumerateOnDeviceThread(MediaStreamType stream_type);
// Opens the device on media stream device thread.
void OpenOnDeviceThread(int session_id, const StreamDeviceInfo& info);
// Callback used by EnumerateOnDeviceThread(), called with a list of
// enumerated devices on IO thread.
void DevicesEnumeratedOnIOThread(
MediaStreamType stream_type,
std::unique_ptr<StreamDeviceInfoArray> devices);
// Callback used by OpenOnDeviceThread(), called with the session_id
// referencing the opened device on IO thread.
void OpenedOnIOThread(int session_id, const StreamDeviceInfo& info);
......@@ -109,7 +94,6 @@ class CONTENT_EXPORT AudioInputDeviceManager : public MediaStreamProvider {
// Only accessed on Browser::IO thread.
MediaStreamProviderListener* listener_;
int next_capture_session_id_;
bool use_fake_device_;
StreamDeviceList devices_;
#if defined(OS_CHROMEOS)
......
......@@ -10,6 +10,7 @@
#include <string>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
......@@ -20,13 +21,11 @@
#include "content/public/common/media_stream_request.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "media/audio/audio_manager_base.h"
#include "media/base/media_switches.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::_;
using testing::InSequence;
using testing::SaveArg;
using testing::Return;
namespace content {
......@@ -63,23 +62,23 @@ class MAYBE_AudioInputDeviceManagerTest : public testing::Test {
protected:
void SetUp() override {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kUseFakeDeviceForMediaStream);
audio_manager_ = media::AudioManager::CreateForTesting(
base::ThreadTaskRunnerHandle::Get());
// Flush the message loop to ensure proper initialization of AudioManager.
base::RunLoop().RunUntilIdle();
manager_ = new AudioInputDeviceManager(audio_manager_.get());
manager_->UseFakeDevice();
audio_input_listener_.reset(new MockAudioInputDeviceManagerListener());
manager_->Register(audio_input_listener_.get(),
audio_manager_->GetTaskRunner());
// Gets the enumerated device list from the AudioInputDeviceManager.
manager_->EnumerateDevices(MEDIA_DEVICE_AUDIO_CAPTURE);
EXPECT_CALL(*audio_input_listener_,
DevicesEnumerated(MEDIA_DEVICE_AUDIO_CAPTURE, _))
.Times(1)
.WillOnce(SaveArg<1>(&devices_));
// Use fake devices.
devices_.emplace_back(MEDIA_DEVICE_AUDIO_CAPTURE, "Fake Device 1",
"fake_device_1");
devices_.emplace_back(MEDIA_DEVICE_AUDIO_CAPTURE, "Fake Device 2",
"fake_device_2");
// Wait until we get the list.
base::RunLoop().RunUntilIdle();
......@@ -101,7 +100,6 @@ class MAYBE_AudioInputDeviceManagerTest : public testing::Test {
// Opens and closes the devices.
TEST_F(MAYBE_AudioInputDeviceManagerTest, OpenAndCloseDevice) {
ASSERT_FALSE(devices_.empty());
InSequence s;
......
......@@ -7,6 +7,7 @@
#include <utility>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file.h"
#include "base/memory/ref_counted.h"
#include "base/memory/shared_memory.h"
......@@ -27,6 +28,7 @@
#include "content/public/browser/web_contents_media_capture_id.h"
#include "media/audio/audio_device_description.h"
#include "media/base/audio_bus.h"
#include "media/base/media_switches.h"
namespace content {
......@@ -367,9 +369,10 @@ void AudioInputRendererHost::DoCreateStream(
}
media::AudioParameters audio_params(config.params);
if (media_stream_manager_->audio_input_device_manager()
->ShouldUseFakeDevice())
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseFakeDeviceForMediaStream)) {
audio_params.set_format(media::AudioParameters::AUDIO_FAKE);
}
// Check if we have the permission to open the device and which device to use.
MediaStreamType type = MEDIA_NO_SERVICE;
......
This diff is collapsed.
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_DEVICES_MANAGER_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_DEVICES_MANAGER_H_
#include <array>
#include <vector>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/system_monitor/system_monitor.h"
#include "content/common/content_export.h"
#include "content/common/media/media_devices.h"
#include "media/capture/video/video_capture_device_descriptor.h"
namespace base {
class SingleThreadTaskRunner;
}
namespace media {
class AudioManager;
}
namespace content {
class MediaStreamManager;
class VideoCaptureManager;
// Use MediaDeviceType values to index on this type.
using MediaDeviceEnumeration =
std::array<MediaDeviceInfoArray, NUM_MEDIA_DEVICE_TYPES>;
// MediaDevicesManager is responsible for doing media-device enumerations.
// In addition it implements caching for enumeration results and device
// monitoring in order to keep caches consistent.
// All its methods must be called on the IO thread.
class CONTENT_EXPORT MediaDevicesManager
: public base::SystemMonitor::DevicesChangedObserver {
public:
// Use MediaDeviceType values to index on this type.
using BoolDeviceTypes = std::array<bool, NUM_MEDIA_DEVICE_TYPES>;
using EnumerationCallback =
base::Callback<void(const MediaDeviceEnumeration&)>;
MediaDevicesManager(
media::AudioManager* audio_manager,
const scoped_refptr<VideoCaptureManager>& video_capture_manager,
MediaStreamManager* media_stream_manager);
~MediaDevicesManager() override;
// Performs a possibly cached device enumeration for the requested device
// types and reports the results to |callback|.
// The enumeration results passed to |callback| are guaranteed to be valid
// only for the types specified in |requested_types|.
// Note that this function is not reentrant, so if |callback| needs to perform
// another call to EnumerateDevices, it must do so by posting a task to the
// IO thread.
void EnumerateDevices(const BoolDeviceTypes& requested_types,
const EnumerationCallback& callback);
// Tries to start device monitoring. If successful, enables caching of
// enumeration results for the device types supported by the monitor.
void StartMonitoring();
// Stops device monitoring and disables caching for all device types.
void StopMonitoring();
// Returns true if device monitoring is active, false otherwise.
bool IsMonitoringStarted();
// Implements base::SystemMonitor::DevicesChangedObserver.
// This function is only called in response to physical audio/video device
// changes.
void OnDevicesChanged(base::SystemMonitor::DeviceType device_type) override;
// TODO(guidou): Remove this function once content::GetMediaDeviceIDForHMAC
// is rewritten to receive devices via a callback.
// See http://crbug.com/648155.
MediaDeviceInfoArray GetCachedDeviceInfo(MediaDeviceType type);
private:
friend class MediaDevicesManagerTest;
struct EnumerationRequest;
// The NO_CACHE policy is such that no previous results are used when
// EnumerateDevices is called. The results of a new or in-progress low-level
// device enumeration are used.
// The SYSTEM_MONITOR policy is such that previous results are re-used,
// provided they were produced by a low-level device enumeration issued after
// the last call to OnDevicesChanged.
enum class CachePolicy {
NO_CACHE,
SYSTEM_MONITOR,
};
// Manually sets a caching policy for a given device type.
void SetCachePolicy(MediaDeviceType type, CachePolicy policy);
// Helpers to issue low-level device enumerations.
void DoEnumerateDevices(MediaDeviceType type);
void EnumerateAudioDevices(bool is_input);
// Callback for VideoCaptureManager::EnumerateDevices.
void VideoInputDevicesEnumerated(
const media::VideoCaptureDeviceDescriptors& descriptors);
// Helpers to handle enumeration results.
void DevicesEnumerated(MediaDeviceType type,
const MediaDeviceInfoArray& snapshot);
void UpdateSnapshot(MediaDeviceType type,
const MediaDeviceInfoArray& new_snapshot);
void ProcessRequests();
bool IsEnumerationRequestReady(const EnumerationRequest& request_info);
// Helpers to handle device-change notification.
void HandleDevicesChanged(MediaDeviceType type);
void NotifyMediaStreamManager(MediaDeviceType type,
const MediaDeviceInfoArray& new_snapshot);
void NotifyDeviceChangeSubscribers(MediaDeviceType type,
const MediaDeviceInfoArray& snapshot);
#if defined(OS_MACOSX)
void StartMonitoringOnUIThread();
#endif
bool use_fake_devices_;
media::AudioManager* const audio_manager_; // not owned
scoped_refptr<VideoCaptureManager> video_capture_manager_;
MediaStreamManager* const media_stream_manager_; // not owned
using CachePolicies = std::array<CachePolicy, NUM_MEDIA_DEVICE_TYPES>;
CachePolicies cache_policies_;
class CacheInfo;
using CacheInfos = std::vector<CacheInfo>;
CacheInfos cache_infos_;
BoolDeviceTypes has_seen_result_;
std::vector<EnumerationRequest> requests_;
MediaDeviceEnumeration current_snapshot_;
bool monitoring_started_;
base::WeakPtrFactory<MediaDevicesManager> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(MediaDevicesManager);
};
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_DEVICES_MANAGER_H_
......@@ -5,6 +5,7 @@
#include "content/browser/renderer_host/media/media_stream_dispatcher_host.h"
#include <stddef.h>
#include <memory>
#include <queue>
#include <string>
#include <utility>
......@@ -33,6 +34,7 @@
#include "content/test/test_content_browser_client.h"
#include "content/test/test_content_client.h"
#include "ipc/ipc_message_macros.h"
#include "media/audio/audio_device_description.h"
#include "media/audio/mock_audio_manager.h"
#include "media/base/media_switches.h"
#include "media/capture/video/fake_video_capture_device_factory.h"
......@@ -59,6 +61,19 @@ const int kPageRequestId = 7;
namespace content {
namespace {
void AudioInputDevicesEnumerated(base::Closure quit_closure,
media::AudioDeviceNames* out,
const MediaDeviceEnumeration& enumeration) {
for (const auto& info : enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT]) {
out->emplace_back(info.label, info.device_id);
}
quit_closure.Run();
}
} // namespace
class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
public TestContentBrowserClient {
public:
......@@ -299,8 +314,13 @@ class MediaStreamDispatcherHostTest : public testing::Test {
&physical_video_devices_);
ASSERT_GT(physical_video_devices_.size(), 0u);
media_stream_manager_->audio_input_device_manager()->GetFakeDeviceNames(
&physical_audio_devices_);
base::RunLoop run_loop;
media_stream_manager_->media_devices_manager()->EnumerateDevices(
{{true, false, false}},
base::Bind(&AudioInputDevicesEnumerated, run_loop.QuitClosure(),
&physical_audio_devices_));
run_loop.Run();
ASSERT_GT(physical_audio_devices_.size(), 0u);
}
......@@ -385,7 +405,7 @@ class MediaStreamDispatcherHostTest : public testing::Test {
run_loop.QuitClosure());
// Simulate a change in the set of devices.
video_capture_device_factory_->set_number_of_devices(5);
media_stream_manager_->OnDevicesChanged(
media_stream_manager_->media_devices_manager()->OnDevicesChanged(
base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
run_loop.Run();
}
......@@ -395,6 +415,14 @@ class MediaStreamDispatcherHostTest : public testing::Test {
media::AudioDeviceNames::const_iterator audio_it =
physical_audio_devices_.begin();
for (; audio_it != physical_audio_devices_.end(); ++audio_it) {
// Skip default and communications audio devices, whose IDs are not
// translated.
if (devices[i].device.id ==
media::AudioDeviceDescription::kDefaultDeviceId ||
devices[i].device.id ==
media::AudioDeviceDescription::kCommunicationsDeviceId) {
continue;
}
if (audio_it->unique_id == devices[i].device.id)
return true;
}
......@@ -913,7 +941,7 @@ TEST_F(MediaStreamDispatcherHostTest, VideoDeviceUnplugged) {
base::RunLoop run_loop;
EXPECT_CALL(*host_.get(), OnDeviceStopped(kRenderId))
.WillOnce(testing::InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
media_stream_manager_->OnDevicesChanged(
media_stream_manager_->media_devices_manager()->OnDevicesChanged(
base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
run_loop.Run();
......
......@@ -389,7 +389,8 @@ TEST_F(MediaStreamManagerTest, NotifyDeviceChanges) {
// Simulate device change
EXPECT_CALL(requester, MockDevicesChanged(_));
audio_manager_->SetNumAudioInputDevices(3);
media_stream_manager_->OnDevicesChanged(base::SystemMonitor::DEVTYPE_AUDIO);
media_stream_manager_->media_devices_manager()->OnDevicesChanged(
base::SystemMonitor::DEVTYPE_AUDIO);
run_loop_device_change.Run();
}
......@@ -404,7 +405,8 @@ TEST_F(MediaStreamManagerTest, NotifyDeviceChanges) {
// Bogus OnDeviceChange, as devices have not changed. Should not trigger
// notification.
EXPECT_CALL(requester, MockDevicesChanged(_)).Times(0);
media_stream_manager_->OnDevicesChanged(base::SystemMonitor::DEVTYPE_AUDIO);
media_stream_manager_->media_devices_manager()->OnDevicesChanged(
base::SystemMonitor::DEVTYPE_AUDIO);
// Do enumeration to be able to quit the RunLoop.
EXPECT_CALL(requester,
......
......@@ -46,10 +46,6 @@ class CONTENT_EXPORT MediaStreamProviderListener {
// Called by a MediaStreamProvider when a stream has been closed.
virtual void Closed(MediaStreamType stream_type, int capture_session_id) = 0;
// Called by a MediaStreamProvider when available devices has been enumerated.
virtual void DevicesEnumerated(MediaStreamType stream_type,
const StreamDeviceInfoArray& devices) = 0;
// Called by a MediaStreamProvider when the device has been aborted due to
// device error.
virtual void Aborted(MediaStreamType stream_type, int capture_session_id) = 0;
......@@ -67,9 +63,6 @@ class CONTENT_EXPORT MediaStreamProvider
const scoped_refptr<base::SingleThreadTaskRunner>&
device_task_runner) = 0;
// Enumerates existing capture devices and calls |DevicesEnumerated|.
virtual void EnumerateDevices(MediaStreamType stream_type) = 0;
// Opens the specified device. The device is not started and it is still
// possible for other applications to open the device before the device is
// started. |Opened| is called when the device is opened.
......
......@@ -294,16 +294,15 @@ void VideoCaptureManager::Unregister() {
listener_ = nullptr;
}
void VideoCaptureManager::EnumerateDevices(MediaStreamType stream_type) {
void VideoCaptureManager::EnumerateDevices(
const EnumerationCallback& client_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DVLOG(1) << "VideoCaptureManager::EnumerateDevices, type " << stream_type;
DCHECK(listener_);
DCHECK_EQ(stream_type, MEDIA_DEVICE_VIDEO_CAPTURE);
DVLOG(1) << "VideoCaptureManager::EnumerateDevices";
#if defined(OS_MACOSX)
if (NeedToInitializeCaptureDeviceApi(stream_type)) {
InitializeCaptureDeviceApiOnUIThread(
base::Bind(&VideoCaptureManager::EnumerateDevices, this, stream_type));
if (NeedToInitializeCaptureDeviceApi(MEDIA_DEVICE_VIDEO_CAPTURE)) {
InitializeCaptureDeviceApiOnUIThread(base::Bind(
&VideoCaptureManager::EnumerateDevices, this, client_callback));
return;
}
#endif
......@@ -314,10 +313,10 @@ void VideoCaptureManager::EnumerateDevices(MediaStreamType stream_type) {
base::Callback<void(std::unique_ptr<VideoCaptureDeviceDescriptors>)>
devices_enumerated_callback = base::Bind(
&VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread, this,
media::BindToCurrentLoop(
base::Bind(&VideoCaptureManager::OnDevicesInfoEnumerated, this,
stream_type, base::Owned(new base::ElapsedTimer()))),
stream_type, devices_info_cache_);
media::BindToCurrentLoop(base::Bind(
&VideoCaptureManager::OnDevicesInfoEnumerated, this,
base::Owned(new base::ElapsedTimer()), client_callback)),
devices_info_cache_);
// OK to use base::Unretained() since we own the VCDFactory and |this| is
// bound in |devices_enumerated_callback|.
device_task_runner_->PostTask(
......@@ -963,35 +962,29 @@ void VideoCaptureManager::OnClosed(
}
void VideoCaptureManager::OnDevicesInfoEnumerated(
MediaStreamType stream_type,
base::ElapsedTimer* timer,
const EnumerationCallback& client_callback,
const VideoCaptureManager::DeviceInfos& new_devices_info_cache) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
UMA_HISTOGRAM_TIMES(
"Media.VideoCaptureManager.GetAvailableDevicesInfoOnDeviceThreadTime",
timer->Elapsed());
if (!listener_) {
// Listener has been removed.
return;
}
devices_info_cache_ = new_devices_info_cache;
// Walk the |devices_info_cache_| and transform from
// VideoCaptureDeviceDescriptor to StreamDeviceInfo for return purposes.
StreamDeviceInfoArray devices;
// Walk the |devices_info_cache_| and produce a
// media::VideoCaptureDeviceDescriptors for return purposes.
media::VideoCaptureDeviceDescriptors devices;
std::vector<std::tuple<media::VideoCaptureDeviceDescriptor,
media::VideoCaptureFormats>>
descriptors_and_formats;
for (const auto& it : devices_info_cache_) {
// TODO(guidou): Implement group IDs for video capture devices.
// http://crbug.com/627793
devices.emplace_back(stream_type, it.descriptor.GetNameAndModel(),
it.descriptor.device_id);
devices.emplace_back(it.descriptor);
descriptors_and_formats.emplace_back(it.descriptor, it.supported_formats);
MediaInternals::GetInstance()->UpdateVideoCaptureDeviceCapabilities(
descriptors_and_formats);
}
listener_->DevicesEnumerated(stream_type, devices);
client_callback.Run(devices);
}
bool VideoCaptureManager::IsOnDeviceThread() const {
......@@ -1001,7 +994,6 @@ bool VideoCaptureManager::IsOnDeviceThread() const {
void VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread(
base::Callback<void(const VideoCaptureManager::DeviceInfos&)>
on_devices_enumerated_callback,
MediaStreamType stream_type,
const VideoCaptureManager::DeviceInfos& old_device_info_cache,
std::unique_ptr<VideoCaptureDeviceDescriptors> descriptors_snapshot) {
DCHECK(IsOnDeviceThread());
......
......@@ -59,11 +59,7 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
void Register(MediaStreamProviderListener* listener,
const scoped_refptr<base::SingleThreadTaskRunner>&
device_task_runner) override;
void EnumerateDevices(MediaStreamType stream_type) override;
int Open(const StreamDeviceInfo& device) override;
void Close(int capture_session_id) override;
// Called by VideoCaptureHost to locate a capture device for |capture_params|,
......@@ -173,6 +169,10 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
void OnApplicationStateChange(base::android::ApplicationState state);
#endif
using EnumerationCallback =
base::Callback<void(const media::VideoCaptureDeviceDescriptors&)>;
void EnumerateDevices(const EnumerationCallback& client_callback);
private:
class CaptureDeviceStartRequest;
class DeviceEntry;
......@@ -192,8 +192,8 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
media::VideoCaptureSessionId capture_session_id);
void OnClosed(MediaStreamType type,
media::VideoCaptureSessionId capture_session_id);
void OnDevicesInfoEnumerated(MediaStreamType stream_type,
base::ElapsedTimer* timer,
void OnDevicesInfoEnumerated(base::ElapsedTimer* timer,
const EnumerationCallback& client_callback,
const DeviceInfos& new_devices_info_cache);
bool IsOnDeviceThread() const;
......@@ -203,7 +203,6 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
// the new devices and sends the new cache to OnDevicesInfoEnumerated().
void ConsolidateDevicesInfoOnDeviceThread(
base::Callback<void(const DeviceInfos&)> on_devices_enumerated_callback,
MediaStreamType stream_type,
const DeviceInfos& old_device_info_cache,
std::unique_ptr<VideoCaptureDeviceDescriptors> descriptors_snapshot);
......
......@@ -205,6 +205,8 @@ source_set("common") {
"media/cdm_info.cc",
"media/cdm_messages.h",
"media/cdm_messages_enums.h",
"media/media_devices.cc",
"media/media_devices.h",
"media/media_metadata_sanitizer.cc",
"media/media_metadata_sanitizer.h",
"media/media_player_delegate_messages.h",
......
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/common/media/media_devices.h"
namespace content {
MediaDeviceInfo::MediaDeviceInfo(const std::string& device_id,
const std::string& label,
const std::string& group_id)
: device_id(device_id), label(label), group_id(group_id) {}
bool operator==(const MediaDeviceInfo& first, const MediaDeviceInfo& second) {
return first.device_id == second.device_id && first.label == second.label;
}
} // namespace content
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_COMMON_MEDIA_MEDIA_DEVICES_H_
#define CONTENT_COMMON_MEDIA_MEDIA_DEVICES_H_
#include <string>
#include <vector>
namespace content {
enum MediaDeviceType {
MEDIA_DEVICE_TYPE_AUDIO_INPUT,
MEDIA_DEVICE_TYPE_VIDEO_INPUT,
MEDIA_DEVICE_TYPE_AUDIO_OUTPUT,
NUM_MEDIA_DEVICE_TYPES,
};
struct MediaDeviceInfo {
MediaDeviceInfo(const std::string& device_id,
const std::string& label,
const std::string& group_id);
std::string device_id;
std::string label;
std::string group_id;
};
using MediaDeviceInfoArray = std::vector<MediaDeviceInfo>;
bool operator==(const MediaDeviceInfo& first, const MediaDeviceInfo& second);
inline bool IsValidMediaDeviceType(MediaDeviceType type) {
return type >= 0 && type < NUM_MEDIA_DEVICE_TYPES;
}
} // namespace content
#endif // CONTENT_COMMON_MEDIA_MEDIA_DEVICES_H_
......@@ -38,9 +38,9 @@ enum MediaStreamType {
// Capture system audio (post-mix loopback stream).
MEDIA_DESKTOP_AUDIO_CAPTURE,
// This is used for enumerating audio output devices.
// TODO(grunell): Output isn't really a part of media streams. Device
// enumeration should be decoupled from media streams and related code.
// TODO(guidou): This is used for device enumerations, but it is not a
// media stream type. Remove when handling of renderer-generated enumeration
// requests is removed from MediaStreamManager. See http://crbug.com/648183.
MEDIA_DEVICE_AUDIO_OUTPUT,
NUM_MEDIA_TYPES
......
......@@ -1161,6 +1161,7 @@ test("content_unittests") {
"../browser/renderer_host/media/audio_input_sync_writer_unittest.cc",
"../browser/renderer_host/media/audio_output_device_enumerator_unittest.cc",
"../browser/renderer_host/media/audio_renderer_host_unittest.cc",
"../browser/renderer_host/media/media_devices_manager_unittest.cc",
"../browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc",
"../browser/renderer_host/media/media_stream_manager_unittest.cc",
"../browser/renderer_host/media/media_stream_ui_proxy_unittest.cc",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment