[libcamera-devel] [PATCH v6 07/10] ipa: rkisp1: af: Add "Windows" Metering mode

Jacopo Mondi jacopo.mondi at ideasonboard.com
Mon Apr 3 15:59:47 CEST 2023


Hi Daniel

On Fri, Mar 31, 2023 at 10:19:27AM +0200, Daniel Semkowicz via libcamera-devel wrote:
> Add platform related code for configuring auto focus window on the
> rkisp1. Connect to the windowUpdateRequested() signal exposed by the
> AfHillClimbing and configure the window on each signal emission.
> This enables support of AfMetering and AfWindows controls on the rkisp1
> platform.
>
> Currently, only one window is enabled, but ISP allows up to three
> of them.
>
> Signed-off-by: Daniel Semkowicz <dse at thaumatec.com>
> ---
>  src/ipa/rkisp1/algorithms/af.cpp | 64 +++++++++++++++++++++++++++++++-
>  src/ipa/rkisp1/algorithms/af.h   | 13 ++++++-
>  2 files changed, 75 insertions(+), 2 deletions(-)
>
> diff --git a/src/ipa/rkisp1/algorithms/af.cpp b/src/ipa/rkisp1/algorithms/af.cpp
> index fde924d4..b6f6eee4 100644
> --- a/src/ipa/rkisp1/algorithms/af.cpp
> +++ b/src/ipa/rkisp1/algorithms/af.cpp
> @@ -32,16 +32,43 @@ namespace ipa::rkisp1::algorithms {
>   *   amount of time on each movement. This parameter should be set according
>   *   to the worst case  - the number of frames it takes to move lens between
>   *   limit positions.
> + * - **isp-threshold:** Threshold used for minimizing the influence of noise.
> + *   This affects the ISP sharpness calculation.
> + * - **isp-var-shift:** The number of bits for the shift operation at the end
> + *   of the calculation chain. This affects the ISP sharpness calculation.

I wonder if the introduction of these values belong to this patch or
not. I guess they affect the AF algorithm globally, as a default
window has to be programmed to have it working (something that happens in this
patch, you might say :)

Regardless of that, have you been able to identify with a little more
accuracy how these values should be computed ? For the threshold I
guess the explanation is somewhat clear, but the var-shift parameter I
wonder how one should compute it ? As I read it, the var-shift value
represents the number number of bits to right-shift the pixel values
before summing them to avoid overflows of the afm_sum register (32
bits). How did you come up with a value of 4 in your configuration
file ? Does this value depend on the window size or does it depend on
the sensor in use ?

>   * .
>   * \sa libcamera::ipa::algorithms::AfHillClimbing for additional tuning
>   * parameters.
>   *
>   * \todo Model the lens delay as number of frames required for the lens position
>   * to stabilize in the CameraLens class.
> + * \todo Check if requested window size is valid. RkISP supports AF window size
> + * few pixels smaller than sensor output size.
> + * \todo Implement support for all available AF windows. RkISP supports up to 3
> + * AF windows.
>   */
>
>  LOG_DEFINE_CATEGORY(RkISP1Af)
>
> +namespace {
> +
> +constexpr rkisp1_cif_isp_window rectangleToIspWindow(const Rectangle &rectangle)
> +{
> +	return rkisp1_cif_isp_window{
> +		.h_offs = static_cast<uint16_t>(rectangle.x),
> +		.v_offs = static_cast<uint16_t>(rectangle.y),
> +		.h_size = static_cast<uint16_t>(rectangle.width),
> +		.v_size = static_cast<uint16_t>(rectangle.height)
> +	};
> +}
> +
> +} /* namespace */
> +
> +Af::Af()
> +{
> +	af.windowUpdateRequested.connect(this, &Af::updateCurrentWindow);
> +}
> +
>  /**
>   * \copydoc libcamera::ipa::Algorithm::init
>   */
> @@ -54,8 +81,12 @@ int Af::init(IPAContext &context, const YamlObject &tuningData)
>  	}
>
>  	waitFramesLens_ = tuningData["wait-frames-lens"].get<uint32_t>(1);
> +	ispThreshold_ = tuningData["isp-threshold"].get<uint32_t>(128);
> +	ispVarShift_ = tuningData["isp-var-shift"].get<uint32_t>(4);
>
> -	LOG(RkISP1Af, Debug) << "waitFramesLens_: " << waitFramesLens_;
> +	LOG(RkISP1Af, Debug) << "waitFramesLens_: " << waitFramesLens_
> +			     << ", ispThreshold_: " << ispThreshold_
> +			     << ", ispVarShift_: " << ispVarShift_;
>
>  	return af.init(lensConfig->minFocusPosition,
>  		       lensConfig->maxFocusPosition, tuningData);
> @@ -89,6 +120,32 @@ void Af::queueRequest([[maybe_unused]] IPAContext &context,
>  	af.queueRequest(controls);
>  }
>
> +/**
> + * \copydoc libcamera::ipa::Algorithm::prepare
> + */
> +void Af::prepare([[maybe_unused]] IPAContext &context,
> +		 [[maybe_unused]] const uint32_t frame,
> +		 [[maybe_unused]] IPAFrameContext &frameContext,
> +		 rkisp1_params_cfg *params)
> +{
> +	if (updateWindow_) {

or
        if (!updateWindow_)
                return;

> +		params->meas.afc_config.num_afm_win = 1;
> +		params->meas.afc_config.thres = ispThreshold_;
> +		params->meas.afc_config.var_shift = ispVarShift_;
> +		params->meas.afc_config.afm_win[0] =
> +			rectangleToIspWindow(*updateWindow_);
> +
> +		params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_AFC;
> +		params->module_ens |= RKISP1_CIF_ISP_MODULE_AFC;
> +		params->module_en_update |= RKISP1_CIF_ISP_MODULE_AFC;
> +
> +		updateWindow_.reset();
> +
> +		/* Wait one frame for the ISP to apply changes. */
> +		af.skipFrames(1);
> +	}
> +}
> +
>  /**
>   * \copydoc libcamera::ipa::Algorithm::process
>   */
> @@ -114,6 +171,11 @@ void Af::process(IPAContext &context, [[maybe_unused]] const uint32_t frame,
>  	}
>  }
>
> +void Af::updateCurrentWindow(const Rectangle &window)
> +{
> +	updateWindow_ = window;
> +}
> +
>  REGISTER_IPA_ALGORITHM(Af, "Af")
>
>  } /* namespace ipa::rkisp1::algorithms */
> diff --git a/src/ipa/rkisp1/algorithms/af.h b/src/ipa/rkisp1/algorithms/af.h
> index 3ba66d38..6f5adb19 100644
> --- a/src/ipa/rkisp1/algorithms/af.h
> +++ b/src/ipa/rkisp1/algorithms/af.h
> @@ -20,21 +20,32 @@ namespace ipa::rkisp1::algorithms {
>  class Af : public Algorithm
>  {
>  public:
> +	Af();
> +
>  	int init(IPAContext &context, const YamlObject &tuningData) override;
>  	int configure(IPAContext &context,
>  		      const IPACameraSensorInfo &configInfo) override;
>  	void queueRequest(IPAContext &context, uint32_t frame,
>  			  IPAFrameContext &frameContext,
>  			  const ControlList &controls) override;
> +	void prepare(IPAContext &context, uint32_t frame,
> +		     IPAFrameContext &frameContext,
> +		     rkisp1_params_cfg *params) override;
>  	void process(IPAContext &context, uint32_t frame,
>  		     IPAFrameContext &frameContext,
>  		     const rkisp1_stat_buffer *stats,
>  		     ControlList &metadata) override;
>
>  private:
> +	void updateCurrentWindow(const Rectangle &window);
> +
>  	ipa::algorithms::AfHillClimbing af;
>
> -	/* Wait number of frames after changing lens position */
> +	std::optional<Rectangle> updateWindow_;
> +	uint32_t ispThreshold_ = 0;
> +	uint32_t ispVarShift_ = 0;
> +
> +	/* Wait number of frames after changing lens position. */
>  	uint32_t waitFramesLens_ = 0;
>  };
>
> --
> 2.39.2
>


More information about the libcamera-devel mailing list