0

Mv camera enumeration to video capture service

Doc: go/mv-camera-enumeration

We define a new class VideoCaptureDevicesChangedObserver that
establishes a mojo connection between the video capture service and
the browser process and receives OnDeviceChanged events from
video_capture::DevicesChangedNotifier.

These changes are exposed under the feature
'kCameraMonitoringInVideoCaptureService' which will gradually be
rolled out following the finch process.

Bug: 1448798
Change-Id: I60048b3a2cc8f7b844bc823002f12419dde79f4e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5002121
Reviewed-by: Henrik Boström <hbos@chromium.org>
Commit-Queue: Palak Agarwal <agpalak@chromium.org>
Reviewed-by: Mark Foltz <mfoltz@chromium.org>
Reviewed-by: Arthur Sonzogni <arthursonzogni@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1228892}
This commit is contained in:
Palak Agarwal
2023-11-24 21:33:54 +00:00
committed by Chromium LUCI CQ
parent 41316deba1
commit f0416e2b4d
21 changed files with 383 additions and 24 deletions

@ -1834,6 +1834,7 @@ source_set("browser") {
"renderer_host/media/video_capture_controller_event_handler.cc",
"renderer_host/media/video_capture_controller_event_handler.h",
"renderer_host/media/video_capture_device_launch_observer.h",
"renderer_host/media/video_capture_devices_changed_observer.cc",
"renderer_host/media/video_capture_host.cc",
"renderer_host/media/video_capture_host.h",
"renderer_host/media/video_capture_manager.cc",

@ -147,6 +147,7 @@
#include "services/network/public/cpp/network_switches.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/transitional_url_loader_factory_owner.h"
#include "services/video_capture/public/cpp/features.h"
#include "skia/ext/event_tracer_impl.h"
#include "skia/ext/skia_memory_dump_provider.h"
#include "sql/sql_memory_dump_provider.h"
@ -1385,9 +1386,14 @@ void BrowserMainLoop::PostCreateThreadsImpl() {
#elif (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && defined(USE_UDEV)
device_monitor_linux_ = std::make_unique<media::DeviceMonitorLinux>();
#elif BUILDFLAG(IS_MAC)
device_monitor_mac_ = std::make_unique<media::DeviceMonitorMac>(
base::ThreadPool::CreateSingleThreadTaskRunner(
{base::TaskPriority::USER_VISIBLE}));
// TODO(crbug.com/1448798): Clean up |device_monitor_mac_| in BrowserMainLoop
// once |kCameraMonitoringInVideoCaptureService| is fully launched.
if (!base::FeatureList::IsEnabled(
video_capture::features::kCameraMonitoringInVideoCaptureService)) {
device_monitor_mac_ = std::make_unique<media::DeviceMonitorMac>(
base::ThreadPool::CreateSingleThreadTaskRunner(
{base::TaskPriority::USER_VISIBLE}));
}
#endif
// Instantiated once using CreateSingletonInstance(), and accessed only using

@ -42,6 +42,7 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/audio/public/mojom/device_notifications.mojom.h"
#include "services/video_capture/public/cpp/features.h"
#include "third_party/blink/public/common/mediastream/media_devices.h"
#include "third_party/blink/public/mojom/mediastream/media_devices.mojom.h"
@ -625,15 +626,37 @@ void MediaDevicesManager::StartMonitoring() {
}
#if BUILDFLAG(IS_MAC)
GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindOnce(&MediaDevicesManager::StartMonitoringOnUIThread,
base::Unretained(this)));
if (base::FeatureList::IsEnabled(
video_capture::features::kCameraMonitoringInVideoCaptureService)) {
CHECK(!video_capture_service_device_changed_observer_);
// base::Unretained(this) is safe here because |this| owns
// |video_capture_service_device_changed_observer_|.
video_capture_service_device_changed_observer_ =
std::make_unique<VideoCaptureDevicesChangedObserver>(
/*disconnect_cb=*/base::BindRepeating(
&MediaDevicesManager::HandleDevicesChanged,
base::Unretained(this), MediaDeviceType::kMediaVideoInput),
/*listener_cb=*/base::BindRepeating([] {
if (auto* monitor = base::SystemMonitor::Get()) {
monitor->ProcessDevicesChanged(
base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
}
}));
video_capture_service_device_changed_observer_->ConnectToService();
} else {
GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(&MediaDevicesManager::StartMonitoringOnUIThread,
base::Unretained(this)));
}
#endif
}
#if BUILDFLAG(IS_MAC)
void MediaDevicesManager::StartMonitoringOnUIThread() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
CHECK(!base::FeatureList::IsEnabled(
video_capture::features::kCameraMonitoringInVideoCaptureService));
BrowserMainLoop* browser_main_loop = content::BrowserMainLoop::GetInstance();
if (!browser_main_loop)
return;

