[libcamera-devel,v3,15/23] libcamera: ipu3: Initialize controls in the pipeline
diff mbox series

Message ID 20220630133902.321099-16-jacopo@jmondi.org
State Not Applicable, archived
Headers show
Series
  • Internal controls, sensor delays and IPA rework
Related show

Commit Message

Jacopo Mondi June 30, 2022, 1:38 p.m. UTC
Currently the map of V4L2 controls collected from the sensor is passed to
the IPA module which initializes Camera controls by inspecting the
sensor control values.

As the CameraSensor class translates V4L2 controls into
libcamera::internal controls, the Camera controls can be initialized
directly in the pipeline handler, without sending them to the IPA which
receives all the information it needs using the CameraSensorInfo.

Remove from the IPA interface the list of V4L2 controls from the sensor
sent to the IPA as it is not used anymore and initialize Camera controls
in the pipeline directly.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
---
 include/libcamera/ipa/ipu3.mojom     |  7 +--
 src/ipa/ipu3/ipu3.cpp                | 86 ++--------------------------
 src/libcamera/pipeline/ipu3/ipu3.cpp | 32 ++++++-----
 3 files changed, 25 insertions(+), 100 deletions(-)

Patch
diff mbox series

diff --git a/include/libcamera/ipa/ipu3.mojom b/include/libcamera/ipa/ipu3.mojom
index d1b1c6b867da..5818cd3a6846 100644
--- a/include/libcamera/ipa/ipu3.mojom
+++ b/include/libcamera/ipa/ipu3.mojom
@@ -18,14 +18,13 @@  struct IPAConfigInfo {
 
 interface IPAIPU3Interface {
 	init(libcamera.IPASettings settings,
-	     libcamera.IPACameraSensorInfo sensorInfo,
-	     libcamera.ControlInfoMap sensorControls)
-		=> (int32 ret, libcamera.ControlInfoMap ipaControls);
+	     libcamera.IPACameraSensorInfo sensorInfo)
+		=> (int32 ret);
 	start() => (int32 ret);
 	stop();
 
 	configure(IPAConfigInfo configInfo)
-		=> (int32 ret, libcamera.ControlInfoMap ipaControls);
+		=> (int32 ret);
 
 	mapBuffers(array<libcamera.IPABuffer> buffers);
 	unmapBuffers(array<uint32> ids);
diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp
index 2f6bb672f7bb..a6e5dcbaada9 100644
--- a/src/ipa/ipu3/ipu3.cpp
+++ b/src/ipa/ipu3/ipu3.cpp
@@ -132,15 +132,12 @@  class IPAIPU3 : public IPAIPU3Interface
 {
 public:
 	int init(const IPASettings &settings,
-		 const IPACameraSensorInfo &sensorInfo,
-		 const ControlInfoMap &sensorControls,
-		 ControlInfoMap *ipaControls) override;
+		 const IPACameraSensorInfo &sensorInfo) override;
 
 	int start() override;
 	void stop() override;
 
-	int configure(const IPAConfigInfo &configInfo,
-		      ControlInfoMap *ipaControls) override;
+	int configure(const IPAConfigInfo &configInfo) override;
 
 	void mapBuffers(const std::vector<IPABuffer> &buffers) override;
 	void unmapBuffers(const std::vector<unsigned int> &ids) override;
@@ -151,9 +148,6 @@  public:
 				const uint32_t bufferId,
 				const ControlList &sensorControls) override;
 private:
-	void updateControls(const IPACameraSensorInfo &sensorInfo,
-			    const ControlInfoMap &sensorControls,
-			    ControlInfoMap *ipaControls);
 	void updateSessionConfiguration(const ControlInfoMap &sensorControls);
 
 	bool validateSensorControls();
@@ -208,68 +202,6 @@  void IPAIPU3::updateSessionConfiguration(const ControlInfoMap &sensorControls)
 	context_.configuration.agc.maxAnalogueGain = camHelper_->gain(maxGain);
 }
 
-/**
- * \brief 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{};
-	double lineDuration = context_.configuration.sensor.lineDuration.get<std::micro>();
-
-	/*
-	 * 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.
-	 */
-	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);
-}
-
 /**
  * \brief Validate that the sensor controls mandatory for the IPA exists
  */
