[PATCH v4 13/18] libcamera: swstats_cpu: Add support for 8, 10 and 12 bpp unpacked bayer input

Milan Zamazal mzamazal at redhat.com
Mon Mar 4 18:30:15 CET 2024


Hans de Goede <hdegoede at redhat.com> writes:

> Add support for 8, 10 and 12 bpp unpacked bayer input for all 4 standard
> bayer orders.
>
> Tested-by: Bryan O'Donoghue <bryan.odonoghue at linaro.org> # sc8280xp Lenovo x13s
> Tested-by: Pavel Machek <pavel at ucw.cz>
> Reviewed-by: Pavel Machek <pavel at ucw.cz>
> Signed-off-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
> Signed-off-by: Hans de Goede <hdegoede at redhat.com>

Reviewed-by: Milan Zamazal <mzamazal at redhat.com>

> ---
>  src/libcamera/software_isp/swstats_cpu.cpp | 128 +++++++++++++++++++++
>  src/libcamera/software_isp/swstats_cpu.h   |   9 ++
>  2 files changed, 137 insertions(+)
>
> diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp
> index 448d0e4c..be310f56 100644
> --- a/src/libcamera/software_isp/swstats_cpu.cpp
> +++ b/src/libcamera/software_isp/swstats_cpu.cpp
> @@ -71,6 +71,83 @@ static const unsigned int kBlueYMul = 29; /* 0.114 * 256 */
>  	stats_.sumG_ += sumG;       \
>  	stats_.sumB_ += sumB;
>  
> +void SwStatsCpu::statsBGGR8Line0(const uint8_t *src[])
> +{
> +	const uint8_t *src0 = src[1] + window_.x;
> +	const uint8_t *src1 = src[2] + window_.x;
> +
> +	SWSTATS_START_LINE_STATS(uint8_t)
> +
> +	if (swapLines_)
> +		std::swap(src0, src1);
> +
> +	/* x += 4 sample every other 2x2 block */
> +	for (int x = 0; x < (int)window_.width; x += 4) {
> +		b = src0[x];
> +		g = src0[x + 1];
> +		g2 = src1[x];
> +		r = src1[x + 1];
> +
> +		g = (g + g2) / 2;
> +
> +		SWSTATS_ACCUMULATE_LINE_STATS(1)
> +	}
> +
> +	SWSTATS_FINISH_LINE_STATS()
> +}
> +
> +void SwStatsCpu::statsBGGR10Line0(const uint8_t *src[])
> +{
> +	const uint16_t *src0 = (const uint16_t *)src[1] + window_.x;
> +	const uint16_t *src1 = (const uint16_t *)src[2] + window_.x;
> +
> +	SWSTATS_START_LINE_STATS(uint16_t)
> +
> +	if (swapLines_)
> +		std::swap(src0, src1);
> +
> +	/* x += 4 sample every other 2x2 block */
> +	for (int x = 0; x < (int)window_.width; x += 4) {
> +		b = src0[x];
> +		g = src0[x + 1];
> +		g2 = src1[x];
> +		r = src1[x + 1];
> +
> +		g = (g + g2) / 2;
> +
> +		/* divide Y by 4 for 10 -> 8 bpp value */
> +		SWSTATS_ACCUMULATE_LINE_STATS(4)
> +	}
> +
> +	SWSTATS_FINISH_LINE_STATS()
> +}
> +
> +void SwStatsCpu::statsBGGR12Line0(const uint8_t *src[])
> +{
> +	const uint16_t *src0 = (const uint16_t *)src[1] + window_.x;
> +	const uint16_t *src1 = (const uint16_t *)src[2] + window_.x;
> +
> +	SWSTATS_START_LINE_STATS(uint16_t)
> +
> +	if (swapLines_)
> +		std::swap(src0, src1);
> +
> +	/* x += 4 sample every other 2x2 block */
> +	for (int x = 0; x < (int)window_.width; x += 4) {
> +		b = src0[x];
> +		g = src0[x + 1];
> +		g2 = src1[x];
> +		r = src1[x + 1];
> +
> +		g = (g + g2) / 2;
> +
> +		/* divide Y by 16 for 12 -> 8 bpp value */
> +		SWSTATS_ACCUMULATE_LINE_STATS(16)
> +	}
> +
> +	SWSTATS_FINISH_LINE_STATS()
> +}
> +
>  void SwStatsCpu::statsBGGR10PLine0(const uint8_t *src[])
>  {
>  	const uint8_t *src0 = src[1] + window_.x * 5 / 4;
> @@ -147,6 +224,42 @@ void SwStatsCpu::finishFrame(void)
>  	statsReady.emit(0);
>  }
>  
> +/**
> + * \brief Setup SwStatsCpu object for standard Bayer orders
> + * \param[in] order The Bayer order
> + *
> + * Check if order is a standard Bayer order and setup xShift_ and swapLines_
> + * so that a single BGGR stats function can be used for all 4 standard orders.
> + */
> +int SwStatsCpu::setupStandardBayerOrder(BayerFormat::Order order)
> +{
> +	switch (order) {
> +	case BayerFormat::BGGR:
> +		xShift_ = 0;
> +		swapLines_ = false;
> +		break;
> +	case BayerFormat::GBRG:
> +		xShift_ = 1; /* BGGR -> GBRG */
> +		swapLines_ = false;
> +		break;
> +	case BayerFormat::GRBG:
> +		xShift_ = 0;
> +		swapLines_ = true; /* BGGR -> GRBG */
> +		break;
> +	case BayerFormat::RGGB:
> +		xShift_ = 1; /* BGGR -> GBRG */
> +		swapLines_ = true; /* GBRG -> RGGB */
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	patternSize_.height = 2;
> +	patternSize_.width = 2;
> +	ySkipMask_ = 0x02; /* Skip every 3th and 4th line */
> +	return 0;
> +}
> +
>  /**
>   * \brief Configure the statistics object for the passed in input format.
>   * \param[in] inputCfg The input format
> @@ -158,6 +271,21 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg)
>  	BayerFormat bayerFormat =
>  		BayerFormat::fromPixelFormat(inputCfg.pixelFormat);
>  
> +	if (bayerFormat.packing == BayerFormat::Packing::None &&
> +	    setupStandardBayerOrder(bayerFormat.order) == 0) {
> +		switch (bayerFormat.bitDepth) {
> +		case 8:
> +			stats0_ = &SwStatsCpu::statsBGGR8Line0;
> +			return 0;
> +		case 10:
> +			stats0_ = &SwStatsCpu::statsBGGR10Line0;
> +			return 0;
> +		case 12:
> +			stats0_ = &SwStatsCpu::statsBGGR12Line0;
> +			return 0;
> +		}
> +	}
> +
>  	if (bayerFormat.bitDepth == 10 &&
>  	    bayerFormat.packing == BayerFormat::Packing::CSI2) {
>  		patternSize_.height = 2;
> diff --git a/src/libcamera/software_isp/swstats_cpu.h b/src/libcamera/software_isp/swstats_cpu.h
> index df13263b..d956c15a 100644
> --- a/src/libcamera/software_isp/swstats_cpu.h
> +++ b/src/libcamera/software_isp/swstats_cpu.h
> @@ -17,6 +17,7 @@
>  
>  #include <libcamera/geometry.h>
>  
> +#include "libcamera/internal/bayer_format.h"
>  #include "libcamera/internal/shared_mem_object.h"
>  #include "libcamera/internal/software_isp/swisp_stats.h"
>  
> @@ -120,6 +121,14 @@ private:
>  	 */
>  	using statsProcessFn = void (SwStatsCpu::*)(const uint8_t *src[]);
>  
> +	int setupStandardBayerOrder(BayerFormat::Order order);
> +	/* Bayer 8 bpp unpacked */
> +	void statsBGGR8Line0(const uint8_t *src[]);
> +	/* Bayer 10 bpp unpacked */
> +	void statsBGGR10Line0(const uint8_t *src[]);
> +	/* Bayer 12 bpp unpacked */
> +	void statsBGGR12Line0(const uint8_t *src[]);
> +	/* Bayer 10 bpp packed */
>  	void statsBGGR10PLine0(const uint8_t *src[]);
>  	void statsGBRG10PLine0(const uint8_t *src[]);



More information about the libcamera-devel mailing list