Merge pull request #4287 from GeorgesStavracas/gbsneto/pipewire

Wayland / PipeWire capture
This commit is contained in:
Jim
2021-03-30 03:16:46 -07:00
committed by GitHub
23 changed files with 1707 additions and 130 deletions
+1 -1
View File
@@ -444,7 +444,7 @@ jobs:
run: |
mkdir ./build
cd ./build
cmake -DUNIX_STRUCTURE=0 -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/obs-studio-portable" -DENABLE_UNIT_TESTS=ON -DENABLE_VLC=ON -DWITH_RTMPS=ON -DBUILD_BROWSER=ON -DCEF_ROOT_DIR="${{ github.workspace }}/cmbuild/cef_binary_${{ env.LINUX_CEF_BUILD_VERSION }}_linux64" -DTWITCH_CLIENTID='${{ env.TWITCH_CLIENTID }}' -DTWITCH_HASH='${{ env.TWITCH_HASH }}' -DRESTREAM_CLIENTID='${{ env.RESTREAM_CLIENTID }}' -DRESTREAM_HASH='${{ env.RESTREAM_HASH }}' ..
cmake -DENABLE_PIPEWIRE=OFF -DUNIX_STRUCTURE=0 -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/obs-studio-portable" -DENABLE_UNIT_TESTS=ON -DENABLE_VLC=ON -DWITH_RTMPS=ON -DBUILD_BROWSER=ON -DCEF_ROOT_DIR="${{ github.workspace }}/cmbuild/cef_binary_${{ env.LINUX_CEF_BUILD_VERSION }}_linux64" -DTWITCH_CLIENTID='${{ env.TWITCH_CLIENTID }}' -DTWITCH_HASH='${{ env.TWITCH_HASH }}' -DRESTREAM_CLIENTID='${{ env.RESTREAM_CLIENTID }}' -DRESTREAM_HASH='${{ env.RESTREAM_HASH }}' ..
- name: 'Build'
shell: bash
working-directory: ${{ github.workspace }}/build
+1 -1
View File
@@ -3,4 +3,4 @@
set -ex
ccache -s || echo "CCache is not available."
mkdir build && cd build
cmake -DBUILD_BROWSER=ON -DCEF_ROOT_DIR="../cef_binary_${LINUX_CEF_BUILD_VERSION}_linux64" ..
cmake -DENABLE_PIPEWIRE=OFF -DBUILD_BROWSER=ON -DCEF_ROOT_DIR="../cef_binary_${LINUX_CEF_BUILD_VERSION}_linux64" ..
+1 -1
View File
@@ -11,7 +11,7 @@
"--device=all",
"--share=network",
"--share=ipc",
"--filesystem=xdg-run/obs-xdg-portal:create",
"--filesystem=xdg-run/pipewire-0",
"--filesystem=host",
"--talk-name=org.kde.StatusNotifierWatcher",
"--talk-name=org.freedesktop.ScreenSaver",
+2 -2
View File
@@ -9,12 +9,12 @@
# Use pkg-config to get the directories and then use these values
# in the find_path() and find_library() calls
find_package(PkgConfig)
pkg_check_modules(PC_GIO gio-2.0)
pkg_check_modules(PC_GIO gio-2.0 gio-unix-2.0)
set(GIO_DEFINITIONS ${PC_GIO_CFLAGS})
find_path(GIO_INCLUDE_DIRS gio.h PATHS ${PC_GIO_INCLUDEDIR} ${PC_GIO_INCLUDE_DIRS} PATH_SUFFIXES glib-2.0/gio/)
find_library(GIO_LIBRARIES NAMES gio-2.0 libgio-2.0 PATHS ${PC_GIO_LIBDIR} ${PC_GIO_LIBRARY_DIRS})
find_library(GIO_LIBRARIES NAMES gio-2.0 libgio-2.0 gio-unix-2.0 PATHS ${PC_GIO_LIBDIR} ${PC_GIO_LIBRARY_DIRS})
mark_as_advanced(GIO_INCLUDE_DIRS GIO_LIBRARIES)
include(FindPackageHandleStandardArgs)
+121
View File
@@ -0,0 +1,121 @@
#.rst:
# FindPipeWire
# -------
#
# Try to find PipeWire on a Unix system.
#
# This will define the following variables:
#
# ``PIPEWIRE_FOUND``
# True if (the requested version of) PipeWire is available
# ``PIPEWIRE_VERSION``
# The version of PipeWire
# ``PIPEWIRE_LIBRARIES``
# This can be passed to target_link_libraries() instead of the ``PipeWire::PipeWire``
# target
# ``PIPEWIRE_INCLUDE_DIRS``
# This should be passed to target_include_directories() if the target is not
# used for linking
# ``PIPEWIRE_DEFINITIONS``
# This should be passed to target_compile_options() if the target is not
# used for linking
#
# If ``PIPEWIRE_FOUND`` is TRUE, it will also define the following imported target:
#
# ``PipeWire::PipeWire``
# The PipeWire library
#
# In general we recommend using the imported target, as it is easier to use.
# Bear in mind, however, that if the target is in the link interface of an
# exported library, it must be made available by the package config file.
#=============================================================================
# Copyright 2014 Alex Merry <alex.merry@kde.org>
# Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
# Copyright 2018-2020 Jan Grulich <jgrulich@redhat.com>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#=============================================================================
# Use pkg-config to get the directories and then use these values
# in the FIND_PATH() and FIND_LIBRARY() calls
find_package(PkgConfig QUIET)
pkg_search_module(PKG_PIPEWIRE QUIET libpipewire-0.3)
pkg_search_module(PKG_SPA QUIET libspa-0.2)
set(PIPEWIRE_DEFINITIONS "${PKG_PIPEWIRE_CFLAGS}" "${PKG_SPA_CFLAGS}")
set(PIPEWIRE_VERSION "${PKG_PIPEWIRE_VERSION}")
find_path(PIPEWIRE_INCLUDE_DIRS
NAMES
pipewire/pipewire.h
HINTS
${PKG_PIPEWIRE_INCLUDE_DIRS}
${PKG_PIPEWIRE_INCLUDE_DIRS}/pipewire-0.3
)
find_path(SPA_INCLUDE_DIRS
NAMES
spa/param/props.h
HINTS
${PKG_SPA_INCLUDE_DIRS}
${PKG_SPA_INCLUDE_DIRS}/spa-0.2
)
find_library(PIPEWIRE_LIBRARIES
NAMES
pipewire-0.3
HINTS
${PKG_PIPEWIRE_LIBRARY_DIRS}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(PipeWire
FOUND_VAR
PIPEWIRE_FOUND
REQUIRED_VARS
PIPEWIRE_LIBRARIES
PIPEWIRE_INCLUDE_DIRS
SPA_INCLUDE_DIRS
VERSION_VAR
PIPEWIRE_VERSION
)
if(PIPEWIRE_FOUND AND NOT TARGET PipeWire::PipeWire)
add_library(PipeWire::PipeWire UNKNOWN IMPORTED)
set_target_properties(PipeWire::PipeWire PROPERTIES
IMPORTED_LOCATION "${PIPEWIRE_LIBRARIES}"
INTERFACE_COMPILE_OPTIONS "${PIPEWIRE_DEFINITIONS}"
INTERFACE_INCLUDE_DIRECTORIES "${PIPEWIRE_INCLUDE_DIRS};${SPA_INCLUDE_DIRS}"
)
endif()
mark_as_advanced(PIPEWIRE_LIBRARIES PIPEWIRE_INCLUDE_DIRS)
include(FeatureSummary)
set_package_properties(PipeWire PROPERTIES
URL "https://www.pipewire.org"
DESCRIPTION "PipeWire - multimedia processing"
)
+1 -71
View File
@@ -50,33 +50,6 @@ typedef void(APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)(
GLenum target, GLeglImageOES image);
static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES;
/* copied from drm_fourcc.h */
#define fourcc_code(a, b, c, d) \
((__u32)(a) | ((__u32)(b) << 8) | ((__u32)(c) << 16) | \
((__u32)(d) << 24))
#define DRM_FORMAT_INVALID 0
#define DRM_FORMAT_R8 fourcc_code('R', '8', ' ', ' ') /* [7:0] R */
#define DRM_FORMAT_R16 \
fourcc_code('R', '1', '6', ' ') /* [15:0] R little endian */
#define DRM_FORMAT_RG88 \
fourcc_code('R', 'G', '8', '8') /* [15:0] R:G 8:8 little endian */
#define DRM_FORMAT_ABGR8888 \
fourcc_code('A', 'B', '2', \
'4') /* [31:0] A:B:G:R 8:8:8:8 little endian */
#define DRM_FORMAT_ABGR2101010 \
fourcc_code('A', 'B', '3', \
'0') /* [31:0] A:B:G:R 2:10:10:10 little endian */
#define DRM_FORMAT_ABGR16161616F \
fourcc_code('A', 'B', '4', \
'H') /* [63:0] A:B:G:R 16:16:16:16 little endian */
#define DRM_FORMAT_ARGB8888 \
fourcc_code('A', 'R', '2', \
'4') /* [31:0] A:R:G:B 8:8:8:8 little endian */
#define DRM_FORMAT_XRGB8888 \
fourcc_code('X', 'R', '2', \
'4') /* [31:0] x:R:G:B 8:8:8:8 little endian */
static bool find_gl_extension(const char *extension)
{
GLint n, i;
@@ -113,42 +86,6 @@ static bool init_egl_image_target_texture_2d_ext(void)
return true;
}
static inline enum gs_color_format gs_format_to_drm_format(uint32_t drm_format)
{
switch (drm_format) {
case GS_R8:
return DRM_FORMAT_R8;
case GS_RGBA:
return DRM_FORMAT_ABGR8888;
case GS_BGRX:
return DRM_FORMAT_XRGB8888;
case GS_BGRA:
return DRM_FORMAT_ARGB8888;
case GS_R10G10B10A2:
return DRM_FORMAT_ABGR2101010;
case GS_R16:
return DRM_FORMAT_R16;
case GS_RGBA16F:
return DRM_FORMAT_ABGR16161616F;
case GS_R8G8:
return DRM_FORMAT_RG88;
case GS_A8:
case GS_R16F:
case GS_RGBA16:
case GS_RG16F:
case GS_R32F:
case GS_RG32F:
case GS_RGBA32F:
case GS_DXT1:
case GS_DXT3:
case GS_DXT5:
case GS_UNKNOWN:
return DRM_FORMAT_INVALID;
}
return DRM_FORMAT_INVALID;
}
static EGLImageKHR
create_dmabuf_egl_image(EGLDisplay egl_display, unsigned int width,
unsigned int height, uint32_t drm_format,
@@ -242,24 +179,17 @@ create_dmabuf_egl_image(EGLDisplay egl_display, unsigned int width,
struct gs_texture *
gl_egl_create_dmabuf_image(EGLDisplay egl_display, unsigned int width,
unsigned int height,
unsigned int height, uint32_t drm_format,
enum gs_color_format color_format, uint32_t n_planes,
const int *fds, const uint32_t *strides,
const uint32_t *offsets, const uint64_t *modifiers)
{
struct gs_texture *texture = NULL;
EGLImage egl_image;
uint32_t drm_format;
if (!init_egl_image_target_texture_2d_ext())
return NULL;
drm_format = gs_format_to_drm_format(color_format);
if (drm_format == DRM_FORMAT_INVALID) {
blog(LOG_ERROR, "Invalid or unsupported image format");
return NULL;
}
egl_image = create_dmabuf_egl_image(egl_display, width, height,
drm_format, n_planes, fds, strides,
offsets, modifiers);
+1 -1
View File
@@ -8,7 +8,7 @@ const char *gl_egl_error_to_string(EGLint error_number);
struct gs_texture *
gl_egl_create_dmabuf_image(EGLDisplay egl_display, unsigned int width,
unsigned int height,
unsigned int height, uint32_t drm_format,
enum gs_color_format color_format, uint32_t n_planes,
const int *fds, const uint32_t *strides,
const uint32_t *offsets, const uint64_t *modifiers);
+5 -5
View File
@@ -126,11 +126,11 @@ extern void device_present(gs_device_t *device)
extern struct gs_texture *device_texture_create_from_dmabuf(
gs_device_t *device, unsigned int width, unsigned int height,
enum gs_color_format color_format, uint32_t n_planes, const int *fds,
const uint32_t *strides, const uint32_t *offsets,
const uint64_t *modifiers)
uint32_t drm_format, enum gs_color_format color_format,
uint32_t n_planes, const int *fds, const uint32_t *strides,
const uint32_t *offsets, const uint64_t *modifiers)
{
return gl_vtable->device_texture_create_from_dmabuf(
device, width, height, color_format, n_planes, fds, strides,
offsets, modifiers);
device, width, height, drm_format, color_format, n_planes, fds,
strides, offsets, modifiers);
}
+2 -2
View File
@@ -56,7 +56,7 @@ struct gl_winsys_vtable {
struct gs_texture *(*device_texture_create_from_dmabuf)(
gs_device_t *device, unsigned int width, unsigned int height,
enum gs_color_format color_format, uint32_t n_planes,
const int *fds, const uint32_t *strides,
uint32_t drm_format, enum gs_color_format color_format,
uint32_t n_planes, const int *fds, const uint32_t *strides,
const uint32_t *offsets, const uint64_t *modifiers);
};
+5 -5
View File
@@ -323,15 +323,15 @@ static void gl_wayland_egl_device_present(gs_device_t *device)
static struct gs_texture *gl_wayland_egl_device_texture_create_from_dmabuf(
gs_device_t *device, unsigned int width, unsigned int height,
enum gs_color_format color_format, uint32_t n_planes, const int *fds,
const uint32_t *strides, const uint32_t *offsets,
const uint64_t *modifiers)
uint32_t drm_format, enum gs_color_format color_format,
uint32_t n_planes, const int *fds, const uint32_t *strides,
const uint32_t *offsets, const uint64_t *modifiers)
{
struct gl_platform *plat = device->plat;
return gl_egl_create_dmabuf_image(plat->display, width, height,
color_format, n_planes, fds, strides,
offsets, modifiers);
drm_format, color_format, n_planes,
fds, strides, offsets, modifiers);
}
static const struct gl_winsys_vtable egl_wayland_winsys_vtable = {
+5 -5
View File
@@ -637,15 +637,15 @@ static void gl_x11_egl_device_present(gs_device_t *device)
static struct gs_texture *gl_x11_egl_device_texture_create_from_dmabuf(
gs_device_t *device, unsigned int width, unsigned int height,
enum gs_color_format color_format, uint32_t n_planes, const int *fds,
const uint32_t *strides, const uint32_t *offsets,
const uint64_t *modifiers)
uint32_t drm_format, enum gs_color_format color_format,
uint32_t n_planes, const int *fds, const uint32_t *strides,
const uint32_t *offsets, const uint64_t *modifiers)
{
struct gl_platform *plat = device->plat;
return gl_egl_create_dmabuf_image(plat->edisplay, width, height,
color_format, n_planes, fds, strides,
offsets, modifiers);
drm_format, color_format, n_planes,
fds, strides, offsets, modifiers);
}
static const struct gl_winsys_vtable egl_x11_winsys_vtable = {
+4 -3
View File
@@ -581,13 +581,14 @@ static void gl_x11_glx_device_present(gs_device_t *device)
static struct gs_texture *gl_x11_glx_device_texture_create_from_dmabuf(
gs_device_t *device, unsigned int width, unsigned int height,
enum gs_color_format color_format, uint32_t n_planes, const int *fds,
const uint32_t *strides, const uint32_t *offsets,
const uint64_t *modifiers)
uint32_t drm_format, enum gs_color_format color_format,
uint32_t n_planes, const int *fds, const uint32_t *strides,
const uint32_t *offsets, const uint64_t *modifiers)
{
UNUSED_PARAMETER(device);
UNUSED_PARAMETER(width);
UNUSED_PARAMETER(height);
UNUSED_PARAMETER(drm_format);
UNUSED_PARAMETER(color_format);
UNUSED_PARAMETER(n_planes);
UNUSED_PARAMETER(fds);
+3 -3
View File
@@ -174,9 +174,9 @@ EXPORT void device_debug_marker_end(gs_device_t *device);
EXPORT gs_texture_t *device_texture_create_from_dmabuf(
gs_device_t *device, unsigned int width, unsigned int height,
enum gs_color_format color_format, uint32_t n_planes, const int *fds,
const uint32_t *strides, const uint32_t *offsets,
const uint64_t *modifiers);
uint32_t drm_format, enum gs_color_format color_format,
uint32_t n_planes, const int *fds, const uint32_t *strides,
const uint32_t *offsets, const uint64_t *modifiers);
#endif
+2 -2
View File
@@ -330,8 +330,8 @@ struct gs_exports {
#elif __linux__
struct gs_texture *(*device_texture_create_from_dmabuf)(
gs_device_t *device, unsigned int width, unsigned int height,
enum gs_color_format color_format, uint32_t n_planes,
const int *fds, const uint32_t *strides,
uint32_t drm_format, enum gs_color_format color_format,
uint32_t n_planes, const int *fds, const uint32_t *strides,
const uint32_t *offsets, const uint64_t *modifiers);
#endif
};
+7 -9
View File
@@ -1365,19 +1365,17 @@ gs_texture_t *gs_texture_create(uint32_t width, uint32_t height,
#if __linux__
gs_texture_t *gs_texture_create_from_dmabuf(unsigned int width,
unsigned int height,
enum gs_color_format color_format,
uint32_t n_planes, const int *fds,
const uint32_t *strides,
const uint32_t *offsets,
const uint64_t *modifiers)
gs_texture_t *gs_texture_create_from_dmabuf(
unsigned int width, unsigned int height, uint32_t drm_format,
enum gs_color_format color_format, uint32_t n_planes, const int *fds,
const uint32_t *strides, const uint32_t *offsets,
const uint64_t *modifiers)
{
graphics_t *graphics = thread_graphics;
return graphics->exports.device_texture_create_from_dmabuf(
graphics->device, width, height, color_format, n_planes, fds,
strides, offsets, modifiers);
graphics->device, width, height, drm_format, color_format,
n_planes, fds, strides, offsets, modifiers);
}
#endif
+5 -6
View File
@@ -917,12 +917,11 @@ EXPORT void gs_unregister_loss_callbacks(void *data);
#elif __linux__
EXPORT gs_texture_t *
gs_texture_create_from_dmabuf(unsigned int width, unsigned int height,
enum gs_color_format color_format,
uint32_t n_planes, const int *fds,
const uint32_t *strides, const uint32_t *offsets,
const uint64_t *modifiers);
EXPORT gs_texture_t *gs_texture_create_from_dmabuf(
unsigned int width, unsigned int height, uint32_t drm_format,
enum gs_color_format color_format, uint32_t n_planes, const int *fds,
const uint32_t *strides, const uint32_t *offsets,
const uint64_t *modifiers);
#endif
+49 -6
View File
@@ -9,7 +9,7 @@ endif()
find_package(XCB COMPONENTS XCB RANDR SHM XFIXES XINERAMA REQUIRED)
find_package(X11_XCB REQUIRED)
include_directories(SYSTEM
set(linux-capture_INCLUDES
"${CMAKE_SOURCE_DIR}/libobs"
${X11_Xcomposite_INCLUDE_PATH}
${X11_X11_INCLUDE_PATH}
@@ -34,11 +34,7 @@ set(linux-capture_HEADERS
xcompcap-helper.hpp
)
add_library(linux-capture MODULE
${linux-capture_SOURCES}
${linux-capture_HEADERS}
)
target_link_libraries(linux-capture
set(linux-capture_LIBRARIES
libobs
glad
${X11_LIBRARIES}
@@ -47,6 +43,53 @@ target_link_libraries(linux-capture
${X11_Xcomposite_LIB}
${XCB_LIBRARIES}
)
option(ENABLE_PIPEWIRE "Enable PipeWire support" ON)
if(ENABLE_PIPEWIRE)
find_package(PipeWire REQUIRED)
find_package(Gio REQUIRED)
add_definitions(-DENABLE_PIPEWIRE)
set(linux-capture_INCLUDES
${linux-capture_INCLUDES}
${GIO_INCLUDE_DIRS}
${PIPEWIRE_INCLUDE_DIRS}
)
add_definitions(
${GIO_DEFINITIONS}
${PIPEWIRE_DEFINITIONS}
)
set(linux-capture_SOURCES
${linux-capture_SOURCES}
pipewire.c
pipewire-capture.c
)
set(linux-capture_HEADERS
${linux-capture_HEADERS}
pipewire.h
pipewire-capture.h
)
set(linux-capture_LIBRARIES
${linux-capture_LIBRARIES}
${GIO_LIBRARIES}
${PIPEWIRE_LIBRARIES}
)
endif()
include_directories(SYSTEM
${linux-capture_INCLUDES}
)
add_library(linux-capture MODULE
${linux-capture_SOURCES}
${linux-capture_HEADERS}
)
target_link_libraries(linux-capture
${linux-capture_LIBRARIES}
)
set_target_properties(linux-capture PROPERTIES FOLDER "plugins")
install_obs_plugin_with_data(linux-capture data)
@@ -13,3 +13,8 @@ SwapRedBlue="Swap red and blue"
LockX="Lock X server when capturing"
IncludeXBorder="Include X Border"
ExcludeAlpha="Use alpha-less texture format (Mesa workaround)"
PipeWireDesktopCapture="Screen Capture (PipeWire)"
PipeWireSelectMonitor="Select Monitor"
PipeWireSelectWindow="Select Window"
PipeWireWindowCapture="Window Capture (PipeWire)"
ShowCursor="Show Cursor"
+23 -7
View File
@@ -17,11 +17,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <obs-module.h>
#include <obs-nix-platform.h>
#ifdef ENABLE_PIPEWIRE
#include "pipewire-capture.h"
#endif
OBS_DECLARE_MODULE()
OBS_MODULE_USE_DEFAULT_LOCALE("linux-xshm", "en-US")
MODULE_EXPORT const char *obs_module_description(void)
{
return "xcomposite/xshm based window/screen capture for X11";
#ifdef ENABLE_PIPEWIRE
if (obs_get_nix_platform() != OBS_NIX_PLATFORM_X11_GLX)
return "PipeWire based window/screen capture for X11 and Wayland";
else
#endif
return "xcomposite/xshm based window/screen capture for X11";
}
extern struct obs_source_info xshm_input;
@@ -31,17 +40,24 @@ extern void xcomposite_unload(void);
bool obs_module_load(void)
{
if (obs_get_nix_platform() != OBS_NIX_PLATFORM_X11_GLX) {
blog(LOG_ERROR, "linux-capture cannot run on EGL platforms");
return false;
if (obs_get_nix_platform() == OBS_NIX_PLATFORM_X11_GLX) {
obs_register_source(&xshm_input);
xcomposite_load();
#ifdef ENABLE_PIPEWIRE
} else {
pipewire_capture_load();
#endif
}
obs_register_source(&xshm_input);
xcomposite_load();
return true;
}
void obs_module_unload(void)
{
xcomposite_unload();
if (obs_get_nix_platform() == OBS_NIX_PLATFORM_X11_GLX)
xcomposite_unload();
#ifdef ENABLE_PIPEWIRE
else
pipewire_capture_unload();
#endif
}
+155
View File
@@ -0,0 +1,155 @@
/* pipewire-capture.c
*
* Copyright 2020 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "pipewire.h"
/* obs_source_info methods */
static const char *pipewire_desktop_capture_get_name(void *data)
{
UNUSED_PARAMETER(data);
return obs_module_text("PipeWireDesktopCapture");
}
static const char *pipewire_window_capture_get_name(void *data)
{
UNUSED_PARAMETER(data);
return obs_module_text("PipeWireWindowCapture");
}
static void *pipewire_desktop_capture_create(obs_data_t *settings,
obs_source_t *source)
{
return obs_pipewire_create(DESKTOP_CAPTURE, settings, source);
}
static void *pipewire_window_capture_create(obs_data_t *settings,
obs_source_t *source)
{
return obs_pipewire_create(WINDOW_CAPTURE, settings, source);
}
static void pipewire_capture_destroy(void *data)
{
obs_pipewire_destroy(data);
}
static void pipewire_capture_get_defaults(obs_data_t *settings)
{
obs_pipewire_get_defaults(settings);
}
static obs_properties_t *pipewire_capture_get_properties(void *data)
{
enum obs_pw_capture_type capture_type;
obs_pipewire_data *obs_pw = data;
capture_type = obs_pipewire_get_capture_type(obs_pw);
switch (capture_type) {
case DESKTOP_CAPTURE:
return obs_pipewire_get_properties(data,
"PipeWireSelectMonitor");
case WINDOW_CAPTURE:
return obs_pipewire_get_properties(data,
"PipeWireSelectWindow");
default:
return NULL;
}
}
static void pipewire_capture_update(void *data, obs_data_t *settings)
{
obs_pipewire_update(data, settings);
}
static void pipewire_capture_show(void *data)
{
obs_pipewire_show(data);
}
static void pipewire_capture_hide(void *data)
{
obs_pipewire_hide(data);
}
static uint32_t pipewire_capture_get_width(void *data)
{
return obs_pipewire_get_width(data);
}
static uint32_t pipewire_capture_get_height(void *data)
{
return obs_pipewire_get_height(data);
}
static void pipewire_capture_video_render(void *data, gs_effect_t *effect)
{
obs_pipewire_video_render(data, effect);
}
void pipewire_capture_load(void)
{
// Desktop capture
const struct obs_source_info pipewire_desktop_capture_info = {
.id = "pipewire-desktop-capture-source",
.type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_VIDEO,
.get_name = pipewire_desktop_capture_get_name,
.create = pipewire_desktop_capture_create,
.destroy = pipewire_capture_destroy,
.get_defaults = pipewire_capture_get_defaults,
.get_properties = pipewire_capture_get_properties,
.update = pipewire_capture_update,
.show = pipewire_capture_show,
.hide = pipewire_capture_hide,
.get_width = pipewire_capture_get_width,
.get_height = pipewire_capture_get_height,
.video_render = pipewire_capture_video_render,
.icon_type = OBS_ICON_TYPE_DESKTOP_CAPTURE,
};
obs_register_source(&pipewire_desktop_capture_info);
// Window capture
const struct obs_source_info pipewire_window_capture_info = {
.id = "pipewire-window-capture-source",
.type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_VIDEO,
.get_name = pipewire_window_capture_get_name,
.create = pipewire_window_capture_create,
.destroy = pipewire_capture_destroy,
.get_defaults = pipewire_capture_get_defaults,
.get_properties = pipewire_capture_get_properties,
.update = pipewire_capture_update,
.show = pipewire_capture_show,
.hide = pipewire_capture_hide,
.get_width = pipewire_capture_get_width,
.get_height = pipewire_capture_get_height,
.video_render = pipewire_capture_video_render,
.icon_type = OBS_ICON_TYPE_WINDOW_CAPTURE,
};
obs_register_source(&pipewire_window_capture_info);
pw_init(NULL, NULL);
}
void pipewire_capture_unload(void)
{
pw_deinit();
}
+24
View File
@@ -0,0 +1,24 @@
/* pipewire-capture.h
*
* Copyright 2020 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
void pipewire_capture_load(void);
void pipewire_capture_unload(void);
File diff suppressed because it is too large Load Diff
+53
View File
@@ -0,0 +1,53 @@
/* pipewire.h
*
* Copyright 2020 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <obs-module.h>
#include <pipewire/pipewire.h>
typedef struct _obs_pipewire_data obs_pipewire_data;
enum obs_pw_capture_type {
DESKTOP_CAPTURE = 1,
WINDOW_CAPTURE = 2,
};
void *obs_pipewire_create(enum obs_pw_capture_type capture_type,
obs_data_t *settings, obs_source_t *source);
void obs_pipewire_destroy(obs_pipewire_data *obs_pw);
void obs_pipewire_get_defaults(obs_data_t *settings);
obs_properties_t *obs_pipewire_get_properties(obs_pipewire_data *obs_pw,
const char *reload_string_id);
void obs_pipewire_update(obs_pipewire_data *obs_pw, obs_data_t *settings);
void obs_pipewire_show(obs_pipewire_data *obs_pw);
void obs_pipewire_hide(obs_pipewire_data *obs_pw);
uint32_t obs_pipewire_get_width(obs_pipewire_data *obs_pw);
uint32_t obs_pipewire_get_height(obs_pipewire_data *obs_pw);
void obs_pipewire_video_render(obs_pipewire_data *obs_pw, gs_effect_t *effect);
enum obs_pw_capture_type
obs_pipewire_get_capture_type(obs_pipewire_data *obs_pw);