@@ -300,9 +232,7 @@  bool IPAIPU3::validateSensorControls()
  * them in the \a ipaControls output parameter.
  */
 int IPAIPU3::init(const IPASettings &settings,
-		  const IPACameraSensorInfo &sensorInfo,
-		  const ControlInfoMap &sensorControls,
-		  ControlInfoMap *ipaControls)
+		  const IPACameraSensorInfo &sensorInfo)
 {
 	camHelper_ = CameraSensorHelperFactory::create(settings.sensorModel);
 	if (camHelper_ == nullptr) {
@@ -323,9 +253,6 @@  int IPAIPU3::init(const IPASettings &settings,
 	algorithms_.push_back(std::make_unique<algorithms::BlackLevelCorrection>());
 	algorithms_.push_back(std::make_unique<algorithms::ToneMapping>());
 
-	/* Initialize controls. */
-	updateControls(sensorInfo, sensorControls, ipaControls);
-
 	return 0;
 }
 
@@ -423,7 +350,6 @@  void IPAIPU3::calculateBdsGrid(const Size &bdsOutputSize)
  * \brief Configure the IPU3 IPA
  * \param[in] configInfo The IPA configuration data, received from the pipeline
  * handler
- * \param[in] ipaControls The IPA controls to update
  *
  * Calculate the best grid for the statistics based on the pipeline handler BDS
  * output, and parse the minimum and maximum exposure and analogue gain control
@@ -434,8 +360,7 @@  void IPAIPU3::calculateBdsGrid(const Size &bdsOutputSize)
  * All algorithm modules are called to allow them to prepare the
  * \a IPASessionConfiguration structure for the \a IPAContext.
  */
-int IPAIPU3::configure(const IPAConfigInfo &configInfo,
-		       ControlInfoMap *ipaControls)
+int IPAIPU3::configure(const IPAConfigInfo &configInfo)
 {
 	if (configInfo.sensorControls.empty()) {
 		LOG(IPAIPU3, Error) << "No sensor controls provided";
@@ -464,9 +389,6 @@  int IPAIPU3::configure(const IPAConfigInfo &configInfo,
 		return -EINVAL;
 	}
 
-	/* Update the camera controls using the new sensor settings. */
-	updateControls(sensorInfo_, sensorCtrls_, ipaControls);
-
 	/* Update the IPASessionConfiguration using the sensor settings. */
 	updateSessionConfiguration(sensorCtrls_);
 
diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index a5a35b6585c6..8c5b6c36ae0b 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -26,6 +26,7 @@ 
 #include "libcamera/internal/camera.h"
 #include "libcamera/internal/camera_lens.h"
 #include "libcamera/internal/camera_sensor.h"
+#include "libcamera/internal/control_ids.h"
 #include "libcamera/internal/device_enumerator.h"
 #include "libcamera/internal/framebuffer.h"
 #include "libcamera/internal/ipa_manager.h"
@@ -82,8 +83,6 @@  public:
 	/* Requests queued to the CIO2 device but not yet processed by the ImgU. */
 	std::queue<Request *> processingRequests_;
 
-	ControlInfoMap ipaControls_;
-
 private:
 	void metadataReady(unsigned int id, const ControlList &metadata);
 	void paramsBufferReady(unsigned int id);
@@ -670,7 +669,7 @@  int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c)
 	configInfo.bdsOutputSize = config->imguConfig().bds;
 	configInfo.iif = config->imguConfig().iif;
 
-	ret = data->ipa_->configure(configInfo, &data->ipaControls_);
+	ret = data->ipa_->configure(configInfo);
 	if (ret) {
 		LOG(IPU3, Error) << "Failed to configure IPA: "
 				 << strerror(-ret);
@@ -946,9 +945,6 @@  bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator)
  * Initialize the camera controls by calculating controls which the pipeline
  * is reponsible for and merge them with the controls computed by the IPA.
  *
- * This function needs data->ipaControls_ to be initialized by the IPA init()
- * function at camera creation time. Always call this function after IPA init().
- *
  * \return 0 on success or a negative error code otherwise
  */
 int PipelineHandlerIPU3::initControls(IPU3CameraData *data)
@@ -978,9 +974,6 @@  int PipelineHandlerIPU3::initControls(IPU3CameraData *data)
  * Compute the camera controls by calculating controls which the pipeline
  * is reponsible for and merge them with the controls computed by the IPA.
  *
- * This function needs data->ipaControls_ to be refreshed when a new
- * configuration is applied to the camera by the IPA configure() function.
- *
  * Always call this function after IPA configure() to make sure to have a
  * properly refreshed IPA controls list.
  *
@@ -1059,9 +1052,21 @@  int PipelineHandlerIPU3::updateControls(IPU3CameraData *data)
 
 	controls[&controls::ScalerCrop] = ControlInfo(minCrop, maxCrop, maxCrop);
 
-	/* Add the IPA registered controls to list of camera controls. */
-	for (const auto &ipaControl : data->ipaControls_)
-		controls[ipaControl.first] = ipaControl.second;
+	/*
+	 * Translate the sensor controls to Camera controls.
+	 *
+	 * Exposure time and the frame duration limits are reported directly
+	 * from the sensor.
+	 */
+	const ControlInfoMap &sensorControls = sensor->controls();
+
+	if (sensorControls.count(&controls::internal::ExposureTime))
+		controls[&controls::ExposureTime] =
+			sensorControls.at(&controls::internal::ExposureTime);
+
+	if (sensorControls.count(&controls::internal::FrameDuration))
+		controls[&controls::FrameDurationLimits] =
+			sensorControls.at(&controls::internal::FrameDuration);
 
 	data->controlInfo_ = ControlInfoMap(std::move(controls),
 					    controls::controls);
@@ -1237,8 +1242,7 @@  int IPU3CameraData::loadIPA()
 	if (ret)
 		return ret;
 
-	ret = ipa_->init(IPASettings{ "", sensor->model() }, sensorInfo,
-			 sensor->v4l2Controls(), &ipaControls_);
+	ret = ipa_->init(IPASettings{ "", sensor->model() }, sensorInfo);
 	if (ret) {
 		LOG(IPU3, Error) << "Failed to initialise the IPU3 IPA";
 		return ret;