summaryrefslogtreecommitdiff
path: root/src/gstreamer/gstlibcamera-utils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gstreamer/gstlibcamera-utils.cpp')
-rw-r--r--src/gstreamer/gstlibcamera-utils.cpp172
1 files changed, 113 insertions, 59 deletions
diff --git a/src/gstreamer/gstlibcamera-utils.cpp b/src/gstreamer/gstlibcamera-utils.cpp
index 469ac810..a548b0c1 100644
--- a/src/gstreamer/gstlibcamera-utils.cpp
+++ b/src/gstreamer/gstlibcamera-utils.cpp
@@ -3,7 +3,7 @@
* Copyright (C) 2020, Collabora Ltd.
* Author: Nicolas Dufresne <nicolas.dufresne@collabora.com>
*
- * gstlibcamera-utils.c - GStreamer libcamera Utility Function
+ * GStreamer libcamera Utility Function
*/
#include "gstlibcamera-utils.h"
@@ -74,6 +74,7 @@ static struct {
{ GST_VIDEO_FORMAT_I420, formats::YUV420 },
{ GST_VIDEO_FORMAT_YV12, formats::YVU420 },
{ GST_VIDEO_FORMAT_Y42B, formats::YUV422 },
+ { GST_VIDEO_FORMAT_Y444, formats::YUV444 },
/* YUV Packed */
{ GST_VIDEO_FORMAT_UYVY, formats::UYVY },
@@ -85,7 +86,7 @@ static struct {
};
static GstVideoColorimetry
-colorimetry_from_colorspace(const ColorSpace &colorSpace)
+colorimetry_from_colorspace(const ColorSpace &colorSpace, GstVideoTransferFunction transfer)
{
GstVideoColorimetry colorimetry;
@@ -113,6 +114,8 @@ colorimetry_from_colorspace(const ColorSpace &colorSpace)
break;
case ColorSpace::TransferFunction::Rec709:
colorimetry.transfer = GST_VIDEO_TRANSFER_BT709;
+ if (transfer != GST_VIDEO_TRANSFER_UNKNOWN)
+ colorimetry.transfer = transfer;
break;
}
@@ -144,7 +147,8 @@ colorimetry_from_colorspace(const ColorSpace &colorSpace)
}
static std::optional<ColorSpace>
-colorspace_from_colorimetry(const GstVideoColorimetry &colorimetry)
+colorspace_from_colorimetry(const GstVideoColorimetry &colorimetry,
+ GstVideoTransferFunction *transfer)
{
std::optional<ColorSpace> colorspace = ColorSpace::Raw;
@@ -188,6 +192,7 @@ colorspace_from_colorimetry(const GstVideoColorimetry &colorimetry)
case GST_VIDEO_TRANSFER_BT2020_12:
case GST_VIDEO_TRANSFER_BT709:
colorspace->transferFunction = ColorSpace::TransferFunction::Rec709;
+ *transfer = colorimetry.transfer;
break;
default:
GST_WARNING("Colorimetry transfer function %d not mapped in gstlibcamera",
@@ -254,52 +259,50 @@ gst_format_to_pixel_format(GstVideoFormat gst_format)
return PixelFormat{};
}
+static const struct {
+ PixelFormat format;
+ const gchar *name;
+} bayer_map[]{
+ { formats::SBGGR8, "bggr" },
+ { formats::SGBRG8, "gbrg" },
+ { formats::SGRBG8, "grbg" },
+ { formats::SRGGB8, "rggb" },
+ { formats::SBGGR10, "bggr10le" },
+ { formats::SGBRG10, "gbrg10le" },
+ { formats::SGRBG10, "grbg10le" },
+ { formats::SRGGB10, "rggb10le" },
+ { formats::SBGGR12, "bggr12le" },
+ { formats::SGBRG12, "gbrg12le" },
+ { formats::SGRBG12, "grbg12le" },
+ { formats::SRGGB12, "rggb12le" },
+ { formats::SBGGR14, "bggr14le" },
+ { formats::SGBRG14, "gbrg14le" },
+ { formats::SGRBG14, "grbg14le" },
+ { formats::SRGGB14, "rggb14le" },
+ { formats::SBGGR16, "bggr16le" },
+ { formats::SGBRG16, "gbrg16le" },
+ { formats::SGRBG16, "grbg16le" },
+ { formats::SRGGB16, "rggb16le" },
+};
+
static const gchar *
-bayer_format_to_string(int format)
+bayer_format_to_string(PixelFormat format)
{
- switch (format) {
- case formats::SBGGR8:
- return "bggr";
- case formats::SGBRG8:
- return "gbrg";
- case formats::SGRBG8:
- return "grbg";
- case formats::SRGGB8:
- return "rggb";
- case formats::SBGGR10:
- return "bggr10le";
- case formats::SGBRG10:
- return "gbrg10le";
- case formats::SGRBG10:
- return "grbg10le";
- case formats::SRGGB10:
- return "rggb10le";
- case formats::SBGGR12:
- return "bggr12le";
- case formats::SGBRG12:
- return "gbrg12le";
- case formats::SGRBG12:
- return "grbg12le";
- case formats::SRGGB12:
- return "rggb12le";
- case formats::SBGGR14:
- return "bggr14le";
- case formats::SGBRG14:
- return "gbrg14le";
- case formats::SGRBG14:
- return "grbg14le";
- case formats::SRGGB14:
- return "rggb14le";
- case formats::SBGGR16:
- return "bggr16le";
- case formats::SGBRG16:
- return "gbrg16le";
- case formats::SGRBG16:
- return "grbg16le";
- case formats::SRGGB16:
- return "rggb16le";
+ for (auto &b : bayer_map) {
+ if (b.format == format)
+ return b.name;
}
- return NULL;
+ return nullptr;
+}
+
+static PixelFormat
+bayer_format_from_string(const gchar *name)
+{
+ for (auto &b : bayer_map) {
+ if (strcmp(b.name, name) == 0)
+ return b.format;
+ }
+ return PixelFormat{};
}
static GstStructure *
@@ -359,13 +362,21 @@ gst_libcamera_stream_formats_to_caps(const StreamFormats &formats)
GValue val = G_VALUE_INIT;
g_value_init(&val, GST_TYPE_INT_RANGE);
- gst_value_set_int_range_step(&val, range.min.width, range.max.width, range.hStep);
- gst_structure_set_value(s, "width", &val);
- gst_value_set_int_range_step(&val, range.min.height, range.max.height, range.vStep);
- gst_structure_set_value(s, "height", &val);
+ if (range.min.width == range.max.width) {
+ gst_structure_set(s, "width", G_TYPE_INT, range.min.width, nullptr);
+ } else {
+ gst_value_set_int_range_step(&val, range.min.width, range.max.width, range.hStep);
+ gst_structure_set_value(s, "width", &val);
+ }
+ if (range.min.height == range.max.height) {
+ gst_structure_set(s, "height", G_TYPE_INT, range.min.height, nullptr);
+ } else {
+ gst_value_set_int_range_step(&val, range.min.height, range.max.height, range.vStep);
+ gst_structure_set_value(s, "height", &val);
+ }
g_value_unset(&val);
- gst_caps_append_structure(caps, s);
+ caps = gst_caps_merge_structure(caps, s);
}
}
@@ -373,7 +384,8 @@ gst_libcamera_stream_formats_to_caps(const StreamFormats &formats)
}
GstCaps *
-gst_libcamera_stream_configuration_to_caps(const StreamConfiguration &stream_cfg)
+gst_libcamera_stream_configuration_to_caps(const StreamConfiguration &stream_cfg,
+ GstVideoTransferFunction transfer)
{
GstCaps *caps = gst_caps_new_empty();
GstStructure *s = bare_structure_from_format(stream_cfg.pixelFormat);
@@ -384,8 +396,8 @@ gst_libcamera_stream_configuration_to_caps(const StreamConfiguration &stream_cfg
nullptr);
if (stream_cfg.colorSpace) {
- GstVideoColorimetry colorimetry = colorimetry_from_colorspace(stream_cfg.colorSpace.value());
- gchar *colorimetry_str = gst_video_colorimetry_to_string(&colorimetry);
+ GstVideoColorimetry colorimetry = colorimetry_from_colorspace(stream_cfg.colorSpace.value(), transfer);
+ g_autofree gchar *colorimetry_str = gst_video_colorimetry_to_string(&colorimetry);
if (colorimetry_str)
gst_structure_set(s, "colorimetry", G_TYPE_STRING, colorimetry_str, nullptr);
@@ -399,9 +411,8 @@ gst_libcamera_stream_configuration_to_caps(const StreamConfiguration &stream_cfg
return caps;
}
-void
-gst_libcamera_configure_stream_from_caps(StreamConfiguration &stream_cfg,
- GstCaps *caps)
+void gst_libcamera_configure_stream_from_caps(StreamConfiguration &stream_cfg,
+ GstCaps *caps, GstVideoTransferFunction *transfer)
{
GstVideoFormat gst_format = pixel_format_to_gst_format(stream_cfg.pixelFormat);
guint i;
@@ -466,6 +477,9 @@ gst_libcamera_configure_stream_from_caps(StreamConfiguration &stream_cfg,
const gchar *format = gst_structure_get_string(s, "format");
gst_format = gst_video_format_from_string(format);
stream_cfg.pixelFormat = gst_format_to_pixel_format(gst_format);
+ } else if (gst_structure_has_name(s, "video/x-bayer")) {
+ const gchar *format = gst_structure_get_string(s, "format");
+ stream_cfg.pixelFormat = bayer_format_from_string(format);
} else if (gst_structure_has_name(s, "image/jpeg")) {
stream_cfg.pixelFormat = formats::MJPEG;
} else {
@@ -480,13 +494,16 @@ gst_libcamera_configure_stream_from_caps(StreamConfiguration &stream_cfg,
/* Configure colorimetry */
if (gst_structure_has_field(s, "colorimetry")) {
- const gchar *colorimetry_str = gst_structure_get_string(s, "colorimetry");
+ const gchar *colorimetry_str;
GstVideoColorimetry colorimetry;
+ gst_structure_fixate_field(s, "colorimetry");
+ colorimetry_str = gst_structure_get_string(s, "colorimetry");
+
if (!gst_video_colorimetry_from_string(&colorimetry, colorimetry_str))
g_critical("Invalid colorimetry %s", colorimetry_str);
- stream_cfg.colorSpace = colorspace_from_colorimetry(colorimetry);
+ stream_cfg.colorSpace = colorspace_from_colorimetry(colorimetry, transfer);
}
}
@@ -582,6 +599,43 @@ gst_task_resume(GstTask *task)
}
#endif
+#if !GST_CHECK_VERSION(1, 22, 0)
+/*
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ * Library <2002> Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) <2007> David A. Schleef <ds@schleef.org>
+ */
+/*
+ * This function has been imported directly from the gstreamer project to
+ * support backwards compatibility and should be removed when the older version
+ * is no longer supported.
+ */
+gint gst_video_format_info_extrapolate_stride(const GstVideoFormatInfo *finfo, gint plane, gint stride)
+{
+ gint estride;
+ gint comp[GST_VIDEO_MAX_COMPONENTS];
+ gint i;
+
+ /* There is nothing to extrapolate on first plane. */
+ if (plane == 0)
+ return stride;
+
+ gst_video_format_info_component(finfo, plane, comp);
+
+ /*
+ * For now, all planar formats have a single component on first plane, but
+ * if there was a planar format with more, we'd have to make a ratio of the
+ * number of component on the first plane against the number of component on
+ * the current plane.
+ */
+ estride = 0;
+ for (i = 0; i < GST_VIDEO_MAX_COMPONENTS && comp[i] >= 0; i++)
+ estride += GST_VIDEO_FORMAT_INFO_SCALE_WIDTH(finfo, comp[i], stride);
+
+ return estride;
+}
+#endif
+
G_LOCK_DEFINE_STATIC(cm_singleton_lock);
static std::weak_ptr<CameraManager> cm_singleton_ptr;