[libcamera-devel] [RFC PATCH v2 2/2] qcam: format_converter: add 10 and 12 bit packed raw Bayer formats
Andrey Konovalov
andrey.konovalov at linaro.org
Tue Sep 8 17:07:39 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>
---
src/qcam/format_converter.cpp | 138 ++++++++++++++++++++++++++++++++++
src/qcam/format_converter.h | 21 ++++++
2 files changed, 159 insertions(+)
diff --git a/src/qcam/format_converter.cpp b/src/qcam/format_converter.cpp
index 3481330..f370907 100644
--- a/src/qcam/format_converter.cpp
+++ b/src/qcam/format_converter.cpp
@@ -10,6 +10,7 @@
#include <errno.h>
#include <QImage>
+#include <QtDebug>
#include <libcamera/formats.h>
@@ -132,6 +133,62 @@ int FormatConverter::configure(const libcamera::PixelFormat &format,
params_.yuv.cb_pos = 1;
break;
+ case libcamera::formats::SRGGB10_CSI2P:
+ formatFamily_ = RAW_CSI2P;
+ params_.rawp.bpp_numer = 5; /* 1.25 bytes per pixel */
+ params_.rawp.bpp_denom = 4;
+ params_.rawp.r_pos = 0;
+ break;
+
+ case libcamera::formats::SGRBG10_CSI2P:
+ formatFamily_ = RAW_CSI2P;
+ params_.rawp.bpp_numer = 5;
+ params_.rawp.bpp_denom = 4;
+ params_.rawp.r_pos = 1;
+ break;
+
+ case libcamera::formats::SGBRG10_CSI2P:
+ formatFamily_ = RAW_CSI2P;
+ params_.rawp.bpp_numer = 5;
+ params_.rawp.bpp_denom = 4;
+ params_.rawp.r_pos = 2;
+ break;
+
+ case libcamera::formats::SBGGR10_CSI2P:
+ formatFamily_ = RAW_CSI2P;
+ params_.rawp.bpp_numer = 5;
+ params_.rawp.bpp_denom = 4;
+ params_.rawp.r_pos = 3;
+ break;
+
+ case libcamera::formats::SRGGB12_CSI2P:
+ formatFamily_ = RAW_CSI2P;
+ params_.rawp.bpp_numer = 3; /* 1.5 bytes per pixel */
+ params_.rawp.bpp_denom = 2;
+ params_.rawp.r_pos = 0;
+ break;
+
+ case libcamera::formats::SGRBG12_CSI2P:
+ formatFamily_ = RAW_CSI2P;
+ params_.rawp.bpp_numer = 3;
+ params_.rawp.bpp_denom = 2;
+ params_.rawp.r_pos = 1;
+ break;
+
+ case libcamera::formats::SGBRG12_CSI2P:
+ formatFamily_ = RAW_CSI2P;
+ params_.rawp.bpp_numer = 3;
+ params_.rawp.bpp_denom = 2;
+ params_.rawp.r_pos = 2;
+ break;
+
+ case libcamera::formats::SBGGR12_CSI2P:
+ formatFamily_ = RAW_CSI2P;
+ params_.rawp.bpp_numer = 3;
+ params_.rawp.bpp_denom = 2;
+ params_.rawp.r_pos = 3;
+ break;
+
case libcamera::formats::MJPEG:
formatFamily_ = MJPEG;
break;
@@ -144,6 +201,45 @@ int FormatConverter::configure(const libcamera::PixelFormat &format,
width_ = size.width();
height_ = size.height();
+ if (formatFamily_ == RAW_CSI2P) {
+ /*
+ * For RAW_CSI2P the assumption is that height_ and width_
+ * are even numbers.
+ */
+ if ( width_ % 2 != 0 || height_ % 2 != 0 ) {
+ qWarning() << "Image width or height isn't even number";
+ return -EINVAL;
+ }
+
+ params_.rawp.srcLineLength = width_ * params_.rawp.bpp_numer /
+ params_.rawp.bpp_denom;
+
+ /*
+ * Calculate [g1,g2,b]_pos based on r_pos.
+ * On entrance, r_pos is the position of red pixel in the
+ * 2-by-2 pixel Bayer pattern, and is from 0 to 3 range:
+ * +---+---+
+ * | 0 | 1 |
+ * +---+---+
+ * | 2 | 3 |
+ * +---+---+
+ * At exit, [r,g1,g2,b]_pos are offsetts of the color
+ * values in the source buffer.
+ */
+ if (params_.rawp.r_pos > 1) {
+ params_.rawp.r_pos = params_.rawp.r_pos - 2 +
+ params_.rawp.srcLineLength;
+ params_.rawp.b_pos = 3 - params_.rawp.r_pos;
+ } else {
+ params_.rawp.b_pos = 1 - params_.rawp.r_pos +
+ params_.rawp.srcLineLength;
+ }
+ params_.rawp.g1_pos = (params_.rawp.r_pos == 0 ||
+ params_.rawp.b_pos == 0) ? 1 : 0;
+ params_.rawp.g2_pos = 1 - params_.rawp.g1_pos +
+ params_.rawp.srcLineLength;
+ }
+
return 0;
}
@@ -163,9 +259,51 @@ void FormatConverter::convert(const unsigned char *src, size_t size,
case NV:
convertNV(src, dst->bits());
break;
+ case RAW_CSI2P:
+ convertRawCSI2P(src, dst->bits());
+ break;
};
}
+void FormatConverter::convertRawCSI2P(const unsigned char *src,
+ unsigned char *dst)
+{
+ unsigned int g;
+ static unsigned char dst_buf[8] = { 0, 0, 0, 0xff };
+ unsigned int dstLineLength = width_ * 4;
+
+ for (unsigned int y = 0; y < height_; y += 2) {
+ for (unsigned x = 0; x < width_; x += params_.rawp.bpp_denom) {
+ for (unsigned int i = 0; i < params_.rawp.bpp_denom ;
+ i += 2) {
+ /*
+ * Process the current 2x2 group.
+ * Use the average of the two green pixels as
+ * the green value for all the pixels in the
+ * group.
+ */
+ dst_buf[0] = src[params_.rawp.b_pos];
+ g = src[params_.rawp.g1_pos];
+ g = (g + src[params_.rawp.g2_pos]) >> 1;
+ dst_buf[1] = (unsigned char)g;
+ dst_buf[2] = src[params_.rawp.r_pos];
+ src += 2;
+
+ memcpy(dst_buf + 4, dst_buf, 4);
+ memcpy(dst, dst_buf, 8);
+ memcpy(dst + dstLineLength, dst_buf, 8);
+ dst += 8;
+ }
+ src += params_.rawp.bpp_numer - params_.rawp.bpp_denom;
+ }
+ /* odd lines are copies of the even lines they follow: */
+ memcpy(dst, dst-dstLineLength, dstLineLength);
+ /* move to the next even line: */
+ src += params_.rawp.srcLineLength;
+ dst += dstLineLength;
+ }
+}
+
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 c53fa28..dc20e0d 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 convertRawCSI2P(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);
@@ -48,6 +50,25 @@ private:
bool nvSwap;
} nv;
+ /* RAW Bayer CSI2P parameters */
+ struct raw_csi2p_params {
+ /*
+ * 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;
+ /*
+ * The fields below are used to hold the values computed
+ * in configure() based on r_pos and width_.
+ */
+ unsigned int g1_pos;
+ unsigned int g2_pos;
+ unsigned int b_pos;
+ unsigned int srcLineLength;
+ } rawp;
+
/* RGB parameters */
struct rgb_params {
unsigned int bpp;
--
2.17.1
More information about the libcamera-devel
mailing list