diff options
Diffstat (limited to 'src/gstreamer')
-rw-r--r-- | src/gstreamer/gstlibcamera-controls.cpp.in | 332 | ||||
-rw-r--r-- | src/gstreamer/gstlibcamera-controls.h | 43 | ||||
-rw-r--r-- | src/gstreamer/gstlibcamera-utils.cpp | 87 | ||||
-rw-r--r-- | src/gstreamer/gstlibcameraprovider.cpp | 15 | ||||
-rw-r--r-- | src/gstreamer/gstlibcamerasrc.cpp | 50 | ||||
-rw-r--r-- | src/gstreamer/gstlibcamerasrc.h | 31 | ||||
-rw-r--r-- | src/gstreamer/meson.build | 10 |
7 files changed, 448 insertions, 120 deletions
diff --git a/src/gstreamer/gstlibcamera-controls.cpp.in b/src/gstreamer/gstlibcamera-controls.cpp.in new file mode 100644 index 00000000..ace36b71 --- /dev/null +++ b/src/gstreamer/gstlibcamera-controls.cpp.in @@ -0,0 +1,332 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Jaslo Ziska + * + * GStreamer Camera Controls + * + * This file is auto-generated. Do not edit. + */ + +#include <vector> + +#include <libcamera/control_ids.h> +#include <libcamera/controls.h> +#include <libcamera/geometry.h> + +#include "gstlibcamera-controls.h" + +using namespace libcamera; + +static void value_set_rectangle(GValue *value, const Rectangle &rect) +{ + Point top_left = rect.topLeft(); + Size size = rect.size(); + + GValue x = G_VALUE_INIT; + g_value_init(&x, G_TYPE_INT); + g_value_set_int(&x, top_left.x); + gst_value_array_append_and_take_value(value, &x); + + GValue y = G_VALUE_INIT; + g_value_init(&y, G_TYPE_INT); + g_value_set_int(&y, top_left.y); + gst_value_array_append_and_take_value(value, &y); + + GValue width = G_VALUE_INIT; + g_value_init(&width, G_TYPE_INT); + g_value_set_int(&width, size.width); + gst_value_array_append_and_take_value(value, &width); + + GValue height = G_VALUE_INIT; + g_value_init(&height, G_TYPE_INT); + g_value_set_int(&x, size.height); + gst_value_array_append_and_take_value(value, &height); +} + +static Rectangle value_get_rectangle(const GValue *value) +{ + const GValue *r; + r = gst_value_array_get_value(value, 0); + int x = g_value_get_int(r); + r = gst_value_array_get_value(value, 1); + int y = g_value_get_int(r); + r = gst_value_array_get_value(value, 2); + int w = g_value_get_int(r); + r = gst_value_array_get_value(value, 3); + int h = g_value_get_int(r); + + return Rectangle(x, y, w, h); +} + +{% for vendor, ctrls in controls %} +{%- for ctrl in ctrls if ctrl.is_enum %} +static const GEnumValue {{ ctrl.name|snake_case }}_types[] = { +{%- for enum in ctrl.enum_values %} + { + controls::{{ ctrl.namespace }}{{ enum.name }}, + {{ enum.description|format_description|indent_str('\t\t') }}, + "{{ enum.gst_name }}" + }, +{%- endfor %} + {0, NULL, NULL} +}; + +#define TYPE_{{ ctrl.name|snake_case|upper }} \ + ({{ ctrl.name|snake_case }}_get_type()) +static GType {{ ctrl.name|snake_case }}_get_type() +{ + static GType {{ ctrl.name|snake_case }}_type = 0; + + if (!{{ ctrl.name|snake_case }}_type) + {{ ctrl.name|snake_case }}_type = + g_enum_register_static("{{ ctrl.name }}", + {{ ctrl.name|snake_case }}_types); + + return {{ ctrl.name|snake_case }}_type; +} +{% endfor %} +{%- endfor %} + +void GstCameraControls::installProperties(GObjectClass *klass, int lastPropId) +{ +{%- for vendor, ctrls in controls %} +{%- for ctrl in ctrls %} + +{%- set spec %} +{%- if ctrl.is_rectangle -%} +gst_param_spec_array( +{%- else -%} +g_param_spec_{{ ctrl.gtype }}( +{%- endif -%} +{%- if ctrl.is_array %} + "{{ ctrl.vendor_prefix }}{{ ctrl.name|kebab_case }}-value", + "{{ ctrl.name }} Value", + "One {{ ctrl.name }} element value", +{%- else %} + "{{ ctrl.vendor_prefix }}{{ ctrl.name|kebab_case }}", + "{{ ctrl.name }}", + {{ ctrl.description|format_description|indent_str('\t') }}, +{%- endif %} +{%- if ctrl.is_enum %} + TYPE_{{ ctrl.name|snake_case|upper }}, + {{ ctrl.default }}, +{%- elif ctrl.is_rectangle %} + g_param_spec_int( + "rectangle-value", + "Rectangle Value", + "One rectangle value, either x, y, width or height.", + {{ ctrl.min }}, {{ ctrl.max }}, {{ ctrl.default }}, + (GParamFlags) (GST_PARAM_CONTROLLABLE | G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS) + ), +{%- elif ctrl.gtype == 'boolean' %} + {{ ctrl.default }}, +{%- elif ctrl.gtype in ['float', 'int', 'int64', 'uchar'] %} + {{ ctrl.min }}, {{ ctrl.max }}, {{ ctrl.default }}, +{%- endif %} + (GParamFlags) (GST_PARAM_CONTROLLABLE | G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS) +) +{%- endset %} + + g_object_class_install_property( + klass, + lastPropId + controls::{{ ctrl.namespace }}{{ ctrl.name|snake_case|upper }}, +{%- if ctrl.is_array %} + gst_param_spec_array( + "{{ ctrl.vendor_prefix }}{{ ctrl.name|kebab_case }}", + "{{ ctrl.name }}", + {{ ctrl.description|format_description|indent_str('\t\t\t') }}, + {{ spec|indent_str('\t\t\t') }}, + (GParamFlags) (GST_PARAM_CONTROLLABLE | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS) + ) +{%- else %} + {{ spec|indent_str('\t\t') }} +{%- endif %} + ); +{%- endfor %} +{%- endfor %} +} + +bool GstCameraControls::getProperty(guint propId, GValue *value, + [[maybe_unused]] GParamSpec *pspec) +{ + if (!controls_acc_.contains(propId)) { + GST_WARNING("Control '%s' is not available, default value will " + "be returned", + controls::controls.at(propId)->name().c_str()); + return true; + } + const ControlValue &cv = controls_acc_.get(propId); + + switch (propId) { +{%- for vendor, ctrls in controls %} +{%- for ctrl in ctrls %} + + case controls::{{ ctrl.namespace }}{{ ctrl.name|snake_case|upper }}: { + auto control = cv.get<{{ ctrl.type }}>(); + +{%- if ctrl.is_array %} + for (size_t i = 0; i < control.size(); ++i) { + GValue element = G_VALUE_INIT; +{%- if ctrl.is_rectangle %} + g_value_init(&element, GST_TYPE_PARAM_ARRAY_LIST); + value_set_rectangle(&element, control[i]); +{%- else %} + g_value_init(&element, G_TYPE_{{ ctrl.gtype|upper }}); + g_value_set_{{ ctrl.gtype }}(&element, control[i]); +{%- endif %} + gst_value_array_append_and_take_value(value, &element); + } +{%- else %} +{%- if ctrl.is_rectangle %} + value_set_rectangle(value, control); +{%- else %} + g_value_set_{{ ctrl.gtype }}(value, control); +{%- endif %} +{%- endif %} + + return true; + } +{%- endfor %} +{%- endfor %} + + default: + return false; + } +} + +bool GstCameraControls::setProperty(guint propId, const GValue *value, + [[maybe_unused]] GParamSpec *pspec) +{ + /* + * Check whether the camera capabilities are already available. + * They might not be available if the pipeline has not started yet. + */ + if (!capabilities_.empty()) { + /* If so, check that the control is supported by the camera. */ + const ControlId *cid = capabilities_.idmap().at(propId); + auto info = capabilities_.find(cid); + + if (info == capabilities_.end()) { + GST_WARNING("Control '%s' is not supported by the " + "camera and will be ignored", + cid->name().c_str()); + return true; + } + } + + switch (propId) { +{%- for vendor, ctrls in controls %} +{%- for ctrl in ctrls %} + + case controls::{{ ctrl.namespace }}{{ ctrl.name|snake_case|upper }}: { + ControlValue control; +{%- if ctrl.is_array %} + size_t size = gst_value_array_get_size(value); +{%- if ctrl.size != 0 %} + if (size != {{ ctrl.size }}) { + GST_ERROR("Incorrect array size for control " + "'{{ ctrl.name|kebab_case }}', must be of " + "size {{ ctrl.size }}"); + return true; + } +{%- endif %} + + std::vector<{{ ctrl.element_type }}> values(size); + for (size_t i = 0; i < size; ++i) { + const GValue *element = + gst_value_array_get_value(value, i); +{%- if ctrl.is_rectangle %} + if (gst_value_array_get_size(element) != 4) { + GST_ERROR("Rectangle in control " + "'{{ ctrl.name|kebab_case }}' at" + "index %zu must be an array of size 4", + i); + return true; + } + values[i] = value_get_rectangle(element); +{%- else %} + values[i] = g_value_get_{{ ctrl.gtype }}(element); +{%- endif %} + } + +{%- if ctrl.size == 0 %} + control.set(Span<const {{ ctrl.element_type }}>(values.data(), + size)); +{%- else %} + control.set(Span<const {{ ctrl.element_type }}, + {{ ctrl.size }}>(values.data(), + {{ ctrl.size }})); +{%- endif %} +{%- else %} +{%- if ctrl.is_rectangle %} + if (gst_value_array_get_size(value) != 4) { + GST_ERROR("Rectangle in control " + "'{{ ctrl.name|kebab_case }}' must be an " + "array of size 4"); + return true; + } + Rectangle val = value_get_rectangle(value); +{%- else %} + auto val = g_value_get_{{ ctrl.gtype }}(value); +{%- endif %} + control.set(val); +{%- endif %} + controls_.set(propId, control); + controls_acc_.set(propId, control); + return true; + } +{%- endfor %} +{%- endfor %} + + default: + return false; + } +} + +void GstCameraControls::setCamera(const std::shared_ptr<libcamera::Camera> &cam) +{ + capabilities_ = cam->controls(); + + /* + * Check the controls which were set before the camera capabilities were + * known. This is required because GStreamer may set properties before + * the pipeline has started and thus before the camera was known. + */ + ControlList new_controls; + for (auto control = controls_acc_.begin(); + control != controls_acc_.end(); + ++control) { + unsigned int id = control->first; + ControlValue value = control->second; + + const ControlId *cid = capabilities_.idmap().at(id); + auto info = capabilities_.find(cid); + + /* Only add controls which are supported. */ + if (info != capabilities_.end()) + new_controls.set(id, value); + else + GST_WARNING("Control '%s' is not supported by the " + "camera and will be ignored", + cid->name().c_str()); + } + + controls_acc_ = new_controls; + controls_ = new_controls; +} + +void GstCameraControls::applyControls(std::unique_ptr<libcamera::Request> &request) +{ + request->controls().merge(controls_); + controls_.clear(); +} + +void GstCameraControls::readMetadata(libcamera::Request *request) +{ + controls_acc_.merge(request->metadata(), + ControlList::MergePolicy::OverwriteExisting); +} diff --git a/src/gstreamer/gstlibcamera-controls.h b/src/gstreamer/gstlibcamera-controls.h new file mode 100644 index 00000000..749220b5 --- /dev/null +++ b/src/gstreamer/gstlibcamera-controls.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Collabora Ltd. + * Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> + * + * GStreamer Camera Controls + */ + +#pragma once + +#include <memory> + +#include <libcamera/camera.h> +#include <libcamera/controls.h> +#include <libcamera/request.h> + +#include "gstlibcamerasrc.h" + +namespace libcamera { + +class GstCameraControls +{ +public: + static void installProperties(GObjectClass *klass, int lastProp); + + bool getProperty(guint propId, GValue *value, GParamSpec *pspec); + bool setProperty(guint propId, const GValue *value, GParamSpec *pspec); + + void setCamera(const std::shared_ptr<libcamera::Camera> &cam); + + void applyControls(std::unique_ptr<libcamera::Request> &request); + void readMetadata(libcamera::Request *request); + +private: + /* Supported controls and limits of camera. */ + ControlInfoMap capabilities_; + /* Set of user modified controls. */ + ControlList controls_; + /* Accumulator of all controls ever set and metadata returned by camera */ + ControlList controls_acc_; +}; + +} /* namespace libcamera */ diff --git a/src/gstreamer/gstlibcamera-utils.cpp b/src/gstreamer/gstlibcamera-utils.cpp index 79f71246..732987ef 100644 --- a/src/gstreamer/gstlibcamera-utils.cpp +++ b/src/gstreamer/gstlibcamera-utils.cpp @@ -254,52 +254,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 * @@ -474,6 +472,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 { diff --git a/src/gstreamer/gstlibcameraprovider.cpp b/src/gstreamer/gstlibcameraprovider.cpp index 4fb1b007..5da96ea3 100644 --- a/src/gstreamer/gstlibcameraprovider.cpp +++ b/src/gstreamer/gstlibcameraprovider.cpp @@ -33,7 +33,6 @@ GST_DEBUG_CATEGORY_STATIC(provider_debug); enum { PROP_DEVICE_NAME = 1, - PROP_AUTO_FOCUS_MODE = 2, }; #define GST_TYPE_LIBCAMERA_DEVICE gst_libcamera_device_get_type() @@ -43,7 +42,6 @@ G_DECLARE_FINAL_TYPE(GstLibcameraDevice, gst_libcamera_device, struct _GstLibcameraDevice { GstDevice parent; gchar *name; - controls::AfModeEnum auto_focus_mode = controls::AfModeManual; }; G_DEFINE_TYPE(GstLibcameraDevice, gst_libcamera_device, GST_TYPE_DEVICE) @@ -60,7 +58,6 @@ gst_libcamera_device_create_element(GstDevice *device, const gchar *name) g_assert(source); g_object_set(source, "camera-name", GST_LIBCAMERA_DEVICE(device)->name, nullptr); - g_object_set(source, "auto-focus-mode", GST_LIBCAMERA_DEVICE(device)->auto_focus_mode, nullptr); return source; } @@ -87,9 +84,6 @@ gst_libcamera_device_set_property(GObject *object, guint prop_id, case PROP_DEVICE_NAME: device->name = g_value_dup_string(value); break; - case PROP_AUTO_FOCUS_MODE: - device->auto_focus_mode = static_cast<controls::AfModeEnum>(g_value_get_enum(value)); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -129,15 +123,6 @@ gst_libcamera_device_class_init(GstLibcameraDeviceClass *klass) (GParamFlags)(G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property(object_class, PROP_DEVICE_NAME, pspec); - - pspec = g_param_spec_enum("auto-focus-mode", - "Set auto-focus mode", - "Available options: AfModeManual, " - "AfModeAuto or AfModeContinuous.", - gst_libcamera_auto_focus_get_type(), - static_cast<gint>(controls::AfModeManual), - G_PARAM_WRITABLE); - g_object_class_install_property(object_class, PROP_AUTO_FOCUS_MODE, pspec); } static GstDevice * diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp index 912a8d55..8efa25f4 100644 --- a/src/gstreamer/gstlibcamerasrc.cpp +++ b/src/gstreamer/gstlibcamerasrc.cpp @@ -37,10 +37,11 @@ #include <gst/base/base.h> +#include "gstlibcamera-controls.h" +#include "gstlibcamera-utils.h" #include "gstlibcameraallocator.h" #include "gstlibcamerapad.h" #include "gstlibcamerapool.h" -#include "gstlibcamera-utils.h" using namespace libcamera; @@ -128,6 +129,7 @@ struct GstLibcameraSrcState { ControlList initControls_; guint group_id_; + GstCameraControls controls_; int queueRequest(); void requestCompleted(Request *request); @@ -142,7 +144,6 @@ struct _GstLibcameraSrc { GstTask *task; gchar *camera_name; - controls::AfModeEnum auto_focus_mode = controls::AfModeManual; std::atomic<GstEvent *> pending_eos; @@ -154,7 +155,7 @@ struct _GstLibcameraSrc { enum { PROP_0, PROP_CAMERA_NAME, - PROP_AUTO_FOCUS_MODE, + PROP_LAST }; static void gst_libcamera_src_child_proxy_init(gpointer g_iface, @@ -185,6 +186,9 @@ int GstLibcameraSrcState::queueRequest() if (!request) return -ENOMEM; + /* Apply controls */ + controls_.applyControls(request); + std::unique_ptr<RequestWrap> wrap = std::make_unique<RequestWrap>(std::move(request)); @@ -228,6 +232,9 @@ GstLibcameraSrcState::requestCompleted(Request *request) { GLibLocker locker(&lock_); + + controls_.readMetadata(request); + wrap = std::move(queuedRequests_.front()); queuedRequests_.pop(); } @@ -410,6 +417,8 @@ gst_libcamera_src_open(GstLibcameraSrc *self) return false; } + self->state->controls_.setCamera(cam); + cam->requestCompleted.connect(self->state, &GstLibcameraSrcState::requestCompleted); /* No need to lock here, we didn't start our threads yet. */ @@ -663,18 +672,6 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread, gst_pad_push_event(srcpad, gst_event_new_segment(&segment)); } - if (self->auto_focus_mode != controls::AfModeManual) { - const ControlInfoMap &infoMap = state->cam_->controls(); - if (infoMap.find(&controls::AfMode) != infoMap.end()) { - state->initControls_.set(controls::AfMode, self->auto_focus_mode); - } else { - GST_ELEMENT_ERROR(self, RESOURCE, SETTINGS, - ("Failed to enable auto focus"), - ("AfMode not supported by this camera, " - "please retry with 'auto-focus-mode=AfModeManual'")); - } - } - ret = state->cam_->start(&state->initControls_); if (ret) { GST_ELEMENT_ERROR(self, RESOURCE, SETTINGS, @@ -736,17 +733,16 @@ gst_libcamera_src_set_property(GObject *object, guint prop_id, { GLibLocker lock(GST_OBJECT(object)); GstLibcameraSrc *self = GST_LIBCAMERA_SRC(object); + GstLibcameraSrcState *state = self->state; switch (prop_id) { case PROP_CAMERA_NAME: g_free(self->camera_name); self->camera_name = g_value_dup_string(value); break; - case PROP_AUTO_FOCUS_MODE: - self->auto_focus_mode = static_cast<controls::AfModeEnum>(g_value_get_enum(value)); - break; default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + if (!state->controls_.setProperty(prop_id - PROP_LAST, value, pspec)) + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } @@ -757,16 +753,15 @@ gst_libcamera_src_get_property(GObject *object, guint prop_id, GValue *value, { GLibLocker lock(GST_OBJECT(object)); GstLibcameraSrc *self = GST_LIBCAMERA_SRC(object); + GstLibcameraSrcState *state = self->state; switch (prop_id) { case PROP_CAMERA_NAME: g_value_set_string(value, self->camera_name); break; - case PROP_AUTO_FOCUS_MODE: - g_value_set_enum(value, static_cast<gint>(self->auto_focus_mode)); - break; default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + if (!state->controls_.getProperty(prop_id - PROP_LAST, value, pspec)) + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } @@ -967,14 +962,7 @@ gst_libcamera_src_class_init(GstLibcameraSrcClass *klass) | G_PARAM_STATIC_STRINGS)); g_object_class_install_property(object_class, PROP_CAMERA_NAME, spec); - spec = g_param_spec_enum("auto-focus-mode", - "Set auto-focus mode", - "Available options: AfModeManual, " - "AfModeAuto or AfModeContinuous.", - gst_libcamera_auto_focus_get_type(), - static_cast<gint>(controls::AfModeManual), - G_PARAM_WRITABLE); - g_object_class_install_property(object_class, PROP_AUTO_FOCUS_MODE, spec); + GstCameraControls::installProperties(object_class, PROP_LAST); } /* GstChildProxy implementation */ diff --git a/src/gstreamer/gstlibcamerasrc.h b/src/gstreamer/gstlibcamerasrc.h index fd1f8193..a27db9ca 100644 --- a/src/gstreamer/gstlibcamerasrc.h +++ b/src/gstreamer/gstlibcamerasrc.h @@ -8,8 +8,6 @@ #pragma once -#include <libcamera/control_ids.h> - #include <gst/gst.h> G_BEGIN_DECLS @@ -19,32 +17,3 @@ G_DECLARE_FINAL_TYPE(GstLibcameraSrc, gst_libcamera_src, GST_LIBCAMERA, SRC, GstElement) G_END_DECLS - -inline GType -gst_libcamera_auto_focus_get_type() -{ - static GType type = 0; - static const GEnumValue values[] = { - { - static_cast<gint>(libcamera::controls::AfModeManual), - "AfModeManual", - "manual-focus", - }, - { - static_cast<gint>(libcamera::controls::AfModeAuto), - "AfModeAuto", - "automatic-auto-focus", - }, - { - static_cast<gint>(libcamera::controls::AfModeContinuous), - "AfModeContinuous", - "continuous-auto-focus", - }, - { 0, NULL, NULL } - }; - - if (!type) - type = g_enum_register_static("GstLibcameraAutoFocus", values); - - return type; -} diff --git a/src/gstreamer/meson.build b/src/gstreamer/meson.build index c2a01e7b..6b7e53b5 100644 --- a/src/gstreamer/meson.build +++ b/src/gstreamer/meson.build @@ -25,6 +25,16 @@ libcamera_gst_sources = [ 'gstlibcamerasrc.cpp', ] +# Generate gstreamer control properties + +gen_gst_controls_template = files('gstlibcamera-controls.cpp.in') +libcamera_gst_sources += custom_target('gstlibcamera-controls.cpp', + input : controls_files, + output : 'gstlibcamera-controls.cpp', + command : [gen_gst_controls, '-o', '@OUTPUT@', + '-t', gen_gst_controls_template, '@INPUT@'], + env : py_build_env) + libcamera_gst_cpp_args = [ '-DVERSION="@0@"'.format(libcamera_git_version), '-DPACKAGE="@0@"'.format(meson.project_name()), |