From 51d4d5ec3c278a1ae6d745634e1234ef2a74c8d1 Mon Sep 17 00:00:00 2001 From: Arun Raghavan Date: Wed, 9 Jul 2025 17:38:43 -0400 Subject: [PATCH] gst: pipewiresrc: Expose cursor position as a ROI meta --- src/gst/gstpipewirepool.c | 1 + src/gst/gstpipewirepool.h | 1 + src/gst/gstpipewiresrc.c | 34 ++++++++++++++++++++++++++-------- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/gst/gstpipewirepool.c b/src/gst/gstpipewirepool.c index f82dfbf46..0b4f30309 100644 --- a/src/gst/gstpipewirepool.c +++ b/src/gst/gstpipewirepool.c @@ -194,6 +194,7 @@ void gst_pipewire_pool_wrap_buffer (GstPipeWirePool *pool, struct pw_buffer *b) gst_buffer_add_video_crop_meta(buf); data->videotransform = spa_buffer_find_meta_data (b->buffer, SPA_META_VideoTransform, sizeof(*data->videotransform)); + data->cursor = spa_buffer_find_meta_data (b->buffer, SPA_META_Cursor, sizeof(*data->cursor)); gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buf), pool_data_quark, diff --git a/src/gst/gstpipewirepool.h b/src/gst/gstpipewirepool.h index f71344354..4953b689c 100644 --- a/src/gst/gstpipewirepool.h +++ b/src/gst/gstpipewirepool.h @@ -39,6 +39,7 @@ struct _GstPipeWirePoolData { gboolean queued; struct spa_meta_region *crop; struct spa_meta_videotransform *videotransform; + struct spa_meta_cursor *cursor; }; struct _GstPipeWirePool { diff --git a/src/gst/gstpipewiresrc.c b/src/gst/gstpipewiresrc.c index 686ceb5de..b9c8a7a7b 100644 --- a/src/gst/gstpipewiresrc.c +++ b/src/gst/gstpipewiresrc.c @@ -714,6 +714,7 @@ static GstBuffer *dequeue_buffer(GstPipeWireSrc *pwsrc) struct spa_meta_header *h; struct spa_meta_region *crop; enum spa_meta_videotransform_value transform_value; + struct spa_meta_cursor *cursor; struct pw_time time; guint i; @@ -806,6 +807,13 @@ static GstBuffer *dequeue_buffer(GstPipeWireSrc *pwsrc) pwsrc->transform_value = transform_value; } + cursor = data->cursor; + if (cursor && cursor->id != 0) { + /* TODO: at some point, maybe we can figure out width and height from the bitmap, + * and even add that to the meta itself */ + gst_buffer_add_video_region_of_interest_meta (buf, "cursor", cursor->position.x, cursor->position.y, 0, 0); + } + if (pwsrc->is_rawvideo) { GstVideoInfo *info = &pwsrc->video_info; uint32_t n_datas = b->buffer->n_datas; @@ -1341,11 +1349,11 @@ handle_format_change (GstPipeWireSrc *pwsrc, } if (pwsrc->caps) { - const struct spa_pod *params[4]; + const struct spa_pod *params[10]; struct spa_pod_builder b = { NULL }; - uint8_t buffer[512]; + uint8_t buffer[16384]; uint32_t buffers = CLAMP (16, pwsrc->min_buffers, pwsrc->max_buffers); - int buffertypes; + int buffertypes, n_params = 0; buffertypes = (1<caps); spa_pod_builder_init (&b, buffer, sizeof (buffer)); - params[0] = spa_pod_builder_add_object (&b, + params[n_params++] = spa_pod_builder_add_object (&b, SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers, SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(buffers, pwsrc->min_buffers, @@ -1365,21 +1373,31 @@ handle_format_change (GstPipeWireSrc *pwsrc, SPA_PARAM_BUFFERS_stride, SPA_POD_CHOICE_RANGE_Int(0, 0, INT32_MAX), SPA_PARAM_BUFFERS_dataType, SPA_POD_CHOICE_FLAGS_Int(buffertypes)); - params[1] = spa_pod_builder_add_object (&b, + params[n_params++] = spa_pod_builder_add_object (&b, SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Header), SPA_PARAM_META_size, SPA_POD_Int(sizeof (struct spa_meta_header))); - params[2] = spa_pod_builder_add_object (&b, + params[n_params++] = spa_pod_builder_add_object (&b, SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, SPA_PARAM_META_type, SPA_POD_Id(SPA_META_VideoCrop), SPA_PARAM_META_size, SPA_POD_Int(sizeof (struct spa_meta_region))); - params[3] = spa_pod_builder_add_object (&b, + params[n_params++] = spa_pod_builder_add_object (&b, SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, SPA_PARAM_META_type, SPA_POD_Id(SPA_META_VideoTransform), SPA_PARAM_META_size, SPA_POD_Int(sizeof (struct spa_meta_videotransform))); +#define CURSOR_META_SIZE(width, height) \ + (sizeof (struct spa_meta_cursor) + \ + sizeof (struct spa_meta_bitmap) + width * height * 4) + params[n_params++] = spa_pod_builder_add_object (&b, + SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, + SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Cursor), + SPA_PARAM_META_size, + SPA_POD_CHOICE_RANGE_Int (CURSOR_META_SIZE(384, 384), + sizeof (struct spa_meta_cursor), + CURSOR_META_SIZE(384, 384))); GST_DEBUG_OBJECT (pwsrc, "doing finish format"); - pw_stream_update_params (pwsrc->stream->pwstream, params, SPA_N_ELEMENTS(params)); + pw_stream_update_params (pwsrc->stream->pwstream, params, n_params); } else { GST_WARNING_OBJECT (pwsrc, "finish format with error"); pw_stream_set_error (pwsrc->stream->pwstream, -EINVAL, "unhandled format");