summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNaushir Patuck <naush@raspberrypi.com>2020-04-24 11:46:58 +0100
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2020-04-27 20:18:12 +0300
commiteff4b1aa01c1a9fa96df5a25d2ae7c540f5d5e84 (patch)
tree876a1efe624f252dbaa1a1224438df7882f32f53
parentfa77a02c0a099ad02ed55935bdbe8cd441a8d893 (diff)
libcamera: controls: Reorder and update description of existing controls
Group AE, AWB, etc. controls together for accessibility. Update descriptions for Contrast, Brightness, and Saturation controls. Update the uvcvideo and vimc pipeline handlers to use the new brightness, contrast and saturation units. UVC has no explicit units for those controls, so map them with a best effort heuristic. For VIMC, hardcode the control range based on knowledge of the driver implementation for simplicity. Signed-off-by: Naushir Patuck <naush@raspberrypi.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-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;