Skip to content
Snippets Groups Projects
Verified Commit 35063286 authored by Jan Alexander Steffens (heftig)'s avatar Jan Alexander Steffens (heftig)
Browse files

1:1.2.0-1

parent 38820b01
No related branches found
Tags 1-1.2.0-1
No related merge requests found
pkgbase = pipewire
pkgdesc = Low-latency audio/video router and processor
pkgver = 1.0.7
pkgrel = 3
pkgver = 1.2.0
pkgrel = 1
epoch = 1
url = https://pipewire.org
arch = x86_64
......@@ -45,30 +45,22 @@ pkgbase = pipewire
makedepends = systemd
makedepends = valgrind
makedepends = webrtc-audio-processing-1
source = git+https://gitlab.freedesktop.org/pipewire/pipewire.git#tag=1.0.7
source = 0001-gst-Add-support-for-DMA_DRM-explicit-modifiers.patch
source = 0002-gst-Sanitize-caps-before-translating.patch
source = 0003-gst-Fix-sanitization-of-non-writable-caps.patch
source = 0004-gst-Re-enable-handling-of-single-long-modifiers.patch
b2sums = 0f48332de9555b7eaca49f7ba1dfa6c86c9797ef161e1b3bec4c04dbf791e867e9e84e93fa6bc57426e79cdc4ee32c244a934064f4e5028d4310b5ec13a16b5d
b2sums = 562fbac6786773dca0d390aa738a3298fbd41b56b2e20fd3f4b8353f8d1ab1ace822194790f7eb530ac86f655ce44390bc02f22899424634dc5e62ee668c676c
b2sums = 5aca6a491907cabeee40765ef6591448bfd5a684327db5f0ffe0b59c99e23bd7cc13994f8aa42b8f5ae9c1bbd8cd69c487c4b04c6fa1dd98e9934bc4b80a17cb
b2sums = 902effec51d1c40191a0a5a8e5dcf54e24062f7228c8de1e25dae5ab622a3adcbbc8156d398fa14ea74a0c8e8fc489144771fbead86f91a79f4435c08f419767
b2sums = 87dc2c9e67121311cd960aae0751ac77652cacd6e27b70be71d0738d356d0675e731f0dad3a82f6e71b9ada2a458a13ebb572fccba3d33f88be4dc350cd5e8b3
source = git+https://gitlab.freedesktop.org/pipewire/pipewire.git#tag=1.2.0
b2sums = a8601fcb9fcd1408ccde0de8baca110dbd494800003274ee65b39dd47db6b9a6a88ea0936941c83232440633b3a8ff4aa9c7f239b66a39989cf5bb6099f9805a
pkgname = pipewire
install = pipewire.install
license = MIT
license = LGPL-2.1-or-later
depends = libpipewire=1:1.2.0-1
depends = gcc-libs
depends = glibc
depends = libpipewire=1:1.0.7-3
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 = libpipewire-0.3.so
depends = libreadline.so
depends = libsystemd.so
depends = libudev.so
......@@ -108,6 +100,7 @@ pkgname = pipewire-audio
depends = gcc-libs
depends = glib2
depends = glibc
depends = libpipewire-0.3.so
depends = libasound.so
depends = libbluetooth.so
depends = libfdk-aac.so
......@@ -117,7 +110,6 @@ pkgname = pipewire-audio
depends = liblilv-0.so
depends = libmysofa.so
depends = libopus.so
depends = libpipewire-0.3.so
depends = libsbc.so
depends = libsndfile.so
depends = libusb-1.0.so
......@@ -143,10 +135,11 @@ pkgname = pipewire-ffado
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 = libpipewire-0.3.so
depends = pipewire
depends = pipewire-audio
conflicts = pipewire-jack
......@@ -154,8 +147,8 @@ pkgname = pipewire-jack-client
pkgname = pipewire-jack
pkgdesc = Low-latency audio/video router and processor - JACK replacement
license = MIT
license = LGPL-2.1-or-later
license = GPL-2.0-only
license = LGPL-2.1-or-later
depends = glibc
depends = libpipewire-0.3.so
depends = pipewire
......@@ -165,8 +158,8 @@ pkgname = pipewire-jack
optdepends = jack-example-tools: for official JACK example-clients and tools
provides = jack
provides = libjack.so
provides = libjackserver.so
provides = libjacknet.so
provides = libjackserver.so
conflicts = jack
conflicts = jack2
conflicts = pipewire-jack-client
......@@ -175,12 +168,13 @@ 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 = libpipewire-0.3.so
depends = libpulse.so
depends = pipewire
depends = pipewire-audio
......@@ -194,6 +188,7 @@ pkgname = pipewire-pulse
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
......@@ -203,6 +198,7 @@ pkgname = pipewire-roc
pkgname = gst-plugin-pipewire
pkgdesc = Multimedia graph framework - pipewire plugin
depends = gcc-libs
depends = glib2
depends = glibc
depends = gst-plugins-base-libs
......@@ -215,9 +211,9 @@ 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 = libpipewire-0.3.so
depends = openssl
depends = opus
depends = pipewire
......@@ -234,8 +230,8 @@ pkgname = pipewire-v4l2
pkgname = pipewire-x11-bell
pkgdesc = Low-latency audio/video router and processor - X11 bell
depends = glibc
depends = libcanberra.so
depends = libpipewire-0.3.so
depends = libcanberra.so
depends = libx11
depends = libxfixes
depends = pipewire
......
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;
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;
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;
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);
......@@ -22,9 +22,8 @@ pkgname=(
pipewire-session-manager
pulse-native-provider
)
pkgver=1.0.7
_so_ver=0.3
pkgrel=3
pkgver=1.2.0
pkgrel=1
epoch=1
pkgdesc="Low-latency audio/video router and processor"
url="https://pipewire.org"
......@@ -75,25 +74,11 @@ checkdepends=(
)
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=('a8601fcb9fcd1408ccde0de8baca110dbd494800003274ee65b39dd47db6b9a6a88ea0936941c83232440633b3a8ff4aa9c7f239b66a39989cf5bb6099f9805a')
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() {
......@@ -106,6 +91,7 @@ build() {
-D rlimits-install=false
-D selinux=disabled
-D session-managers=[]
-D snap=disabled
-D udevrulesdir=/usr/lib/udev/rules.d
)
......@@ -127,18 +113,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
......@@ -173,9 +165,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
......@@ -183,36 +175,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
......@@ -224,28 +228,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
......@@ -261,7 +269,7 @@ package_libpipewire() {
glibc
gcc-libs
)
provides=(libpipewire-$_so_ver.so)
provides=(lib$_pwname.so)
mv lib/* "$pkgdir"
......@@ -291,6 +299,7 @@ package_pipewire-audio() {
gcc-libs
glib2
glibc
lib$_pwname.so
libasound.so
libbluetooth.so
libfdk-aac.so
......@@ -300,7 +309,6 @@ package_pipewire-audio() {
liblilv-0.so
libmysofa.so
libopus.so
libpipewire-$_so_ver.so
libsbc.so
libsndfile.so
libusb-1.0.so
......@@ -343,7 +351,7 @@ package_pipewire-ffado() {
depends=(
glibc
libffado.so
libpipewire-$_so_ver.so
lib$_pwname.so
pipewire
pipewire-audio
)
......@@ -356,10 +364,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
)
......@@ -372,18 +381,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"
......@@ -400,11 +424,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
......@@ -436,8 +461,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
......@@ -452,11 +478,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
)
......@@ -471,8 +498,8 @@ package_pipewire-zeroconf() {
depends=(
gcc-libs
glibc
lib$_pwname.so
libavahi-{client,common}.so
libpipewire-$_so_ver.so
openssl
opus
pipewire
......@@ -488,7 +515,7 @@ package_pipewire-v4l2() {
pkgdesc+=" - V4L2 interceptor"
depends=(
glibc
libpipewire-$_so_ver.so
lib$_pwname.so
pipewire
pipewire-session-manager
sh
......@@ -503,8 +530,8 @@ package_pipewire-x11-bell() {
pkgdesc+=" - X11 bell"
depends=(
glibc
lib$_pwname.so
libcanberra.so
libpipewire-$_so_ver.so
libx11
libxfixes
pipewire
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment