diff --git a/src/gstreamer/gstlibcamera-controls.cpp b/src/gstreamer/gstlibcamera-controls.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6b458b1fa48ac9f59e67f625f9019da3f8ba9c55 --- /dev/null +++ b/src/gstreamer/gstlibcamera-controls.cpp @@ -0,0 +1,545 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Collabora Ltd. + * Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> + * + * gstlibcamera-controls.cpp - GStreamer Camera Controls + */ + +#include "gstlibcamera-controls.h" + +#include <libcamera/control_ids.h> + +using namespace libcamera; + +#define AE_CONSTRAINT_MODE (ae_constraint_mode_get_type()) +static const GEnumValue ae_constraint_modes[] = { + {controls::ConstraintNormal, "Default constraint mode. " + "This mode aims to balance the exposure of different parts of the " + "image so as to reach a reasonable average level. However, highlights " + "in the image may appear over-exposed and lowlights may appear " + "under-exposed", "normal"}, + {controls::ConstraintHighlight, + "Highlight constraint mode. " + "This mode adjusts the exposure levels in order to try and avoid " + "over-exposing the brightest parts (highlights) of an image. " + "Other non-highlight parts of the image may appear under-exposed.", + "highlight"}, + {controls::ConstraintShadows, + "Shadows constraint mode. " + "This mode adjusts the exposure levels in order to try and avoid " + "under-exposing the dark parts (shadows) of an image. Other normally " + "exposed parts of the image may appear over-exposed.", + "shadows"}, + {controls::ConstraintCustom, "Custom constraint mode", "custom"}, + {0, NULL, NULL}, +}; + +static GType +ae_constraint_mode_get_type (void) +{ + static GType ae_constraint_mode_type = 0; + + if (!ae_constraint_mode_type) { + ae_constraint_mode_type = + g_enum_register_static ("AeConstraintMode", + ae_constraint_modes); + } + return ae_constraint_mode_type; +} + +#define AE_EXPOSURE_MODE (ae_exposure_mode_get_type()) +static const GEnumValue ae_exposure_modes[] = { + {controls::ExposureNormal, "Default exposure mode", "normal"}, + {controls::ExposureShort, + "Exposure mode allowing only short exposure times", + "short"}, + {controls::ExposureLong, + "Exposure mode allowing long exposure times", "long"}, + {controls::ExposureCustom, "Custom exposure mode", "custom"}, + {0, NULL, NULL}, +}; + +static GType +ae_exposure_mode_get_type (void) +{ + static GType ae_exposure_mode_type = 0; + + if (!ae_exposure_mode_type) { + ae_exposure_mode_type = + g_enum_register_static ("AeExposureMode", + ae_exposure_modes); + } + return ae_exposure_mode_type; +} + +#define AE_METERING_MODE (ae_metering_mode_get_type()) +static const GEnumValue ae_metering_modes[] = { + {controls::MeteringCentreWeighted, "Centre-weighted metering mode", + "centre-weighted"}, + {controls::MeteringSpot, "Spot metering mode", "spot"}, + {controls::MeteringMatrix, "Matrix metering mode", "matrix"}, + {controls::MeteringCustom, "Custom metering mode", "custom"}, + {0, NULL, NULL}, +}; + +static GType +ae_metering_mode_get_type (void) +{ + static GType ae_metering_mode_type = 0; + + if (!ae_metering_mode_type) { + ae_metering_mode_type = + g_enum_register_static ("AeMeteringMode", + ae_metering_modes); + } + return ae_metering_mode_type; +} + +#define AWB_MODE (awb_mode_get_type()) +static const GEnumValue awb_modes[] = { + {controls::AwbAuto, + "Search over the whole colour temperature range", "auto"}, + {controls::AwbIncandescent, "Incandescent AWB lamp mode", + "incandescent"}, + {controls::AwbTungsten, "Tungsten AWB lamp mode", "tungsten"}, + {controls::AwbFluorescent, "Fluorescent AWB lamp mode", + "fluorescent"}, + {controls::AwbIndoor, "Indoor AWB lighting mode", "indoor"}, + {controls::AwbDaylight, "Daylight AWB lighting mode", "daylight"}, + {controls::AwbCloudy, "Cloudy AWB lighting mode", "cloudy"}, + {controls::AwbCustom, "Custom AWB mode", "custom"}, + {0, NULL, NULL}, +}; + +static GType +awb_mode_get_type (void) +{ + static GType awb_mode_type = 0; + + if (!awb_mode_type) { + awb_mode_type = g_enum_register_static ("AwbMode", + awb_modes); + } + return awb_mode_type; +} + +#define NOISE_REDUCTION_MODE (noise_reduction_mode_get_type()) +static const GEnumValue noise_reduction_modes[] = { + {controls::draft::NoiseReductionModeOff, "No noise reduction is applied", + "off"}, + {controls::draft::NoiseReductionModeFast, + "Noise reduction is applied without reducing the frame rate", + "fast"}, + {controls::draft::NoiseReductionModeHighQuality, + "High quality noise reduction at the expense of frame rate", + "high-quality"}, + {controls::draft::NoiseReductionModeMinimal, + "Minimal noise reduction is applied without reducing the frame rate", + "minimal"}, + {controls::draft::NoiseReductionModeZSL, + "Noise reduction is applied at different levels to different streams", + "zsl"}, + {0, NULL, NULL}, +}; + +static GType +noise_reduction_mode_get_type (void) +{ + static GType noise_reduction_mode_type = 0; + + if (!noise_reduction_mode_type) { + noise_reduction_mode_type = + g_enum_register_static ("NoiseReductionMode", + noise_reduction_modes); + } + return noise_reduction_mode_type; +} + +void GstCameraControls::installProperties(GObjectClass *klass, int lastPropId) +{ + g_object_class_install_property (klass, lastPropId + AeAnalogueGain, + g_param_spec_float("ae-analogue-gain", "AE Analogue Gain", + "Analogue gain value applied in the sensor device. " + "The value of the control specifies the gain multiplier applied to all " + "colour channels. This value cannot be lower than 1.0. " + "Setting this value means that it is now fixed and the AE algorithm may " + "not change it. Setting it back to zero returns it to the control of the " + "AE algorithm.", + 0.0f, 16.0f, 1.0f, + (GParamFlags)(GST_PARAM_CONTROLLABLE + | G_PARAM_READWRITE + | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property (klass, lastPropId + AeExposureMode, + g_param_spec_enum ("ae-constraint-mode", "Constraint Mode", + "Specify a constraint mode for the AE algorithm to use. These determine " + "how the measured scene brightness is adjusted to reach the desired " + "target exposure. Constraint modes may be platform specific, and not " + "all constraint modes may be supported.", + AE_CONSTRAINT_MODE, + controls::ConstraintNormal, + (GParamFlags)(GST_PARAM_CONTROLLABLE + | G_PARAM_READWRITE + | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property (klass, lastPropId + AeEnable, + g_param_spec_boolean ("ae-enable", + "Auto Exposure", + "Enable or disable the Automatic Exposure algorithm.", + true, + (GParamFlags)(GST_PARAM_CONTROLLABLE + | G_PARAM_READWRITE + | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property (klass, lastPropId + AeExposureMode, + g_param_spec_enum ("ae-exposure-mode", "Exposure Mode", + "Specify an exposure mode for the AE algorithm to use. These specify " + "how the desired total exposure is divided between the shutter time " + "and the sensor's analogue gain. The exposure modes are platform " + "specific, and not all exposure modes may be supported. ", + AE_EXPOSURE_MODE, + controls::ExposureNormal, + (GParamFlags)(GST_PARAM_CONTROLLABLE + | G_PARAM_READWRITE + | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property(klass, lastPropId + AeExposureTime, + g_param_spec_int("ae-exposure-time", "Exposure time", + "Exposure time (shutter speed) for the frame applied in the sensor " + "device. This value is specified in micro-seconds. " + "Setting this value means that it is now fixed and the AE algorithm may " + "not change it. Setting it back to zero returns it to the control of the " + "AE algorithm.", + 0, 66666, 0, + (GParamFlags)(GST_PARAM_CONTROLLABLE + | G_PARAM_READWRITE + | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property (klass, lastPropId + AeExposureValue, + g_param_spec_float ("ae-exposure-value", + "Exposure Value", + "Specify an Exposure Value (EV) parameter. The EV parameter will only be " + "applied if the AE algorithm is currently enabled. " + "By convention EV adjusts the exposure as log2. For example " + "EV = [-2, -1, 0.5, 0, 0.5, 1, 2] results in an exposure adjustment " + "of [1/4x, 1/2x, 1/sqrt(2)x, 1x, sqrt(2)x, 2x, 4x].", + -8.0f, 8.0f, 0.0f, + (GParamFlags)(GST_PARAM_CONTROLLABLE + | G_PARAM_READWRITE + | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property (klass, lastPropId + AeMeteringMode, + g_param_spec_enum ("ae-metering-mode", "Metering Mode", + "Specify a metering mode for the AE algorithm to use. The metering " + "modes determine which parts of the image are used to determine the " + "scene brightness. Metering modes may be platform specific and not " + "all metering modes may be supported.", + AE_METERING_MODE, + controls::MeteringCentreWeighted, + (GParamFlags)(GST_PARAM_CONTROLLABLE + | G_PARAM_READWRITE + | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property (klass, lastPropId + AwbColorGainBlue, + g_param_spec_float("awb-gain-blue", "AWB Blue Gain", + "Manual AWB Gain for blue channel when awb-enable=0", + 0.0f, 32.0f, 0.0f, + (GParamFlags)(GST_PARAM_CONTROLLABLE + | G_PARAM_READWRITE + | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property (klass, lastPropId + AwbColorGainRed, + g_param_spec_float("awb-gain-red", "AWB Red Gain","" + "Manual AWB Gain for red channel when awb-enable=0", + 0.0f, 32.0f, 0.0f, + (GParamFlags)(GST_PARAM_CONTROLLABLE + | G_PARAM_READWRITE + | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property (klass, lastPropId + AwbEnable, + g_param_spec_boolean ("awb-enable", + "Enable Automatic White Balance", + "Enable or disable the AWB.", + true, + (GParamFlags)(GST_PARAM_CONTROLLABLE + | G_PARAM_READWRITE + | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property (klass, lastPropId + AwbMode, + g_param_spec_enum ("awb-mode", + "Automatic White Balance Mode", + "Specify the range of illuminants to use for the AWB algorithm. The modes " + "supported are platform specific, and not all modes may be supported.", + AWB_MODE, controls::AwbAuto, + (GParamFlags)(GST_PARAM_CONTROLLABLE + | G_PARAM_READWRITE + | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property(klass, lastPropId + Brightness, + g_param_spec_float("brightness", "Brightness", + "Specify a fixed brightness parameter. Positive values (up to 1.0) " + "produce brighter images; negative values (up to -1.0) produce darker " + "images and 0.0 leaves pixels unchanged.", + -1.0f, 1.0f, 0.0f, + (GParamFlags)(GST_PARAM_CONTROLLABLE + | G_PARAM_READWRITE + | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property(klass, lastPropId + Contrast, + g_param_spec_float("contrast", "Contrast", + "Specify a fixed contrast parameter. Normal contrast is given by the " + "value 1.0; larger values produce images with more contrast.", + 0.0f, 32.0f, 1.0f, + (GParamFlags)(GST_PARAM_CONTROLLABLE + | G_PARAM_READWRITE + | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property (klass, lastPropId + NoiseReductionMode, + g_param_spec_enum ("noise-reduction-mode", "Noise Reduction Mode", + "Control to select the noise reduction algorithm mode. Currently " + "identical to ANDROID_NOISE_REDUCTION_MODE.", + NOISE_REDUCTION_MODE, + controls::draft::NoiseReductionModeOff, + (GParamFlags)(GST_PARAM_CONTROLLABLE + | G_PARAM_READWRITE + | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property(klass, lastPropId + Saturation, + g_param_spec_float("saturation", "Saturation", + "Specify a fixed saturation parameter. Normal saturation is given by " + "the value 1.0; larger values produce more saturated colours; 0.0 " + "produces a greyscale image.", + 0.0f, 32.0f, 1.0f, + (GParamFlags)(GST_PARAM_CONTROLLABLE + | G_PARAM_READWRITE + | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property(klass, lastPropId + Sharpness, + g_param_spec_float("sharpness", "Sharpness", + "A value of 0.0 means no sharpening. The minimum value means " + "minimal sharpening, and shall be 0.0 unless the camera can't " + "disable sharpening completely. The default value shall give a " + "'reasonable' level of sharpening, suitable for most use cases. " + "The maximum value may apply extremely high levels of sharpening, " + "higher than anyone could reasonably want. Negative values are " + "not allowed. Note also that sharpening is not applied to raw " + "streams.", + 0.0f, 16.0f, 1.0f, + (GParamFlags)(GST_PARAM_CONTROLLABLE + | G_PARAM_READWRITE + | G_PARAM_STATIC_STRINGS))); +} + +bool GstCameraControls::getProperty(guint propId, GValue *value, GParamSpec *pspec) +{ + switch (propId) { + case AeAnalogueGain: { + auto val = controls_.get(controls::AnalogueGain); + auto spec = G_PARAM_SPEC_FLOAT(pspec); + g_value_set_float(value, + val.value_or(spec->default_value)); + return true; + } + case AeConstraintMode: { + auto val = controls_.get(controls::AeConstraintMode); + auto spec = G_PARAM_SPEC_ENUM(pspec); + g_value_set_enum(value, val.value_or(spec->default_value)); + return true; + } + case AeEnable: { + auto val = controls_.get(controls::AeEnable); + auto spec = G_PARAM_SPEC_BOOLEAN(pspec); + g_value_set_boolean(value, + val.value_or(spec->default_value)); + return true; + } + case AeExposureMode: { + auto val = controls_.get(controls::AeExposureMode); + auto spec = G_PARAM_SPEC_ENUM(pspec); + g_value_set_enum(value, val.value_or(spec->default_value)); + return true; + } + case AeExposureTime: { + auto val = controls_.get(controls::ExposureTime); + auto spec = G_PARAM_SPEC_INT(pspec); + g_value_set_int(value, val.value_or(spec->default_value)); + return true; + } + case AeExposureValue: { + auto val = controls_.get(controls::ExposureValue); + auto spec = G_PARAM_SPEC_FLOAT(pspec); + g_value_set_float(value, + val.value_or(spec->default_value)); + return true; + } + case AeMeteringMode: { + auto val = controls_.get(controls::AeMeteringMode); + auto spec = G_PARAM_SPEC_ENUM(pspec); + g_value_set_enum(value, val.value_or(spec->default_value)); + return true; + } + case AwbColorGainBlue: { + auto spec = G_PARAM_SPEC_FLOAT(pspec); + const auto &colourGains = + controls_.get(controls::ColourGains); + auto val = colourGains ? + (*colourGains)[1] : spec->default_value; + g_value_set_float(value, val); + return true; + } + case AwbColorGainRed: { + auto spec = G_PARAM_SPEC_FLOAT(pspec); + const auto &colourGains = + controls_.get(controls::ColourGains); + auto val = colourGains ? + (*colourGains)[0] : spec->default_value; + g_value_set_float(value, val); + return true; + } + case AwbEnable: { + auto val = controls_.get(controls::AwbEnable); + auto spec = G_PARAM_SPEC_BOOLEAN(pspec); + g_value_set_boolean(value, + val.value_or(spec->default_value)); + return true; + } + case AwbMode: { + auto val = controls_.get(controls::AwbMode); + auto *spec = G_PARAM_SPEC_ENUM(pspec); + g_value_set_enum(value, + val.value_or(spec->default_value)); + return true; + } + case Brightness: { + auto val = controls_.get(controls::Brightness); + auto spec = G_PARAM_SPEC_FLOAT(pspec); + /* FIXME the default from the init controls*/ + g_value_set_float(value, + val.value_or(spec->default_value)); + return true; + } + case Contrast: { + auto val = controls_.get(controls::Contrast); + auto spec = G_PARAM_SPEC_FLOAT(pspec); + g_value_set_float(value, + val.value_or(spec->default_value)); + return true; + } + case NoiseReductionMode: { + auto val = + controls_.get(controls::draft::NoiseReductionMode); + auto spec = G_PARAM_SPEC_ENUM(pspec); + g_value_set_enum(value, val.value_or(spec->default_value)); + return true; + } + case Saturation: { + auto val = controls_.get(controls::Saturation); + auto spec = G_PARAM_SPEC_FLOAT(pspec); + g_value_set_float(value, + val.value_or(spec->default_value)); + return true; + } + case Sharpness: { + auto val = controls_.get(controls::Sharpness); + auto spec = G_PARAM_SPEC_FLOAT(pspec); + g_value_set_float(value, + val.value_or(spec->default_value)); + return true; + } + default: + return false; + } +} + +bool GstCameraControls::setProperty(guint propId, const GValue *value, + GParamSpec *pspec) +{ + switch (propId) { + case AeAnalogueGain: + controls_.set(controls::AnalogueGain, + g_value_get_float(value)); + return true; + case AeConstraintMode: + controls_.set(controls::AeConstraintMode, + g_value_get_int(value)); + return true; + case AeEnable: + controls_.set(controls::AeEnable, + g_value_get_boolean(value)); + return true; + case AeExposureMode: + controls_.set(controls::AeExposureMode, + g_value_get_int(value)); + return true; + case AeExposureTime: + controls_.set(controls::ExposureTime, + g_value_get_int(value)); + return true; + case AeExposureValue: + controls_.set(controls::ExposureValue, + g_value_get_float(value)); + return true; + case AeMeteringMode: + controls_.set(controls::AeMeteringMode, + g_value_get_int(value)); + return true; + case AwbColorGainBlue: { + auto spec = G_PARAM_SPEC_FLOAT(pspec); + const auto &colourGains = + controls_.get(controls::ColourGains); + auto red_val = colourGains ? + (*colourGains)[0] : spec->default_value; + controls_.set(controls::ColourGains, + {red_val, g_value_get_float(value)}); + return true; + } + case AwbColorGainRed: { + auto spec = G_PARAM_SPEC_FLOAT(pspec); + const auto &colourGains = + controls_.get(controls::ColourGains); + auto blue_val = colourGains ? + (*colourGains)[1] : spec->default_value; + controls_.set(controls::ColourGains, + {g_value_get_float(value), blue_val}); + return true; + } + case AwbEnable: + controls_.set(controls::AwbEnable, + g_value_get_boolean(value)); + return true; + case AwbMode: + controls_.set(controls::AwbMode, + g_value_get_int(value)); + return true; + case Brightness: + controls_.set(controls::Brightness, + g_value_get_float(value)); + return true; + case Contrast: + controls_.set(controls::Contrast, + g_value_get_float(value)); + return true; + case NoiseReductionMode: + controls_.set(controls::draft::NoiseReductionMode, + g_value_get_int(value)); + return true; + case Saturation: + controls_.set(controls::Saturation, + g_value_get_float(value)); + return true; + case Sharpness: + controls_.set(controls::Sharpness, + g_value_get_float(value)); + return true; + default: + break; + } + + return false; +} + +void GstCameraControls::applyControls(std::unique_ptr<libcamera::Request> &request) +{ + request->controls().merge(controls_); +} diff --git a/src/gstreamer/gstlibcamera-controls.h b/src/gstreamer/gstlibcamera-controls.h new file mode 100644 index 0000000000000000000000000000000000000000..157aa5103633060c2a93caf5b89773a0b075da13 --- /dev/null +++ b/src/gstreamer/gstlibcamera-controls.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Collabora Ltd. + * Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> + * + * gstlibcamera-controls.cpp - GStreamer Camera Controls + */ + +#pragma once + +#include <libcamera/controls.h> +#include <libcamera/request.h> + +#include "gstlibcamerasrc.h" + +namespace libcamera { + +class GstCameraControls +{ +public: + enum Prop { + AeAnalogueGain = 0, + AeConstraintMode, + AeEnable, + AeExposureMode, + AeExposureTime, + AeExposureValue, + AeMeteringMode, + AutoFocusMode, + AwbColorGainBlue, + AwbColorGainRed, + AwbEnable, + AwbMode, + Brightness, + Contrast, + NoiseReductionMode, + Saturation, + Sharpness, + }; + + GstCameraControls(){}; + ~GstCameraControls(){}; + + 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 applyControls(std::unique_ptr<libcamera::Request> &request); + +private: + /* set of user modified controls */ + ControlList controls_; +}; + +} /* namespace libcamera */ diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp index a10cbd4f084b8ca4fd4ee4c3f0d69717e584a08a..c15a263f0095e9c9ffc11c84d7afd2e4172c118a 100644 --- a/src/gstreamer/gstlibcamerasrc.cpp +++ b/src/gstreamer/gstlibcamerasrc.cpp @@ -40,10 +40,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; @@ -133,6 +134,7 @@ struct GstLibcameraSrcState { ControlList initControls_; guint group_id_; + GstCameraControls controls_; int queueRequest(); void requestCompleted(Request *request); @@ -154,7 +156,8 @@ struct _GstLibcameraSrc { enum { PROP_0, - PROP_CAMERA_NAME + PROP_CAMERA_NAME, + PROP_LAST }; G_DEFINE_TYPE_WITH_CODE(GstLibcameraSrc, gst_libcamera_src, GST_TYPE_ELEMENT, @@ -180,6 +183,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)); @@ -653,6 +659,7 @@ 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: @@ -660,7 +667,8 @@ gst_libcamera_src_set_property(GObject *object, guint prop_id, self->camera_name = g_value_dup_string(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; } } @@ -671,13 +679,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; 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; } } @@ -844,4 +854,6 @@ gst_libcamera_src_class_init(GstLibcameraSrcClass *klass) | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property(object_class, PROP_CAMERA_NAME, spec); + + GstCameraControls::installProperties(object_class, PROP_LAST); } diff --git a/src/gstreamer/meson.build b/src/gstreamer/meson.build index eda246d7ffc86b9d8fe3d2dcdefebb21d29cd1fe..6a472b2f53faad33a13b941c9dcb2648f7dbcabc 100644 --- a/src/gstreamer/meson.build +++ b/src/gstreamer/meson.build @@ -16,6 +16,7 @@ endif gst_enabled = true libcamera_gst_sources = [ + 'gstlibcamera-controls.cpp', 'gstlibcamera-utils.cpp', 'gstlibcamera.cpp', 'gstlibcameraallocator.cpp',