diff --git a/pipewire/.SRCINFO b/pipewire/.SRCINFO new file mode 100644 index 0000000000..e61be01c51 --- /dev/null +++ b/pipewire/.SRCINFO @@ -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 diff --git a/pipewire/.nvchecker.toml b/pipewire/.nvchecker.toml new file mode 100644 index 0000000000..7e3e7eb02c --- /dev/null +++ b/pipewire/.nvchecker.toml @@ -0,0 +1,4 @@ +[pipewire] +source = "git" +git = "https://gitlab.freedesktop.org/pipewire/pipewire.git" +include_regex = '\d+\.\d+\.[1-7]?\d' diff --git a/pipewire/0001-gst-Add-support-for-DMA_DRM-explicit-modifiers.patch b/pipewire/0001-gst-Add-support-for-DMA_DRM-explicit-modifiers.patch deleted file mode 100644 index 4a72bdeaaf..0000000000 --- a/pipewire/0001-gst-Add-support-for-DMA_DRM-explicit-modifiers.patch +++ /dev/null @@ -1,939 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Robert Mader -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 - - #include - #include - #include - #include - - #include - #include - #include - #include --#include -+#include - - #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<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< - #include - -@@ -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; diff --git a/pipewire/0002-gst-Sanitize-caps-before-translating.patch b/pipewire/0002-gst-Sanitize-caps-before-translating.patch deleted file mode 100644 index a435eb9f7e..0000000000 --- a/pipewire/0002-gst-Sanitize-caps-before-translating.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Robert Mader -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; diff --git a/pipewire/0003-gst-Fix-sanitization-of-non-writable-caps.patch b/pipewire/0003-gst-Fix-sanitization-of-non-writable-caps.patch deleted file mode 100644 index 2a56e9380f..0000000000 --- a/pipewire/0003-gst-Fix-sanitization-of-non-writable-caps.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Robert Mader -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; diff --git a/pipewire/0004-gst-Re-enable-handling-of-single-long-modifiers.patch b/pipewire/0004-gst-Re-enable-handling-of-single-long-modifiers.patch deleted file mode 100644 index 70a0cb9479..0000000000 --- a/pipewire/0004-gst-Re-enable-handling-of-single-long-modifiers.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Robert Mader -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 ---- - 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); diff --git a/pipewire/PKGBUILD b/pipewire/PKGBUILD index bd9f5341d1..66d2223164 100644 --- a/pipewire/PKGBUILD +++ b/pipewire/PKGBUILD @@ -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) }