[libcamera-devel] [PATCH v4 4/9] ipa: rkisp1: Add support for manual gain and exposure

Jacopo Mondi jacopo at jmondi.org
Thu Nov 24 13:23:11 CET 2022


Hi Laurent

On Thu, Nov 24, 2022 at 04:51:28AM +0200, Laurent Pinchart via libcamera-devel wrote:
> From: Paul Elder <paul.elder at ideasonboard.com>
>
> Add support for manual gain and exposure in the rkisp1 IPA.
>
> Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>

Looks good!
Reviewed-by: Jacopo Mondi <jacopo at jmondi.org>

Thanks
  j

> ---
> Changes since v3:
>
> - Convert exposure and gain V4L2 controls limits to libcamera values
> - Convert exposure control from duration to lines in AGC
> - Initialize lineDuration in init()
> - Small fixes in debug messages
> - Drop unnecessary curly braces
> - Use std::piecewise_construct
> ---
>  src/ipa/rkisp1/algorithms/agc.cpp | 63 +++++++++++++++++++++++++++----
>  src/ipa/rkisp1/algorithms/agc.h   |  4 ++
>  src/ipa/rkisp1/ipa_context.h      | 13 ++++++-
>  src/ipa/rkisp1/rkisp1.cpp         | 25 ++++++++++++
>  4 files changed, 96 insertions(+), 9 deletions(-)
>
> diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp
> index 169afe372803..ccbcd4a9583d 100644
> --- a/src/ipa/rkisp1/algorithms/agc.cpp
> +++ b/src/ipa/rkisp1/algorithms/agc.cpp
> @@ -74,9 +74,14 @@ Agc::Agc()
>  int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo)
>  {
>  	/* Configure the default exposure and gain. */
> -	context.activeState.agc.gain = std::max(context.configuration.sensor.minAnalogueGain,
> -						kMinAnalogueGain);
> -	context.activeState.agc.exposure = 10ms / context.configuration.sensor.lineDuration;
> +	context.activeState.agc.automatic.gain =
> +		std::max(context.configuration.sensor.minAnalogueGain,
> +			 kMinAnalogueGain);
> +	context.activeState.agc.automatic.exposure =
> +		10ms / context.configuration.sensor.lineDuration;
> +	context.activeState.agc.manual.gain = context.activeState.agc.automatic.gain;
> +	context.activeState.agc.manual.exposure = context.activeState.agc.automatic.exposure;
> +	context.activeState.agc.autoEnabled = true;
>
>  	/*
>  	 * According to the RkISP1 documentation:
> @@ -108,14 +113,58 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo)
>  	return 0;
>  }
>
> +/**
> + * \copydoc libcamera::ipa::Algorithm::queueRequest
> + */
> +void Agc::queueRequest(IPAContext &context,
> +		       [[maybe_unused]] const uint32_t frame,
> +		       IPAFrameContext &frameContext,
> +		       const ControlList &controls)
> +{
> +	auto &agc = context.activeState.agc;
> +
> +	const auto &agcEnable = controls.get(controls::AeEnable);
> +	if (agcEnable && *agcEnable != agc.autoEnabled) {
> +		agc.autoEnabled = *agcEnable;
> +
> +		LOG(RkISP1Agc, Debug)
> +			<< (agc.autoEnabled ? "Enabling" : "Disabling") << " AGC";
> +	}
> +
> +	const auto &exposure = controls.get(controls::ExposureTime);
> +	if (exposure && !agc.autoEnabled) {
> +		agc.manual.exposure = *exposure * 1.0us
> +				    / context.configuration.sensor.lineDuration;
> +
> +		LOG(RkISP1Agc, Debug)
> +			<< "Set exposure to " << agc.manual.exposure;
> +	}
> +
> +	const auto &gain = controls.get(controls::AnalogueGain);
> +	if (gain && !agc.autoEnabled) {
> +		agc.manual.gain = *gain;
> +
> +		LOG(RkISP1Agc, Debug) << "Set gain to " << agc.manual.gain;
> +	}
> +
> +	frameContext.agc.autoEnabled = agc.autoEnabled;
> +
> +	if (!frameContext.agc.autoEnabled) {
> +		frameContext.agc.exposure = agc.manual.exposure;
> +		frameContext.agc.gain = agc.manual.gain;
> +	}
> +}
> +
>  /**
>   * \copydoc libcamera::ipa::Algorithm::prepare
>   */
>  void Agc::prepare(IPAContext &context, const uint32_t frame,
>  		  IPAFrameContext &frameContext, rkisp1_params_cfg *params)
>  {
> -	frameContext.agc.exposure = context.activeState.agc.exposure;
> -	frameContext.agc.gain = context.activeState.agc.gain;
> +	if (frameContext.agc.autoEnabled) {
> +		frameContext.agc.exposure = context.activeState.agc.automatic.exposure;
> +		frameContext.agc.gain = context.activeState.agc.automatic.gain;
> +	}
>
>  	if (frame > 0)
>  		return;
> @@ -263,8 +312,8 @@ void Agc::computeExposure(IPAContext &context, IPAFrameContext &frameContext,
>  			      << stepGain;
>
>  	/* Update the estimated exposure and gain. */
> -	activeState.agc.exposure = shutterTime / configuration.sensor.lineDuration;
> -	activeState.agc.gain = stepGain;
> +	activeState.agc.automatic.exposure = shutterTime / configuration.sensor.lineDuration;
> +	activeState.agc.automatic.gain = stepGain;
>  }
>
>  /**
> diff --git a/src/ipa/rkisp1/algorithms/agc.h b/src/ipa/rkisp1/algorithms/agc.h
> index da4d2d4e8359..a228d0c37768 100644
> --- a/src/ipa/rkisp1/algorithms/agc.h
> +++ b/src/ipa/rkisp1/algorithms/agc.h
> @@ -26,6 +26,10 @@ public:
>  	~Agc() = default;
>
>  	int configure(IPAContext &context, const IPACameraSensorInfo &configInfo) override;
> +	void queueRequest(IPAContext &context,
> +			  const uint32_t frame,
> +			  IPAFrameContext &frameContext,
> +			  const ControlList &controls) override;
>  	void prepare(IPAContext &context, const uint32_t frame,
>  		     IPAFrameContext &frameContext,
>  		     rkisp1_params_cfg *params) override;
> diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h
> index 3e47ac663c58..b9b2065328d6 100644
> --- a/src/ipa/rkisp1/ipa_context.h
> +++ b/src/ipa/rkisp1/ipa_context.h
> @@ -54,8 +54,16 @@ struct IPASessionConfiguration {
>
>  struct IPAActiveState {
>  	struct {
> -		uint32_t exposure;
> -		double gain;
> +		struct {
> +			uint32_t exposure;
> +			double gain;
> +		} manual;
> +		struct {
> +			uint32_t exposure;
> +			double gain;
> +		} automatic;
> +
> +		bool autoEnabled;
>  	} agc;
>
>  	struct {
> @@ -96,6 +104,7 @@ struct IPAFrameContext : public FrameContext {
>  	struct {
>  		uint32_t exposure;
>  		double gain;
> +		bool autoEnabled;
>  	} agc;
>
>  	struct {
> diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp
> index 6ac29df8ec8d..76e818d2d11e 100644
> --- a/src/ipa/rkisp1/rkisp1.cpp
> +++ b/src/ipa/rkisp1/rkisp1.cpp
> @@ -158,6 +158,9 @@ int IPARkISP1::init(const IPASettings &settings, unsigned int hwRevision,
>  		return -ENODEV;
>  	}
>
> +	context_.configuration.sensor.lineDuration = sensorInfo.minLineLength
> +						   * 1.0s / sensorInfo.pixelRate;
> +
>  	/* Load the tuning data file. */
>  	File file(settings.configurationFile);
>  	if (!file.open(File::OpenModeFlag::ReadOnly)) {
> @@ -377,6 +380,28 @@ void IPARkISP1::updateControls(const IPACameraSensorInfo &sensorInfo,
>  {
>  	ControlInfoMap::Map ctrlMap = rkisp1Controls;
>
> +	/*
> +	 * Compute exposure time limits from the V4L2_CID_EXPOSURE control
> +	 * limits and the line duration.
> +	 */
> +	double lineDuration = context_.configuration.sensor.lineDuration.get<std::micro>();
> +	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;
> +	ctrlMap.emplace(std::piecewise_construct,
> +			std::forward_as_tuple(&controls::ExposureTime),
> +			std::forward_as_tuple(minExposure, maxExposure, defExposure));
> +
> +	/* Compute the analogue gain limits. */
> +	const ControlInfo &v4l2Gain = sensorControls.find(V4L2_CID_ANALOGUE_GAIN)->second;
> +	float minGain = camHelper_->gain(v4l2Gain.min().get<int32_t>());
> +	float maxGain = camHelper_->gain(v4l2Gain.max().get<int32_t>());
> +	float defGain = camHelper_->gain(v4l2Gain.def().get<int32_t>());
> +	ctrlMap.emplace(std::piecewise_construct,
> +			std::forward_as_tuple(&controls::AnalogueGain),
> +			std::forward_as_tuple(minGain, maxGain, defGain));
> +
>  	/*
>  	 * Compute the frame duration limits.
>  	 *
> --
> Regards,
>
> Laurent Pinchart
>


More information about the libcamera-devel mailing list