* update pipewire to 1:1.2.1-1

This commit is contained in:
Alexander Baldeck 2024-09-15 20:46:37 +02:00
parent 7a1b02f84d
commit 190ab44c95
7 changed files with 349 additions and 1249 deletions

248
pipewire/.SRCINFO Normal file
View File

@ -0,0 +1,248 @@
pkgbase = pipewire
pkgdesc = Low-latency audio/video router and processor
pkgver = 1.2.1
pkgrel = 1
epoch = 1
url = https://pipewire.org
arch = x86_64
license = MIT
checkdepends = desktop-file-utils
checkdepends = openal
makedepends = alsa-lib
makedepends = avahi
makedepends = bluez-libs
makedepends = dbus
makedepends = doxygen
makedepends = git
makedepends = glib2
makedepends = glib2-devel
makedepends = graphviz
makedepends = gst-plugins-base
makedepends = jack2
makedepends = libcamera
makedepends = libcanberra
makedepends = libfdk-aac
makedepends = libffado
makedepends = libfreeaptx
makedepends = liblc3
makedepends = libldac
makedepends = libmysofa
makedepends = libpulse
makedepends = libsndfile
makedepends = libusb
makedepends = libx11
makedepends = libxfixes
makedepends = lilv
makedepends = meson
makedepends = ncurses
makedepends = opus
makedepends = python-docutils
makedepends = readline
makedepends = roc-toolkit
makedepends = rtkit
makedepends = sbc
makedepends = sdl2
makedepends = systemd
makedepends = valgrind
makedepends = webrtc-audio-processing-1
source = git+https://gitlab.freedesktop.org/pipewire/pipewire.git#tag=1.2.1
b2sums = c956faaa5caeb95ea9c802744c0584f25b251f3f7d5460f938aafe75def298df136824a9aff5ce7ecaad6241db51e88a19f39a89aa9e30e2256bd8cee21dbcbb
pkgname = pipewire
install = pipewire.install
license = MIT
license = LGPL-2.1-or-later
depends = libpipewire=1:1.2.1-1
depends = gcc-libs
depends = glibc
depends = libpipewire-0.3.so
depends = libcamera-base.so
depends = libcamera.so
depends = libdbus-1.so
depends = libglib-2.0.so
depends = libncursesw.so
depends = libreadline.so
depends = libsystemd.so
depends = libudev.so
optdepends = gst-plugin-pipewire: GStreamer plugin
optdepends = pipewire-alsa: ALSA configuration
optdepends = pipewire-audio: Audio support
optdepends = pipewire-docs: Documentation
optdepends = pipewire-ffado: FireWire support
optdepends = pipewire-jack-client: PipeWire as JACK client
optdepends = pipewire-jack: JACK replacement
optdepends = pipewire-pulse: PulseAudio replacement
optdepends = pipewire-roc: ROC streaming
optdepends = pipewire-session-manager: Session manager
optdepends = pipewire-v4l2: V4L2 interceptor
optdepends = pipewire-x11-bell: X11 bell
optdepends = pipewire-zeroconf: Zeroconf support
optdepends = realtime-privileges: realtime privileges with rt module
optdepends = rtkit: realtime privileges with rtkit module
pkgname = libpipewire
pkgdesc = Low-latency audio/video router and processor - client library
depends = glibc
depends = gcc-libs
provides = libpipewire-0.3.so
pkgname = alsa-card-profiles
pkgdesc = Low-latency audio/video router and processor - ALSA card profiles
license = LGPL-2.1-or-later
pkgname = pipewire-docs
pkgdesc = Low-latency audio/video router and processor - documentation
pkgname = pipewire-audio
pkgdesc = Low-latency audio/video router and processor - Audio support
depends = alsa-card-profiles
depends = dbus
depends = gcc-libs
depends = glib2
depends = glibc
depends = libpipewire-0.3.so
depends = libasound.so
depends = libbluetooth.so
depends = libfdk-aac.so
depends = libfreeaptx.so
depends = liblc3.so
depends = libldacBT_enc.so
depends = liblilv-0.so
depends = libmysofa.so
depends = libopus.so
depends = libsbc.so
depends = libsndfile.so
depends = libusb-1.0.so
depends = libwebrtc-audio-processing-1.so
depends = pipewire
depends = systemd-libs
pkgname = pipewire-alsa
pkgdesc = Low-latency audio/video router and processor - ALSA configuration
depends = pipewire
depends = pipewire-audio
depends = pipewire-session-manager
provides = pulseaudio-alsa
conflicts = pulseaudio-alsa
pkgname = pipewire-ffado
pkgdesc = Low-latency audio/video router and processor - FireWire support
depends = glibc
depends = libffado.so
depends = libpipewire-0.3.so
depends = pipewire
depends = pipewire-audio
pkgname = pipewire-jack-client
pkgdesc = Low-latency audio/video router and processor - PipeWire as JACK client
depends = gcc-libs
depends = glibc
depends = libpipewire-0.3.so
depends = libdbus-1.so
depends = libjack.so
depends = pipewire
depends = pipewire-audio
conflicts = pipewire-jack
pkgname = pipewire-jack
pkgdesc = Low-latency audio/video router and processor - JACK replacement
license = MIT
license = GPL-2.0-only
license = LGPL-2.1-or-later
depends = glibc
depends = libpipewire-0.3.so
depends = pipewire
depends = pipewire-audio
depends = pipewire-session-manager
depends = sh
optdepends = jack-example-tools: for official JACK example-clients and tools
provides = jack
provides = libjack.so
provides = libjacknet.so
provides = libjackserver.so
conflicts = jack
conflicts = jack2
conflicts = pipewire-jack-client
pkgname = pipewire-pulse
pkgdesc = Low-latency audio/video router and processor - PulseAudio replacement
install = pipewire-pulse.install
depends = dbus
depends = dconf
depends = gcc-libs
depends = glibc
depends = libpipewire-0.3.so
depends = libavahi-client.so
depends = libavahi-common.so
depends = libglib-2.0.so
depends = libpulse.so
depends = pipewire
depends = pipewire-audio
depends = pipewire-session-manager
depends = systemd-libs
provides = pulse-native-provider
provides = pulseaudio
provides = pulseaudio-bluetooth
conflicts = pulseaudio
conflicts = pulseaudio-bluetooth
pkgname = pipewire-roc
pkgdesc = Low-latency audio/video router and processor - ROC streaming support
depends = gcc-libs
depends = glibc
depends = libpipewire-0.3.so
depends = libroc.so
depends = pipewire
depends = pipewire-audio
depends = roc-toolkit
pkgname = gst-plugin-pipewire
pkgdesc = Multimedia graph framework - pipewire plugin
depends = gcc-libs
depends = glib2
depends = glibc
depends = gst-plugins-base-libs
depends = gstreamer
depends = libpipewire-0.3.so
depends = pipewire
depends = pipewire-session-manager
pkgname = pipewire-zeroconf
pkgdesc = Low-latency audio/video router and processor - Zeroconf support
depends = gcc-libs
depends = glibc
depends = libpipewire-0.3.so
depends = libavahi-client.so
depends = libavahi-common.so
depends = openssl
depends = opus
depends = pipewire
depends = pipewire-audio
pkgname = pipewire-v4l2
pkgdesc = Low-latency audio/video router and processor - V4L2 interceptor
depends = glibc
depends = libpipewire-0.3.so
depends = pipewire
depends = pipewire-session-manager
depends = sh
pkgname = pipewire-x11-bell
pkgdesc = Low-latency audio/video router and processor - X11 bell
depends = glibc
depends = libpipewire-0.3.so
depends = libcanberra.so
depends = libx11
depends = libxfixes
depends = pipewire
depends = pipewire-audio
pkgname = pipewire-session-manager
pkgdesc = Session manager for PipeWire (default provider)
license = CC0-1.0
depends = wireplumber
pkgname = pulse-native-provider
pkgdesc = PulseAudio sound server (default provider)
license = CC0-1.0
depends = pipewire-pulse

4
pipewire/.nvchecker.toml Normal file
View File

@ -0,0 +1,4 @@
[pipewire]
source = "git"
git = "https://gitlab.freedesktop.org/pipewire/pipewire.git"
include_regex = '\d+\.\d+\.[1-7]?\d'

View File

