mirror of
https://github.com/obsproject/obs-studio.git
synced 2026-09-24 23:31:36 +08:00
Merge pull request #4287 from GeorgesStavracas/gbsneto/pipewire
Wayland / PipeWire capture
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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" ..
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
Reference in New Issue
Block a user