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/constructor_magic.h" 22 23 namespace webrtc { 24 25 class PipeWireType { 26 public: 27 spa_type_media_type media_type; 28 spa_type_media_subtype media_subtype; 29 spa_type_format_video format_video; 30 spa_type_video_format video_format; 31 }; 32 33 class BaseCapturerPipeWire : public DesktopCapturer { 34 public: 35 enum CaptureSourceType { Screen = 1, Window }; 36 37 explicit BaseCapturerPipeWire(CaptureSourceType source_type); 38 ~BaseCapturerPipeWire() override; 39 40 // DesktopCapturer interface. 41 void Start(Callback* delegate) override; 42 void CaptureFrame() override; 43 bool GetSourceList(SourceList* sources) override; 44 bool SelectSource(SourceId id) override; 45 46 private: 47 // PipeWire types --> 48 pw_core* pw_core_ = nullptr; 49 pw_type* pw_core_type_ = nullptr; 50 pw_stream* pw_stream_ = nullptr; 51 pw_remote* pw_remote_ = nullptr; 52 pw_loop* pw_loop_ = nullptr; 53 pw_thread_loop* pw_main_loop_ = nullptr; 54 PipeWireType* pw_type_ = nullptr; 55 56 spa_hook spa_stream_listener_ = {}; 57 spa_hook spa_remote_listener_ = {}; 58 59 pw_stream_events pw_stream_events_ = {}; 60 pw_remote_events pw_remote_events_ = {}; 61 62 spa_video_info_raw* spa_video_format_ = nullptr; 63 64 gint32 pw_fd_ = -1; 65 66 CaptureSourceType capture_source_type_ = 67 BaseCapturerPipeWire::CaptureSourceType::Screen; 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 DesktopSize desktop_size_ = {}; 83 DesktopCaptureOptions options_ = {}; 84 85 uint8_t* current_frame_ = nullptr; 86 Callback* callback_ = nullptr; 87 88 bool portal_init_failed_ = false; 89 90 void InitPortal(); 91 void InitPipeWire(); 92 void InitPipeWireTypes(); 93 94 void CreateReceivingStream(); 95 void HandleBuffer(pw_buffer* buffer); 96 97 void ConvertRGBxToBGRx(uint8_t* frame, uint32_t size); 98 99 static void OnStateChanged(void* data, 100 pw_remote_state old_state, 101 pw_remote_state state, 102 const char* error); 103 static void OnStreamStateChanged(void* data, 104 pw_stream_state old_state, 105 pw_stream_state state, 106 const char* error_message); 107 108 static void OnStreamFormatChanged(void* data, const struct spa_pod* format); 109 static void OnStreamProcess(void* data); 110 static void OnNewBuffer(void* data, uint32_t id); 111 112 guint SetupRequestResponseSignal(const gchar* object_path, 113 GDBusSignalCallback callback); 114 115 static void OnProxyRequested(GObject* object, 116 GAsyncResult* result, 117 gpointer user_data); 118 119 static gchar* PrepareSignalHandle(GDBusConnection* connection, 120 const gchar* token); 121 122 void SessionRequest(); 123 static void OnSessionRequested(GDBusProxy *proxy, 124 GAsyncResult* result, 125 gpointer user_data); 126 static void OnSessionRequestResponseSignal(GDBusConnection* connection, 127 const gchar* sender_name, 128 const gchar* object_path, 129 const gchar* interface_name, 130 const gchar* signal_name, 131 GVariant* parameters, 132 gpointer user_data); 133 134 void SourcesRequest(); 135 static void OnSourcesRequested(GDBusProxy *proxy, 136 GAsyncResult* result, 137 gpointer user_data); 138 static void OnSourcesRequestResponseSignal(GDBusConnection* connection, 139 const gchar* sender_name, 140 const gchar* object_path, 141 const gchar* interface_name, 142 const gchar* signal_name, 143 GVariant* parameters, 144 gpointer user_data); 145 146 void StartRequest(); 147 static void OnStartRequested(GDBusProxy *proxy, 148 GAsyncResult* result, 149 gpointer user_data); 150 static void OnStartRequestResponseSignal(GDBusConnection* connection, 151 const gchar* sender_name, 152 const gchar* object_path, 153 const gchar* interface_name, 154 const gchar* signal_name, 155 GVariant* parameters, 156 gpointer user_data); 157 158 void OpenPipeWireRemote(); 159 static void OnOpenPipeWireRemoteRequested(GDBusProxy *proxy, 160 GAsyncResult* result, 161 gpointer user_data); 162 163 RTC_DISALLOW_COPY_AND_ASSIGN(BaseCapturerPipeWire); 164 }; 165 166 } // namespace webrtc 167 168 #endif // MODULES_DESKTOP_CAPTURE_LINUX_BASE_CAPTURER_PIPEWIRE_H_ 169