[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