[libcamera-devel] [PATCH v2 4/6] ipa: raspberry: Port to the new AEGC controls

paul.elder at ideasonboard.com paul.elder at ideasonboard.com
Tue Aug 16 07:30:55 CEST 2022


Hi Jacopo,

On Thu, Aug 11, 2022 at 05:02:17PM +0200, Jacopo Mondi via libcamera-devel wrote:
> The newly introduced controls to driver the AEGC algorithm allow

s/driver/drive/

> to control the computation of the exposure time and analogue gain

s/to control/controlling/

> separately.
> 
> The RPi AEGC implementation already computes the shutter and gain
> values separately but does not expose separate functions to control
> them.
> 
> Augment the AgcAlgorithm interface to allow to pause/resume the shutter

s#to pause/resume#pausing/resuming#

> and gain automatic computations separately and plumb them to the newly
> introduced controls.
> 
> Add safety checks to ignore ExposureTime and AnalogueGain values if the
> algorithms are not paused, and report the correct AeState value by
> checking if both algorithms have been paused or if they have converged.
> 
> Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>

Reviewed-by: Paul Elder <paul.elder at ideasonboard.com>

> ---
>  .../raspberrypi/controller/agc_algorithm.h    |  6 ++
>  src/ipa/raspberrypi/controller/rpi/agc.cpp    | 24 +++++-
>  src/ipa/raspberrypi/controller/rpi/agc.h      |  8 +-
>  src/ipa/raspberrypi/raspberrypi.cpp           | 76 ++++++++++++++++---
>  4 files changed, 99 insertions(+), 15 deletions(-)
> 
> diff --git a/src/ipa/raspberrypi/controller/agc_algorithm.h b/src/ipa/raspberrypi/controller/agc_algorithm.h
> index 3a91444c3a61..bf9c501db553 100644
> --- a/src/ipa/raspberrypi/controller/agc_algorithm.h
> +++ b/src/ipa/raspberrypi/controller/agc_algorithm.h
> @@ -17,6 +17,12 @@ class AgcAlgorithm : public Algorithm
>  public:
>  	AgcAlgorithm(Controller *controller) : Algorithm(controller) {}
>  	/* An AGC algorithm must provide the following: */
> +	virtual void pauseShutter();
> +	virtual void resumeShutter();
> +	virtual bool isShutterPaused() const;
> +	virtual void pauseGain();
> +	virtual void resumeGain();
> +	virtual bool isGainPaused() const;
>  	virtual unsigned int getConvergenceFrames() const = 0;
>  	virtual void setEv(double ev) = 0;
>  	virtual void setFlickerPeriod(libcamera::utils::Duration flickerPeriod) = 0;
> diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp b/src/ipa/raspberrypi/controller/rpi/agc.cpp
> index bd54a639d637..3d04724349f7 100644
> --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp
> +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp
> @@ -275,18 +275,36 @@ bool Agc::isPaused() const
>  	return false;
>  }
>  
> -void Agc::pause()
> +void Agc::pauseShutter()
>  {
>  	fixedShutter_ = status_.shutterTime;
> -	fixedAnalogueGain_ = status_.analogueGain;
>  }
>  
> -void Agc::resume()
> +void Agc::resumeShutter()
>  {
>  	fixedShutter_ = 0s;
> +}
> +
> +bool Agc::isShutterPaused() const
> +{
> +	return fixedShutter_ != 0s;
> +}
> +
> +void Agc::pauseGain()
> +{
> +	fixedAnalogueGain_ = status_.analogueGain;
> +}
> +
> +void Agc::resumeGain()
> +{
>  	fixedAnalogueGain_ = 0;
>  }
>  
> +bool Agc::isGainPaused() const
> +{
> +	return fixedAnalogueGain_ != 0;
> +}
> +
>  unsigned int Agc::getConvergenceFrames() const
>  {
>  	/*
> diff --git a/src/ipa/raspberrypi/controller/rpi/agc.h b/src/ipa/raspberrypi/controller/rpi/agc.h
> index 6d6b0e5ad857..cfb57f41848b 100644
> --- a/src/ipa/raspberrypi/controller/rpi/agc.h
> +++ b/src/ipa/raspberrypi/controller/rpi/agc.h
> @@ -77,8 +77,12 @@ public:
>  	int read(const libcamera::YamlObject &params) override;
>  	/* AGC handles "pausing" for itself. */
>  	bool isPaused() const override;
> -	void pause() override;
> -	void resume() override;
> +	void pauseShutter() override;
> +	void resumeShutter() override;
> +	bool isShutterPaused() const override;
> +	void pauseGain() override;
> +	void resumeGain() override;
> +	bool isGainPaused() const override;
>  	unsigned int getConvergenceFrames() const override;
>  	void setEv(double ev) override;
>  	void setFlickerPeriod(libcamera::utils::Duration flickerPeriod) override;
> diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp
> index 69c73f8c780a..c041aac008eb 100644
> --- a/src/ipa/raspberrypi/raspberrypi.cpp
> +++ b/src/ipa/raspberrypi/raspberrypi.cpp
> @@ -74,8 +74,13 @@ constexpr Duration controllerMinFrameDuration = 1.0s / 30.0;
>  
>  /* List of controls handled by the Raspberry Pi IPA */
>  static const ControlInfoMap::Map ipaControls{
> -	{ &controls::AeEnable, ControlInfo(false, true) },
> +	{ &controls::ExposureTimeMode,
> +	  ControlInfo(static_cast<int32_t>(controls::ExposureTimeModeAuto),
> +		      static_cast<int32_t>(controls::ExposureTimeModeManual)) },
>  	{ &controls::ExposureTime, ControlInfo(0, 66666) },
> +	{ &controls::AnalogueGainMode,
> +	  ControlInfo(static_cast<int32_t>(controls::AnalogueGainModeAuto),
> +		      static_cast<int32_t>(controls::AnalogueGainModeManual)) },
>  	{ &controls::AnalogueGain, ControlInfo(1.0f, 16.0f) },
>  	{ &controls::AeMeteringMode, ControlInfo(controls::AeMeteringModeValues) },
>  	{ &controls::AeConstraintMode, ControlInfo(controls::AeConstraintModeValues) },
> @@ -556,9 +561,18 @@ void IPARPi::reportMetadata()
>  	}
>  
>  	AgcStatus *agcStatus = rpiMetadata_.getLocked<AgcStatus>("agc.status");
> -	if (agcStatus) {
> -		libcameraMetadata_.set(controls::AeLocked, agcStatus->locked);
> +	if (agcStatus)
>  		libcameraMetadata_.set(controls::DigitalGain, agcStatus->digitalGain);
> +
> +	RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>(
> +		controller_.getAlgorithm("agc"));
> +	if (agc) {
> +		if (agc->isShutterPaused() && agc->isGainPaused())
> +			libcameraMetadata_.set(controls::AeState, controls::AeStateIdle);
> +		else if (agcStatus)
> +			libcameraMetadata_.set(controls::AeState,
> +					       agcStatus->locked ? controls::AeStateConverged
> +								 : controls::AeStateSearching);
>  	}
>  
>  	LuxStatus *luxStatus = rpiMetadata_.getLocked<LuxStatus>("lux.status");
> @@ -703,20 +717,22 @@ void IPARPi::queueRequest(const ControlList &controls)
>  				   << " = " << ctrl.second.toString();
>  
>  		switch (ctrl.first) {
> -		case controls::AE_ENABLE: {
> -			RPiController::Algorithm *agc = controller_.getAlgorithm("agc");
> +		case controls::EXPOSURE_TIME_MODE: {
> +			RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>(
> +				controller_.getAlgorithm("agc"));
>  			if (!agc) {
>  				LOG(IPARPI, Warning)
> -					<< "Could not set AE_ENABLE - no AGC algorithm";
> +					<< "Could not set EXPOSURE_TIME_MODE - no AGC algorithm";
>  				break;
>  			}
>  
> -			if (ctrl.second.get<bool>() == false)
> -				agc->pause();
> +			if (ctrl.second.get<int32_t>() == controls::ExposureTimeModeManual)
> +				agc->pauseShutter();
>  			else
> -				agc->resume();
> +				agc->resumeShutter();
>  
> -			libcameraMetadata_.set(controls::AeEnable, ctrl.second.get<bool>());
> +			libcameraMetadata_.set(controls::ExposureTimeMode,
> +					       ctrl.second.get<int32_t>());
>  			break;
>  		}
>  
> @@ -729,6 +745,13 @@ void IPARPi::queueRequest(const ControlList &controls)
>  				break;
>  			}
>  
> +			/*
> +			 * Ignore manual exposure time when the auto exposure
> +			 * algorithm is running.
> +			 */
> +			if (!agc->isShutterPaused())
> +				break;
> +
>  			/* The control provides units of microseconds. */
>  			agc->setFixedShutter(ctrl.second.get<int32_t>() * 1.0us);
>  
> @@ -736,6 +759,25 @@ void IPARPi::queueRequest(const ControlList &controls)
>  			break;
>  		}
>  
> +		case controls::ANALOGUE_GAIN_MODE: {
> +			RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>(
> +				controller_.getAlgorithm("agc"));
> +			if (!agc) {
> +				LOG(IPARPI, Warning)
> +					<< "Could not set ANALOGUE_GAIN_MODE - no AGC algorithm";
> +				break;
> +			}
> +
> +			if (ctrl.second.get<int32_t>() == controls::AnalogueGainModeManual)
> +				agc->pauseGain();
> +			else
> +				agc->resumeGain();
> +
> +			libcameraMetadata_.set(controls::AnalogueGainMode,
> +					       ctrl.second.get<int32_t>());
> +			break;
> +		}
> +
>  		case controls::ANALOGUE_GAIN: {
>  			RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>(
>  				controller_.getAlgorithm("agc"));
> @@ -745,6 +787,13 @@ void IPARPi::queueRequest(const ControlList &controls)
>  				break;
>  			}
>  
> +			/*
> +			 * Ignore manual analogue gain value when the auto gain
> +			 * algorithm is running.
> +			 */
> +			if (!agc->isGainPaused())
> +				break;
> +
>  			agc->setFixedAnalogueGain(ctrl.second.get<float>());
>  
>  			libcameraMetadata_.set(controls::AnalogueGain,
> @@ -801,6 +850,13 @@ void IPARPi::queueRequest(const ControlList &controls)
>  				break;
>  			}
>  
> +			/*
> +			 * Ignore AE_EXPOSURE_MODE if the shutter or the gain
> +			 * are in auto mode.
> +			 */
> +			if (!agc->isShutterPaused() || !agc->isGainPaused())
> +				break;
> +
>  			int32_t idx = ctrl.second.get<int32_t>();
>  			if (ExposureModeTable.count(idx)) {
>  				agc->setExposureMode(ExposureModeTable.at(idx));
> -- 
> 2.37.1
> 


More information about the libcamera-devel mailing list