@ -14,6 +14,7 @@
#include "base/containers/flat_map.h"
#include "base/functional/callback.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/system/system_monitor.h"
@ -24,8 +25,11 @@
#include "media/capture/video/video_capture_device_descriptor.h"
#include "media/capture/video_capture_types.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/unique_receiver_set.h"
#include "services/video_capture/public/mojom/devices_changed_observer.mojom.h"
#include "services/video_capture/public/mojom/video_source_provider.mojom.h"
#include "third_party/blink/public/common/mediastream/media_devices.h"
#include "third_party/blink/public/mojom/mediastream/media_devices.mojom.h"
@ -175,6 +179,39 @@ class CONTENT_EXPORT MediaDevicesManager
get_salt_and_origin_cb_ = std::move(callback);
}
// Implementation of video_capture::mojom::DevicesChangedObserver that
// forwards a devices changed event to the global (process-local) instance of
// base::DeviceMonitor.
// Defined in a separate file video_capture_devices_changed_observer.cc
class VideoCaptureDevicesChangedObserver
: public video_capture::mojom::DevicesChangedObserver {
friend class MockVideoCaptureDevicesChangedObserver;
public:
explicit VideoCaptureDevicesChangedObserver(
base::RepeatingClosure disconnect_cb,
base::RepeatingClosure listener_cb);
~VideoCaptureDevicesChangedObserver() override;
void ConnectToService();
private:
// video_capture::mojom::DevicesChangedObserver implementation:
void OnDevicesChanged() override;
void OnConnectionError();
// |disconnect_cb_| is a callback used to invalidate the cache and do a
// fresh enumeration to avoid losing out on the changes that might happen
// when the video capture service is not active.
const base::RepeatingClosure disconnect_cb_;
const base::RepeatingClosure listener_cb_;
mojo::Receiver<video_capture::mojom::DevicesChangedObserver> receiver_{
this};
mojo::Remote<video_capture::mojom::VideoSourceProvider>
mojo_device_notifier_;
};
private:
friend class MediaDevicesManagerTest;
struct EnumerationRequest;
@ -366,6 +403,8 @@ class CONTENT_EXPORT MediaDevicesManager
class AudioServiceDeviceListener;
std::unique_ptr<AudioServiceDeviceListener> audio_service_device_listener_;
std::unique_ptr<VideoCaptureDevicesChangedObserver>
video_capture_service_device_changed_observer_;
std::map<uint32_t, EnumerationState> enumeration_states_;
uint32_t next_enumeration_state_id_ = 0;

@ -0,0 +1,52 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/renderer_host/media/media_devices_manager.h"
#include "content/public/browser/video_capture_service.h"
#include "services/video_capture/public/cpp/features.h"
#include "services/video_capture/public/mojom/video_capture_service.mojom.h"
namespace content {
MediaDevicesManager::VideoCaptureDevicesChangedObserver::
VideoCaptureDevicesChangedObserver(base::RepeatingClosure disconnect_cb,
base::RepeatingClosure listener_cb)
: disconnect_cb_(std::move(disconnect_cb)),
listener_cb_(std::move(listener_cb)) {}
MediaDevicesManager::VideoCaptureDevicesChangedObserver::
~VideoCaptureDevicesChangedObserver() = default;
void MediaDevicesManager::VideoCaptureDevicesChangedObserver::
OnDevicesChanged() {
listener_cb_.Run();
}
void MediaDevicesManager::VideoCaptureDevicesChangedObserver::
ConnectToService() {
CHECK(!mojo_device_notifier_);
CHECK(!receiver_.is_bound());
GetVideoCaptureService().ConnectToVideoSourceProvider(
mojo_device_notifier_.BindNewPipeAndPassReceiver());
mojo_device_notifier_.set_disconnect_handler(
base::BindOnce(&MediaDevicesManager::VideoCaptureDevicesChangedObserver::
OnConnectionError,
base::Unretained(this)));
mojo_device_notifier_->RegisterDevicesChangedObserver(
receiver_.BindNewPipeAndPassRemote());
}
void MediaDevicesManager::VideoCaptureDevicesChangedObserver::
OnConnectionError() {
mojo_device_notifier_.reset();
receiver_.reset();
if (disconnect_cb_) {
disconnect_cb_.Run();
}
ConnectToService();
}
} // namespace content

