[PATCH v7 16/18] libcamera: software_isp: Use DelayedControls

Umang Jain umang.jain at ideasonboard.com
Thu Sep 26 21:25:34 CEST 2024


Hi Milan,

On 21/09/24 12:01 am, Milan Zamazal wrote:
> Use the standard libcamera mechanism to report the "current" controls
> rather than delaying updates by counting from the last update.
>
> A problem is that with software ISP we cannot be sure about the sensor
> delay.  The original implementation simply skips exposure updates for 2
> frames, which should be enough in most cases.  After this change, we
> assume the delay being exactly 2 frames, which may or may not be correct
> and may work with outdated values if the delay is shorter.
>
> According to Kieran, the wrong parts are also wrong on the
> IPU3/RKISP1/Mali pipelines and only RPi have this correct.  We need to
> fix this, by correctly specifying the gains in the libipa camera sensor
> helpers.  The sooner the better because this change could introduce a
> risk of increasing oscillations.
>
> This patch also prepares moving exposure+gain to an algorithm module
> where the original delay mechanism would be a (possibly unnecessary)
> complication.
>
> Resolves software ISP TODO #11 + #12.
>
> Signed-off-by: Milan Zamazal <mzamazal at redhat.com>
> Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>

Reviewed-by: Umang Jain <umang.jain at ideasonboard.com>
> ---
>   src/ipa/simple/soft_simple.cpp           | 16 +------------
>   src/libcamera/pipeline/simple/simple.cpp | 18 ++++++++++++---
>   src/libcamera/software_isp/TODO          | 29 ------------------------
>   3 files changed, 16 insertions(+), 47 deletions(-)
>
> diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp
> index f8d923c5..60310a8e 100644
> --- a/src/ipa/simple/soft_simple.cpp
> +++ b/src/ipa/simple/soft_simple.cpp
> @@ -59,8 +59,7 @@ class IPASoftSimple : public ipa::soft::IPASoftInterface, public Module
>   public:
>   	IPASoftSimple()
>   		: params_(nullptr), stats_(nullptr),
> -		  context_({ {}, {}, { kMaxFrameContexts } }),
> -		  ignoreUpdates_(0)
> +		  context_({ {}, {}, { kMaxFrameContexts } })
>   	{
>   	}
>   
> @@ -98,7 +97,6 @@ private:
>   	int32_t exposure_;
>   	double againMin_, againMax_, againMinStep_;
>   	double again_;
> -	unsigned int ignoreUpdates_;
>   };
>   
>   IPASoftSimple::~IPASoftSimple()
> @@ -298,16 +296,6 @@ void IPASoftSimple::processStats(const uint32_t frame,
>   
>   	/* \todo Switch to the libipa/algorithm.h API someday. */
>   
> -	/*
> -	 * AE / AGC, use 2 frames delay to make sure that the exposure and
> -	 * the gain set have applied to the camera sensor.
> -	 * \todo This could be handled better with DelayedControls.
> -	 */
> -	if (ignoreUpdates_ > 0) {
> -		--ignoreUpdates_;
> -		return;
> -	}
> -
>   	/*
>   	 * Calculate Mean Sample Value (MSV) according to formula from:
>   	 * https://www.araa.asn.au/acra/acra2007/papers/paper84final.pdf
> @@ -356,8 +344,6 @@ void IPASoftSimple::processStats(const uint32_t frame,
>   	ctrls.set(V4L2_CID_ANALOGUE_GAIN,
>   		  static_cast<int32_t>(camHelper_ ? camHelper_->gainCode(again_) : again_));
>   
> -	ignoreUpdates_ = 2;
> -
>   	setSensorControls.emit(ctrls);
>   
>   	LOG(IPASoft, Debug) << "exposureMSV " << exposureMSV
> diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
> index 61157fe6..1e13bd74 100644
> --- a/src/libcamera/pipeline/simple/simple.cpp
> +++ b/src/libcamera/pipeline/simple/simple.cpp
> @@ -32,6 +32,7 @@
>   #include "libcamera/internal/camera.h"
>   #include "libcamera/internal/camera_sensor.h"
>   #include "libcamera/internal/converter.h"
> +#include "libcamera/internal/delayed_controls.h"
>   #include "libcamera/internal/device_enumerator.h"
>   #include "libcamera/internal/media_device.h"
>   #include "libcamera/internal/pipeline_handler.h"
> @@ -278,6 +279,8 @@ public:
>   	std::vector<Configuration> configs_;
>   	std::map<PixelFormat, std::vector<const Configuration *>> formats_;
>   
> +	std::unique_ptr<DelayedControls> delayedCtrls_;
> +
>   	std::vector<std::unique_ptr<FrameBuffer>> conversionBuffers_;
>   	std::queue<std::map<const Stream *, FrameBuffer *>> conversionQueue_;
>   	bool useConversion_;
> @@ -896,14 +899,13 @@ void SimpleCameraData::conversionOutputDone(FrameBuffer *buffer)
>   
>   void SimpleCameraData::ispStatsReady(uint32_t frame, uint32_t bufferId)
>   {
> -	/* \todo Use the DelayedControls class */
>   	swIsp_->processStats(frame, bufferId,
> -			     sensor_->getControls({ V4L2_CID_ANALOGUE_GAIN,
> -						    V4L2_CID_EXPOSURE }));
> +			     delayedCtrls_->get(frame));
>   }
>   
>   void SimpleCameraData::setSensorControls(const ControlList &sensorControls)
>   {
> +	delayedCtrls_->push(sensorControls);
>   	ControlList ctrls(sensorControls);
>   	sensor_->setControls(&ctrls);
>   }
> @@ -1284,6 +1286,16 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c)
>   	if (outputCfgs.empty())
>   		return 0;
>   
> +	std::unordered_map<uint32_t, DelayedControls::ControlParams> params = {
> +		{ V4L2_CID_ANALOGUE_GAIN, { 2, false } },
> +		{ V4L2_CID_EXPOSURE, { 2, false } },
> +	};
> +	data->delayedCtrls_ =
> +		std::make_unique<DelayedControls>(data->sensor_->device(),
> +						  params);
> +	data->video_->frameStart.connect(data->delayedCtrls_.get(),
> +					 &DelayedControls::applyControls);
> +
>   	StreamConfiguration inputCfg;
>   	inputCfg.pixelFormat = pipeConfig->captureFormat;
>   	inputCfg.size = pipeConfig->captureSize;
> diff --git a/src/libcamera/software_isp/TODO b/src/libcamera/software_isp/TODO
> index 9978afc0..8eeede46 100644
> --- a/src/libcamera/software_isp/TODO
> +++ b/src/libcamera/software_isp/TODO
> @@ -209,35 +209,6 @@ At some point, yes.
>   
>   ---
>   
> -11. Improve handling the sensor controls which take effect with a delay
> -
> -> void IPASoftSimple::processStats(const ControlList &sensorControls)
> -> {
> ->       ...
> ->	/*
> ->	 * AE / AGC, use 2 frames delay to make sure that the exposure and
> ->	 * the gain set have applied to the camera sensor.
> ->	 */
> ->	if (ignore_updates_ > 0) {
> ->		--ignore_updates_;
> ->		return;
> ->	}
> -
> -This could be handled better with DelayedControls.
> -
> ----
> -
> -12. Use DelayedControls class in ispStatsReady()
> -
> -> void SimpleCameraData::ispStatsReady()
> -> {
> -> 	swIsp_->processStats(sensor_->getControls({ V4L2_CID_ANALOGUE_GAIN,
> -> 						    V4L2_CID_EXPOSURE }));
> -
> -You should use the DelayedControls class.
> -
> ----
> -
>   13. Improve black level and colour gains application
>   
>   I think the black level should eventually be moved before debayering, and



More information about the libcamera-devel mailing list