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:

committed by
Chromium LUCI CQ

parent
41316deba1
commit
f0416e2b4d
content
media/device_monitors
services/video_capture
@ -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
|
127
content/browser/renderer_host/media/video_capture_devices_changed_observer_unittest.cc
Normal file
127
content/browser/renderer_host/media/video_capture_devices_changed_observer_unittest.cc
Normal file
@ -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",
|
||||
|
17
services/video_capture/public/cpp/features.cc
Normal file
17
services/video_capture/public/cpp/features.cc
Normal file
@ -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
|
20
services/video_capture/public/cpp/features.h
Normal file
20
services/video_capture/public/cpp/features.h
Normal file
@ -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_;
|
||||
|
Reference in New Issue
Block a user