[libcamera-devel,IPU3-IPA] ipu3: Update camera controls in configure()
diff mbox series

Message ID 20211015151004.291295-1-kieran.bingham@ideasonboard.com
State Accepted
Headers show
Series
  • [libcamera-devel,IPU3-IPA] ipu3: Update camera controls in configure()
Related show

Commit Message

Kieran Bingham Oct. 15, 2021, 3:10 p.m. UTC
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@ideasonboard.com>
---
 ipu3.cpp | 127 ++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 78 insertions(+), 49 deletions(-)

Comments

Laurent Pinchart Oct. 15, 2021, 11:04 p.m. UTC | #1
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@ideasonboard.com>

Reviewed-by: Laurent Pinchart <laurent.pinchart@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;
>  }
>
Umang Jain Oct. 18, 2021, 1:36 p.m. UTC | #2
Hello,

Thanks for the patch.

On 10/15/21 8:40 PM, 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@ideasonboard.com>


Reviewed-by: Umang Jain<umang.jain@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;
>   }
>

Patch
diff mbox series

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;
 }