[gnome-remote-desktop] vnc-pipewire-stream: Add support for explicit DMA buffer modifiers
- From: Jonas Ådahl <jadahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-remote-desktop] vnc-pipewire-stream: Add support for explicit DMA buffer modifiers
- Date: Wed, 8 Dec 2021 09:09:51 +0000 (UTC)
commit 346af9a1fe0cf861595a5705355ccbb64f12fc4b
Author: Jonas Ådahl <jadahl gmail com>
Date: Fri Nov 26 12:13:11 2021 +0100
vnc-pipewire-stream: Add support for explicit DMA buffer modifiers
This is needed for proper DMA buffer PipeWire support if the producer is
updated to require a modifier property for enabling DMA buffer
allocation. It does not break compatibility with old producers, and as a
bonus, explicit DMA buffer support will work once the producer supports
it.
src/grd-vnc-pipewire-stream.c | 122 +++++++++++++++++++++++++++++++++---------
1 file changed, 98 insertions(+), 24 deletions(-)
---
diff --git a/src/grd-vnc-pipewire-stream.c b/src/grd-vnc-pipewire-stream.c
index b79158d..5ed3ae9 100644
--- a/src/grd-vnc-pipewire-stream.c
+++ b/src/grd-vnc-pipewire-stream.c
@@ -620,44 +620,118 @@ static const struct pw_stream_events stream_events = {
.process = on_stream_process,
};
+static void
+add_common_format_params (struct spa_pod_builder *pod_builder,
+ enum spa_video_format spa_format)
+{
+ struct spa_rectangle min_rect;
+ struct spa_rectangle max_rect;
+ struct spa_fraction min_framerate;
+ struct spa_fraction max_framerate;
+
+ min_rect = SPA_RECTANGLE (1, 1);
+ max_rect = SPA_RECTANGLE (INT32_MAX, INT32_MAX);
+ min_framerate = SPA_FRACTION (1, 1);
+ max_framerate = SPA_FRACTION (30, 1);
+
+ spa_pod_builder_add (pod_builder,
+ SPA_FORMAT_mediaType,
+ SPA_POD_Id (SPA_MEDIA_TYPE_video), 0);
+ spa_pod_builder_add (pod_builder,
+ SPA_FORMAT_mediaSubtype,
+ SPA_POD_Id (SPA_MEDIA_SUBTYPE_raw), 0);
+ spa_pod_builder_add (pod_builder,
+ SPA_FORMAT_VIDEO_format,
+ SPA_POD_Id (spa_format), 0);
+ spa_pod_builder_add (pod_builder,
+ SPA_FORMAT_VIDEO_size,
+ SPA_POD_CHOICE_RANGE_Rectangle (&min_rect,
+ &min_rect,
+ &max_rect), 0);
+ spa_pod_builder_add (pod_builder,
+ SPA_FORMAT_VIDEO_framerate,
+ SPA_POD_Fraction (&SPA_FRACTION (0, 1)), 0);
+ spa_pod_builder_add (pod_builder,
+ SPA_FORMAT_VIDEO_maxFramerate,
+ SPA_POD_CHOICE_RANGE_Fraction (&min_framerate,
+ &min_framerate,
+ &max_framerate), 0);
+}
+
static gboolean
connect_to_stream (GrdVncPipeWireStream *stream,
GError **error)
{
+ GrdSession *session = GRD_SESSION (stream->session);
+ GrdContext *context = grd_session_get_context (session);
struct pw_stream *pipewire_stream;
uint8_t params_buffer[1024];
struct spa_pod_builder pod_builder;
- struct spa_rectangle min_rect;
- struct spa_rectangle max_rect;
- struct spa_fraction min_framerate;
- struct spa_fraction max_framerate;
const struct spa_pod *params[2];
int ret;
+ enum spa_video_format spa_format = SPA_VIDEO_FORMAT_BGRx;
+ GrdEglThread *egl_thread;
+ struct spa_pod_frame format_frame;
+ gboolean need_fallback_format = FALSE;
pipewire_stream = pw_stream_new (stream->pipewire_core,
"grd-vnc-pipewire-stream",
NULL);
- min_rect = SPA_RECTANGLE (1, 1);
- max_rect = SPA_RECTANGLE (INT32_MAX, INT32_MAX);
- min_framerate = SPA_FRACTION (1, 1);
- max_framerate = SPA_FRACTION (30, 1);
-
pod_builder = SPA_POD_BUILDER_INIT (params_buffer, sizeof (params_buffer));
- params[0] = spa_pod_builder_add_object (
- &pod_builder,
- SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
- SPA_FORMAT_mediaType, SPA_POD_Id (SPA_MEDIA_TYPE_video),
- SPA_FORMAT_mediaSubtype, SPA_POD_Id (SPA_MEDIA_SUBTYPE_raw),
- SPA_FORMAT_VIDEO_format, SPA_POD_Id (SPA_VIDEO_FORMAT_BGRx),
- SPA_FORMAT_VIDEO_size, SPA_POD_CHOICE_RANGE_Rectangle (&min_rect,
- &min_rect,
- &max_rect),
- SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction (&SPA_FRACTION(0, 1)),
- SPA_FORMAT_VIDEO_maxFramerate, SPA_POD_CHOICE_RANGE_Fraction (&min_framerate,
- &min_framerate,
- &max_framerate),
- 0);
+
+ spa_pod_builder_push_object (&pod_builder, &format_frame,
+ SPA_TYPE_OBJECT_Format,
+ SPA_PARAM_EnumFormat);
+ add_common_format_params (&pod_builder, spa_format);
+
+ egl_thread = grd_context_get_egl_thread (context);
+ if (egl_thread)
+ {
+ uint32_t drm_format;
+ int n_modifiers;
+ g_autofree uint64_t *modifiers = NULL;
+
+ grd_get_spa_format_details (spa_format, &drm_format, NULL);
+ if (grd_egl_thread_get_modifiers_for_format (egl_thread, drm_format,
+ &n_modifiers,
+ &modifiers))
+ {
+ struct spa_pod_frame modifier_frame;
+ int i;
+
+ spa_pod_builder_prop (&pod_builder,
+ SPA_FORMAT_VIDEO_modifier,
+ (SPA_POD_PROP_FLAG_MANDATORY |
+ SPA_POD_PROP_FLAG_DONT_FIXATE));
+
+ spa_pod_builder_push_choice (&pod_builder, &modifier_frame,
+ SPA_CHOICE_Enum, 0);
+ spa_pod_builder_long (&pod_builder, modifiers[0]);
+
+ for (i = 0; i < n_modifiers; i++)
+ {
+ uint64_t modifier = modifiers[i];
+
+ spa_pod_builder_long (&pod_builder, modifier);
+ }
+ spa_pod_builder_long (&pod_builder, DRM_FORMAT_MOD_INVALID);
+ spa_pod_builder_pop (&pod_builder, &modifier_frame);
+
+ need_fallback_format = TRUE;
+ }
+ }
+
+ params[0] = spa_pod_builder_pop (&pod_builder, &format_frame);
+
+ if (need_fallback_format)
+ {
+ spa_pod_builder_push_object (&pod_builder, &format_frame,
+ SPA_TYPE_OBJECT_Format,
+ SPA_PARAM_EnumFormat);
+ add_common_format_params (&pod_builder, spa_format);
+ params[1] = spa_pod_builder_pop (&pod_builder, &format_frame);
+ }
stream->pipewire_stream = pipewire_stream;
@@ -671,7 +745,7 @@ connect_to_stream (GrdVncPipeWireStream *stream,
stream->src_node_id,
(PW_STREAM_FLAG_RT_PROCESS |
PW_STREAM_FLAG_AUTOCONNECT),
- params, 1);
+ params, need_fallback_format ? 2 : 1);
if (ret < 0)
{
g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (-ret),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]