[libcamera-devel] [PATCH v3.1 2/5] libcamera: pipeline: uvcvideo: Update exposure/gain ctrls set with new units
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Thu Apr 23 21:04:43 CEST 2020
From: Naushir Patuck <naush at raspberrypi.com>
The ExposureTime control now uses units of 1 micro-second, and UVC
uses units of 100 micro-seconds. Correctly map the values before
setting V4L2_CID_EXPOSURE_ABSOLUTE on the V4L2 device.
The AnalogueGain control now uses floats to allow fractional gain
values. Since UVC has no explicit gain units, map the default gain value
to 1.0 and linearly map to the requested value.
Signed-off-by: Naushir Patuck <naush at raspberrypi.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
---
Changes since v3:
- Round the gain value to the nearest integer when converting from float
- Use float values for the gain range
---
Hi Naush,
I realized there were two issues in the previous version of the patch:
- The gain was always rounded down, preventing my sine wave gain test
from reaching the maximum value as I never hit the case where sin(w*t)
was exactly equal to 1.0.
- The gain control info was reported as int32_t values, when the control
is of type float. This was reported by an error message in
ControlInfoMap::generateIdmap() which I initially missed, wondering
why the gain was not applied.
This new version fixes both issues. The conversion from int32_t to float
for the range may not be very nice, but I propose addressing that
separately on top if we deem it necessary.
src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 28 +++++++++++++++++---
1 file changed, 25 insertions(+), 3 deletions(-)
diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
index d7df95e4519a..09176b4e0d17 100644
--- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
+++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
@@ -253,9 +253,22 @@ int PipelineHandlerUVC::processControls(UVCCameraData *data, Request *request)
controls.set(V4L2_CID_SATURATION, value);
} else if (id == controls::ExposureTime) {
controls.set(V4L2_CID_EXPOSURE_AUTO, static_cast<int32_t>(1));
- controls.set(V4L2_CID_EXPOSURE_ABSOLUTE, value);
+ /*
+ * controls::ExposureTime is in units of 1 us, and UVC
+ * expects V4L2_CID_EXPOSURE_ABSOLUTE in units of 100 us.
+ */
+ controls.set(V4L2_CID_EXPOSURE_ABSOLUTE,
+ value.get<int32_t>() / 100);
} else if (id == controls::AnalogueGain) {
- controls.set(V4L2_CID_GAIN, value);
+ /*
+ * controls::AnalogueGain is specified as an absolute
+ * multiplier for all RGB samples. Map this multiplier
+ * in a linear way such that 1.0 -> default gain
+ * of the V4L2_CID_GAIN control on the uvcvideo device.
+ */
+ const ControlInfo &gainInfo = controls.infoMap()->at(V4L2_CID_GAIN);
+ int32_t gain = lroundf(value.get<float>() * gainInfo.def().get<int32_t>());
+ controls.set(V4L2_CID_GAIN, gain);
}
}
@@ -350,7 +363,7 @@ int UVCCameraData::init(MediaEntity *entity)
ControlInfoMap::Map ctrls;
for (const auto &ctrl : controls) {
- const ControlInfo &info = ctrl.second;
+ ControlInfo info = ctrl.second;
const ControlId *id;
switch (ctrl.first->id()) {
@@ -368,6 +381,15 @@ int UVCCameraData::init(MediaEntity *entity)
break;
case V4L2_CID_GAIN:
id = &controls::AnalogueGain;
+ /*
+ * AnalogueGain is a float control, convert the type of
+ * the range.
+ */
+ info = ControlInfo{
+ { static_cast<float>(info.min().get<int32_t>()) },
+ { static_cast<float>(info.max().get<int32_t>()) },
+ { static_cast<float>(info.def().get<int32_t>()) }
+ };
break;
default:
continue;
--
Regards,
Laurent Pinchart
More information about the libcamera-devel
mailing list