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

Pavel Machek pavel at ucw.cz
Thu Dec 14 22:37:28 CET 2023


---

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?


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;

-- 
People of Russia, stop Putin before his war on Ukraine escalates.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 195 bytes
Desc: not available
URL: <https://lists.libcamera.org/pipermail/libcamera-devel/attachments/20231214/f8cd926d/attachment.sig>


More information about the libcamera-devel mailing list