From 023577e3912b5193ea969d54bef7ec7743fce939 Mon Sep 17 00:00:00 2001 From: Huang-Huang Bao Date: Fri, 3 Feb 2023 13:02:49 +0800 Subject: [PATCH] gst: add buffer video meta support Fixes video buffer strides handling. This enables passing of image datas with right line padding. --- src/gst/gstpipewirepool.c | 47 +++++++++++++++++++++++++++++++++++++++ src/gst/gstpipewirepool.h | 5 +++++ src/gst/gstpipewiresink.c | 14 ++++++++++++ src/gst/gstpipewiresrc.c | 22 ++++++++++++++++++ src/gst/gstpipewiresrc.h | 5 +++++ 5 files changed, 93 insertions(+) diff --git a/src/gst/gstpipewirepool.c b/src/gst/gstpipewirepool.c index 7ecb8020d..007b87632 100644 --- a/src/gst/gstpipewirepool.c +++ b/src/gst/gstpipewirepool.c @@ -109,6 +109,16 @@ void gst_pipewire_pool_wrap_buffer (GstPipeWirePool *pool, struct pw_buffer *b) gst_buffer_insert_memory (buf, i, gmem); } + if (pool->add_metavideo) { + gst_buffer_add_video_meta_full (buf, GST_VIDEO_FRAME_FLAG_NONE, + GST_VIDEO_INFO_FORMAT (&pool->video_info), + GST_VIDEO_INFO_WIDTH (&pool->video_info), + GST_VIDEO_INFO_HEIGHT (&pool->video_info), + GST_VIDEO_INFO_N_PLANES (&pool->video_info), + pool->video_info.offset, + pool->video_info.stride); + } + data->pool = gst_object_ref (pool); data->owner = NULL; data->header = spa_buffer_find_meta_data (b->buffer, SPA_META_Header, sizeof(*data->header)); @@ -208,6 +218,41 @@ no_more_buffers: } } +static const gchar ** +get_options (GstBufferPool * pool) +{ + static const gchar *options[] = { GST_BUFFER_POOL_OPTION_VIDEO_META, NULL }; + return options; +} + +static gboolean +set_config (GstBufferPool * pool, GstStructure * config) +{ + GstPipeWirePool *p = GST_PIPEWIRE_POOL (pool); + GstCaps *caps; + guint size, min_buffers, max_buffers; + gboolean has_video; + + if (!gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers, &max_buffers)) { + GST_WARNING_OBJECT (pool, "invalid config"); + return FALSE; + } + + if (caps == NULL) { + GST_WARNING_OBJECT (pool, "no caps in config"); + return FALSE; + } + + has_video = gst_video_info_from_caps (&p->video_info, caps); + + p->add_metavideo = has_video && gst_buffer_pool_config_has_option (config, + GST_BUFFER_POOL_OPTION_VIDEO_META); + + gst_buffer_pool_config_set_params (config, caps, p->video_info.size, min_buffers, max_buffers); + + return GST_BUFFER_POOL_CLASS (gst_pipewire_pool_parent_class)->set_config (pool, config); +} + static void flush_start (GstBufferPool * pool) { @@ -252,6 +297,8 @@ gst_pipewire_pool_class_init (GstPipeWirePoolClass * klass) gobject_class->finalize = gst_pipewire_pool_finalize; + bufferpool_class->get_options = get_options; + bufferpool_class->set_config = set_config; bufferpool_class->start = do_start; bufferpool_class->flush_start = flush_start; bufferpool_class->acquire_buffer = acquire_buffer; diff --git a/src/gst/gstpipewirepool.h b/src/gst/gstpipewirepool.h index acf81064f..06b6024a3 100644 --- a/src/gst/gstpipewirepool.h +++ b/src/gst/gstpipewirepool.h @@ -27,6 +27,8 @@ #include +#include + #include G_BEGIN_DECLS @@ -66,6 +68,9 @@ struct _GstPipeWirePool { struct pw_stream *stream; struct pw_type *t; + gboolean add_metavideo; + GstVideoInfo video_info; + GstAllocator *fd_allocator; GstAllocator *dmabuf_allocator; diff --git a/src/gst/gstpipewiresink.c b/src/gst/gstpipewiresink.c index 91bdfcc74..ff235cbd7 100644 --- a/src/gst/gstpipewiresink.c +++ b/src/gst/gstpipewiresink.c @@ -142,6 +142,7 @@ gst_pipewire_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) GstPipeWireSink *pwsink = GST_PIPEWIRE_SINK (bsink); gst_query_add_allocation_pool (query, GST_BUFFER_POOL_CAST (pwsink->pool), 0, 0, 0); + gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); return TRUE; } @@ -504,6 +505,19 @@ do_send_buffer (GstPipeWireSink *pwsink, GstBuffer *buffer) d->chunk->stride = 0; } + GstVideoMeta *meta = gst_buffer_get_video_meta (buffer); + if (meta) { + if (meta->n_planes == b->n_datas) { + for (i = 0; i < meta->n_planes; i++) { + struct spa_data *d = &b->datas[i]; + d->chunk->offset = meta->offset[i]; + d->chunk->stride = meta->stride[i]; + } + } else { + GST_ERROR ("plane num not matching, meta:%d buffer:%d", meta->n_planes, b->n_datas); + } + } + if ((res = pw_stream_queue_buffer (pwsink->stream, data->b)) < 0) { g_warning ("can't send buffer %s", spa_strerror(res)); } diff --git a/src/gst/gstpipewiresrc.c b/src/gst/gstpipewiresrc.c index 7243cc160..5c3043634 100644 --- a/src/gst/gstpipewiresrc.c +++ b/src/gst/gstpipewiresrc.c @@ -615,6 +615,24 @@ static GstBuffer *dequeue_buffer(GstPipeWireSrc *pwsrc) } } + if (pwsrc->is_video) { + GstVideoInfo *info = &pwsrc->video_info; + GstVideoMeta *meta = gst_buffer_add_video_meta_full (buf, GST_VIDEO_FRAME_FLAG_NONE, + GST_VIDEO_INFO_FORMAT (info), + GST_VIDEO_INFO_WIDTH (info), + GST_VIDEO_INFO_HEIGHT (info), + GST_VIDEO_INFO_N_PLANES (info), + info->offset, + info->stride); + + meta->n_planes = b->buffer->n_datas; + for (i = 0; i < b->buffer->n_datas; i++) { + struct spa_data *d = &b->buffer->datas[i]; + meta->offset[i] = d->chunk->offset; + meta->stride[i] = d->chunk->stride; + } + } + for (i = 0; i < b->buffer->n_datas; i++) { struct spa_data *d = &b->buffer->datas[i]; GstMemory *pmem = gst_buffer_peek_memory (data->buf, i); @@ -958,6 +976,10 @@ 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; + pwsrc->negotiated = pwsrc->caps != NULL; if (pwsrc->negotiated) { diff --git a/src/gst/gstpipewiresrc.h b/src/gst/gstpipewiresrc.h index e1def85b3..cd7fab19f 100644 --- a/src/gst/gstpipewiresrc.h +++ b/src/gst/gstpipewiresrc.h @@ -28,6 +28,8 @@ #include #include +#include + #include #include #include @@ -71,6 +73,9 @@ struct _GstPipeWireSrc { GstCaps *caps; + gboolean is_video; + GstVideoInfo video_info; + gboolean negotiated; gboolean flushing; gboolean started;