[PATCH v2] gstreamer: Add GstVideoMeta support

Hou Qi qi.hou at nxp.com
Fri Nov 8 10:21:13 CET 2024


GStreamer video-info calculated stride and offset may differ from
those used by the camera.

This patch enhances downstream plugin's support for videometa by
adding videometa support for libcamerasrc. It ensures that when
downstream plugin supports videometa by allocation query, libcamerasrc
also attaches videometa to buffer, preventing discrepancies
between the stride and offset calculated by video-info and camera.

Signed-off-by: Hou Qi <qi.hou at nxp.com>
---
 src/gstreamer/gstlibcamerapool.cpp | 28 ++++++++++++++++++++++++----
 src/gstreamer/gstlibcamerapool.h   |  2 +-
 src/gstreamer/gstlibcamerasrc.cpp  | 14 +++++++++++++-
 3 files changed, 38 insertions(+), 6 deletions(-)

diff --git a/src/gstreamer/gstlibcamerapool.cpp b/src/gstreamer/gstlibcamerapool.cpp
index 9cd7eccb..6593b3ca 100644
--- a/src/gstreamer/gstlibcamerapool.cpp
+++ b/src/gstreamer/gstlibcamerapool.cpp
@@ -135,16 +135,36 @@ gst_libcamera_pool_class_init(GstLibcameraPoolClass *klass)
 }
 
 GstLibcameraPool *
-gst_libcamera_pool_new(GstLibcameraAllocator *allocator, Stream *stream)
+gst_libcamera_pool_new(GstLibcameraAllocator *allocator, const StreamConfiguration &stream_cfg,
+		       GstCaps *caps, gboolean add_video_meta)
 {
 	auto *pool = GST_LIBCAMERA_POOL(g_object_new(GST_TYPE_LIBCAMERA_POOL, nullptr));
+	GstVideoInfo info;
 
 	pool->allocator = GST_LIBCAMERA_ALLOCATOR(g_object_ref(allocator));
-	pool->stream = stream;
-
-	gsize pool_size = gst_libcamera_allocator_get_pool_size(allocator, stream);
+	pool->stream = stream_cfg.stream();
+
+	if (caps && gst_video_info_from_caps(&info, caps)) {
+		guint k, stride;
+		gsize offset = 0;
+		for (k = 0; k < GST_VIDEO_INFO_N_PLANES(&info); k++) {
+			stride = gst_video_format_info_extrapolate_stride(info.finfo, k, stream_cfg.stride);
+			info.stride[k] = stride;
+			info.offset[k] = offset;
+			offset += stride * GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT(info.finfo, k, GST_VIDEO_INFO_HEIGHT(&info));
+		}
+	} else
+		add_video_meta = false;
+
+	gsize pool_size = gst_libcamera_allocator_get_pool_size(allocator, stream_cfg.stream());
 	for (gsize i = 0; i < pool_size; i++) {
 		GstBuffer *buffer = gst_buffer_new();
+		if (add_video_meta) {
+			gst_buffer_add_video_meta_full(buffer, 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);
+		}
 		pool->queue->push_back(buffer);
 	}
 
diff --git a/src/gstreamer/gstlibcamerapool.h b/src/gstreamer/gstlibcamerapool.h
index 2a7a9c77..8ad87cab 100644
--- a/src/gstreamer/gstlibcamerapool.h
+++ b/src/gstreamer/gstlibcamerapool.h
@@ -21,7 +21,7 @@
 G_DECLARE_FINAL_TYPE(GstLibcameraPool, gst_libcamera_pool, GST_LIBCAMERA, POOL, GstBufferPool)
 
 GstLibcameraPool *gst_libcamera_pool_new(GstLibcameraAllocator *allocator,
-					 libcamera::Stream *stream);
+					 const libcamera::StreamConfiguration &stream_cfg, GstCaps *caps, gboolean add_video_meta);
 
 libcamera::Stream *gst_libcamera_pool_get_stream(GstLibcameraPool *self);
 
diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp
index 8efa25f4..c05a31e7 100644
--- a/src/gstreamer/gstlibcamerasrc.cpp
+++ b/src/gstreamer/gstlibcamerasrc.cpp
@@ -497,9 +497,21 @@ gst_libcamera_src_negotiate(GstLibcameraSrc *self)
 	for (gsize i = 0; i < state->srcpads_.size(); i++) {
 		GstPad *srcpad = state->srcpads_[i];
 		const StreamConfiguration &stream_cfg = state->config_->at(i);
+		GstQuery *query = NULL;
+		gboolean add_video_meta = false;
+
+		g_autoptr(GstCaps) caps = gst_libcamera_stream_configuration_to_caps(stream_cfg);
+		gst_libcamera_framerate_to_caps(caps, element_caps);
+
+		query = gst_query_new_allocation(caps, false);
+		if (!gst_pad_peer_query(srcpad, query))
+			GST_DEBUG_OBJECT(self, "didn't get downstream ALLOCATION hints");
+		else
+			add_video_meta = gst_query_find_allocation_meta(query, GST_VIDEO_META_API_TYPE, NULL);
+		gst_query_unref(query);
 
 		GstLibcameraPool *pool = gst_libcamera_pool_new(self->allocator,
-								stream_cfg.stream());
+								stream_cfg, caps, add_video_meta);
 		g_signal_connect_swapped(pool, "buffer-notify",
 					 G_CALLBACK(gst_task_resume), self->task);
 
-- 
2.34.1



More information about the libcamera-devel mailing list