[libcamera-devel] [PATCH v3 08/23] libcamera: camera_sensor: Initialize controls

Kieran Bingham kieran.bingham at ideasonboard.com
Fri Jul 1 00:57:19 CEST 2022


Quoting Jacopo Mondi via libcamera-devel (2022-06-30 14:38:47)
> Initialize the control interface of the CameraSensor class by
> registering the control limits for controls::internal::ExposureTime,
> controls::internal::FrameDuration and controls::internal::AnalogueGain.
> 
> Update the CameraSensor controls in the CameraSensor::updateControlInfo()
> function after having updated the subdevice V4L2 controls.
> 
> Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
> ---
>  include/libcamera/internal/camera_sensor.h    |  3 +
>  src/libcamera/camera_sensor/camera_sensor.cpp | 90 +++++++++++++++++++
>  2 files changed, 93 insertions(+)
> 
> diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
> index 2a850dedc0aa..1eab5e9d53f0 100644
> --- a/include/libcamera/internal/camera_sensor.h
> +++ b/include/libcamera/internal/camera_sensor.h
> @@ -63,6 +63,7 @@ public:
>         V4L2Subdevice *device() { return subdev_.get(); }
>  
>         const ControlList &properties() const { return properties_; }
> +       const ControlInfoMap &controls() const { return controls_; }
>         int sensorInfo(IPACameraSensorInfo *info) const;
>  
>         void updateControlInfo();
> @@ -81,6 +82,7 @@ private:
>         void initStaticProperties();
>         void initTestPatternModes();
>         int initProperties();
> +       int updateControls();
>         int applyTestPatternMode(controls::draft::TestPatternModeEnum mode);
>         int discoverAncillaryDevices();
>  
> @@ -104,6 +106,7 @@ private:
>         const BayerFormat *bayerFormat_;
>  
>         ControlList properties_;
> +       ControlInfoMap controls_;
>  
>         std::unique_ptr<CameraLens> focusLens_;
>         std::unique_ptr<CameraSensorHelper> helper_;
> diff --git a/src/libcamera/camera_sensor/camera_sensor.cpp b/src/libcamera/camera_sensor/camera_sensor.cpp
> index 26cfa7d0f65a..976d34aaf876 100644
> --- a/src/libcamera/camera_sensor/camera_sensor.cpp
> +++ b/src/libcamera/camera_sensor/camera_sensor.cpp
> @@ -22,6 +22,7 @@
>  #include "libcamera/internal/bayer_format.h"
>  #include "libcamera/internal/camera_lens.h"
>  #include "libcamera/internal/camera_sensor_properties.h"
> +#include "libcamera/internal/control_ids.h"
>  #include "libcamera/internal/formats.h"
>  #include "libcamera/internal/sysfs.h"
>  
> @@ -180,6 +181,10 @@ int CameraSensor::init()
>                 return -ENODEV;
>         }
>  
> +       ret = updateControls();
> +       if (ret)
> +               return ret;
> +
>         ret = discoverAncillaryDevices();
>         if (ret)
>                 return ret;
> @@ -455,6 +460,84 @@ int CameraSensor::initProperties()
>         return 0;
>  }
>  
> +int CameraSensor::updateControls()
> +{
> +       if (!bayerFormat_)
> +               return 0;
> +
> +       ControlInfoMap::Map controlsMap;
> +
> +       /* The subdev driver has been validate already, the controls are there! */

/validate/validated/

> +       ControlList subdevControls = subdev_->getControls({ V4L2_CID_PIXEL_RATE,
> +                                                           V4L2_CID_HBLANK });
> +       uint64_t pixelRate = subdevControls.get(V4L2_CID_PIXEL_RATE).get<int64_t>();
> +       uint32_t hblank = subdevControls.get(V4L2_CID_HBLANK).get<int32_t>();
> +
> +       /*  Assume the sensor has a single source pad #0. */

/*  Assume/* Assume/
double space can be single.

> +       V4L2SubdeviceFormat subdevFormat;
> +       subdev_->getFormat(0, &subdevFormat);
> +
> +       const ControlInfoMap &subdevControlsInfo = subdev_->controls();
> +
> +       /*
> +        * Compute controls::ExposureTime limits by using line length and pixel
> +        * rate converted to microseconds. Use the V4L2_CID_EXPOSURE control to
> +        * get exposure min, max and default and convert it from lines to
> +        * microseconds.
> +        */
> +       uint32_t lineLength = subdevFormat.size.width + hblank;
> +       double lineDuration = lineLength / (pixelRate / 1000000.0F);
> +       const ControlInfo &v4l2Exposure = subdevControlsInfo.at(V4L2_CID_EXPOSURE);
> +       int32_t minExposure = v4l2Exposure.min().get<int32_t>() * lineDuration;
> +       int32_t maxExposure = v4l2Exposure.max().get<int32_t>() * lineDuration;
> +       int32_t defExposure = v4l2Exposure.def().get<int32_t>() * lineDuration;
> +
> +       controlsMap[&controls::internal::ExposureTime] =
> +               ControlInfo(minExposure, maxExposure, defExposure);
> +
> +       /*
> +        * Compute the frame duration limits.
> +        *
> +        * The frame length is computed assuming a fixed line length combined
> +        * with the vertical frame sizes.
> +        */
> +       const ControlInfo &v4l2VBlank = subdevControlsInfo.at(V4L2_CID_VBLANK);

Does this need to be refreshed from the subdev?

> +       std::array<uint32_t, 3> frameHeights{
> +               v4l2VBlank.min().get<int32_t>() + subdevFormat.size.height,
> +               v4l2VBlank.max().get<int32_t>() + subdevFormat.size.height,
> +               v4l2VBlank.def().get<int32_t>() + subdevFormat.size.height,
> +       };
> +
> +       std::array<int64_t, 3> frameDurations;
> +       for (unsigned int i = 0; i < frameHeights.size(); ++i) {
> +               uint64_t frameSize = lineLength * frameHeights[i];
> +               frameDurations[i] = frameSize / (pixelRate / 1000000.0F);
> +       }
> +
> +       controlsMap[&controls::internal::FrameDuration] =
> +               ControlInfo(frameDurations[0], frameDurations[1], frameDurations[2]);
> +
> +       /*
> +        * Analogue gain values.
> +        *
> +        * Translate the V4L2 analogue gain, expressed in sensor-specific
> +        * gain codes, and translate them to analogue gain values.
> +        *
> +        * \todo: CameraSensorHelper returns a double; there's no ControlValue
> +        * overload for the double type.
> +        */
> +       const ControlInfo &v4l2AGain = subdevControlsInfo.at(V4L2_CID_ANALOGUE_GAIN);
> +       controlsMap[&controls::internal::AnalogueGain] =
> +               ControlInfo(static_cast<float>(helper_->gain(v4l2AGain.min().get<int32_t>())),
> +                           static_cast<float>(helper_->gain(v4l2AGain.max().get<int32_t>())),
> +                           static_cast<float>(helper_->gain(v4l2AGain.def().get<int32_t>())));
> +
> +       controls_ = ControlInfoMap(std::move(controlsMap),
> +                                  controls::internal::controls);
> +
> +       return 0;
> +}
> +
>  /**
>   * \brief Check for and initialise any ancillary devices
>   *
> @@ -815,6 +898,12 @@ int CameraSensor::setV4L2Controls(ControlList *ctrls)
>   * \return The list of camera sensor properties
>   */
>  
> +/**
> + * \fn CameraSensor::controls()
> + * \brief Retrieve the map of the camera sensor controls limits
> + * \return The map of camera sensor control information
> + */
> +
>  /**
>   * \brief Assemble and return the camera sensor info
>   * \param[out] info The camera sensor info
> @@ -910,6 +999,7 @@ int CameraSensor::sensorInfo(IPACameraSensorInfo *info) const
>  void CameraSensor::updateControlInfo()
>  {
>         subdev_->updateControlInfo();
> +       updateControls();

Aha - that answers my vblank question I think...

Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>

>  }
>  
>  /**
> -- 
> 2.36.1
>


More information about the libcamera-devel mailing list