[libcamera-devel] [IPU3-IPA PATCH] ipu3: Update camera controls in configure()

Laurent Pinchart laurent.pinchart at ideasonboard.com
Sat Oct 16 01:04:18 CEST 2021


Hi Kieran,

Thank you for the patch.

On Fri, Oct 15, 2021 at 04:10:04PM +0100, Kieran Bingham wrote:
> When a new CameraConfiguration is applied to the Camera the IPA is
> configured as well, using the newly applied sensor configuration and its
> updated V4L2 controls.
> 
> Also update the Camera controls at IPA::configure() time by re-computing
> the controls::ExposureTime and controls::FrameDurationLimits limits and
> update the controls on the pipeline handler side after having configured
> the IPA.
> 
> This commit corresponds to the libcamera commit 4ed22985a846 ("ipa:
> ipu3: Update camera controls in configure()") and applies the same
> changes to this IPA.
> 
> Signed-off-by: Kieran Bingham <kieran.bingham at ideasonboard.com>

Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>

> ---
>  ipu3.cpp | 127 ++++++++++++++++++++++++++++++++++---------------------
>  1 file changed, 78 insertions(+), 49 deletions(-)
> 
> diff --git a/ipu3.cpp b/ipu3.cpp
> index 7589eecbb64c..8126e9d659df 100644
> --- a/ipu3.cpp
> +++ b/ipu3.cpp
> @@ -44,13 +44,17 @@ public:
>  	int start() override;
>  	void stop() override {}
>  
> -	int configure(const IPAConfigInfo &configInfo) override;
> +	int configure(const IPAConfigInfo &configInfo,
> +		      ControlInfoMap *ipaControls) override;
>  
>  	void mapBuffers(const std::vector<IPABuffer> &buffers) override;
>  	void unmapBuffers(const std::vector<unsigned int> &ids) override;
>  	void processEvent(const IPU3Event &event) override;
>  
>  private:
> +	void updateControls(const IPACameraSensorInfo &sensorInfo,
> +			    const ControlInfoMap &sensorControls,
> +			    ControlInfoMap *ipaControls);
>  	void processControls(unsigned int frame, const ControlList &metadata);
>  	void fillParams(unsigned int frame, ipu3_uapi_params *params);
>  	void parseStatistics(unsigned int frame,
> @@ -86,6 +90,68 @@ private:
>  	BinaryData aiqd_;
>  };
>  
> +/*
> + * Compute camera controls using the sensor information and the sensor
> + * v4l2 controls.
> + *
> + * Some of the camera controls are computed by the pipeline handler, some others
> + * by the IPA module which is in charge of handling, for example, the exposure
> + * time and the frame duration.
> + *
> + * This function computes:
> + * - controls::ExposureTime
> + * - controls::FrameDurationLimits
> + */
> +void IPAIPU3::updateControls(const IPACameraSensorInfo &sensorInfo,
> +			     const ControlInfoMap &sensorControls,
> +			     ControlInfoMap *ipaControls)
> +{
> +	ControlInfoMap::Map controls{};
> +
> +	/*
> +	 * Compute exposure time 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.
> +	 */
> +	double lineDuration = sensorInfo.lineLength / (sensorInfo.pixelRate / 1e6);
> +	const ControlInfo &v4l2Exposure = sensorControls.find(V4L2_CID_EXPOSURE)->second;
> +	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;
> +	controls[&controls::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 &v4l2HBlank = sensorControls.find(V4L2_CID_HBLANK)->second;
> +	uint32_t hblank = v4l2HBlank.def().get<int32_t>();
> +	uint32_t lineLength = sensorInfo.outputSize.width + hblank;
> +
> +	const ControlInfo &v4l2VBlank = sensorControls.find(V4L2_CID_VBLANK)->second;
> +	std::array<uint32_t, 3> frameHeights{
> +		v4l2VBlank.min().get<int32_t>() + sensorInfo.outputSize.height,
> +		v4l2VBlank.max().get<int32_t>() + sensorInfo.outputSize.height,
> +		v4l2VBlank.def().get<int32_t>() + sensorInfo.outputSize.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 / (sensorInfo.pixelRate / 1000000U);
> +	}
> +
> +	controls[&controls::FrameDurationLimits] = ControlInfo(frameDurations[0],
> +							       frameDurations[1],
> +							       frameDurations[2]);
> +
> +	*ipaControls = ControlInfoMap(std::move(controls), controls::controls);
> +}
> +
>  int IPAIPU3::init(const IPASettings &settings,
>  		  const IPACameraSensorInfo &sensorInfo,
>  		  const ControlInfoMap &sensorControls,
> @@ -141,53 +207,8 @@ int IPAIPU3::init(const IPASettings &settings,
>  
>  	aiqInputParams_.init();
>  
> -	/* Initialize Controls. */
> -	ControlInfoMap::Map controls{};
> -
> -	/*
> -	 * Compute exposure time limits.
> -	 *
> -	 * Initialize the control using the line length and pixel rate of the
> -	 * current configuration converted to microseconds. Use the
> -	 * V4L2_CID_EXPOSURE control to get exposure min, max and default and
> -	 * convert it from lines to microseconds.
> -	 */
> -	double lineDuration = sensorInfo.lineLength / (sensorInfo.pixelRate / 1e6);
> -	const ControlInfo &v4l2Exposure = sensorControls.find(V4L2_CID_EXPOSURE)->second;
> -	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;
> -	controls[&controls::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 &v4l2HBlank = sensorControls.find(V4L2_CID_HBLANK)->second;
> -	uint32_t hblank = v4l2HBlank.def().get<int32_t>();
> -	uint32_t lineLength = sensorInfo.outputSize.width + hblank;
> -
> -	const ControlInfo &v4l2VBlank = sensorControls.find(V4L2_CID_VBLANK)->second;
> -	std::array<uint32_t, 3> frameHeights{
> -		v4l2VBlank.min().get<int32_t>() + sensorInfo.outputSize.height,
> -		v4l2VBlank.max().get<int32_t>() + sensorInfo.outputSize.height,
> -		v4l2VBlank.def().get<int32_t>() + sensorInfo.outputSize.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 / (sensorInfo.pixelRate / 1000000U);
> -	}
> -
> -	controls[&controls::FrameDurationLimits] = ControlInfo(frameDurations[0],
> -							       frameDurations[1],
> -							       frameDurations[2]);
> -
> -	*ipaControls = ControlInfoMap(std::move(controls), controls::controls);
> +	/* Initialize controls. */
> +	updateControls(sensorInfo, sensorControls, ipaControls);
>  
>  	return 0;
>  }
> @@ -199,7 +220,8 @@ int IPAIPU3::start()
>  	return 0;
>  }
>  
> -int IPAIPU3::configure(const IPAConfigInfo &configInfo)
> +int IPAIPU3::configure(const IPAConfigInfo &configInfo,
> +		       ControlInfoMap *ipaControls)
>  {
>  	if (configInfo.sensorControls.empty()) {
>  		LOG(IPAIPU3, Error) << "No sensor controls provided";
> @@ -208,6 +230,10 @@ int IPAIPU3::configure(const IPAConfigInfo &configInfo)
>  
>  	sensorInfo_ = configInfo.sensorInfo;
>  
> +	/*
> +	 * Compute the sensor V4L2 controls to be used by the algorithms and
> +	 * to be set on the sensor.
> +	 */
>  	ctrls_ = configInfo.sensorControls;
>  
>  	const auto itExp = ctrls_.find(V4L2_CID_EXPOSURE);
> @@ -253,6 +279,9 @@ int IPAIPU3::configure(const IPAConfigInfo &configInfo)
>  	/* Set AE/AWB defaults, this typically might not belong here */
>  	aiqInputParams_.setAeAwbAfDefaults();
>  
> +	/* Upate the camera controls using the new sensor settings. */
> +	updateControls(sensorInfo_, ctrls_, ipaControls);
> +
>  	return 0;
>  }
>  

-- 
Regards,

Laurent Pinchart


More information about the libcamera-devel mailing list