@ -1,939 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Robert Mader <robert.mader@collabora.com>
Date: Fri, 2 Feb 2024 02:20:29 +0100
Subject: [PATCH] gst: Add support for DMA_DRM / explicit modifiers
Gstreamer 1.24 added and largely switched to a new, modifier aware
DMABuf API. Unfortunately that breaks the existing DMABuf support in the
PW Gst element.
Add support for the new API.
---
meson.build | 8 +
src/gst/gstpipewireformat.c | 521 +++++++++++++++++++++++++-----------
src/gst/gstpipewireformat.h | 4 +-
src/gst/gstpipewiresink.c | 2 +-
src/gst/gstpipewiresrc.c | 46 +++-
src/gst/gstpipewiresrc.h | 5 +
6 files changed, 417 insertions(+), 169 deletions(-)
diff --git a/meson.build b/meson.build
index 0ea256e9bcbb..61cfa3eac325 100644
--- a/meson.build
+++ b/meson.build
@@ -361,26 +361,34 @@ gst_deps_def = {
}
gst_dep = []
+gst_dma_drm_found = false
foreach depname, kwargs: gst_deps_def
dep = dependency(depname, required: gst_option, kwargs: kwargs)
summary({depname: dep.found()}, bool_yn: true, section: 'GStreamer modules')
if not dep.found()
# Beware, there's logic below depending on the array clear here!
gst_dep = []
if get_option('gstreamer-device-provider').enabled()
error('`gstreamer-device-provider` is enabled but `@0@` was not found.'.format(depname))
endif
break
endif
gst_dep += [dep]
+
+ if depname == 'gstreamer-allocators-1.0' and dep.version().version_compare('>= 1.23.1')
+ gst_dma_drm_found = true
+ endif
endforeach
# This code relies on the array being empty if any dependency was not found
gst_dp_found = gst_dep.length() > 0
summary({'gstreamer-device-provider': gst_dp_found}, bool_yn: true, section: 'Backend')
cdata.set('HAVE_GSTREAMER_DEVICE_PROVIDER', get_option('gstreamer-device-provider').allowed())
+summary({'gstreamer DMA_DRM support': gst_dma_drm_found}, bool_yn: true, section: 'Backend')
+cdata.set('HAVE_GSTREAMER_DMA_DRM', gst_dma_drm_found)
+
webrtc_dep = dependency('webrtc-audio-processing-1',
version : ['>= 1.2' ],
required : false)
diff --git a/src/gst/gstpipewireformat.c b/src/gst/gstpipewireformat.c
index b16f7b1cf002..ff1752a06565 100644
--- a/src/gst/gstpipewireformat.c
+++ b/src/gst/gstpipewireformat.c
@@ -2,21 +2,27 @@
/* SPDX-FileCopyrightText: Copyright © 2018 Wim Taymans */
/* SPDX-License-Identifier: MIT */
+#include "config.h"
+
#include <stdio.h>
#include <gst/gst.h>
#include <gst/allocators/gstdmabuf.h>
#include <gst/video/video.h>
#include <gst/audio/audio.h>
#include <spa/utils/string.h>
#include <spa/utils/type.h>
#include <spa/param/video/format-utils.h>
#include <spa/param/audio/format-utils.h>
-#include <spa/pod/builder.h>
+#include <spa/pod/dynamic.h>
#include "gstpipewireformat.h"
+#ifndef DRM_FORMAT_INVALID
+#define DRM_FORMAT_INVALID 0
+#endif
+
#ifndef DRM_FORMAT_MOD_INVALID
#define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1)
#endif
@@ -169,9 +175,7 @@ static const uint32_t audio_format_map[] = {
};
typedef struct {
- struct spa_pod_builder b;
const struct media_type *type;
- uint32_t id;
const GstCapsFeatures *cf;
const GstStructure *cs;
GPtrArray *array;
@@ -358,89 +362,221 @@ get_range_type2 (const GValue *v1, const GValue *v2)
return SPA_CHOICE_Range;
}
-static gboolean
-handle_video_fields (ConvertData *d)
+static void
+add_limits (struct spa_pod_dynamic_builder *b, ConvertData *d)
{
- const GValue *value, *value2;
- int i;
struct spa_pod_choice *choice;
struct spa_pod_frame f;
+ const GValue *value, *value2;
+ int i;
- value = gst_structure_get_value (d->cs, "format");
- if (value) {
- const char *v;
- int idx;
- for (i = 0; (v = get_nth_string (value, i)); i++) {
- if (i == 0) {
- spa_pod_builder_prop (&d->b, SPA_FORMAT_VIDEO_format, 0);
- spa_pod_builder_push_choice(&d->b, &f, get_range_type (value), 0);
- }
-
- idx = gst_video_format_from_string (v);
- if (idx != GST_VIDEO_FORMAT_UNKNOWN && idx < (int)SPA_N_ELEMENTS (video_format_map))
- spa_pod_builder_id (&d->b, video_format_map[idx]);
- }
- if (i > 0) {
- choice = spa_pod_builder_pop(&d->b, &f);
- if (i == 1)
- choice->body.type = SPA_CHOICE_None;
- }
- }
value = gst_structure_get_value (d->cs, "width");
value2 = gst_structure_get_value (d->cs, "height");
if (value && value2) {
struct spa_rectangle v;
for (i = 0; get_nth_rectangle (value, value2, i, &v); i++) {
if (i == 0) {
- spa_pod_builder_prop (&d->b, SPA_FORMAT_VIDEO_size, 0);
- spa_pod_builder_push_choice(&d->b, &f, get_range_type2 (value, value2), 0);
+ spa_pod_builder_prop (&b->b, SPA_FORMAT_VIDEO_size, 0);
+ spa_pod_builder_push_choice(&b->b, &f, get_range_type2 (value, value2), 0);
}
- spa_pod_builder_rectangle (&d->b, v.width, v.height);
+ spa_pod_builder_rectangle (&b->b, v.width, v.height);
}
if (i > 0) {
- choice = spa_pod_builder_pop(&d->b, &f);
+ choice = spa_pod_builder_pop(&b->b, &f);
if (i == 1)
choice->body.type = SPA_CHOICE_None;
}
}
value = gst_structure_get_value (d->cs, "framerate");
if (value) {
struct spa_fraction v;
for (i = 0; get_nth_fraction (value, i, &v); i++) {
if (i == 0) {
- spa_pod_builder_prop (&d->b, SPA_FORMAT_VIDEO_framerate, 0);
- spa_pod_builder_push_choice(&d->b, &f, get_range_type (value), 0);
+ spa_pod_builder_prop (&b->b, SPA_FORMAT_VIDEO_framerate, 0);
+ spa_pod_builder_push_choice(&b->b, &f, get_range_type (value), 0);
}
- spa_pod_builder_fraction (&d->b, v.num, v.denom);
+ spa_pod_builder_fraction (&b->b, v.num, v.denom);
}
if (i > 0) {
- choice = spa_pod_builder_pop(&d->b, &f);
+ choice = spa_pod_builder_pop(&b->b, &f);
if (i == 1)
choice->body.type = SPA_CHOICE_None;
}
}
value = gst_structure_get_value (d->cs, "max-framerate");
if (value) {
struct spa_fraction v;
for (i = 0; get_nth_fraction (value, i, &v); i++) {
if (i == 0) {
- spa_pod_builder_prop (&d->b, SPA_FORMAT_VIDEO_maxFramerate, 0);
- spa_pod_builder_push_choice(&d->b, &f, get_range_type (value), 0);
+ spa_pod_builder_prop (&b->b, SPA_FORMAT_VIDEO_maxFramerate, 0);
+ spa_pod_builder_push_choice(&b->b, &f, get_range_type (value), 0);
}
- spa_pod_builder_fraction (&d->b, v.num, v.denom);
+ spa_pod_builder_fraction (&b->b, v.num, v.denom);
}
if (i > 0) {
- choice = spa_pod_builder_pop(&d->b, &f);
+ choice = spa_pod_builder_pop(&b->b, &f);
if (i == 1)
choice->body.type = SPA_CHOICE_None;
}
}
- return TRUE;
+}
+
+static void
+add_video_format (gpointer format_ptr,
+ gpointer modifiers_ptr,
+ gpointer user_data)
+{
+ uint32_t format = GPOINTER_TO_UINT (format_ptr);
+ GHashTable *modifiers = modifiers_ptr;
+ ConvertData *d = user_data;
+ struct spa_pod_dynamic_builder b;
+ struct spa_pod_frame f;
+
+ spa_pod_dynamic_builder_init (&b, NULL, 0, 1024);
+
+ spa_pod_builder_push_object (&b.b, &f, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
+
+ spa_pod_builder_prop (&b.b, SPA_FORMAT_mediaType, 0);
+ spa_pod_builder_id(&b.b, d->type->media_type);
+
+ spa_pod_builder_prop (&b.b, SPA_FORMAT_mediaSubtype, 0);
+ spa_pod_builder_id(&b.b, d->type->media_subtype);
+
+ spa_pod_builder_prop (&b.b, SPA_FORMAT_VIDEO_format, 0);
+ spa_pod_builder_id (&b.b, format);
+
+ if (g_hash_table_size (modifiers) > 0) {
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_hash_table_iter_init (&iter, modifiers);
+ if (g_hash_table_size (modifiers) > 1) {
+ struct spa_pod_frame f2;
+
+ spa_pod_builder_prop (&b.b, SPA_FORMAT_VIDEO_modifier,
+ (SPA_POD_PROP_FLAG_MANDATORY | SPA_POD_PROP_FLAG_DONT_FIXATE));
+ spa_pod_builder_push_choice (&b.b, &f2, SPA_CHOICE_Enum, 0);
+ g_hash_table_iter_next (&iter, &key, &value);
+ spa_pod_builder_long (&b.b, (uint64_t) key);
+ do {
+ spa_pod_builder_long (&b.b, (uint64_t) key);
+ } while (g_hash_table_iter_next (&iter, &key, &value));
+ spa_pod_builder_pop (&b.b, &f2);
+ } else {
+ g_hash_table_iter_next (&iter, &key, &value);
+ spa_pod_builder_prop (&b.b, SPA_FORMAT_VIDEO_modifier,
+ SPA_POD_PROP_FLAG_MANDATORY);
+ spa_pod_builder_long (&b.b, (uint64_t) key);
+ }
+ }
+
+ add_limits (&b, d);
+
+ g_ptr_array_add (d->array, spa_pod_builder_pop (&b.b, &f));
+}
+
+static void
+handle_video_fields (ConvertData *d)
+{
+ g_autoptr (GHashTable) formats = NULL;
+ const GValue *value;
+ gboolean dmabuf_caps;
+ int i;
+
+ formats = g_hash_table_new_full (NULL, NULL, NULL,
+ (GDestroyNotify) g_hash_table_unref);
+ dmabuf_caps = (d->cf &&
+ gst_caps_features_contains (d->cf,
+ GST_CAPS_FEATURE_MEMORY_DMABUF));
+
+ value = gst_structure_get_value (d->cs, "format");
+ if (value) {
+ const char *v;
+
+ for (i = 0; (v = get_nth_string (value, i)); i++) {
+ int idx;
+
+ idx = gst_video_format_from_string (v);
+#ifdef HAVE_GSTREAMER_DMA_DRM
+ if (dmabuf_caps && idx == GST_VIDEO_FORMAT_DMA_DRM) {
+ const GValue *value2;
+
+ value2 = gst_structure_get_value (d->cs, "drm-format");
+ if (value2) {
+ const char *v2;
+ int j;
+
+ for (j = 0; (v2 = get_nth_string (value2, j)); j++) {
+ uint32_t fourcc;
+ uint64_t mod;
+ int idx2;
+
+ fourcc = gst_video_dma_drm_fourcc_from_string (v2, &mod);
+ idx2 = gst_video_dma_drm_fourcc_to_format (fourcc);
+
+ if (idx2 != GST_VIDEO_FORMAT_UNKNOWN &&
+ idx2 < (int)SPA_N_ELEMENTS (video_format_map)) {
+ GHashTable *modifiers =
+ g_hash_table_lookup (formats,
+ GINT_TO_POINTER (video_format_map[idx2]));
+ if (!modifiers) {
+ modifiers = g_hash_table_new (NULL, NULL);
+ g_hash_table_insert (formats,
+ GINT_TO_POINTER (video_format_map[idx2]),
+ modifiers);
+ }
+
+ g_hash_table_add (modifiers, GINT_TO_POINTER (mod));
+ }
+ }
+ }
+ } else
+#endif
+ if (idx != GST_VIDEO_FORMAT_UNKNOWN &&
+ idx < (int)SPA_N_ELEMENTS (video_format_map)) {
+ GHashTable *modifiers =
+ g_hash_table_lookup (formats,
+ GINT_TO_POINTER (video_format_map[idx]));
+ if (!modifiers) {
+ modifiers = g_hash_table_new (NULL, NULL);
+ g_hash_table_insert (formats,
+ GINT_TO_POINTER (video_format_map[idx]),
+ modifiers);
+ }
+
+ if (dmabuf_caps) {
+ g_hash_table_add (modifiers, GINT_TO_POINTER (DRM_FORMAT_MOD_LINEAR));
+ g_hash_table_add (modifiers, GINT_TO_POINTER (DRM_FORMAT_MOD_INVALID));
+ }
+ }
+ }
+ }
+
+ if (g_hash_table_size (formats) > 0) {
+ g_hash_table_foreach (formats, add_video_format, d);
+ } else if (!dmabuf_caps) {
+ struct spa_pod_dynamic_builder b;
+ struct spa_pod_frame f;
+
+ spa_pod_dynamic_builder_init (&b, NULL, 0, 1024);
+
+ spa_pod_builder_push_object (&b.b, &f, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
+
+ spa_pod_builder_prop (&b.b, SPA_FORMAT_mediaType, 0);
+ spa_pod_builder_id(&b.b, d->type->media_type);
+
+ spa_pod_builder_prop (&b.b, SPA_FORMAT_mediaSubtype, 0);
+ spa_pod_builder_id(&b.b, d->type->media_subtype);
+
+ add_limits (&b, d);
+
+ g_ptr_array_add (d->array, spa_pod_builder_pop (&b.b, &f));
+ }
}
static void
@@ -481,237 +617,207 @@ set_default_channels (struct spa_pod_builder *b, uint32_t channels)
SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, channels, position), 0);
}
-static gboolean
+static void
handle_audio_fields (ConvertData *d)
{
const GValue *value;
+ struct spa_pod_dynamic_builder b;
struct spa_pod_choice *choice;
- struct spa_pod_frame f;
+ struct spa_pod_frame f, f0;
int i = 0;
+ spa_pod_dynamic_builder_init (&b, NULL, 0, 1024);
+
+ spa_pod_builder_push_object (&b.b, &f0, SPA_TYPE_OBJECT_Format,
+ SPA_PARAM_EnumFormat);
+
+ spa_pod_builder_prop (&b.b, SPA_FORMAT_mediaType, 0);
+ spa_pod_builder_id(&b.b, d->type->media_type);
+
+ spa_pod_builder_prop (&b.b, SPA_FORMAT_mediaSubtype, 0);
+ spa_pod_builder_id(&b.b, d->type->media_subtype);
+
value = gst_structure_get_value (d->cs, "format");
if (value) {
const char *v;
int idx;
for (i = 0; (v = get_nth_string (value, i)); i++) {
if (i == 0) {
- spa_pod_builder_prop (&d->b, SPA_FORMAT_AUDIO_format, 0);
- spa_pod_builder_push_choice(&d->b, &f, get_range_type (value), 0);
+ spa_pod_builder_prop (&b.b, SPA_FORMAT_AUDIO_format, 0);
+ spa_pod_builder_push_choice(&b.b, &f, get_range_type (value), 0);
}
idx = gst_audio_format_from_string (v);
if (idx < (int)SPA_N_ELEMENTS (audio_format_map))
- spa_pod_builder_id (&d->b, audio_format_map[idx]);
+ spa_pod_builder_id (&b.b, audio_format_map[idx]);
}
if (i > 0) {
- choice = spa_pod_builder_pop(&d->b, &f);
+ choice = spa_pod_builder_pop(&b.b, &f);
if (i == 1)
choice->body.type = SPA_CHOICE_None;
}
} else if (strcmp(d->type->name, "audio/x-mulaw") == 0) {
- spa_pod_builder_prop (&d->b, SPA_FORMAT_AUDIO_format, 0);
- spa_pod_builder_id (&d->b, SPA_AUDIO_FORMAT_ULAW);
+ spa_pod_builder_prop (&b.b, SPA_FORMAT_AUDIO_format, 0);
+ spa_pod_builder_id (&b.b, SPA_AUDIO_FORMAT_ULAW);
} else if (strcmp(d->type->name, "audio/x-alaw") == 0) {
- spa_pod_builder_prop (&d->b, SPA_FORMAT_AUDIO_format, 0);
- spa_pod_builder_id (&d->b, SPA_AUDIO_FORMAT_ALAW);
+ spa_pod_builder_prop (&b.b, SPA_FORMAT_AUDIO_format, 0);
+ spa_pod_builder_id (&b.b, SPA_AUDIO_FORMAT_ALAW);
} else if (strcmp(d->type->name, "audio/mpeg") == 0) {
- spa_pod_builder_prop (&d->b, SPA_FORMAT_AUDIO_format, 0);
- spa_pod_builder_id (&d->b, SPA_AUDIO_FORMAT_ENCODED);
+ spa_pod_builder_prop (&b.b, SPA_FORMAT_AUDIO_format, 0);
+ spa_pod_builder_id (&b.b, SPA_AUDIO_FORMAT_ENCODED);
} else if (strcmp(d->type->name, "audio/x-flac") == 0) {
- spa_pod_builder_prop (&d->b, SPA_FORMAT_AUDIO_format, 0);
- spa_pod_builder_id (&d->b, SPA_AUDIO_FORMAT_ENCODED);
+ spa_pod_builder_prop (&b.b, SPA_FORMAT_AUDIO_format, 0);
+ spa_pod_builder_id (&b.b, SPA_AUDIO_FORMAT_ENCODED);
}
#if 0
value = gst_structure_get_value (d->cs, "layout");
if (value) {
const char *v;
for (i = 0; (v = get_nth_string (value, i)); i++) {
enum spa_audio_layout layout;
if (spa_streq(v, "interleaved"))
layout = SPA_AUDIO_LAYOUT_INTERLEAVED;
else if (spa_streq(v, "non-interleaved"))
layout = SPA_AUDIO_LAYOUT_NON_INTERLEAVED;
else
break;
if (i == 0) {
- spa_pod_builder_prop (&d->b, SPA_FORMAT_AUDIO_layout, 0);
- spa_pod_builder_push_choice(&d->b, &f, get_range_type (value), 0);
+ spa_pod_builder_prop (&b.b, SPA_FORMAT_AUDIO_layout, 0);
+ spa_pod_builder_push_choice(&b.b, &f, get_range_type (value), 0);
}
- spa_pod_builder_id (&d->b, layout);
+ spa_pod_builder_id (&b.b, layout);
}
if (i > 0) {
- choice = spa_pod_builder_pop(&d->b, &f);
+ choice = spa_pod_builder_pop(&b.b, &f);
if (i == 1)
choice->body.type = SPA_CHOICE_None;
}
}
#endif
value = gst_structure_get_value (d->cs, "rate");
if (value) {
int v;
for (i = 0; get_nth_int (value, i, &v); i++) {
if (i == 0) {
- spa_pod_builder_prop (&d->b, SPA_FORMAT_AUDIO_rate, 0);
- spa_pod_builder_push_choice(&d->b, &f, get_range_type (value), 0);
+ spa_pod_builder_prop (&b.b, SPA_FORMAT_AUDIO_rate, 0);
+ spa_pod_builder_push_choice(&b.b, &f, get_range_type (value), 0);
}
- spa_pod_builder_int (&d->b, v);
+ spa_pod_builder_int (&b.b, v);
}
if (i > 0) {
- choice = spa_pod_builder_pop(&d->b, &f);
+ choice = spa_pod_builder_pop(&b.b, &f);
if (i == 1)
choice->body.type = SPA_CHOICE_None;
}
}
value = gst_structure_get_value (d->cs, "channels");
if (value) {
int v;
for (i = 0; get_nth_int (value, i, &v); i++) {
if (i == 0) {
- spa_pod_builder_prop (&d->b, SPA_FORMAT_AUDIO_channels, 0);
- spa_pod_builder_push_choice(&d->b, &f, get_range_type (value), 0);
+ spa_pod_builder_prop (&b.b, SPA_FORMAT_AUDIO_channels, 0);
+ spa_pod_builder_push_choice(&b.b, &f, get_range_type (value), 0);
}
- spa_pod_builder_int (&d->b, v);
+ spa_pod_builder_int (&b.b, v);
}
if (i > 0) {
- choice = spa_pod_builder_pop(&d->b, &f);
+ choice = spa_pod_builder_pop(&b.b, &f);
if (i == 1) {
choice->body.type = SPA_CHOICE_None;
- set_default_channels (&d->b, v);
+ set_default_channels (&b.b, v);
}
}
}
- return TRUE;
+
+ g_ptr_array_add (d->array, spa_pod_builder_pop (&b.b, &f0));
}
-static int
-builder_overflow (void *event_data, uint32_t size)
+static void
+handle_fields (ConvertData *d)
{
- struct spa_pod_builder *b = event_data;
- b->size = SPA_ROUND_UP_N (size, 512);
- b->data = realloc (b->data, b->size);
- if (b->data == NULL)
- return -errno;
- return 0;
-}
-
-static const struct spa_pod_builder_callbacks builder_callbacks = {
- SPA_VERSION_POD_BUILDER_CALLBACKS,
- .overflow = builder_overflow
-};
-
-static struct spa_pod *
-convert_1 (ConvertData *d)
-{
- struct spa_pod_frame f;
-
if (!(d->type = find_media_types (gst_structure_get_name (d->cs))))
- return NULL;
-
- spa_pod_builder_set_callbacks(&d->b, &builder_callbacks, &d->b);
-
- spa_pod_builder_push_object (&d->b, &f, SPA_TYPE_OBJECT_Format, d->id);
-
- spa_pod_builder_prop (&d->b, SPA_FORMAT_mediaType, 0);
- spa_pod_builder_id(&d->b, d->type->media_type);
-
- spa_pod_builder_prop (&d->b, SPA_FORMAT_mediaSubtype, 0);
- spa_pod_builder_id(&d->b, d->type->media_subtype);
-
- if (d->cf && gst_caps_features_contains (d->cf, GST_CAPS_FEATURE_MEMORY_DMABUF)) {
- struct spa_pod_frame f2;
-
- spa_pod_builder_prop (&d->b, SPA_FORMAT_VIDEO_modifier,
- (SPA_POD_PROP_FLAG_MANDATORY | SPA_POD_PROP_FLAG_DONT_FIXATE));
- spa_pod_builder_push_choice (&d->b, &f2, SPA_CHOICE_Enum, 0);
- spa_pod_builder_long (&d->b, DRM_FORMAT_MOD_INVALID);
- spa_pod_builder_long (&d->b, DRM_FORMAT_MOD_INVALID);
- spa_pod_builder_long (&d->b, DRM_FORMAT_MOD_LINEAR);
- spa_pod_builder_pop (&d->b, &f2);
- }
+ return;
if (d->type->media_type == SPA_MEDIA_TYPE_video)
handle_video_fields (d);
else if (d->type->media_type == SPA_MEDIA_TYPE_audio)
handle_audio_fields (d);
-
- spa_pod_builder_pop (&d->b, &f);
-
- return SPA_PTROFF (d->b.data, 0, struct spa_pod);
-}
-
-struct spa_pod *
-gst_caps_to_format (GstCaps *caps, guint index, uint32_t id)
-{
- ConvertData d;
- struct spa_pod *res;
-
- g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
- g_return_val_if_fail (gst_caps_is_fixed (caps), NULL);
-
- spa_zero (d);
- d.cf = gst_caps_get_features (caps, index);
- d.cs = gst_caps_get_structure (caps, index);
- d.id = id;
-
- res = convert_1 (&d);
-
- return res;
}
static gboolean
-foreach_func (GstCapsFeatures *features,
- GstStructure *structure,
- ConvertData *d)
+foreach_func_dmabuf (GstCapsFeatures *features,
+ GstStructure *structure,
+ ConvertData *d)
{
- struct spa_pod *fmt;
- int idx;
+ if (!features || !gst_caps_features_contains (features, GST_CAPS_FEATURE_MEMORY_DMABUF))
+ return TRUE;
- spa_zero(d->b);
d->cf = features;
d->cs = structure;
- if (d->cf && gst_caps_features_contains (d->cf, GST_CAPS_FEATURE_MEMORY_DMABUF))
- idx = 0;
- else
- idx = -1;
+ handle_fields (d);
- if ((fmt = convert_1 (d)))
- g_ptr_array_insert (d->array, idx, fmt);
+ return TRUE;
+}
+
+static gboolean
+foreach_func_no_dmabuf (GstCapsFeatures *features,
+ GstStructure *structure,
+ ConvertData *d)
+{
+ if (features && gst_caps_features_contains (features, GST_CAPS_FEATURE_MEMORY_DMABUF))
+ return TRUE;
+
+ d->cf = features;
+ d->cs = structure;
+
+ handle_fields (d);
return TRUE;
}
GPtrArray *
-gst_caps_to_format_all (GstCaps *caps, uint32_t id)
+gst_caps_to_format_all (GstCaps *caps)
{
ConvertData d;
- spa_zero (d);
- d.id = id;
d.array = g_ptr_array_new_full (gst_caps_get_size (caps), (GDestroyNotify)g_free);
- gst_caps_foreach (caps, (GstCapsForeachFunc) foreach_func, &d);
+ gst_caps_foreach (caps, (GstCapsForeachFunc) foreach_func_dmabuf, &d);
+ gst_caps_foreach (caps, (GstCapsForeachFunc) foreach_func_no_dmabuf, &d);
return d.array;
}
typedef const char *(*id_to_string_func)(uint32_t id);
static const char *video_id_to_string(uint32_t id)
{
int idx;
if ((idx = find_index(video_format_map, SPA_N_ELEMENTS(video_format_map), id)) == -1)
return NULL;
return gst_video_format_to_string(idx);
}
+#ifdef HAVE_GSTREAMER_DMA_DRM
+static char *video_id_to_dma_drm_fourcc(uint32_t id, uint64_t mod)
+{
+ int idx;
+ guint32 fourcc;
+ if ((idx = find_index(video_format_map, SPA_N_ELEMENTS(video_format_map), id)) == -1)
+ return NULL;
+ fourcc = gst_video_dma_drm_fourcc_from_format(idx);
+ return gst_video_dma_drm_fourcc_to_string(fourcc, mod);
+}
+#endif
+
static const char *audio_id_to_string(uint32_t id)
{
int idx;
@@ -762,6 +868,109 @@ handle_id_prop (const struct spa_pod_prop *prop, const char *key, id_to_string_f
}
}
+static void
+handle_dmabuf_prop (const struct spa_pod_prop *prop,
+ const struct spa_pod_prop *prop_modifier, GstCaps *res)
+{
+ g_autoptr (GPtrArray) fmt_array = NULL;
+ g_autoptr (GPtrArray) drm_fmt_array = NULL;
+ const struct spa_pod *pod_modifier;
+ struct spa_pod *val;
+ uint32_t *id, n_fmts, n_mods, choice, i, j;
+ uint64_t *mods;
+
+
+ val = spa_pod_get_values (&prop->value, &n_fmts, &choice);
+ if (val->type != SPA_TYPE_Id)
+ return;
+
+ id = SPA_POD_BODY (val);
+ if (n_fmts > 1) {
+ n_fmts--;
+ id++;
+ }
+
+ pod_modifier = &prop_modifier->value;
+ mods = SPA_POD_CHOICE_VALUES (pod_modifier);
+ n_mods = SPA_POD_CHOICE_N_VALUES (pod_modifier);
+ if (n_mods > 1) {
+ n_mods--;
+ mods++;
+ }
+
+ fmt_array = g_ptr_array_new_with_free_func (g_free);
+ drm_fmt_array = g_ptr_array_new_with_free_func (g_free);
+
+ for (i = 0; i < n_fmts; i++) {
+ for (j = 0; j < n_mods; j++) {
+ const char *fmt_str;
+
+ if ((mods[j] == DRM_FORMAT_MOD_LINEAR ||
+ mods[j] == DRM_FORMAT_MOD_INVALID) &&
+ (fmt_str = video_id_to_string(id[i])))
+ g_ptr_array_add(fmt_array, g_strdup_printf ("%s", fmt_str));
+
+#ifdef HAVE_GSTREAMER_DMA_DRM
+ {
+ char *drm_str;
+
+ if ((drm_str = video_id_to_dma_drm_fourcc(id[i], mods[j])))
+ g_ptr_array_add(drm_fmt_array, drm_str);
+ }
+#endif
+ }
+ }
+
+#ifdef HAVE_GSTREAMER_DMA_DRM
+ if (drm_fmt_array->len > 0) {
+ g_ptr_array_add (fmt_array, g_strdup_printf ("DMA_DRM"));
+
+ if (drm_fmt_array->len == 1) {
+ gst_caps_set_simple (res, "drm-format", G_TYPE_STRING,
+ g_ptr_array_index (drm_fmt_array, 0), NULL);
+ } else {
+ GValue list = { 0 };
+
+ g_value_init (&list, GST_TYPE_LIST);
+ for (i = 0; i < drm_fmt_array->len; i++) {
+ GValue v = { 0 };
+
+ g_value_init (&v, G_TYPE_STRING);
+ g_value_set_string (&v, g_ptr_array_index (drm_fmt_array, i));
+ gst_value_list_append_and_take_value (&list, &v);
+ }
+
+ gst_caps_set_value (res, "drm-format", &list);
+ g_value_unset (&list);
+ }
+ }
+#endif
+
+ if (fmt_array->len > 0) {
+ gst_caps_set_features_simple (res,
+ gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_DMABUF));
+
+ if (fmt_array->len == 1) {
+ gst_caps_set_simple (res, "format", G_TYPE_STRING,
+ g_ptr_array_index (fmt_array, 0), NULL);
+ } else {
+ GValue list = { 0 };
+
+ g_value_init (&list, GST_TYPE_LIST);
+ for (i = 0; i < fmt_array->len; i++) {
+ GValue v = { 0 };
+
+ g_value_init (&v, G_TYPE_STRING);
+ g_value_set_string (&v, g_ptr_array_index (fmt_array, i));
+ gst_value_list_append_and_take_value (&list, &v);
+ }
+
+ gst_caps_set_value (res, "format", &list);
+ g_value_unset (&list);
+ }
+ }
+}
+
static void
handle_int_prop (const struct spa_pod_prop *prop, const char *key, GstCaps *res)
{
@@ -916,9 +1125,17 @@ gst_caps_from_format (const struct spa_pod *format)
if (media_type == SPA_MEDIA_TYPE_video) {
if (media_subtype == SPA_MEDIA_SUBTYPE_raw) {
+ const struct spa_pod_prop *prop_modifier;
+
res = gst_caps_new_empty_simple ("video/x-raw");
- if ((prop = spa_pod_object_find_prop (obj, prop, SPA_FORMAT_VIDEO_format))) {
- handle_id_prop (prop, "format", video_id_to_string, res);
+
+ if ((prop = spa_pod_object_find_prop (obj, prop, SPA_FORMAT_VIDEO_format)) &&
+ (prop_modifier = spa_pod_object_find_prop (obj, NULL, SPA_FORMAT_VIDEO_modifier))) {
+ handle_dmabuf_prop (prop, prop_modifier, res);
+ } else {
+ if ((prop = spa_pod_object_find_prop (obj, prop, SPA_FORMAT_VIDEO_format))) {
+ handle_id_prop (prop, "format", video_id_to_string, res);
+ }
}
}
else if (media_subtype == SPA_MEDIA_SUBTYPE_mjpg) {
diff --git a/src/gst/gstpipewireformat.h b/src/gst/gstpipewireformat.h
index d82dbee20cef..abd45c4e9bbb 100644
--- a/src/gst/gstpipewireformat.h
+++ b/src/gst/gstpipewireformat.h
@@ -11,9 +11,7 @@
G_BEGIN_DECLS
-struct spa_pod * gst_caps_to_format (GstCaps *caps,
- guint index, uint32_t id);
-GPtrArray * gst_caps_to_format_all (GstCaps *caps, uint32_t id);
+GPtrArray * gst_caps_to_format_all (GstCaps *caps);
GstCaps * gst_caps_from_format (const struct spa_pod *format);
diff --git a/src/gst/gstpipewiresink.c b/src/gst/gstpipewiresink.c
index 8a6541615ccb..2f3ec9b8bd93 100644
--- a/src/gst/gstpipewiresink.c
+++ b/src/gst/gstpipewiresink.c
@@ -575,7 +575,7 @@ gst_pipewire_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
pwsink = GST_PIPEWIRE_SINK (bsink);
- possible = gst_caps_to_format_all (caps, SPA_PARAM_EnumFormat);
+ possible = gst_caps_to_format_all (caps);
pw_thread_loop_lock (pwsink->core->loop);
state = pw_stream_get_state (pwsink->stream, &error);
diff --git a/src/gst/gstpipewiresrc.c b/src/gst/gstpipewiresrc.c
index a66ef964b9cc..f96da74ba3d0 100644
--- a/src/gst/gstpipewiresrc.c
+++ b/src/gst/gstpipewiresrc.c
@@ -15,7 +15,6 @@
#define PW_ENABLE_DEPRECATED
-#include "config.h"
#include "gstpipewiresrc.h"
#include "gstpipewireformat.h"
@@ -869,7 +868,7 @@ gst_pipewire_src_negotiate (GstBaseSrc * basesrc)
}
/* open a connection with these caps */
- possible = gst_caps_to_format_all (possible_caps, SPA_PARAM_EnumFormat);
+ possible = gst_caps_to_format_all (possible_caps);
/* first disconnect */
pw_thread_loop_lock (pwsrc->core->loop);
@@ -1013,26 +1012,47 @@ on_param_changed (void *data, uint32_t id,
gst_caps_unref(pwsrc->caps);
pwsrc->caps = gst_caps_from_format (param);
- pwsrc->is_video = pwsrc->caps != NULL
- ? gst_video_info_from_caps (&pwsrc->video_info, pwsrc->caps)
- : FALSE;
+ if (pwsrc->caps && gst_caps_is_fixed (pwsrc->caps)) {
+ pwsrc->negotiated = TRUE;
- pwsrc->negotiated = pwsrc->caps != NULL;
+#ifdef HAVE_GSTREAMER_DMA_DRM
+ if (gst_video_is_dma_drm_caps (pwsrc->caps)) {
+ if (!gst_video_info_dma_drm_from_caps (&pwsrc->drm_info, pwsrc->caps)) {
+ GST_WARNING_OBJECT (pwsrc, "Can't create drm video info from caps");
+ pw_stream_set_error (pwsrc->stream, -EINVAL, "internal error");
+ return;
+ }
- if (pwsrc->negotiated) {
+ if (!gst_video_info_dma_drm_to_video_info (&pwsrc->drm_info,
+ &pwsrc->video_info)) {
+ GST_WARNING_OBJECT (pwsrc, "Can't create video info from drm video info");
+ pw_stream_set_error (pwsrc->stream, -EINVAL, "internal error");
+ return;
+ }
+
+ pwsrc->is_video = TRUE;
+ } else {
+ gst_video_info_dma_drm_init (&pwsrc->drm_info);
+#endif
+ pwsrc->is_video = gst_video_info_from_caps (&pwsrc->video_info,
+ pwsrc->caps);
+#ifdef HAVE_GSTREAMER_DMA_DRM
+ }
+#endif
+ } else {
+ pwsrc->negotiated = FALSE;
+ pwsrc->is_video = FALSE;
+ }
+
+ if (pwsrc->caps) {
const struct spa_pod *params[4];
struct spa_pod_builder b = { NULL };
uint8_t buffer[512];
uint32_t buffers = CLAMP (16, pwsrc->min_buffers, pwsrc->max_buffers);
int buffertypes;
buffertypes = (1<<SPA_DATA_DmaBuf);
- if (spa_pod_find_prop (param, NULL, SPA_FORMAT_VIDEO_modifier)) {
- gst_caps_features_remove (gst_caps_get_features (pwsrc->caps, 0),
- GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY);
- gst_caps_features_add (gst_caps_get_features (pwsrc->caps, 0),
- GST_CAPS_FEATURE_MEMORY_DMABUF);
- } else {
+ if (!spa_pod_find_prop (param, NULL, SPA_FORMAT_VIDEO_modifier)) {
buffertypes |= ((1<<SPA_DATA_MemFd) | (1<<SPA_DATA_MemPtr));
}
diff --git a/src/gst/gstpipewiresrc.h b/src/gst/gstpipewiresrc.h
index 97f636fb301f..0a61853f50ec 100644
--- a/src/gst/gstpipewiresrc.h
+++ b/src/gst/gstpipewiresrc.h
@@ -5,6 +5,8 @@
#ifndef __GST_PIPEWIRE_SRC_H__
#define __GST_PIPEWIRE_SRC_H__
+#include "config.h"
+
#include <gst/gst.h>
#include <gst/base/gstpushsrc.h>
@@ -56,6 +58,9 @@ struct _GstPipeWireSrc {
gboolean is_video;
GstVideoInfo video_info;
+#ifdef HAVE_GSTREAMER_DMA_DRM
+ GstVideoInfoDmaDrm drm_info;
+#endif
gboolean negotiated;
gboolean flushing;

View File

@ -1,96 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Robert Mader <robert.mader@collabora.com>
Date: Sun, 25 Feb 2024 17:36:08 +0100
Subject: [PATCH] gst: Sanitize caps before translating
DMABuf caps without concrete formats and modifiers don't map well to the
Pipewire negotiation process.
Introduce a new gst_caps_sanitize() helper function, where such cases
can be handled.
---
src/gst/gstpipewireformat.c | 40 +++++++++++++++++++++++++++++++++++++
src/gst/gstpipewireformat.h | 2 ++
src/gst/gstpipewiresrc.c | 6 +++++-
3 files changed, 47 insertions(+), 1 deletion(-)
diff --git a/src/gst/gstpipewireformat.c b/src/gst/gstpipewireformat.c
index ff1752a06565..6830de234a8d 100644
--- a/src/gst/gstpipewireformat.c
+++ b/src/gst/gstpipewireformat.c
@@ -1176,3 +1176,43 @@ gst_caps_from_format (const struct spa_pod *format)
}
return res;
}
+
+static gboolean
+filter_dmabuf_caps (GstCapsFeatures *features,
+ GstStructure *structure,
+ gpointer user_data)
+{
+ const GValue *value;
+ const char *v;
+
+ if (!gst_caps_features_contains (features, GST_CAPS_FEATURE_MEMORY_DMABUF))
+ return TRUE;
+
+ if (!(value = gst_structure_get_value (structure, "format")) ||
+ !(v = get_nth_string (value, 0)))
+ return FALSE;
+
+#ifdef HAVE_GSTREAMER_DMA_DRM
+ {
+ int idx;
+
+ idx = gst_video_format_from_string (v);
+ if (idx == GST_VIDEO_FORMAT_UNKNOWN)
+ return FALSE;
+
+ if (idx == GST_VIDEO_FORMAT_DMA_DRM &&
+ !gst_structure_get_value (structure, "drm-format"))
+ return FALSE;
+ }
+#endif
+
+ return TRUE;
+}
+
+GstCaps *
+gst_caps_sanitize (GstCaps *caps)
+{
+ caps = gst_caps_make_writable (caps);
+ gst_caps_filter_and_map_in_place (caps, filter_dmabuf_caps, NULL);
+ return caps;
+}
diff --git a/src/gst/gstpipewireformat.h b/src/gst/gstpipewireformat.h
index abd45c4e9bbb..ca76b70c2f06 100644
--- a/src/gst/gstpipewireformat.h
+++ b/src/gst/gstpipewireformat.h
@@ -15,6 +15,8 @@ GPtrArray * gst_caps_to_format_all (GstCaps *caps);
GstCaps * gst_caps_from_format (const struct spa_pod *format);
+GstCaps * gst_caps_sanitize (GstCaps *caps);
+
G_END_DECLS
#endif
diff --git a/src/gst/gstpipewiresrc.c b/src/gst/gstpipewiresrc.c
index f96da74ba3d0..a9ef7d1b2430 100644
--- a/src/gst/gstpipewiresrc.c
+++ b/src/gst/gstpipewiresrc.c
@@ -847,10 +847,14 @@ gst_pipewire_src_negotiate (GstBaseSrc * basesrc)
/* no peer, work with our own caps then */
possible_caps = g_steal_pointer (&thiscaps);
}
+
+ GST_DEBUG_OBJECT (basesrc, "have common caps: %" GST_PTR_FORMAT, possible_caps);
+ gst_caps_sanitize (possible_caps);
+
if (gst_caps_is_empty (possible_caps))
goto no_common_caps;
- GST_DEBUG_OBJECT (basesrc, "have common caps: %" GST_PTR_FORMAT, possible_caps);
+ GST_DEBUG_OBJECT (basesrc, "have common caps (sanitized): %" GST_PTR_FORMAT, possible_caps);
if (pw_stream_get_state(pwsrc->stream, NULL) == PW_STREAM_STATE_STREAMING) {
g_autoptr (GstCaps) current_caps = NULL;

View File

@ -1,67 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Robert Mader <robert.mader@collabora.com>
Date: Thu, 7 Mar 2024 06:55:09 +0100
Subject: [PATCH] gst: Fix sanitization of non-writable caps
`gst_caps_make_writable()` may create a copy which we have to keep
using afterwards. The return value was meant to be used for that,
but was promptly forgotten for the initial user.
Avoid such errors in the future by using an in-out parameter instead.
While on it, add a type check and remove a check for an impossible
condition.
Fixes: 8a271a87b ("gst: Sanitize caps before translating")
---
src/gst/gstpipewireformat.c | 11 ++++++-----
src/gst/gstpipewireformat.h | 2 +-
src/gst/gstpipewiresrc.c | 2 +-
3 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/src/gst/gstpipewireformat.c b/src/gst/gstpipewireformat.c
index 6830de234a8d..a0f64747697c 100644
--- a/src/gst/gstpipewireformat.c
+++ b/src/gst/gstpipewireformat.c
@@ -1209,10 +1209,11 @@ filter_dmabuf_caps (GstCapsFeatures *features,
return TRUE;
}
-GstCaps *
-gst_caps_sanitize (GstCaps *caps)
+void
+gst_caps_sanitize (GstCaps **caps)
{
- caps = gst_caps_make_writable (caps);
- gst_caps_filter_and_map_in_place (caps, filter_dmabuf_caps, NULL);
- return caps;
+ g_return_if_fail (GST_IS_CAPS (*caps));
+
+ *caps = gst_caps_make_writable (*caps);
+ gst_caps_filter_and_map_in_place (*caps, filter_dmabuf_caps, NULL);
}
diff --git a/src/gst/gstpipewireformat.h b/src/gst/gstpipewireformat.h
index ca76b70c2f06..1c3a239baeaf 100644
--- a/src/gst/gstpipewireformat.h
+++ b/src/gst/gstpipewireformat.h
@@ -15,7 +15,7 @@ GPtrArray * gst_caps_to_format_all (GstCaps *caps);
GstCaps * gst_caps_from_format (const struct spa_pod *format);
-GstCaps * gst_caps_sanitize (GstCaps *caps);
+void gst_caps_sanitize (GstCaps **caps);
G_END_DECLS
diff --git a/src/gst/gstpipewiresrc.c b/src/gst/gstpipewiresrc.c
index a9ef7d1b2430..5e518884f2f8 100644
--- a/src/gst/gstpipewiresrc.c
+++ b/src/gst/gstpipewiresrc.c
@@ -849,7 +849,7 @@ gst_pipewire_src_negotiate (GstBaseSrc * basesrc)
}
GST_DEBUG_OBJECT (basesrc, "have common caps: %" GST_PTR_FORMAT, possible_caps);
- gst_caps_sanitize (possible_caps);
+ gst_caps_sanitize (&possible_caps);
if (gst_caps_is_empty (possible_caps))
goto no_common_caps;

View File

@ -1,70 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Robert Mader <robert.mader@collabora.com>
Date: Thu, 28 Mar 2024 14:01:20 +0100
Subject: [PATCH] gst: Re-enable handling of single long modifiers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
A peer may announce support for a single modifier, in which case it may
not use a choice-pod. And while the documentation in `dma-buf.dox`
requires modifiers to always be announced as `SPA_CHOICE_Enum`, this has
been supported in the past - as well as matching Pipewire conventions.
Thus, in order to not break existing clients not crash, reintroduce
handling of modifiers as a single long.
Fixes: f1b75fc6f (gst: Add support for DMA_DRM / explicit modifiers)
Solution suggested by Barnabás Pőcze <pobrn@protonmail.com>
---
src/gst/gstpipewireformat.c | 24 +++++++++++++++++-------
1 file changed, 17 insertions(+), 7 deletions(-)
diff --git a/src/gst/gstpipewireformat.c b/src/gst/gstpipewireformat.c
index a0f64747697c..e4159835da76 100644
--- a/src/gst/gstpipewireformat.c
+++ b/src/gst/gstpipewireformat.c
@@ -877,25 +877,35 @@ handle_dmabuf_prop (const struct spa_pod_prop *prop,
const struct spa_pod *pod_modifier;
struct spa_pod *val;
uint32_t *id, n_fmts, n_mods, choice, i, j;
- uint64_t *mods;
-
+ uint64_t *mods, single_modifier;
val = spa_pod_get_values (&prop->value, &n_fmts, &choice);
if (val->type != SPA_TYPE_Id)
return;
id = SPA_POD_BODY (val);
if (n_fmts > 1) {
n_fmts--;
id++;
}
pod_modifier = &prop_modifier->value;
- mods = SPA_POD_CHOICE_VALUES (pod_modifier);
- n_mods = SPA_POD_CHOICE_N_VALUES (pod_modifier);
- if (n_mods > 1) {
- n_mods--;
- mods++;
+ if (spa_pod_is_long (pod_modifier) &&
+ spa_pod_get_long (pod_modifier, (int64_t *) &single_modifier)) {
+ mods = &single_modifier;
+ n_mods = 1;
+ } else if (spa_pod_is_choice (pod_modifier) &&
+ SPA_POD_CHOICE_TYPE (pod_modifier) == SPA_CHOICE_Enum &&
+ SPA_POD_CHOICE_VALUE_TYPE (pod_modifier) == SPA_TYPE_Long) {
+ mods = SPA_POD_CHOICE_VALUES (pod_modifier);
+ n_mods = SPA_POD_CHOICE_N_VALUES (pod_modifier);
+
+ if (n_mods > 1) {
+ n_mods--;
+ mods++;
+ }
+ } else {
+ return;
}
fmt_array = g_ptr_array_new_with_free_func (g_free);

View File

@ -23,9 +23,8 @@ pkgname=(
pipewire-session-manager
pulse-native-provider
)
pkgver=1.0.7
_so_ver=0.3
pkgrel=2
pkgver=1.2.1
pkgrel=1
epoch=1
pkgdesc="Low-latency audio/video router and processor"
url="https://pipewire.org"
@ -49,6 +48,7 @@ makedepends=(
libffado
libfreeaptx
liblc3
libldac
libmysofa
libpulse
libsndfile
@ -60,7 +60,6 @@ makedepends=(
ncurses
opus
python-docutils
python-packaging
readline
roc-toolkit
rtkit
@ -70,34 +69,17 @@ makedepends=(
valgrind
webrtc-audio-processing-1
)
makedepends_powerpc64le=(libldac)
makedepends_riscv64=(libldac)
makedepends_x86_64=(libldac)
checkdepends=(
desktop-file-utils
openal
)
source=(
"git+https://gitlab.freedesktop.org/pipewire/pipewire.git#tag=$pkgver"
0001-gst-Add-support-for-DMA_DRM-explicit-modifiers.patch
0002-gst-Sanitize-caps-before-translating.patch
0003-gst-Fix-sanitization-of-non-writable-caps.patch
0004-gst-Re-enable-handling-of-single-long-modifiers.patch
)
b2sums=('0f48332de9555b7eaca49f7ba1dfa6c86c9797ef161e1b3bec4c04dbf791e867e9e84e93fa6bc57426e79cdc4ee32c244a934064f4e5028d4310b5ec13a16b5d'
'562fbac6786773dca0d390aa738a3298fbd41b56b2e20fd3f4b8353f8d1ab1ace822194790f7eb530ac86f655ce44390bc02f22899424634dc5e62ee668c676c'
'5aca6a491907cabeee40765ef6591448bfd5a684327db5f0ffe0b59c99e23bd7cc13994f8aa42b8f5ae9c1bbd8cd69c487c4b04c6fa1dd98e9934bc4b80a17cb'
'902effec51d1c40191a0a5a8e5dcf54e24062f7228c8de1e25dae5ab622a3adcbbc8156d398fa14ea74a0c8e8fc489144771fbead86f91a79f4435c08f419767'
'87dc2c9e67121311cd960aae0751ac77652cacd6e27b70be71d0738d356d0675e731f0dad3a82f6e71b9ada2a458a13ebb572fccba3d33f88be4dc350cd5e8b3')
b2sums=('c956faaa5caeb95ea9c802744c0584f25b251f3f7d5460f938aafe75def298df136824a9aff5ce7ecaad6241db51e88a19f39a89aa9e30e2256bd8cee21dbcbb')
prepare() {
cd pipewire
# Gst plugin fixes
git apply -3 ../0001-gst-Add-support-for-DMA_DRM-explicit-modifiers.patch
git apply -3 ../0002-gst-Sanitize-caps-before-translating.patch
git apply -3 ../0003-gst-Fix-sanitization-of-non-writable-caps.patch
git apply -3 ../0004-gst-Re-enable-handling-of-single-long-modifiers.patch
}
build() {
@ -110,13 +92,10 @@ build() {
-D rlimits-install=false
-D selinux=disabled
-D session-managers=[]
-D snap=disabled
-D udevrulesdir=/usr/lib/udev/rules.d
)
case "${CARCH}" in
powerpc|powerpc64) meson_options+=(-D bluez5-codec-ldac=disabled) ;;
esac
arch-meson pipewire build "${meson_options[@]}"
meson compile -C build
}
@ -135,18 +114,24 @@ _pick() {
done
}
_pwname=pipewire-0.3
_spaname=spa-0.2
package_pipewire() {
license+=(LGPL-2.1-or-later) # libspa-alsa
license+=(
# libspa-alsa
LGPL-2.1-or-later
)
depends=(
"libpipewire=$epoch:$pkgver-$pkgrel"
gcc-libs
glibc
"libpipewire=$epoch:$pkgver-$pkgrel"
lib$_pwname.so
libcamera-base.so
libcamera.so
libdbus-1.so
libglib-2.0.so
libncursesw.so
libpipewire-$_so_ver.so
libreadline.so
libsystemd.so
libudev.so
@ -181,9 +166,9 @@ package_pipewire() {
ln -sf pipewire usr/bin/$_f
done
_pick lib usr/include/{pipewire-$_so_ver,spa-0.2}
_pick lib usr/lib/libpipewire-$_so_ver.so*
_pick lib usr/lib/pkgconfig/lib{pipewire-$_so_ver,spa-0.2}.pc
_pick lib usr/include/{$_pwname,$_spaname}
_pick lib usr/lib/lib$_pwname.so*
_pick lib usr/lib/pkgconfig/lib{$_pwname,$_spaname}.pc
_pick acp usr/lib/udev
_pick acp usr/share/alsa-card-profile
@ -191,36 +176,48 @@ package_pipewire() {
_pick docs usr/share/doc
_pick audio usr/bin/pipewire-{aes67,avb}
_pick audio usr/bin/pw-{cat,{,enc}play,record,midi{play,record},dsdplay}
_pick audio usr/bin/pw-{loopback,mididump}
_pick audio usr/bin/pw-{cat,loopback,mididump}
_pick audio usr/bin/pw-{dsd,enc,midi,}play
_pick audio usr/bin/pw-{midi,}record
_pick audio usr/bin/spa-{acp-tool,resample}
_pick audio usr/lib/alsa-lib
_pick audio usr/lib/pipewire-$_so_ver/libpipewire-module-avb.so
_pick audio usr/lib/pipewire-$_so_ver/libpipewire-module-echo-cancel.so
_pick audio usr/lib/pipewire-$_so_ver/libpipewire-module-fallback-sink.so
_pick audio usr/lib/pipewire-$_so_ver/libpipewire-module-filter-chain*.so
_pick audio usr/lib/pipewire-$_so_ver/libpipewire-module-loopback.so
_pick audio usr/lib/pipewire-$_so_ver/libpipewire-module-netjack2*.so
_pick audio usr/lib/pipewire-$_so_ver/libpipewire-module-pipe-tunnel.so
_pick audio usr/lib/pipewire-$_so_ver/libpipewire-module-protocol-simple.so
_pick audio usr/lib/pipewire-$_so_ver/libpipewire-module-rtp-{sap,sink,source}.so
_pick audio usr/lib/pipewire-$_so_ver/libpipewire-module-vban*.so
_pick audio usr/lib/spa-0.2/{aec,alsa,audio*,avb,bluez5}
_pick audio usr/lib/$_pwname/libpipewire-module-avb.so
_pick audio usr/lib/$_pwname/libpipewire-module-echo-cancel.so
_pick audio usr/lib/$_pwname/libpipewire-module-fallback-sink.so
_pick audio usr/lib/$_pwname/libpipewire-module-filter-chain*.so
_pick audio usr/lib/$_pwname/libpipewire-module-loopback.so
_pick audio usr/lib/$_pwname/libpipewire-module-netjack2*.so
_pick audio usr/lib/$_pwname/libpipewire-module-parametric-equalizer.so
_pick audio usr/lib/$_pwname/libpipewire-module-pipe-tunnel.so
_pick audio usr/lib/$_pwname/libpipewire-module-protocol-simple.so
_pick audio usr/lib/$_pwname/libpipewire-module-rtp-{sap,sink,source}.so
_pick audio usr/lib/$_pwname/libpipewire-module-vban*.so
_pick audio usr/lib/$_spaname/{aec,alsa,audio*,avb,bluez5}
_pick audio usr/lib/systemd/user/filter-chain.service
_pick audio usr/share/alsa
_pick audio usr/share/man/man1/pw-{cat,loopback,mididump}.1
_pick audio usr/share/man/man1/spa-{acp-tool,resample}.1
_pick audio usr/share/man/man5/pipewire-filter-chain.conf.5
_pick audio usr/share/man/man7/libpipewire-module-{avb,echo-cancel,fallback-sink,filter-chain*,loopback,netjack2*,pipe-tunnel,protocol-simple,rtp-{sap,sink,source},vban*}.7
_pick audio usr/share/man/man7/libpipewire-module-avb.7
_pick audio usr/share/man/man7/libpipewire-module-echo-cancel.7
_pick audio usr/share/man/man7/libpipewire-module-fallback-sink.7
_pick audio usr/share/man/man7/libpipewire-module-filter-chain*.7
_pick audio usr/share/man/man7/libpipewire-module-loopback.7
_pick audio usr/share/man/man7/libpipewire-module-netjack2*.7
_pick audio usr/share/man/man7/libpipewire-module-parametric-equalizer.7
_pick audio usr/share/man/man7/libpipewire-module-pipe-tunnel.7
_pick audio usr/share/man/man7/libpipewire-module-protocol-simple.7
_pick audio usr/share/man/man7/libpipewire-module-rtp-{sap,sink,source}.7
_pick audio usr/share/man/man7/libpipewire-module-vban*.7
_pick audio usr/share/pipewire/filter-chain*
_pick audio usr/share/pipewire/pipewire-{aes67,avb}.conf
_pick audio usr/share/spa-0.2/bluez5
_pick audio usr/share/$_spaname/bluez5
_pick ffado usr/lib/pipewire-$_so_ver/libpipewire-module-ffado*.so
_pick ffado usr/lib/$_pwname/libpipewire-module-ffado*.so
_pick ffado usr/share/man/man7/libpipewire-module-ffado-driver.7
_pick jack-client usr/lib/pipewire-$_so_ver/libpipewire-module-jack{-tunnel,dbus-detect}.so
_pick jack-client usr/lib/spa-0.2/jack
_pick jack-client usr/lib/$_pwname/libpipewire-module-jack{-tunnel,dbus-detect}.so
_pick jack-client usr/lib/$_spaname/jack
_pick jack-client usr/share/man/man7/libpipewire-module-jack{-tunnel,dbus-detect}.7
_pick jack usr/bin/pw-jack
@ -232,28 +229,32 @@ package_pipewire() {
_pick jack usr/share/pipewire/jack.conf
_pick pulse usr/bin/pipewire-pulse
_pick pulse usr/lib/pipewire-$_so_ver/libpipewire-module-protocol-pulse.so
_pick pulse usr/lib/pipewire-$_so_ver/libpipewire-module-pulse-tunnel.so
_pick pulse usr/lib/$_pwname/libpipewire-module-protocol-pulse.so
_pick pulse usr/lib/$_pwname/libpipewire-module-pulse-tunnel.so
_pick pulse usr/lib/systemd/user/pipewire-pulse.*
_pick pulse usr/share/glib-2.0/schemas/org.freedesktop.pulseaudio.gschema.xml
_pick pulse usr/share/man/man1/pipewire-pulse.1
_pick pulse usr/share/man/man5/pipewire-pulse.conf.5
_pick pulse usr/share/man/man7/pipewire-pulse*.7
_pick pulse usr/share/man/man7/libpipewire-module-{protocol-pulse,pulse-tunnel}.7
_pick pulse usr/share/man/man7/pipewire-pulse*.7
_pick pulse usr/share/pipewire/pipewire-pulse.conf
_pick roc usr/lib/pipewire-$_so_ver/libpipewire-module-roc*.so
_pick roc usr/lib/$_pwname/libpipewire-module-roc*.so
_pick roc usr/share/man/man7/libpipewire-module-roc-{sink,source}.7
_pick gst usr/lib/gstreamer-1.0
_pick zeroconf usr/lib/pipewire-$_so_ver/libpipewire-module-{raop,zeroconf}-*.so
_pick zeroconf usr/lib/pipewire-$_so_ver/libpipewire-module-rtp-session.so
_pick zeroconf usr/share/man/man7/libpipewire-module-{raop-*,rtp-session,zeroconf*}.7
_pick zeroconf usr/lib/$_pwname/libpipewire-module-{raop,zeroconf}-*.so
_pick zeroconf usr/lib/$_pwname/libpipewire-module-rtp-session.so
_pick zeroconf usr/lib/$_pwname/libpipewire-module-snapcast-discover.so
_pick zeroconf usr/share/man/man7/libpipewire-module-{raop,zeroconf}-*.7
_pick zeroconf usr/share/man/man7/libpipewire-module-rtp-session.7
_pick zeroconf usr/share/man/man7/libpipewire-module-snapcast-discover.7
_pick v4l2 usr/bin/pw-v4l2 usr/lib/pipewire-$_so_ver/v4l2
_pick v4l2 usr/bin/pw-v4l2 usr/lib/$_pwname/v4l2
_pick v4l2 usr/share/man/man1/pw-v4l2.1
_pick x11-bell usr/lib/pipewire-$_so_ver/libpipewire-module-x11-bell.so
_pick x11-bell usr/lib/$_pwname/libpipewire-module-x11-bell.so
_pick x11-bell usr/share/man/man7/libpipewire-module-x11-bell.7
# directories for overrides
@ -269,7 +270,7 @@ package_libpipewire() {
glibc
gcc-libs
)
provides=(libpipewire-$_so_ver.so)
provides=(lib$_pwname.so)
mv lib/* "$pkgdir"
@ -299,15 +300,16 @@ package_pipewire-audio() {
gcc-libs
glib2
glibc
lib$_pwname.so
libasound.so
libbluetooth.so
libfdk-aac.so
libfreeaptx.so
liblc3.so
libldacBT_enc.so
liblilv-0.so
libmysofa.so
libopus.so
libpipewire-$_so_ver.so
libsbc.so
libsndfile.so
libusb-1.0.so
@ -315,9 +317,6 @@ package_pipewire-audio() {
pipewire
systemd-libs
)
depends_powerpc64le=(libldacBT_enc.so)
depends_riscv64=(libldacBT_enc.so)
depends_x86_64=(libldacBT_enc.so)
mv audio/* "$pkgdir"
@ -353,7 +352,7 @@ package_pipewire-ffado() {
depends=(
glibc
libffado.so
libpipewire-$_so_ver.so
lib$_pwname.so
pipewire
pipewire-audio
)
@ -366,10 +365,11 @@ package_pipewire-ffado() {
package_pipewire-jack-client() {
pkgdesc+=" - PipeWire as JACK client"
depends=(
gcc-libs
glibc
lib$_pwname.so
libdbus-1.so
libjack.so
libpipewire-$_so_ver.so
pipewire
pipewire-audio
)
@ -382,18 +382,33 @@ package_pipewire-jack-client() {
package_pipewire-jack() {
pkgdesc+=" - JACK replacement"
license+=(LGPL-2.1-or-later GPL-2.0-only) # libjackserver
license+=(
# libjackserver
GPL-2.0-only
LGPL-2.1-or-later
)
depends=(
glibc
libpipewire-$_so_ver.so
lib$_pwname.so
pipewire
pipewire-audio
pipewire-session-manager
sh
)
optdepends=('jack-example-tools: for official JACK example-clients and tools')
conflicts=(jack jack2 pipewire-jack-client)
provides=(jack libjack.so libjackserver.so libjacknet.so)
optdepends=(
'jack-example-tools: for official JACK example-clients and tools'
)
conflicts=(
jack
jack2
pipewire-jack-client
)
provides=(
jack
libjack.so
libjacknet.so
libjackserver.so
)
mv jack/* "$pkgdir"
@ -410,11 +425,12 @@ package_pipewire-pulse() {
pkgdesc+=" - PulseAudio replacement"
depends=(
dbus
dconf
gcc-libs
glibc
lib$_pwname.so
libavahi-{client,common}.so
libglib-2.0.so
libpipewire-$_so_ver.so
libpulse.so
pipewire
pipewire-audio
@ -446,8 +462,9 @@ package_pipewire-pulse() {
package_pipewire-roc() {
pkgdesc+=" - ROC streaming support"
depends=(
gcc-libs
glibc
libpipewire-$_so_ver.so
lib$_pwname.so
libroc.so
pipewire
pipewire-audio
@ -462,11 +479,12 @@ package_pipewire-roc() {
package_gst-plugin-pipewire() {
pkgdesc="Multimedia graph framework - pipewire plugin"
depends=(
gcc-libs
glib2
glibc
gst-plugins-base-libs
gstreamer
libpipewire-$_so_ver.so
lib$_pwname.so
pipewire
pipewire-session-manager
)
@ -481,8 +499,8 @@ package_pipewire-zeroconf() {
depends=(
gcc-libs
glibc
lib$_pwname.so
libavahi-{client,common}.so
libpipewire-$_so_ver.so
openssl
opus
pipewire
@ -498,7 +516,7 @@ package_pipewire-v4l2() {
pkgdesc+=" - V4L2 interceptor"
depends=(
glibc
libpipewire-$_so_ver.so
lib$_pwname.so
pipewire
pipewire-session-manager
sh
@ -513,8 +531,8 @@ package_pipewire-x11-bell() {
pkgdesc+=" - X11 bell"
depends=(
glibc
lib$_pwname.so
libcanberra.so
libpipewire-$_so_ver.so
libx11
libxfixes
pipewire
@ -528,11 +546,13 @@ package_pipewire-x11-bell() {
package_pipewire-session-manager() {
pkgdesc="Session manager for PipeWire (default provider)"
license=(CC0-1.0)
depends=(wireplumber)
}
package_pulse-native-provider() {
pkgdesc="PulseAudio sound server (default provider)"
license=(CC0-1.0)
depends=(pipewire-pulse)
}