[libcamera-devel] [PATCH v1 02/23] gst: Add utility to convert StreamFormats to GstCaps

Nicolas Dufresne nicolas at ndufresne.ca
Wed Jan 29 04:31:49 CET 2020


From: Nicolas Dufresne <nicolas.dufresne at collabora.com>

This transform the basic information found in StreamFormats to GstCaps.
This can be handy to reply to early caps query or inside a device
provider. Note that we ignored generated range as they are harmful to
caps negotiation. We also don't simplify the caps for readability
reasons, so some of the discrete value may be included in a range.

Signed-off-by: Nicolas Dufresne <nicolas.dufresne at collabora.com>
---
 src/gstreamer/gstlibcamera-utils.cpp | 102 +++++++++++++++++++++++++++
 src/gstreamer/gstlibcamera-utils.h   |  18 +++++
 src/gstreamer/meson.build            |   1 +
 3 files changed, 121 insertions(+)
 create mode 100644 src/gstreamer/gstlibcamera-utils.cpp
 create mode 100644 src/gstreamer/gstlibcamera-utils.h

diff --git a/src/gstreamer/gstlibcamera-utils.cpp b/src/gstreamer/gstlibcamera-utils.cpp
new file mode 100644
index 0000000..2540be0
--- /dev/null
+++ b/src/gstreamer/gstlibcamera-utils.cpp
@@ -0,0 +1,102 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2020, Collabora Ltd.
+ *     Author: Nicolas Dufresne <nicolas.dufresne at collabora.com>
+ *
+ * gstlibcamera-utils.c - GStreamer Libcamera Utility Function
+ */
+
+#include "gstlibcamera-utils.h"
+#include <linux/drm_fourcc.h>
+
+using namespace libcamera;
+
+static struct {
+	GstVideoFormat gst_format;
+	guint drm_fourcc;
+} format_map[] = {
+	{ GST_VIDEO_FORMAT_ENCODED, DRM_FORMAT_MJPEG },
+	{ GST_VIDEO_FORMAT_RGB, DRM_FORMAT_BGR888 },
+	{ GST_VIDEO_FORMAT_BGR, DRM_FORMAT_RGB888 },
+	{ GST_VIDEO_FORMAT_ARGB, DRM_FORMAT_BGRA8888 },
+	{ GST_VIDEO_FORMAT_NV12, DRM_FORMAT_NV12 },
+	{ GST_VIDEO_FORMAT_NV21, DRM_FORMAT_NV21 },
+	{ GST_VIDEO_FORMAT_NV16, DRM_FORMAT_NV16 },
+	{ GST_VIDEO_FORMAT_NV61, DRM_FORMAT_NV61 },
+	{ GST_VIDEO_FORMAT_NV24, DRM_FORMAT_NV24 },
+	/* { GST_VIDEO_FORMAT_NV42,    DRM_FORMAT_NV42 }, */
+	{ GST_VIDEO_FORMAT_UYVY, DRM_FORMAT_UYVY },
+	{ GST_VIDEO_FORMAT_VYUY, DRM_FORMAT_VYUY },
+	{ GST_VIDEO_FORMAT_YUY2, DRM_FORMAT_YUYV },
+	{ GST_VIDEO_FORMAT_YVYU, DRM_FORMAT_YVYU },
+};
+#define FORMAT_MAP_SIZE G_N_ELEMENTS(format_map)
+
+static inline GstVideoFormat
+drm_to_gst_format(guint drm_fourcc)
+{
+	for (guint i = 0; i < FORMAT_MAP_SIZE; i++)
+		if (format_map[i].drm_fourcc == drm_fourcc)
+			return format_map[i].gst_format;
+	return GST_VIDEO_FORMAT_UNKNOWN;
+}
+
+static GstStructure *
+bare_structure_from_fourcc(guint fourcc)
+{
+	GstVideoFormat gst_format = drm_to_gst_format(fourcc);
+
+	if (gst_format == GST_VIDEO_FORMAT_UNKNOWN)
+		return NULL;
+
+	if (gst_format != GST_VIDEO_FORMAT_ENCODED)
+		return gst_structure_new("video/x-raw", "format", G_TYPE_STRING,
+					 gst_video_format_to_string(gst_format), NULL);
+
+	switch (fourcc) {
+	case DRM_FORMAT_MJPEG:
+		return gst_structure_new_empty("image/jpeg");
+	default:
+		break;
+	}
+
+	return NULL;
+}
+
+GstCaps *
+gst_libcamera_stream_formats_to_caps(const StreamFormats &formats)
+{
+	GstCaps *caps = gst_caps_new_empty();
+
+	for (unsigned int fourcc : formats.pixelformats()) {
+		g_autoptr(GstStructure) bare_s = bare_structure_from_fourcc(fourcc);
+
+		if (!bare_s) {
+			GST_WARNING("Unsupported DRM format %" GST_FOURCC_FORMAT,
+				    GST_FOURCC_ARGS(fourcc));
+			continue;
+		}
+
+		for (const Size &size : formats.sizes(fourcc)) {
+			GstStructure *s = gst_structure_copy(bare_s);
+			gst_structure_set(s,
+					  "width", G_TYPE_INT, size.width,
+					  "height", G_TYPE_INT, size.height,
+					  NULL);
+			gst_caps_append_structure(caps, s);
+		}
+
+		const SizeRange &range = formats.range(fourcc);
+		if (range.hStep && range.vStep) {
+			GstStructure *s = gst_structure_copy(bare_s);
+
+			gst_structure_set(s,
+				"width", GST_TYPE_INT_RANGE, range.min.width, range.max.width, range.hStep,
+				"height", GST_TYPE_INT_RANGE, range.min.height, range.max.height, range.vStep,
+				NULL);
+			gst_caps_append_structure(caps, s);
+		}
+	}
+
+	return caps;
+}
diff --git a/src/gstreamer/gstlibcamera-utils.h b/src/gstreamer/gstlibcamera-utils.h
new file mode 100644
index 0000000..4545512
--- /dev/null
+++ b/src/gstreamer/gstlibcamera-utils.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2020, Collabora Ltd.
+ *     Author: Nicolas Dufresne <nicolas.dufresne at collabora.com>
+ *
+ * gstlibcamera-utils.h - GStreamer Libcamera Utility Functions
+ */
+
+#include <gst/gst.h>
+#include <gst/video/video.h>
+
+#include <libcamera/stream.h>
+
+#ifndef __GST_LIBCAMERA_UTILS_H_
+
+GstCaps *gst_libcamera_stream_formats_to_caps(const libcamera::StreamFormats &formats);
+
+#endif /* __GST_LIBCAMERA_UTILS_H_ */
diff --git a/src/gstreamer/meson.build b/src/gstreamer/meson.build
index 32d4233..39a34e7 100644
--- a/src/gstreamer/meson.build
+++ b/src/gstreamer/meson.build
@@ -1,5 +1,6 @@
 libcamera_gst_sources = [
     'gstlibcamera.c',
+    'gstlibcamera-utils.cpp',
     'gstlibcamerasrc.cpp',
 ]
 
-- 
2.24.1



More information about the libcamera-devel mailing list