Source code
Revision control
Copy as Markdown
Other Tools
/*
* Copyright (c) 2022 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef MODULES_VIDEO_CAPTURE_LINUX_PIPEWIRE_SESSION_H_
#define MODULES_VIDEO_CAPTURE_LINUX_PIPEWIRE_SESSION_H_
#include <pipewire/core.h>
#include <pipewire/pipewire.h>
#include <deque>
#include <string>
#include <vector>
#include "api/ref_counted_base.h"
#include "api/scoped_refptr.h"
#include "modules/portal/pipewire_utils.h"
#include "modules/video_capture/linux/camera_portal.h"
#include "modules/video_capture/video_capture.h"
#include "modules/video_capture/video_capture_options.h"
#include "rtc_base/synchronization/mutex.h"
namespace webrtc {
namespace videocapturemodule {
class DeviceInfoPipeWire;
class PipeWireSession;
class VideoCaptureModulePipeWire;
// PipeWireNode objects are the local representation of PipeWire node objects.
// The portal API ensured that only camera nodes are visible to the client.
// So they all represent one camera that is available via PipeWire.
class PipeWireNode {
public:
struct PipeWireNodeDeleter {
void operator()(PipeWireNode* node) const noexcept;
};
using PipeWireNodePtr =
std::unique_ptr<PipeWireNode, PipeWireNode::PipeWireNodeDeleter>;
static PipeWireNodePtr Create(PipeWireSession* session,
uint32_t id,
const spa_dict* props);
uint32_t id() const { return id_; }
std::string display_name() const { return display_name_; }
std::string unique_id() const { return unique_id_; }
std::string model_id() const { return model_id_; }
std::vector<VideoCaptureCapability> capabilities() const {
return capabilities_;
}
protected:
PipeWireNode(PipeWireSession* session, uint32_t id, const spa_dict* props);
private:
static void OnNodeInfo(void* data, const pw_node_info* info);
static void OnNodeParam(void* data,
int seq,
uint32_t id,
uint32_t index,
uint32_t next,
const spa_pod* param);
static bool ParseFormat(const spa_pod* param, VideoCaptureCapability* cap);
pw_proxy* proxy_;
spa_hook node_listener_;
PipeWireSession* session_;
uint32_t id_;
std::string display_name_;
std::string unique_id_;
std::string model_id_;
std::vector<VideoCaptureCapability> capabilities_;
};
class CameraPortalNotifier : public CameraPortal::PortalNotifier {
public:
CameraPortalNotifier(PipeWireSession* session);
~CameraPortalNotifier() = default;
void OnCameraRequestResult(xdg_portal::RequestResponse result,
int fd) override;
private:
PipeWireSession* session_;
};
class PipeWireSession : public rtc::RefCountedNonVirtual<PipeWireSession> {
public:
PipeWireSession();
~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_;
}
friend class CameraPortalNotifier;
friend class PipeWireNode;
friend class VideoCaptureModulePipeWire;
private:
void InitPipeWire(int fd);
bool StartPipeWire(int fd);
void StopPipeWire();
void PipeWireSync();
void NotifyDeviceChange();
static void OnCoreError(void* data,
uint32_t id,
int seq,
int res,
const char* message);
static void OnCoreDone(void* data, uint32_t id, int seq);
static void OnRegistryGlobal(void* data,
uint32_t id,
uint32_t permissions,
const char* type,
uint32_t version,
const spa_dict* props);
static void OnRegistryGlobalRemove(void* data, uint32_t id);
void Finish(VideoCaptureOptions::Status status);
void Cleanup();
webrtc::Mutex callback_lock_;
VideoCaptureOptions::Callback* callback_ RTC_GUARDED_BY(&callback_lock_) =
nullptr;
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;
struct pw_core* pw_core_ = nullptr;
struct spa_hook core_listener_;
struct pw_registry* pw_registry_ = nullptr;
struct spa_hook registry_listener_;
int sync_seq_ = 0;
std::deque<PipeWireNode::PipeWireNodePtr> nodes_;
std::unique_ptr<CameraPortal> portal_;
std::unique_ptr<CameraPortalNotifier> portal_notifier_;
};
} // namespace videocapturemodule
} // namespace webrtc
#endif // MODULES_VIDEO_CAPTURE_LINUX_PIPEWIRE_SESSION_H_