85157a42c7
Also backport upstream fixes for PipeWire camera support. Resolves: RHEL-64749
191 lines
7.0 KiB
Diff
191 lines
7.0 KiB
Diff
From a4eb4517f2bdeb6591c05a09109b4b543b83fef1 Mon Sep 17 00:00:00 2001
|
|
From: Jan Grulich <jgrulich@redhat.com>
|
|
Date: Thu, 5 Sep 2024 16:04:48 +0000
|
|
Subject: [PATCH] Bug 1830275 - Add missing support for device change
|
|
notifications r=pehrsons,webrtc-reviewers
|
|
|
|
Registers each DeviceInfoPipeWire in PipeWireSession we use and calls
|
|
DeviceChange() for each once there is a new camera added or removed to
|
|
invoke OnDeviceChange() for every registered VideoInputFeedback.
|
|
|
|
Differential Revision: https://phabricator.services.mozilla.com/D219218
|
|
---
|
|
.../linux/device_info_pipewire.cc | 10 +++-
|
|
.../video_capture/linux/pipewire_session.cc | 47 ++++++++++++++++++-
|
|
.../video_capture/linux/pipewire_session.h | 26 +++++++++-
|
|
3 files changed, 79 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/third_party/libwebrtc/modules/video_capture/linux/device_info_pipewire.cc b/third_party/libwebrtc/modules/video_capture/linux/device_info_pipewire.cc
|
|
index db2a3c7099..a0607b4aba 100644
|
|
--- a/third_party/libwebrtc/modules/video_capture/linux/device_info_pipewire.cc
|
|
+++ b/third_party/libwebrtc/modules/video_capture/linux/device_info_pipewire.cc
|
|
@@ -29,13 +29,19 @@
|
|
namespace webrtc {
|
|
namespace videocapturemodule {
|
|
DeviceInfoPipeWire::DeviceInfoPipeWire(VideoCaptureOptions* options)
|
|
- : DeviceInfoImpl(), pipewire_session_(options->pipewire_session()) {}
|
|
+ : DeviceInfoImpl(), pipewire_session_(options->pipewire_session()) {
|
|
+ const bool ret = pipewire_session_->RegisterDeviceInfo(this);
|
|
+ RTC_CHECK(ret);
|
|
+}
|
|
|
|
int32_t DeviceInfoPipeWire::Init() {
|
|
return 0;
|
|
}
|
|
|
|
-DeviceInfoPipeWire::~DeviceInfoPipeWire() = default;
|
|
+DeviceInfoPipeWire::~DeviceInfoPipeWire() {
|
|
+ const bool ret = pipewire_session_->DeRegisterDeviceInfo(this);
|
|
+ RTC_CHECK(ret);
|
|
+}
|
|
|
|
uint32_t DeviceInfoPipeWire::NumberOfDevices() {
|
|
RTC_CHECK(pipewire_session_);
|
|
diff --git a/third_party/libwebrtc/modules/video_capture/linux/pipewire_session.cc b/third_party/libwebrtc/modules/video_capture/linux/pipewire_session.cc
|
|
index ac12d04372..0b78c16df2 100644
|
|
--- a/third_party/libwebrtc/modules/video_capture/linux/pipewire_session.cc
|
|
+++ b/third_party/libwebrtc/modules/video_capture/linux/pipewire_session.cc
|
|
@@ -9,6 +9,7 @@
|
|
*/
|
|
|
|
#include "modules/video_capture/linux/pipewire_session.h"
|
|
+#include "modules/video_capture/linux/device_info_pipewire.h"
|
|
|
|
#include <spa/monitor/device.h>
|
|
#include <spa/param/format-utils.h>
|
|
@@ -274,6 +275,28 @@ void PipeWireSession::InitPipeWire(int fd) {
|
|
Finish(VideoCaptureOptions::Status::ERROR);
|
|
}
|
|
|
|
+bool PipeWireSession::RegisterDeviceInfo(DeviceInfoPipeWire* device_info) {
|
|
+ RTC_CHECK(device_info);
|
|
+ MutexLock lock(&device_info_lock_);
|
|
+ auto it = std::find(device_info_list_.begin(), device_info_list_.end(), device_info);
|
|
+ if (it == device_info_list_.end()) {
|
|
+ device_info_list_.push_back(device_info);
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
+bool PipeWireSession::DeRegisterDeviceInfo(DeviceInfoPipeWire* device_info) {
|
|
+ RTC_CHECK(device_info);
|
|
+ MutexLock lock(&device_info_lock_);
|
|
+ auto it = std::find(device_info_list_.begin(), device_info_list_.end(), device_info);
|
|
+ if (it != device_info_list_.end()) {
|
|
+ device_info_list_.erase(it);
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
bool PipeWireSession::StartPipeWire(int fd) {
|
|
pw_init(/*argc=*/nullptr, /*argv=*/nullptr);
|
|
|
|
@@ -344,6 +367,21 @@ void PipeWireSession::PipeWireSync() {
|
|
sync_seq_ = pw_core_sync(pw_core_, PW_ID_CORE, sync_seq_);
|
|
}
|
|
|
|
+void PipeWireSession::NotifyDeviceChange() {
|
|
+ RTC_LOG(LS_INFO) << "Notify about device list changes";
|
|
+ MutexLock lock(&device_info_lock_);
|
|
+
|
|
+ // It makes sense to notify about device changes only once we are
|
|
+ // properly initialized.
|
|
+ if (status_ != VideoCaptureOptions::Status::SUCCESS) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ for (auto* deviceInfo : device_info_list_) {
|
|
+ deviceInfo->DeviceChange();
|
|
+ }
|
|
+}
|
|
+
|
|
// static
|
|
void PipeWireSession::OnCoreError(void* data,
|
|
uint32_t id,
|
|
@@ -401,6 +439,8 @@ void PipeWireSession::OnRegistryGlobal(void* data,
|
|
|
|
that->nodes_.push_back(PipeWireNode::Create(that, id, props));
|
|
that->PipeWireSync();
|
|
+
|
|
+ that->NotifyDeviceChange();
|
|
}
|
|
|
|
// static
|
|
@@ -412,10 +452,15 @@ void PipeWireSession::OnRegistryGlobalRemove(void* data, uint32_t id) {
|
|
return node->id() == id;
|
|
});
|
|
that->nodes_.erase(it, that->nodes_.end());
|
|
+
|
|
+ that->NotifyDeviceChange();
|
|
}
|
|
|
|
void PipeWireSession::Finish(VideoCaptureOptions::Status status) {
|
|
- status_ = status;
|
|
+ {
|
|
+ MutexLock lock(&device_info_lock_);
|
|
+ status_ = status;
|
|
+ }
|
|
|
|
webrtc::MutexLock lock(&callback_lock_);
|
|
|
|
diff --git a/third_party/libwebrtc/modules/video_capture/linux/pipewire_session.h b/third_party/libwebrtc/modules/video_capture/linux/pipewire_session.h
|
|
index 84273ea695..1f3a00614f 100644
|
|
--- a/third_party/libwebrtc/modules/video_capture/linux/pipewire_session.h
|
|
+++ b/third_party/libwebrtc/modules/video_capture/linux/pipewire_session.h
|
|
@@ -29,6 +29,7 @@
|
|
namespace webrtc {
|
|
namespace videocapturemodule {
|
|
|
|
+class DeviceInfoPipeWire;
|
|
class PipeWireSession;
|
|
class VideoCaptureModulePipeWire;
|
|
|
|
@@ -97,6 +98,21 @@ class PipeWireSession : public rtc::RefCountedNonVirtual<PipeWireSession> {
|
|
|
|
void Init(VideoCaptureOptions::Callback* callback,
|
|
int fd = kInvalidPipeWireFd);
|
|
+
|
|
+ // [De]Register DeviceInfo for device change updates
|
|
+ // These methods will add or remove references to DeviceInfo
|
|
+ // objects that we want to notify about device changes.
|
|
+ // NOTE: We do not take ownership of these objects and
|
|
+ // they should never be released by us. All the instances
|
|
+ // of DeviceInfoPipeWire must outlive their registration.
|
|
+
|
|
+ // Returns true when DeviceInfo was successfuly registered
|
|
+ // or false otherwise, when it was already registered before.
|
|
+ bool RegisterDeviceInfo(DeviceInfoPipeWire* device_info);
|
|
+ // Returns true when DeviceInfo was successfuly unregistered
|
|
+ // or false otherwise, when it was not previously registered.
|
|
+ bool DeRegisterDeviceInfo(DeviceInfoPipeWire* device_info);
|
|
+
|
|
const std::deque<PipeWireNode::PipeWireNodePtr>& nodes() const {
|
|
return nodes_;
|
|
}
|
|
@@ -111,6 +127,8 @@ class PipeWireSession : public rtc::RefCountedNonVirtual<PipeWireSession> {
|
|
void StopPipeWire();
|
|
void PipeWireSync();
|
|
|
|
+ void NotifyDeviceChange();
|
|
+
|
|
static void OnCoreError(void* data,
|
|
uint32_t id,
|
|
int seq,
|
|
@@ -133,7 +151,13 @@ class PipeWireSession : public rtc::RefCountedNonVirtual<PipeWireSession> {
|
|
VideoCaptureOptions::Callback* callback_ RTC_GUARDED_BY(&callback_lock_) =
|
|
nullptr;
|
|
|
|
- VideoCaptureOptions::Status status_;
|
|
+ webrtc::Mutex device_info_lock_;
|
|
+ std::vector<DeviceInfoPipeWire*> device_info_list_
|
|
+ RTC_GUARDED_BY(device_info_lock_);
|
|
+ // Guard with device_info_lock, because currently it's the only place where
|
|
+ // we use this status information.
|
|
+ VideoCaptureOptions::Status status_
|
|
+ RTC_GUARDED_BY(device_info_lock_);
|
|
|
|
struct pw_thread_loop* pw_main_loop_ = nullptr;
|
|
struct pw_context* pw_context_ = nullptr;
|