libcamera: controls: Updates to gain and exposure controls

Rename:
ManualExposure -> ExposureTime
ManualGain -> AnalogueGain

Use micro-seconds units for ExposureTime. This is changed from milli-
seconds. The latter would not allow very low exposure times.
AnalogueGain switch to use a float to allow fractional gain adjustments.

Update the uvcvideo pipeline handler to use the new exposure and gain
units. For ExposureTime, UVC uses units of 100 micro-seconds, so map
the values before setting V4L2_CID_EXPOSURE_ABSOLUTE. For AnalogueGain,
UVC has no explicit gain units, so map the default gain value to 1.0
and linearly scale to the requested value.

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>
Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
This commit is contained in:
Naushir Patuck 2020-04-24 11:46:57 +01:00 committed by Laurent Pinchart
parent 47d09a13b3
commit fa77a02c0a
2 changed files with 88 additions and 12 deletions

View file

@ -12,7 +12,7 @@ controls:
description: |
Enable or disable the AE.
\sa ManualExposure
\sa ExposureTime AnalogueGain
- AeLocked:
type: bool
@ -30,8 +30,6 @@ controls:
description: |
Enable or disable the AWB.
\sa ManualGain
- Brightness:
type: int32_t
description: Specify a fixed brightness parameter
@ -44,12 +42,20 @@ controls:
type: int32_t
description: Specify a fixed saturation parameter
- ManualExposure:
- ExposureTime:
type: int32_t
description: Specify a fixed exposure time in milli-seconds
description: |
Exposure time (shutter speed) for the frame applied in the sensor
device. This value is specified in micro-seconds.
- ManualGain:
type: int32_t
description: Specify a fixed gain parameter
\sa AnalogueGain AeEnable
- AnalogueGain:
type: float
description: |
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.
\sa ExposureTime AeEnable
...

View file

@ -7,6 +7,7 @@
#include <algorithm>
#include <iomanip>
#include <math.h>
#include <sys/sysmacros.h>
#include <tuple>
@ -254,13 +255,19 @@ int PipelineHandlerUVC::processControl(ControlList *controls, unsigned int id,
cid = V4L2_CID_SATURATION;
else if (id == controls::AeEnable)
cid = V4L2_CID_EXPOSURE_AUTO;
else if (id == controls::ManualExposure)
else if (id == controls::ExposureTime)
cid = V4L2_CID_EXPOSURE_ABSOLUTE;
else if (id == controls::ManualGain)
else if (id == controls::AnalogueGain)
cid = V4L2_CID_GAIN;
else
return -EINVAL;
const ControlInfo &v4l2Info = controls->infoMap()->at(cid);
/*
* See UVCCameraData::addControl() for explanations of the different
* value mappings.
*/
switch (cid) {
case V4L2_CID_EXPOSURE_AUTO: {
int32_t ivalue = value.get<bool>()
@ -270,6 +277,28 @@ int PipelineHandlerUVC::processControl(ControlList *controls, unsigned int id,
break;
}
case V4L2_CID_EXPOSURE_ABSOLUTE:
controls->set(cid, value.get<int32_t>() / 100);
break;
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;
if (m * min + p < 0.5f) {
m = (1.0f - 0.5f) / (def - min);
p = 1.0f - m * def;
}
float fvalue = (value.get<float>() - p) / m;
controls->set(cid, static_cast<int32_t>(lroundf(fvalue)));
break;
}
default: {
int32_t ivalue = value.get<int32_t>();
controls->set(cid, ivalue);
@ -413,21 +442,62 @@ void UVCCameraData::addControl(uint32_t cid, const ControlInfo &v4l2Info,
id = &controls::AeEnable;
break;
case V4L2_CID_EXPOSURE_ABSOLUTE:
id = &controls::ManualExposure;
id = &controls::ExposureTime;
break;
case V4L2_CID_GAIN:
id = &controls::ManualGain;
id = &controls::AnalogueGain;
break;
default:
return;
}
/* Map the control info. */
int32_t min = v4l2Info.min().get<int32_t>();
int32_t max = v4l2Info.max().get<int32_t>();
int32_t def = v4l2Info.def().get<int32_t>();
switch (cid) {
case V4L2_CID_EXPOSURE_AUTO:
info = ControlInfo{ false, true, true };
break;
case V4L2_CID_EXPOSURE_ABSOLUTE:
/*
* ExposureTime is in units of 1 µs, and UVC expects
* V4L2_CID_EXPOSURE_ABSOLUTE in units of 100 µs.
*/
info = ControlInfo{
{ min * 100 },
{ max * 100 },
{ def * 100 }
};
break;
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.
*/
float m = (4.0f - 1.0f) / (max - def);
float p = 1.0f - m * def;
if (m * min + p < 0.5f) {
m = (1.0f - 0.5f) / (def - min);
p = 1.0f - m * def;
}
info = ControlInfo{
{ m * min + p },
{ m * max + p },
{ 1.0f }
};
break;
}
default:
info = v4l2Info;
break;