summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libcamera/control_ids.yaml42
-rw-r--r--src/libcamera/pipeline/uvcvideo/uvcvideo.cpp67
-rw-r--r--src/libcamera/pipeline/vimc/vimc.cpp32
3 files changed, 105 insertions, 36 deletions
diff --git a/src/libcamera/control_ids.yaml b/src/libcamera/control_ids.yaml
index d8bdb382..f2ac052b 100644
--- a/src/libcamera/control_ids.yaml
+++ b/src/libcamera/control_ids.yaml
@@ -25,23 +25,6 @@ controls:
\sa AeEnable
- - AwbEnable:
- type: bool
- description: |
- Enable or disable the AWB.
-
- - Brightness:
- type: int32_t
- description: Specify a fixed brightness parameter
-
- - Contrast:
- type: int32_t
- description: Specify a fixed contrast parameter
-
- - Saturation:
- type: int32_t
- description: Specify a fixed saturation parameter
-
- ExposureTime:
type: int32_t
description: |
@@ -58,4 +41,29 @@ controls:
colour channels. This value cannot be lower than 1.0.
\sa ExposureTime AeEnable
+
+ - Brightness:
+ type: float
+ description: |
+ 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.
+
+ - Contrast:
+ type: float
+ description: |
+ Specify a fixed contrast parameter. Normal contrast is given by the
+ value 1.0; larger values produce images with more contrast.
+
+ - AwbEnable:
+ type: bool
+ description: |
+ Enable or disable the AWB.
+
+ - Saturation:
+ type: float
+ description: |
+ 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.
...
diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
index 08462542..030ac686 100644
--- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
+++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
@@ -263,12 +263,29 @@ int PipelineHandlerUVC::processControl(ControlList *controls, unsigned int id,
return -EINVAL;
const ControlInfo &v4l2Info = controls->infoMap()->at(cid);
+ int32_t min = v4l2Info.min().get<int32_t>();
+ int32_t def = v4l2Info.def().get<int32_t>();
+ int32_t max = v4l2Info.max().get<int32_t>();
/*
* See UVCCameraData::addControl() for explanations of the different
* value mappings.
*/
switch (cid) {
+ case V4L2_CID_BRIGHTNESS: {
+ float scale = std::max(max - def, def - min);
+ float fvalue = value.get<float>() * scale + def;
+ controls->set(cid, static_cast<int32_t>(lroundf(fvalue)));
+ break;
+ }
+
+ case V4L2_CID_SATURATION: {
+ float scale = def - min;
+ float fvalue = value.get<float>() * scale + min;
+ controls->set(cid, static_cast<int32_t>(lroundf(fvalue)));
+ break;
+ }
+
case V4L2_CID_EXPOSURE_AUTO: {
int32_t ivalue = value.get<bool>()
? V4L2_EXPOSURE_APERTURE_PRIORITY
@@ -281,11 +298,8 @@ int PipelineHandlerUVC::processControl(ControlList *controls, unsigned int id,
controls->set(cid, value.get<int32_t>() / 100);
break;
+ case V4L2_CID_CONTRAST:
case V4L2_CID_GAIN: {
- int32_t min = v4l2Info.min().get<int32_t>();
- int32_t max = v4l2Info.max().get<int32_t>();
- int32_t def = v4l2Info.def().get<int32_t>();
-
float m = (4.0f - 1.0f) / (max - def);
float p = 1.0f - m * def;
@@ -457,6 +471,38 @@ void UVCCameraData::addControl(uint32_t cid, const ControlInfo &v4l2Info,
int32_t def = v4l2Info.def().get<int32_t>();
switch (cid) {
+ case V4L2_CID_BRIGHTNESS: {
+ /*
+ * The Brightness control is a float, with 0.0 mapped to the
+ * default value. The control range is [-1.0, 1.0], but the V4L2
+ * default may not be in the middle of the V4L2 range.
+ * Accommodate this by restricting the range of the libcamera
+ * control, but always within the maximum limits.
+ */
+ float scale = std::max(max - def, def - min);
+
+ info = ControlInfo{
+ { static_cast<float>(min - def) / scale },
+ { static_cast<float>(max - def) / scale },
+ { 0.0f }
+ };
+ break;
+ }
+
+ case V4L2_CID_SATURATION:
+ /*
+ * The Saturation control is a float, with 0.0 mapped to the
+ * minimum value (corresponding to a fully desaturated image)
+ * and 1.0 mapped to the default value. Calculate the maximum
+ * value accordingly.
+ */
+ info = ControlInfo{
+ { 0.0f },
+ { static_cast<float>(max - min) / (def - min) },
+ { 1.0f }
+ };
+ break;
+
case V4L2_CID_EXPOSURE_AUTO:
info = ControlInfo{ false, true, true };
break;
@@ -473,14 +519,15 @@ void UVCCameraData::addControl(uint32_t cid, const ControlInfo &v4l2Info,
};
break;
+ case V4L2_CID_CONTRAST:
case V4L2_CID_GAIN: {
/*
- * The AnalogueGain control is a float, with 1.0 mapped to the
- * default value. UVC doesn't specify units, and cameras have
- * been seen to expose very different ranges for the gain
- * control. Arbitrarily assume that the minimum and maximum
- * values are respectively no lower than 0.5 and no higher than
- * 4.0.
+ * The Contrast and AnalogueGain controls are floats, with 1.0
+ * mapped to the default value. UVC doesn't specify units, and
+ * cameras have been seen to expose very different ranges for
+ * the controls. Arbitrarily assume that the minimum and
+ * maximum values are respectively no lower than 0.5 and no
+ * higher than 4.0.
*/
float m = (4.0f - 1.0f) / (max - def);
float p = 1.0f - m * def;
diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp
index c5eea3a0..77de4c38 100644
--- a/src/libcamera/pipeline/vimc/vimc.cpp
+++ b/src/libcamera/pipeline/vimc/vimc.cpp
@@ -8,6 +8,7 @@
#include <algorithm>
#include <array>
#include <iomanip>
+#include <math.h>
#include <tuple>
#include <linux/media-bus-format.h>
@@ -304,14 +305,24 @@ int PipelineHandlerVimc::processControls(VimcCameraData *data, Request *request)
for (auto it : request->controls()) {
unsigned int id = it.first;
- ControlValue &value = it.second;
-
- if (id == controls::Brightness)
- controls.set(V4L2_CID_BRIGHTNESS, value);
- else if (id == controls::Contrast)
- controls.set(V4L2_CID_CONTRAST, value);
- else if (id == controls::Saturation)
- controls.set(V4L2_CID_SATURATION, value);
+ unsigned int offset;
+ uint32_t cid;
+
+ if (id == controls::Brightness) {
+ cid = V4L2_CID_BRIGHTNESS;
+ offset = 128;
+ } else if (id == controls::Contrast) {
+ cid = V4L2_CID_CONTRAST;
+ offset = 0;
+ } else if (id == controls::Saturation) {
+ cid = V4L2_CID_SATURATION;
+ offset = 0;
+ } else {
+ continue;
+ }
+
+ int32_t value = lroundf(it.second.get<float>() * 128 + offset);
+ controls.set(cid, utils::clamp(value, 0, 255));
}
for (const auto &ctrl : controls)
@@ -434,18 +445,21 @@ int VimcCameraData::init(MediaDevice *media)
ControlInfoMap::Map ctrls;
for (const auto &ctrl : controls) {
- const ControlInfo &info = ctrl.second;
const ControlId *id;
+ ControlInfo info;
switch (ctrl.first->id()) {
case V4L2_CID_BRIGHTNESS:
id = &controls::Brightness;
+ info = ControlInfo{ { -1.0f }, { 1.0f }, { 0.0f } };
break;
case V4L2_CID_CONTRAST:
id = &controls::Contrast;
+ info = ControlInfo{ { 0.0f }, { 2.0f }, { 1.0f } };
break;
case V4L2_CID_SATURATION:
id = &controls::Saturation;
+ info = ControlInfo{ { 0.0f }, { 2.0f }, { 1.0f } };
break;
default:
continue;