[libcamera-devel] [RFC PATCH] qcam: format_converter: add 10 and 12 bit packed raw Bayer formats

Andrey Konovalov andrey.konovalov at linaro.org
Mon Aug 31 10:46:45 CEST 2020


No interpolation is used to get more speed by the price of lower image
quality. In qcam format_converter is used for viewfinder only, and in
this case lower lag is more important than the image quality.

Signed-off-by: Andrey Konovalov <andrey.konovalov at linaro.org>
---
 Only SRGGB10P and SRGGB12P formats were tested (the ones I can get from
 the camera sensor I am currently using)

 src/qcam/format_converter.cpp | 118 ++++++++++++++++++++++++++++++++++
 src/qcam/format_converter.h   |  14 ++++
 2 files changed, 132 insertions(+)

diff --git a/src/qcam/format_converter.cpp b/src/qcam/format_converter.cpp
index 4b9722d..c9f94d3 100644
--- a/src/qcam/format_converter.cpp
+++ b/src/qcam/format_converter.cpp
@@ -136,6 +136,62 @@ int FormatConverter::configure(const libcamera::PixelFormat &format,
 		formatFamily_ = MJPEG;
 		break;
 
+	case libcamera::formats::SRGGB10_CSI2P:
+		formatFamily_ = RAW_CSI2P;
+		r_pos_ = 0;
+		bpp_numer_ = 4;
+		bpp_denom_ = 5;
+		break;
+
+	case libcamera::formats::SGRBG10_CSI2P:
+		formatFamily_ = RAW_CSI2P;
+		r_pos_ = 1;
+		bpp_numer_ = 4;
+		bpp_denom_ = 5;
+		break;
+
+	case libcamera::formats::SGBRG10_CSI2P:
+		formatFamily_ = RAW_CSI2P;
+		r_pos_ = 2;
+		bpp_numer_ = 4;
+		bpp_denom_ = 5;
+		break;
+
+	case libcamera::formats::SBGGR10_CSI2P:
+		formatFamily_ = RAW_CSI2P;
+		r_pos_ = 3;
+		bpp_numer_ = 4;
+		bpp_denom_ = 5;
+		break;
+
+	case libcamera::formats::SRGGB12_CSI2P:
+		formatFamily_ = RAW_CSI2P;
+		r_pos_ = 0;
+		bpp_numer_ = 2;
+		bpp_denom_ = 3;
+		break;
+
+	case libcamera::formats::SGRBG12_CSI2P:
+		formatFamily_ = RAW_CSI2P;
+		r_pos_ = 1;
+		bpp_numer_ = 2;
+		bpp_denom_ = 3;
+		break;
+
+	case libcamera::formats::SGBRG12_CSI2P:
+		formatFamily_ = RAW_CSI2P;
+		r_pos_ = 2;
+		bpp_numer_ = 2;
+		bpp_denom_ = 3;
+		break;
+
+	case libcamera::formats::SBGGR12_CSI2P:
+		formatFamily_ = RAW_CSI2P;
+		r_pos_ = 3;
+		bpp_numer_ = 2;
+		bpp_denom_ = 3;
+		break;
+
 	default:
 		return -EINVAL;
 	};
@@ -163,9 +219,71 @@ void FormatConverter::convert(const unsigned char *src, size_t size,
 	case NV:
 		convertNV(src, dst->bits());
 		break;
+	case RAW_CSI2P:
+		convertRAW_CSI2P(src, dst->bits());
+		break;
 	};
 }
 
+/*
+ * The pixels are processed in groups of 4 (2 by 2 squares), and the
+ * assumption is that height_ and width_ are even numbers.
+ */
+void FormatConverter::convertRAW_CSI2P(const unsigned char *src,
+				       unsigned char *dst)
+{
+	unsigned int r_pos, b_pos, g1_pos, g2_pos;
+	unsigned char r, g1, g2, b;
+	unsigned int s_linelen = width_ * bpp_denom_ / bpp_numer_;
+	unsigned int d_linelen = width_ * 4;
+
+	/*
+	 * Calculate the offsets of the color values in the src buffer.
+	 * g1 is green value from the even (upper) line, g2 is the green
+	 * value from the odd (lower) line.
+	 */
+	if ( r_pos_ > 1) {
+		r_pos = r_pos_ - 2 + s_linelen;
+		b_pos = 3 - r_pos_;
+	} else {
+		r_pos = r_pos_;
+		b_pos = 1 - r_pos_ + s_linelen;
+	}
+	g1_pos = (r_pos == 0 || b_pos == 0) ? 1 : 0;
+	g2_pos = 1 - g1_pos + s_linelen;
+
+	for (unsigned int y = 0; y < height_; y += 2) {
+		for (unsigned x = 0; x < width_; x += bpp_numer_) {
+			for (unsigned int i = 0; i < bpp_numer_ ; i += 2) {
+				/* read the colors for the current 2x2 group: */
+				r = src[r_pos];
+				g1 = src[g1_pos];
+				g2 = src[g2_pos];
+				b = src[b_pos];
+				src += 2;
+				/* two left pixels of the four: */
+				dst[0] = dst[0 + d_linelen] = b;
+				dst[1] = g1;
+				dst[1 + d_linelen] = g2;
+				dst[2] = dst[2 + d_linelen] = r;
+				dst[3] = dst[3 + d_linelen] = 0xff;
+				dst += 4;
+				/* two right pixels of the four: */
+				dst[0] = dst[0 + d_linelen] = b;
+				dst[1] = g1;
+				dst[1 + d_linelen] = g2;
+				dst[2] = dst[2 + d_linelen] = r;
+				dst[3] = dst[3 + d_linelen] = 0xff;
+				dst += 4;
+			}
+			src += bpp_denom_ - bpp_numer_;
+		}
+		/* move to the next even line: */
+		src += s_linelen;
+		dst += d_linelen;
+	}
+}
+
 static void yuv_to_rgb(int y, int u, int v, int *r, int *g, int *b)
 {
 	int c = y - 16;
diff --git a/src/qcam/format_converter.h b/src/qcam/format_converter.h
index e389b24..5d4f31f 100644
--- a/src/qcam/format_converter.h
+++ b/src/qcam/format_converter.h
@@ -26,11 +26,13 @@ private:
 	enum FormatFamily {
 		MJPEG,
 		NV,
+		RAW_CSI2P,
 		RGB,
 		YUV,
 	};
 
 	void convertNV(const unsigned char *src, unsigned char *dst);
+	void convertRAW_CSI2P(const unsigned char *src, unsigned char *dst);
 	void convertRGB(const unsigned char *src, unsigned char *dst);
 	void convertYUV(const unsigned char *src, unsigned char *dst);
 
@@ -45,6 +47,18 @@ private:
 	unsigned int vertSubSample_;
 	bool nvSwap_;
 
+	/* RAW Bayer CSI2P parameters */
+	/*
+	 * Bytes per pixel is a fractional number, and is represented by
+	 * integer numerator and denominator.
+	 */
+	unsigned int bpp_numer_;
+	unsigned int bpp_denom_;
+	/*
+	 * Unsigned int r_pos_ from RGB parameters is reused; blue
+	 * and green positions are deduced from the red one.
+	 */
+
 	/* RGB parameters */
 	unsigned int bpp_;
 	unsigned int r_pos_;
-- 
2.17.1



More information about the libcamera-devel mailing list