1 /* 2 * Copyright 2018 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_DESKTOP_CAPTURE_LINUX_BASE_CAPTURER_PIPEWIRE_H_ 12 #define MODULES_DESKTOP_CAPTURE_LINUX_BASE_CAPTURER_PIPEWIRE_H_ 13 14 #include <gio/gio.h> 15 #define typeof __typeof__ 16 #include <pipewire/pipewire.h> 17 #include <spa/param/video/format-utils.h> 18 19 #include "modules/desktop_capture/desktop_capture_options.h" 20 #include "modules/desktop_capture/desktop_capturer.h" 21 #include "rtc_base/constructormagic.h" 22 23 namespace webrtc { 24 25 class BaseCapturerPipeWire : public DesktopCapturer { 26 public: 27 enum CaptureSourceType : uint32_t { 28 kScreen = 0b01, 29 kWindow = 0b10, 30 kAny = 0b11 31 }; 32 33 explicit BaseCapturerPipeWire(CaptureSourceType source_type); 34 ~BaseCapturerPipeWire() override; 35 36 // DesktopCapturer interface. 37 void Start(Callback* delegate) override; 38 void CaptureFrame() override; 39 bool GetSourceList(SourceList* sources) override; 40 bool SelectSource(SourceId id) override; 41 42 static std::unique_ptr<DesktopCapturer> CreateRawScreenCapturer( 43 const DesktopCaptureOptions& options); 44 45 static std::unique_ptr<DesktopCapturer> CreateRawWindowCapturer( 46 const DesktopCaptureOptions& options); 47 48 private: 49 // PipeWire types --> 50 pw_context* pw_context_ = nullptr; 51 pw_core* pw_core_ = nullptr; 52 pw_stream* pw_stream_ = nullptr; 53 pw_thread_loop* pw_main_loop_ = nullptr; 54 55 spa_hook spa_core_listener_ = {}; 56 spa_hook spa_stream_listener_ = {}; 57 58 pw_core_events pw_core_events_ = {}; 59 pw_stream_events pw_stream_events_ = {}; 60 61 struct spa_video_info_raw spa_video_format_; 62 63 guint32 pw_stream_node_id_ = 0; 64 gint32 pw_fd_ = -1; 65 66 CaptureSourceType capture_source_type_ = 67 BaseCapturerPipeWire::CaptureSourceType::kAny; 68 69 // <-- end of PipeWire types 70 71 GDBusConnection* connection_ = nullptr; 72 GDBusProxy* proxy_ = nullptr; 73 GCancellable *cancellable_ = nullptr; 74 gchar* portal_handle_ = nullptr; 75 gchar* session_handle_ = nullptr; 76 gchar* sources_handle_ = nullptr; 77 gchar* start_handle_ = nullptr; 78 guint session_request_signal_id_ = 0; 79 guint sources_request_signal_id_ = 0; 80 guint start_request_signal_id_ = 0; 81 82 bool video_metadata_use_ = false; 83 DesktopSize video_size_; 84 DesktopSize desktop_size_ = {}; 85 DesktopCaptureOptions options_ = {}; 86 87 rtc::CriticalSection current_frame_lock_; 88 std::unique_ptr<uint8_t[]> current_frame_; 89 Callback* callback_ = nullptr; 90 91 bool portal_init_failed_ = false; 92 93 void InitPortal(); 94 void InitPipeWire(); 95 96 pw_stream* CreateReceivingStream(); 97 void HandleBuffer(pw_buffer* buffer); 98 99 void ConvertRGBxToBGRx(uint8_t* frame, uint32_t size); 100 101 static void OnCoreError(void *data, 102 uint32_t id, 103 int seq, 104 int res, 105 const char *message); 106 static void OnStreamParamChanged(void *data, 107 uint32_t id, 108 const struct spa_pod *format); 109 static void OnStreamStateChanged(void* data, 110 pw_stream_state old_state, 111 pw_stream_state state, 112 const char* error_message); 113 static void OnStreamProcess(void* data); 114 static void OnNewBuffer(void* data, uint32_t id); 115 116 guint SetupRequestResponseSignal(const gchar* object_path, 117 GDBusSignalCallback callback); 118 119 static void OnProxyRequested(GObject* object, 120 GAsyncResult* result, 121 gpointer user_data); 122 123 static gchar* PrepareSignalHandle(GDBusConnection* connection, 124 const gchar* token); 125 126 void SessionRequest(); 127 static void OnSessionRequested(GDBusProxy *proxy, 128 GAsyncResult* result, 129 gpointer user_data); 130 static void OnSessionRequestResponseSignal(GDBusConnection* connection, 131 const gchar* sender_name, 132 const gchar* object_path, 133 const gchar* interface_name, 134 const gchar* signal_name, 135 GVariant* parameters, 136 gpointer user_data); 137 138 void SourcesRequest(); 139 static void OnSourcesRequested(GDBusProxy *proxy, 140 GAsyncResult* result, 141 gpointer user_data); 142 static void OnSourcesRequestResponseSignal(GDBusConnection* connection, 143 const gchar* sender_name, 144 const gchar* object_path, 145 const gchar* interface_name, 146 const gchar* signal_name, 147 GVariant* parameters, 148 gpointer user_data); 149 150 void StartRequest(); 151 static void OnStartRequested(GDBusProxy *proxy, 152 GAsyncResult* result, 153 gpointer user_data); 154 static void OnStartRequestResponseSignal(GDBusConnection* connection, 155 const gchar* sender_name, 156 const gchar* object_path, 157 const gchar* interface_name, 158 const gchar* signal_name, 159 GVariant* parameters, 160 gpointer user_data); 161 162 void OpenPipeWireRemote(); 163 static void OnOpenPipeWireRemoteRequested(GDBusProxy *proxy, 164 GAsyncResult* result, 165 gpointer user_data); 166 167 RTC_DISALLOW_COPY_AND_ASSIGN(BaseCapturerPipeWire); 168 }; 169 170 } // namespace webrtc 171 172 #endif // MODULES_DESKTOP_CAPTURE_LINUX_BASE_CAPTURER_PIPEWIRE_H_ 173