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:
parent
47d09a13b3
commit
fa77a02c0a
2 changed files with 88 additions and 12 deletions
|
@ -12,7 +12,7 @@ controls:
|
||||||
description: |
|
description: |
|
||||||
Enable or disable the AE.
|
Enable or disable the AE.
|
||||||
|
|
||||||
\sa ManualExposure
|
\sa ExposureTime AnalogueGain
|
||||||
|
|
||||||
- AeLocked:
|
- AeLocked:
|
||||||
type: bool
|
type: bool
|
||||||
|
@ -30,8 +30,6 @@ controls:
|
||||||
description: |
|
description: |
|
||||||
Enable or disable the AWB.
|
Enable or disable the AWB.
|
||||||
|
|
||||||
\sa ManualGain
|
|
||||||
|
|
||||||
- Brightness:
|
- Brightness:
|
||||||
type: int32_t
|
type: int32_t
|
||||||
description: Specify a fixed brightness parameter
|
description: Specify a fixed brightness parameter
|
||||||
|
@ -44,12 +42,20 @@ controls:
|
||||||
type: int32_t
|
type: int32_t
|
||||||
description: Specify a fixed saturation parameter
|
description: Specify a fixed saturation parameter
|
||||||
|
|
||||||
- ManualExposure:
|
- ExposureTime:
|
||||||
type: int32_t
|
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:
|
\sa AnalogueGain AeEnable
|
||||||
type: int32_t
|
|
||||||
description: Specify a fixed gain parameter
|
|
||||||
|
|
||||||
|
- 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
|
||||||
...
|
...
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <math.h>
|
||||||
#include <sys/sysmacros.h>
|
#include <sys/sysmacros.h>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
|
@ -254,13 +255,19 @@ int PipelineHandlerUVC::processControl(ControlList *controls, unsigned int id,
|
||||||
cid = V4L2_CID_SATURATION;
|
cid = V4L2_CID_SATURATION;
|
||||||
else if (id == controls::AeEnable)
|
else if (id == controls::AeEnable)
|
||||||
cid = V4L2_CID_EXPOSURE_AUTO;
|
cid = V4L2_CID_EXPOSURE_AUTO;
|
||||||
else if (id == controls::ManualExposure)
|
else if (id == controls::ExposureTime)
|
||||||
cid = V4L2_CID_EXPOSURE_ABSOLUTE;
|
cid = V4L2_CID_EXPOSURE_ABSOLUTE;
|
||||||
else if (id == controls::ManualGain)
|
else if (id == controls::AnalogueGain)
|
||||||
cid = V4L2_CID_GAIN;
|
cid = V4L2_CID_GAIN;
|
||||||
else
|
else
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
const ControlInfo &v4l2Info = controls->infoMap()->at(cid);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See UVCCameraData::addControl() for explanations of the different
|
||||||
|
* value mappings.
|
||||||
|
*/
|
||||||
switch (cid) {
|
switch (cid) {
|
||||||
case V4L2_CID_EXPOSURE_AUTO: {
|
case V4L2_CID_EXPOSURE_AUTO: {
|
||||||
int32_t ivalue = value.get<bool>()
|
int32_t ivalue = value.get<bool>()
|
||||||
|
@ -270,6 +277,28 @@ int PipelineHandlerUVC::processControl(ControlList *controls, unsigned int id,
|
||||||
break;
|
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: {
|
default: {
|
||||||
int32_t ivalue = value.get<int32_t>();
|
int32_t ivalue = value.get<int32_t>();
|
||||||
controls->set(cid, ivalue);
|
controls->set(cid, ivalue);
|
||||||
|
@ -413,21 +442,62 @@ void UVCCameraData::addControl(uint32_t cid, const ControlInfo &v4l2Info,
|
||||||
id = &controls::AeEnable;
|
id = &controls::AeEnable;
|
||||||
break;
|
break;
|
||||||
case V4L2_CID_EXPOSURE_ABSOLUTE:
|
case V4L2_CID_EXPOSURE_ABSOLUTE:
|
||||||
id = &controls::ManualExposure;
|
id = &controls::ExposureTime;
|
||||||
break;
|
break;
|
||||||
case V4L2_CID_GAIN:
|
case V4L2_CID_GAIN:
|
||||||
id = &controls::ManualGain;
|
id = &controls::AnalogueGain;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Map the control info. */
|
/* 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) {
|
switch (cid) {
|
||||||
case V4L2_CID_EXPOSURE_AUTO:
|
case V4L2_CID_EXPOSURE_AUTO:
|
||||||
info = ControlInfo{ false, true, true };
|
info = ControlInfo{ false, true, true };
|
||||||
break;
|
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:
|
default:
|
||||||
info = v4l2Info;
|
info = v4l2Info;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue