[libcamera-devel] [RFC] Add 8-bit bayer support.

Hans de Goede hdegoede at redhat.com
Fri Dec 15 15:17:44 CET 2023


Hi Pavel,

On 12/14/23 22:37, Pavel Machek wrote:
> ---
> 
> Did I get it mostly right? I can't test other formats but providing
> them should not be too hard. Does it make sense to add this to your
> series or is it better to just wait for v1 to be merged?

Yes this looks about right. Yesterday I finished about a 10
day libcamera sprint so for now I'm not going to touch
libcamera for a few days.

I plan to get back to libcamera again on Wednesday.
I'll add a commit adding 8bpp bayer, all 4 orders,
to my personal libcamera softisp branch then and when
that is in place I'll send you an email asking to test it.

Regards,

Hans


> 
> 
> diff --git a/include/libcamera/internal/software_isp/debayer_cpu.h b/include/libcamera/internal/software_isp/debayer_cpu.h
> index 7fb5be77..f3bb4321 100644
> --- a/include/libcamera/internal/software_isp/debayer_cpu.h
> +++ b/include/libcamera/internal/software_isp/debayer_cpu.h
> @@ -67,6 +67,9 @@ private:
>  	void debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src);
>  	void debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src);
>  
> +	void debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src);
> +	void debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src);
> +
>  	typedef void (DebayerCpu::*debayerFn)(uint8_t *dst, const uint8_t *src);
>  
>  	struct DebayerInputConfig {
> diff --git a/include/libcamera/internal/software_isp/swstats_cpu.h b/include/libcamera/internal/software_isp/swstats_cpu.h
> index 0ceb995f..3c43e146 100644
> --- a/include/libcamera/internal/software_isp/swstats_cpu.h
> +++ b/include/libcamera/internal/software_isp/swstats_cpu.h
> @@ -29,6 +29,8 @@ public:
>  	/* FIXME this should be dropped once AWB has moved to the IPA */
>  	SwIspStats getStats() { return *sharedStats_; }
>  private:
> +	void statsBGGR8Line0(const uint8_t *src, unsigned int stride);
> +
>  	void statsBGGR10PLine0(const uint8_t *src, unsigned int stride);
>  	void statsGBRG10PLine0(const uint8_t *src, unsigned int stride);
>  	void statsGRBG10PLine0(const uint8_t *src, unsigned int stride);
> diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp
> index 3eacdd5d..52910a03 100644
> --- a/src/libcamera/software_isp/debayer_cpu.cpp
> +++ b/src/libcamera/software_isp/debayer_cpu.cpp
> @@ -111,6 +111,36 @@ void DebayerCpu::debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src)
>  	}
>  }
>  
> +void DebayerCpu::debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src)
> +{
> +	const int width_in_bytes = window_.width;
> +	struct ctxt_8bit_src c = {
> +		src - inputConfig_.stride, src, src + inputConfig_.stride,
> +		red_, green_, blue_ };
> +
> +	for (int x = 0; x < width_in_bytes; ) {
> +		/* Even pixel */
> +		bggr8_bgr888(c, dst, x++, 1, 1);
> +		/* Odd pixel BGGR -> GBRG */
> +		gbrg8_bgr888(c, dst, x++, 1, 1);
> +	}
> +}
> +
> +void DebayerCpu::debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src)
> +{
> +	const int width_in_bytes = window_.width;
> +	struct ctxt_8bit_src c = {
> +		src - inputConfig_.stride, src, src + inputConfig_.stride,
> +		red_, green_, blue_ };
> +
> +	for (int x = 0; x < width_in_bytes; ) {
> +		/* Even pixel */
> +		grbg8_bgr888(c, dst, x++, 1, 1);
> +		/* Odd pixel GRBG -> RGGB */
> +		rggb8_bgr888(c, dst, x++, 1, 1);
> +	}
> +}
> +
>  void DebayerCpu::debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src)
>  {
>  	const int width_in_bytes = window_.width * 5 / 4;
> @@ -152,6 +182,22 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf
>  	BayerFormat bayerFormat =
>  		BayerFormat::fromPixelFormat(inputFormat);
>  
> +	if (bayerFormat.bitDepth == 8) {
> +	    	config.bpp = 8;
> +		config.patternSize.height = 2;
> +		config.patternSize.width = 4;
> +		config.x_shift = 0;
> +		config.outputFormats = std::vector<PixelFormat>({ formats::RGB888 });
> +
> +		switch (bayerFormat.order) {
> +		case BayerFormat::BGGR:
> +			return 0;
> +		default:
> +			break;
> +		}
> +	/* } else if (future supported fmts) { ... */
> +	}
> +
>  	if (bayerFormat.bitDepth == 10 &&
>  	    bayerFormat.packing == BayerFormat::Packing::CSI2) {
>  	    	config.bpp = 10;
> @@ -195,6 +241,17 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, [[maybe_unused]] Pi
>  	BayerFormat bayerFormat =
>  		BayerFormat::fromPixelFormat(inputFormat);
>  
> +	if (bayerFormat.bitDepth == 8) {
> +		switch (bayerFormat.order) {
> +		case BayerFormat::BGGR:
> +			debayer0_ = &DebayerCpu::debayer8_BGBG_BGR888;
> +			debayer1_ = &DebayerCpu::debayer8_GRGR_BGR888;
> +			return 0;
> +		default:
> +			break;
> +		}
> +	}
> +
>  	if (bayerFormat.bitDepth == 10 &&
>  	    bayerFormat.packing == BayerFormat::Packing::CSI2) {
>  		switch (bayerFormat.order) {
> diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp
> index 15f23953..e65b1b65 100644
> --- a/src/libcamera/software_isp/swstats_cpu.cpp
> +++ b/src/libcamera/software_isp/swstats_cpu.cpp
> @@ -37,9 +37,9 @@ static const unsigned int GREEN_Y_MUL = 150;		/* 0.59 * 256 */
>  static const unsigned int BLUE_Y_MUL = 29;		/* 0.11 * 256 */
>  
>  static inline __attribute__((always_inline)) void
> -statsBayer10P(const int width, const uint8_t *src0, const uint8_t *src1, bool bggr, unsigned int &bright_sum_, unsigned int &too_bright_sum_, SwIspStats &stats_)
> +statsBayer10P(const int width, const uint8_t *src0, const uint8_t *src1, bool bggr, unsigned int &bright_sum_, unsigned int &too_bright_sum_, SwIspStats &stats_, bool is10p)
>  {
> -	const int width_in_bytes = width * 5 / 4;
> +	const int width_in_bytes = width * (4 + is10p) / 4;
>  	uint8_t r, g, b, g2;
>  	unsigned int y_val;
>  	unsigned int sumR = 0;
> @@ -49,7 +49,7 @@ statsBayer10P(const int width, const uint8_t *src0, const uint8_t *src1, bool bg
>  	unsigned int bright_sum = 0;
>  	unsigned int too_bright_sum = 0;
>  
> -	for (int x = 0; x < width_in_bytes; x += 5) {
> +	for (int x = 0; x < width_in_bytes; x += (4 + is10p)) {
>  		if (bggr) {
>  			/* BGGR */
>  			b  = src0[x];
> @@ -84,26 +84,31 @@ statsBayer10P(const int width, const uint8_t *src0, const uint8_t *src1, bool bg
>  	too_bright_sum_ += too_bright_sum;
>  }
>  
> +void SwStatsCpu::statsBGGR8Line0(const uint8_t *src, unsigned int stride)
> +{
> +	statsBayer10P(window_.width, src, src + stride, true, bright_sum_, too_bright_sum_, stats_, false);
> +}
> +
>  void SwStatsCpu::statsBGGR10PLine0(const uint8_t *src, unsigned int stride)
>  {
> -	statsBayer10P(window_.width, src, src + stride, true, bright_sum_, too_bright_sum_, stats_);
> +	statsBayer10P(window_.width, src, src + stride, true, bright_sum_, too_bright_sum_, stats_, true);
>  }
>  
>  void SwStatsCpu::statsGBRG10PLine0(const uint8_t *src, unsigned int stride)
>  {
> -	statsBayer10P(window_.width, src, src + stride, false, bright_sum_, too_bright_sum_, stats_);
> +	statsBayer10P(window_.width, src, src + stride, false, bright_sum_, too_bright_sum_, stats_, true);
>  }
>  
>  void SwStatsCpu::statsGRBG10PLine0(const uint8_t *src, unsigned int stride)
>  {
>  	/* GRBG is BGGR with the lines swapped */
> -	statsBayer10P(window_.width, src + stride, src, true, bright_sum_, too_bright_sum_, stats_);
> +	statsBayer10P(window_.width, src + stride, src, true, bright_sum_, too_bright_sum_, stats_, true);
>  }
>  
>  void SwStatsCpu::statsRGGB10PLine0(const uint8_t *src, unsigned int stride)
>  {
>  	/* RGGB is GBRG with the lines swapped */
> -	statsBayer10P(window_.width, src + stride, src, false, bright_sum_, too_bright_sum_, stats_);
> +	statsBayer10P(window_.width, src + stride, src, false, bright_sum_, too_bright_sum_, stats_, true);
>  }
>  
>  void SwStatsCpu::resetStats(void)
> @@ -134,6 +139,24 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg)
>  	startFrame_ = (SwStats::statsVoidFn)&SwStatsCpu::resetStats;
>  	finishFrame_ = (SwStats::statsVoidFn)&SwStatsCpu::finishStats;
>  
> +	if (bayerFormat.bitDepth == 8) {
> +		bpp_ = 8;
> +		patternSize_.height = 2;
> +		patternSize_.width = 4;
> +		y_skip_mask_ = 0x0c; /* Skip every 3th and 4th line */
> +		x_shift_ = 0;
> +
> +		switch (bayerFormat.order) {
> +		case BayerFormat::BGGR:
> +			stats0_ = (SwStats::statsProcessFn)&SwStatsCpu::statsBGGR8Line0;
> +			return 0;
> +		default:
> +			break;
> +		}
> +	/* } else if (future supported fmts) { ... */
> +	}
> +
> +
>  	if (bayerFormat.bitDepth == 10 &&
>  	    bayerFormat.packing == BayerFormat::Packing::CSI2) {
>  		bpp_ = 10;
> 



More information about the libcamera-devel mailing list