[libcamera-devel] [PATCH v5.2 4/7] libcamera: controls: Updates to gain and exposure controls
Jacopo Mondi
jacopo at jmondi.org
Mon Apr 27 16:44:01 CEST 2020
Hi Laurent,
On Sun, Apr 26, 2020 at 03:23:28AM +0300, Laurent Pinchart wrote:
> From: Naushir Patuck <naush at raspberrypi.com>
>
> 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 at raspberrypi.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo at jmondi.org>
Thanks
j
> ---
> Changes since v5:
>
> - Include math.h in uvcvideo.cpp
> ---
> src/libcamera/control_ids.yaml | 22 ++++--
> src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 78 +++++++++++++++++++-
> 2 files changed, 88 insertions(+), 12 deletions(-)
>
> diff --git a/src/libcamera/control_ids.yaml b/src/libcamera/control_ids.yaml
> index bcbab195a374..d8bdb3829be4 100644
> --- a/src/libcamera/control_ids.yaml
> +++ b/src/libcamera/control_ids.yaml
> @@ -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
> ...
> diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> index b040f2460b1c..08462542a79b 100644
> --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> @@ -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;
> --
> Regards,
>
> Laurent Pinchart
>
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel at lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel
More information about the libcamera-devel
mailing list