[libcamera-devel] [PATCH v3 03/13] ipa: rkisp1: Support raw capture in IPA operations

paul.elder at ideasonboard.com paul.elder at ideasonboard.com
Mon Oct 24 04:02:20 CEST 2022


On Mon, Oct 24, 2022 at 03:03:46AM +0300, Laurent Pinchart wrote:
> The RkISP1 can capture raw frames by bypassing the ISP. In that mode,
> the ISP will not produce statistics nor consume parameters. Most
> algorithms will thus be unable to run, with one exception: the AGC will
> still be able to configure the sensor exposure time and analog gain in
> manual mode.
> 
> To prepare for this, add the ability to disable algorithms for the
> duration of the capture session based on the camera configuration.
> Individual algorithms report whether they support raw formats at
> construction time, and the IPA module disables algorithms in configure()
> based on the stream configurations.
> 
> Disabled algorithms are skipped during the capture session in the
> processStatsBuffer() operation. As the ISP doesn't produce statistics,
> don't try to access the stats buffer. There is no need for similar logic
> in fillParamsBuffer() as that operation won't be called for raw capture.
> 
> All algorithms report not supporting raw capture by default. Raw support
> in AGC will be added separately.
> 
> The feature is implemented in the RkISP1 module without any support from
> libipa at this point to avoid designing a generic API based on a single
> user. This may be changed in the future.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> ---
>  src/ipa/rkisp1/algorithms/algorithm.h | 12 +++++++-
>  src/ipa/rkisp1/ipa_context.cpp        |  5 ++++
>  src/ipa/rkisp1/ipa_context.h          |  2 ++
>  src/ipa/rkisp1/rkisp1.cpp             | 42 +++++++++++++++++++++++----
>  4 files changed, 54 insertions(+), 7 deletions(-)
> 
> diff --git a/src/ipa/rkisp1/algorithms/algorithm.h b/src/ipa/rkisp1/algorithms/algorithm.h
> index c3212cff76fe..9454c9a1fc06 100644
> --- a/src/ipa/rkisp1/algorithms/algorithm.h
> +++ b/src/ipa/rkisp1/algorithms/algorithm.h
> @@ -15,7 +15,17 @@ namespace libcamera {
>  
>  namespace ipa::rkisp1 {
>  
> -using Algorithm = libcamera::ipa::Algorithm<Module>;
> +class Algorithm : public libcamera::ipa::Algorithm<Module>
> +{
> +public:
> +	Algorithm()
> +		: disabled_(false), supportsRaw_(false)
> +	{
> +	}
> +
> +	bool disabled_;
> +	bool supportsRaw_;
> +};
>  
>  } /* namespace ipa::rkisp1 */
>  
> diff --git a/src/ipa/rkisp1/ipa_context.cpp b/src/ipa/rkisp1/ipa_context.cpp
> index 7a987497bd03..9bbf368432fa 100644
> --- a/src/ipa/rkisp1/ipa_context.cpp
> +++ b/src/ipa/rkisp1/ipa_context.cpp
> @@ -89,6 +89,11 @@ namespace libcamera::ipa::rkisp1 {
>   * \brief Sensor output resolution
>   */
>  
> +/**
> + * \var IPASessionConfiguration::raw
> + * \brief Indicates if the camera is configured to capture raw frames
> + */
> +
>  /**
>   * \struct IPAActiveState
>   * \brief Active state for algorithms
> diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h
> index bb60ab9eab72..3e47ac663c58 100644
> --- a/src/ipa/rkisp1/ipa_context.h
> +++ b/src/ipa/rkisp1/ipa_context.h
> @@ -48,6 +48,8 @@ struct IPASessionConfiguration {
>  	struct {
>  		rkisp1_cif_isp_version revision;
>  	} hw;
> +
> +	bool raw;
>  };
>  
>  struct IPAActiveState {
> diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp
> index fcb9dacccc3c..538e42cb6f7f 100644
> --- a/src/ipa/rkisp1/rkisp1.cpp
> +++ b/src/ipa/rkisp1/rkisp1.cpp
> @@ -24,6 +24,7 @@
>  #include <libcamera/ipa/rkisp1_ipa_interface.h>
>  #include <libcamera/request.h>
>  
> +#include "libcamera/internal/formats.h"
>  #include "libcamera/internal/mapped_framebuffer.h"
>  #include "libcamera/internal/yaml_parser.h"
>  
> @@ -207,7 +208,7 @@ void IPARkISP1::stop()
>   * before accessing them.
>   */
>  int IPARkISP1::configure([[maybe_unused]] const IPACameraSensorInfo &info,
> -			 [[maybe_unused]] const std::map<uint32_t, IPAStream> &streamConfig,
> +			 const std::map<uint32_t, IPAStream> &streamConfig,
>  			 const std::map<uint32_t, ControlInfoMap> &entityControls)
>  {
>  	if (entityControls.empty())
> @@ -264,7 +265,21 @@ int IPARkISP1::configure([[maybe_unused]] const IPACameraSensorInfo &info,
>  	context_.configuration.sensor.minAnalogueGain = camHelper_->gain(minGain);
>  	context_.configuration.sensor.maxAnalogueGain = camHelper_->gain(maxGain);
>  
> -	for (auto const &algo : algorithms()) {
> +	context_.configuration.raw = std::any_of(streamConfig.begin(), streamConfig.end(),
> +		[](auto &cfg) -> bool {
> +			PixelFormat pixelFormat{ cfg.second.pixelFormat };
> +			const PixelFormatInfo &format = PixelFormatInfo::info(pixelFormat);
> +			return format.colourEncoding == PixelFormatInfo::ColourEncodingRAW;
> +		});
> +
> +	for (auto const &a : algorithms()) {
> +		Algorithm *algo = static_cast<Algorithm *>(a.get());
> +
> +		/* Disable algorithms that don't support raw formats. */
> +		algo->disabled_ = context_.configuration.raw && !algo->supportsRaw_;
> +		if (algo->disabled_)
> +			continue;
> +

On one hand I was thinking if the algorithms should internally nop if
they're in raw mode, but I think that indeed it's the job of the IPA to
control its algorithms based on its own config, so this is fine.

>  		int ret = algo->configure(context_, info);
>  		if (ret)
>  			return ret;
> @@ -307,8 +322,12 @@ void IPARkISP1::queueRequest(const uint32_t frame, const ControlList &controls)
>  {
>  	IPAFrameContext &frameContext = context_.frameContexts.alloc(frame);
>  
> -	for (auto const &algo : algorithms())
> +	for (auto const &a : algorithms()) {
> +		Algorithm *algo = static_cast<Algorithm *>(a.get());
> +		if (algo->disabled_)
> +			continue;
>  		algo->queueRequest(context_, frame, frameContext, controls);
> +	}
>  }
>  
>  void IPARkISP1::fillParamsBuffer(const uint32_t frame, const uint32_t bufferId)
> @@ -333,9 +352,16 @@ void IPARkISP1::processStatsBuffer(const uint32_t frame, const uint32_t bufferId
>  {
>  	IPAFrameContext &frameContext = context_.frameContexts.get(frame);
>  
> -	const rkisp1_stat_buffer *stats =
> -		reinterpret_cast<rkisp1_stat_buffer *>(
> +	/*
> +	 * In raw capture mode, the ISP is bypassed and no statistics buffer is
> +	 * provided.
> +	 */
> +	const rkisp1_stat_buffer *stats;
> +	if (!context_.configuration.raw)
> +		stats = reinterpret_cast<rkisp1_stat_buffer *>(
>  			mappedBuffers_.at(bufferId).planes()[0].data());
> +	else
> +		stats = nullptr;

processStatsBuffer() won't ever be called in raw mode *except* for
(before the pipeline hander is adjusted (I expect it to be later in the
series)) the first buffer that got queued at start time, and which would
be bufferReady-dequeued at streamoff. At least this protects against
dereferencing the null stats buffer, plus we don't report supporting raw
formats yet anyway, so I guess it's fine.

Just thinking aloud :)


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

>  
>  	frameContext.sensor.exposure =
>  		sensorControls.get(V4L2_CID_EXPOSURE).get<int32_t>();
> @@ -344,8 +370,12 @@ void IPARkISP1::processStatsBuffer(const uint32_t frame, const uint32_t bufferId
>  
>  	ControlList metadata(controls::controls);
>  
> -	for (auto const &algo : algorithms())
> +	for (auto const &a : algorithms()) {
> +		Algorithm *algo = static_cast<Algorithm *>(a.get());
> +		if (algo->disabled_)
> +			continue;
>  		algo->process(context_, frame, frameContext, stats, metadata);
> +	}
>  
>  	setControls(frame);
>  
> -- 
> Regards,
> 
> Laurent Pinchart
> 


More information about the libcamera-devel mailing list