pipewire_session.h (6187B)
1 /* 2 * Copyright (c) 2022 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef MODULES_VIDEO_CAPTURE_LINUX_PIPEWIRE_SESSION_H_ 12 #define MODULES_VIDEO_CAPTURE_LINUX_PIPEWIRE_SESSION_H_ 13 14 #include <pipewire/pipewire.h> 15 #include <spa/pod/pod.h> 16 #include <spa/utils/dict.h> 17 #include <spa/utils/hook.h> 18 19 #include <cstdint> 20 #include <deque> 21 #include <memory> 22 #include <string> 23 #include <vector> 24 25 #include "api/ref_counted_base.h" 26 #include "modules/portal/pipewire_utils.h" 27 #include "modules/portal/portal_request_response.h" 28 #include "modules/video_capture/linux/camera_portal.h" 29 #include "modules/video_capture/video_capture_defines.h" 30 #include "modules/video_capture/video_capture_options.h" 31 #include "rtc_base/synchronization/mutex.h" 32 #include "rtc_base/thread_annotations.h" 33 34 namespace webrtc { 35 namespace videocapturemodule { 36 37 class DeviceInfoPipeWire; 38 class PipeWireSession; 39 class VideoCaptureModulePipeWire; 40 41 // PipeWireNode objects are the local representation of PipeWire node objects. 42 // The portal API ensured that only camera nodes are visible to the client. 43 // So they all represent one camera that is available via PipeWire. 44 class PipeWireNode { 45 public: 46 struct PipeWireNodeDeleter { 47 void operator()(PipeWireNode* node) const noexcept; 48 }; 49 50 using PipeWireNodePtr = 51 std::unique_ptr<PipeWireNode, PipeWireNode::PipeWireNodeDeleter>; 52 static PipeWireNodePtr Create(PipeWireSession* session, 53 uint32_t id, 54 const spa_dict* props); 55 56 uint32_t id() const { return id_; } 57 std::string display_name() const { return display_name_; } 58 std::string unique_id() const { return unique_id_; } 59 std::string model_id() const { return model_id_; } 60 std::vector<VideoCaptureCapability> capabilities() const { 61 return capabilities_; 62 } 63 64 protected: 65 PipeWireNode(PipeWireSession* session, uint32_t id, const spa_dict* props); 66 67 private: 68 static void OnNodeInfo(void* data, const pw_node_info* info); 69 static void OnNodeParam(void* data, 70 int seq, 71 uint32_t id, 72 uint32_t index, 73 uint32_t next, 74 const spa_pod* param); 75 static bool ParseFormat(const spa_pod* param, VideoCaptureCapability* cap); 76 77 struct pw_proxy* proxy_; 78 struct spa_hook node_listener_; 79 PipeWireSession* session_; 80 uint32_t id_; 81 std::string display_name_; 82 std::string unique_id_; 83 std::string model_id_; 84 std::vector<VideoCaptureCapability> capabilities_; 85 }; 86 87 class CameraPortalNotifier : public CameraPortal::PortalNotifier { 88 public: 89 CameraPortalNotifier(PipeWireSession* session); 90 ~CameraPortalNotifier() = default; 91 92 void OnCameraRequestResult(xdg_portal::RequestResponse result, 93 int fd) override; 94 95 private: 96 PipeWireSession* session_; 97 }; 98 99 class PipeWireSession : public webrtc::RefCountedNonVirtual<PipeWireSession> { 100 public: 101 PipeWireSession(); 102 ~PipeWireSession(); 103 104 void Init(VideoCaptureOptions::Callback* callback, 105 int fd = kInvalidPipeWireFd); 106 107 // [De]Register DeviceInfo for device change updates 108 // These methods will add or remove references to DeviceInfo 109 // objects that we want to notify about device changes. 110 // NOTE: We do not take ownership of these objects and 111 // they should never be released by us. All the instances 112 // of DeviceInfoPipeWire must outlive their registration. 113 114 // Returns true when DeviceInfo was successfuly registered 115 // or false otherwise, when it was already registered before. 116 bool RegisterDeviceInfo(DeviceInfoPipeWire* device_info); 117 // Returns true when DeviceInfo was successfuly unregistered 118 // or false otherwise, when it was not previously registered. 119 bool DeRegisterDeviceInfo(DeviceInfoPipeWire* device_info); 120 121 const std::deque<PipeWireNode::PipeWireNodePtr>& nodes() const { 122 return nodes_; 123 } 124 125 friend class CameraPortalNotifier; 126 friend class PipeWireNode; 127 friend class VideoCaptureModulePipeWire; 128 129 private: 130 void InitPipeWire(int fd); 131 bool StartPipeWire(int fd); 132 void StopPipeWire(); 133 void PipeWireSync(); 134 135 void NotifyDeviceChange(); 136 137 static void OnCoreError(void* data, 138 uint32_t id, 139 int seq, 140 int res, 141 const char* message); 142 static void OnCoreDone(void* data, uint32_t id, int seq); 143 144 static void OnRegistryGlobal(void* data, 145 uint32_t id, 146 uint32_t permissions, 147 const char* type, 148 uint32_t version, 149 const spa_dict* props); 150 static void OnRegistryGlobalRemove(void* data, uint32_t id); 151 152 void Finish(VideoCaptureOptions::Status status); 153 void Cleanup(); 154 155 webrtc::Mutex callback_lock_; 156 VideoCaptureOptions::Callback* callback_ RTC_GUARDED_BY(&callback_lock_) = 157 nullptr; 158 159 webrtc::Mutex device_info_lock_; 160 std::vector<DeviceInfoPipeWire*> device_info_list_ 161 RTC_GUARDED_BY(device_info_lock_); 162 // Guard with device_info_lock, because currently it's the only place where 163 // we use this status information. 164 VideoCaptureOptions::Status status_ 165 RTC_GUARDED_BY(device_info_lock_); 166 167 struct pw_thread_loop* pw_main_loop_ = nullptr; 168 struct pw_context* pw_context_ = nullptr; 169 struct pw_core* pw_core_ = nullptr; 170 struct spa_hook core_listener_; 171 172 struct pw_registry* pw_registry_ = nullptr; 173 struct spa_hook registry_listener_; 174 175 int sync_seq_ = 0; 176 177 std::deque<PipeWireNode::PipeWireNodePtr> nodes_; 178 std::unique_ptr<CameraPortal> portal_; 179 std::unique_ptr<CameraPortalNotifier> portal_notifier_; 180 }; 181 182 } // namespace videocapturemodule 183 } // namespace webrtc 184 185 #endif // MODULES_VIDEO_CAPTURE_LINUX_PIPEWIRE_SESSION_H_