@ -0,0 +1,127 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/test/mock_devices_changed_observer.h"
#include "content/browser/renderer_host/media/media_devices_manager.h"
#include "content/public/browser/video_capture_service.h"
#include "content/public/test/browser_task_environment.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/video_capture/public/cpp/mock_video_capture_service.h"
#include "services/video_capture/public/cpp/mock_video_source_provider.h"
#include "services/video_capture/public/mojom/video_source_provider.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::_;
using testing::Invoke;
namespace content {
class MockVideoCaptureDevicesChangedObserver
: public MediaDevicesManager::VideoCaptureDevicesChangedObserver {
public:
MockVideoCaptureDevicesChangedObserver()
: VideoCaptureDevicesChangedObserver(
/*disconnect_cb=*/base::BindRepeating(
&MockVideoCaptureDevicesChangedObserver::HandleDevicesChanged,
base::Unretained(this),
MediaDeviceType::kMediaVideoInput),
/*listener_cb=*/base::BindRepeating([] {
if (auto* monitor = base::SystemMonitor::Get()) {
monitor->ProcessDevicesChanged(
base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
}
})),
source_provider_receiver_(&mock_source_provider_) {
OverrideVideoCaptureServiceForTesting(&mock_video_capture_service_);
ON_CALL(mock_video_capture_service_, DoConnectToVideoSourceProvider(_))
.WillByDefault(Invoke(
[this](
mojo::PendingReceiver<video_capture::mojom::VideoSourceProvider>
receiver) {
if (source_provider_receiver_.is_bound()) {
source_provider_receiver_.reset();
}
source_provider_receiver_.Bind(std::move(receiver));
base::RunLoop().RunUntilIdle();
}));
ConnectToService();
base::RunLoop().RunUntilIdle();
}
void CrashService() { source_provider_receiver_.reset(); }
MOCK_METHOD1(HandleDevicesChanged, void(MediaDeviceType type));
mojo::Receiver<video_capture::mojom::VideoSourceProvider>
source_provider_receiver_;
video_capture::MockVideoCaptureService mock_video_capture_service_;
video_capture::MockVideoSourceProvider mock_source_provider_;
};
class DevicesChangedObserverTest : public testing::Test {
public:
DevicesChangedObserverTest()
: mock_video_capture_service_device_changed_observer_(
std::make_unique<MockVideoCaptureDevicesChangedObserver>()) {
system_monitor_.AddDevicesChangedObserver(&observer);
}
void RaiseVirtualDeviceChangeEvent() {
mock_video_capture_service_device_changed_observer_->mock_source_provider_
.RaiseVirtualDeviceChangeEvent();
}
void RaiseDeviceChangeEvent() {
mock_video_capture_service_device_changed_observer_->mock_source_provider_
.RaiseDeviceChangeEvent();
}
void TearDown() override {
system_monitor_.RemoveDevicesChangedObserver(&observer);
}
protected:
content::BrowserTaskEnvironment task_environment_;
base::SystemMonitor system_monitor_;
base::MockDevicesChangedObserver observer;
std::unique_ptr<MockVideoCaptureDevicesChangedObserver>
mock_video_capture_service_device_changed_observer_;
};
TEST_F(DevicesChangedObserverTest,
RegisteredObserverReceivesDeviceChangeEvents) {
EXPECT_CALL(observer,
OnDevicesChanged(base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE))
.Times(1);
RaiseDeviceChangeEvent();
base::RunLoop().RunUntilIdle();
// No OnDevicesChanged event should be observed when a virtual device change
// event occurs.
RaiseVirtualDeviceChangeEvent();
base::RunLoop().RunUntilIdle();
}
TEST_F(DevicesChangedObserverTest, ServiceCrashes) {
EXPECT_CALL(observer,
OnDevicesChanged(base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE))
.Times(2);
RaiseDeviceChangeEvent();
base::RunLoop().RunUntilIdle();
// Crashing the service should call disconnect_cb resulting in calling
// |HandleDevicesChanged|. But device change events are still registered
// because the OnConnectionError() function calls ConnectToService().
EXPECT_CALL(*mock_video_capture_service_device_changed_observer_,
HandleDevicesChanged(MediaDeviceType::kMediaVideoInput))
.Times(1);
mock_video_capture_service_device_changed_observer_->CrashService();
base::RunLoop().RunUntilIdle();
RaiseDeviceChangeEvent();
base::RunLoop().RunUntilIdle();
}
} // namespace content

@ -39,7 +39,8 @@ video_capture::mojom::VideoCaptureService* g_service_override = nullptr;
void BindInProcessInstance(
mojo::PendingReceiver<video_capture::mojom::VideoCaptureService> receiver) {
static base::NoDestructor<video_capture::VideoCaptureServiceImpl> service(
std::move(receiver), GetUIThreadTaskRunner({}));
std::move(receiver), GetUIThreadTaskRunner({}),
/*create_system_monitor=*/false);
}
mojo::Remote<video_capture::mojom::VideoCaptureService>& GetUIThreadRemote() {

@ -2822,6 +2822,7 @@ test("content_unittests") {
"../browser/media/capture/screen_capture_kit_fullscreen_module_unittest.mm",
"../browser/renderer_host/input/mouse_wheel_rails_filter_unittest_mac.cc",
"../browser/renderer_host/input/web_input_event_builders_mac_unittest.mm",
"../browser/renderer_host/media/video_capture_devices_changed_observer_unittest.cc",
"../browser/renderer_host/native_web_keyboard_event_mac_unittest.mm",
"../browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm",
"../browser/renderer_host/render_widget_host_view_mac_unittest.mm",

@ -166,7 +166,8 @@ class UtilityThreadVideoCaptureServiceImpl final
mojo::PendingReceiver<video_capture::mojom::VideoCaptureService> receiver,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
: VideoCaptureServiceImpl(std::move(receiver),
std::move(ui_task_runner)) {}
std::move(ui_task_runner),
/*create_system_monitor=*/true) {}
private:
#if BUILDFLAG(IS_WIN)

@ -39,9 +39,10 @@ class MEDIA_EXPORT DeviceMonitorMac {
void StartMonitoring();
// Method called by the internal DeviceMonitorMacImpl object
// |device_monitor_impl_| when a device of type |type| has been added to or
// removed from the system. This code executes in the notification thread.
void NotifyDeviceChanged(base::SystemMonitor::DeviceType type);
// |device_monitor_impl_| when a device of type DEVTYPE_VIDEO_CAPTURE has been
// added to or removed from the system. This code executes in the notification
// thread.
void NotifyDeviceChanged();
private:
scoped_refptr<base::SingleThreadTaskRunner> device_task_runner_;

@ -147,8 +147,7 @@ void SuspendObserverDelegate::OnDeviceChanged() {
if (avfoundation_monitor_impl_) {
// Forward the event to MediaDevicesManager::OnDevicesChanged, which will
// enumerate the devices on its own.
avfoundation_monitor_impl_->monitor()->NotifyDeviceChanged(
base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
avfoundation_monitor_impl_->monitor()->NotifyDeviceChanged();
}
}
@ -339,11 +338,10 @@ void DeviceMonitorMac::StartMonitoring() {
std::make_unique<AVFoundationMonitorImpl>(this, device_task_runner_);
}
void DeviceMonitorMac::NotifyDeviceChanged(
base::SystemMonitor::DeviceType type) {
void DeviceMonitorMac::NotifyDeviceChanged() {
DCHECK(thread_checker_.CalledOnValidThread());
// TODO(xians): Remove the global variable for SystemMonitor.
base::SystemMonitor::Get()->ProcessDevicesChanged(type);
base::SystemMonitor::Get()->ProcessDevicesChanged(
base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
}
} // namespace media

@ -3,6 +3,7 @@ include_rules = [
"+chromeos/lacros",
"+gpu/command_buffer/client",
"+media/base",
"+media/device_monitors",
"+media/mojo",
"+media/capture",
"+ui/gfx",

@ -4,6 +4,8 @@
source_set("cpp") {
sources = [
"features.cc",
"features.h",
"receiver_media_to_mojo_adapter.cc",
"receiver_media_to_mojo_adapter.h",
"receiver_mojo_to_media_adapter.cc",

@ -0,0 +1,17 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/video_capture/public/cpp/features.h"
namespace video_capture::features {
// Enables video capture device monitoring in video capture service instead of
// the browser process. Currently implemented only for mac.
#if BUILDFLAG(IS_MAC)
BASE_FEATURE(kCameraMonitoringInVideoCaptureService,
"CameraMonitoringInVideoCaptureService",
base::FEATURE_DISABLED_BY_DEFAULT);
#endif
} // namespace video_capture::features

@ -0,0 +1,20 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SERVICES_VIDEO_CAPTURE_PUBLIC_CPP_FEATURES_H_
#define SERVICES_VIDEO_CAPTURE_PUBLIC_CPP_FEATURES_H_
#include "base/component_export.h"
#include "base/feature_list.h"
namespace video_capture::features {
#if BUILDFLAG(IS_MAC)
COMPONENT_EXPORT(VIDEO_CAPTURE)
BASE_DECLARE_FEATURE(kCameraMonitoringInVideoCaptureService);
#endif
} // namespace video_capture::features
#endif // SERVICES_VIDEO_CAPTURE_PUBLIC_CPP_FEATURES_H_

@ -7,6 +7,7 @@
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote_set.h"
#include "services/video_capture/public/mojom/devices_changed_observer.mojom.h"
#include "services/video_capture/public/mojom/producer.mojom.h"
#include "services/video_capture/public/mojom/video_source_provider.mojom.h"
@ -40,12 +41,24 @@ class MockVideoSourceProvider
mojo::PendingRemote<video_capture::mojom::DevicesChangedObserver>
observer,
bool raise_event_if_virtual_devices_already_present) override {
NOTIMPLEMENTED();
virtual_device_observers_.Add(std::move(observer));
}
void RegisterDevicesChangedObserver(
mojo::PendingRemote<video_capture::mojom::DevicesChangedObserver>
observer) override {
NOTIMPLEMENTED();
device_observers_.Add(std::move(observer));
}
void RaiseVirtualDeviceChangeEvent() {
for (const auto& observer : virtual_device_observers_) {
observer->OnDevicesChanged();
}
}
void RaiseDeviceChangeEvent() {
for (const auto& observer : device_observers_) {
observer->OnDevicesChanged();
}
}
void Close(CloseCallback callback) override;
@ -68,6 +81,9 @@ class MockVideoSourceProvider
mojo::PendingReceiver<video_capture::mojom::TextureVirtualDevice>
virtual_device_receiver));
MOCK_METHOD1(DoClose, void(CloseCallback& callback));
mojo::RemoteSet<mojom::DevicesChangedObserver> device_observers_;
mojo::RemoteSet<mojom::DevicesChangedObserver> virtual_device_observers_;
};
} // namespace video_capture

@ -47,7 +47,8 @@ class VideoCaptureServiceLifecycleTest : public ::testing::Test {
switches::kUseFakeDeviceForMediaStream);
service_impl_ = std::make_unique<VideoCaptureServiceImpl>(
service_remote_.BindNewPipeAndPassReceiver(),
task_environment_.GetMainThreadTaskRunner());
task_environment_.GetMainThreadTaskRunner(),
/*create_system_monitor=*/true);
service_remote_.set_idle_handler(
base::TimeDelta(),
base::BindRepeating(&VideoCaptureServiceLifecycleTest::OnServiceIdle,

@ -7,6 +7,7 @@
#include "base/command_line.h"
#include "base/task/single_thread_task_runner.h"
#include "media/base/media_switches.h"
#include "services/video_capture/public/cpp/features.h"
#include "services/video_capture/public/cpp/mock_producer.h"
#include "services/video_capture/public/mojom/constants.mojom.h"
@ -35,10 +36,15 @@ void VideoCaptureServiceTest::SetUp() {
switches::kUseFakeMjpegDecodeAccelerator);
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
switches::kUseFakeDeviceForMediaStream, "device-count=3");
#if BUILDFLAG(IS_MAC)
scoped_feature_list_.InitWithFeatures(
{video_capture::features::kCameraMonitoringInVideoCaptureService}, {});
#endif
service_impl_ = std::make_unique<VideoCaptureServiceImpl>(
service_remote_.BindNewPipeAndPassReceiver(),
base::SingleThreadTaskRunner::GetCurrentDefault());
base::SingleThreadTaskRunner::GetCurrentDefault(),
/*create_system_monitor=*/true);
// Note, that we explicitly do *not* call
// |service_remote_->InjectGpuDependencies()| here. Test case

@ -6,6 +6,7 @@
#define SERVICES_VIDEO_CAPTURE_TEST_VIDEO_CAPTURE_SERVICE_TEST_H_
#include "base/test/mock_callback.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
@ -57,6 +58,7 @@ class VideoCaptureServiceTest : public testing::Test {
base::MockCallback<mojom::VideoSourceProvider::GetSourceInfosCallback>
device_info_receiver_;
base::test::ScopedFeatureList scoped_feature_list_;
media::VideoCaptureParams requestable_settings_;
};

@ -24,6 +24,7 @@
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "services/video_capture/device_factory_impl.h"
#include "services/video_capture/public/cpp/features.h"
#include "services/video_capture/testing_controls_impl.h"
#include "services/video_capture/video_source_provider_impl.h"
#include "services/video_capture/virtual_device_enabled_device_factory.h"
@ -229,9 +230,20 @@ bool ShouldUseVCDFromAsh() {
VideoCaptureServiceImpl::VideoCaptureServiceImpl(
mojo::PendingReceiver<mojom::VideoCaptureService> receiver,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
bool create_system_monitor)
: receiver_(this, std::move(receiver)),
ui_task_runner_(std::move(ui_task_runner)) {}
ui_task_runner_(std::move(ui_task_runner)) {
if (create_system_monitor && !base::SystemMonitor::Get()) {
system_monitor_ = std::make_unique<base::SystemMonitor>();
}
#if BUILDFLAG(IS_MAC)
if (base::FeatureList::IsEnabled(
features::kCameraMonitoringInVideoCaptureService)) {
InitializeDeviceMonitor();
}
#endif
}
VideoCaptureServiceImpl::~VideoCaptureServiceImpl() {
#if BUILDFLAG(IS_CHROMEOS_ASH)
@ -376,6 +388,20 @@ void VideoCaptureServiceImpl::OnLastSourceProviderClientDisconnected() {
video_source_provider_.reset();
}
void VideoCaptureServiceImpl::InitializeDeviceMonitor() {
#if BUILDFLAG(IS_MAC)
CHECK(base::FeatureList::IsEnabled(
features::kCameraMonitoringInVideoCaptureService));
if (video_capture_device_monitor_mac_) {
return;
}
video_capture_device_monitor_mac_ = std::make_unique<media::DeviceMonitorMac>(
base::ThreadPool::CreateSingleThreadTaskRunner(
{base::TaskPriority::USER_VISIBLE}));
video_capture_device_monitor_mac_->StartMonitoring();
#endif
}
#if BUILDFLAG(IS_WIN)
void VideoCaptureServiceImpl::OnGpuInfoUpdate(const CHROME_LUID& luid) {
LazyInitializeDeviceFactory();

@ -7,7 +7,9 @@
#include <memory>
#include "base/feature_list.h"
#include "base/memory/scoped_refptr.h"
#include "base/system/system_monitor.h"
#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
@ -28,6 +30,10 @@
#include "services/viz/public/cpp/gpu/gpu.h"
#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN)
#if BUILDFLAG(IS_MAC)
#include "media/device_monitors/device_monitor_mac.h"
#endif
namespace video_capture {
class VirtualDeviceEnabledDeviceFactory;
@ -37,7 +43,8 @@ class VideoCaptureServiceImpl : public mojom::VideoCaptureService {
public:
VideoCaptureServiceImpl(
mojo::PendingReceiver<mojom::VideoCaptureService> receiver,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
bool create_system_monitor);
VideoCaptureServiceImpl(const VideoCaptureServiceImpl&) = delete;
VideoCaptureServiceImpl& operator=(const VideoCaptureServiceImpl&) = delete;
@ -72,8 +79,19 @@ class VideoCaptureServiceImpl : public mojom::VideoCaptureService {
void LazyInitializeDeviceFactory();
void LazyInitializeVideoSourceProvider();
void OnLastSourceProviderClientDisconnected();
// Initializes a platform-specific device monitor for device-change
// notifications. If the client uses the DeviceNotifier interface to get
// notifications this function should be called before the DeviceMonitor is
// created. If the client uses base::SystemMonitor to get notifications,
// this function should be called on service startup.
void InitializeDeviceMonitor();
#if BUILDFLAG(IS_MAC)
std::unique_ptr<media::DeviceMonitorMac> video_capture_device_monitor_mac_;
#endif
mojo::Receiver<mojom::VideoCaptureService> receiver_;
std::unique_ptr<base::SystemMonitor> system_monitor_;
std::unique_ptr<VirtualDeviceEnabledDeviceFactory> device_factory_;
std::unique_ptr<VideoSourceProviderImpl> video_source_provider_;
std::unique_ptr<GpuDependenciesContext> gpu_dependencies_context_;