summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2024-04-16 11:13:51 +0200
committerKieran Bingham <kieran.bingham@ideasonboard.com>2024-04-16 13:00:21 +0100
commit17c58df4b408ea703cc26e2c05bdd6840e50bebc (patch)
tree8d279b0b5d62b235798617a230f7058830e04c3a
parente19adc453f8cb6e9243d119c0babd80a5a06eae3 (diff)
libcamera: debayer_cpu: Add support for 8, 10 and 12 bpp unpacked bayer input
Add support for 8, 10 and 12 bpp unpacked bayer input for all 4 standard bayer orders. Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s Tested-by: Pavel Machek <pavel@ucw.cz> Reviewed-by: Pavel Machek <pavel@ucw.cz> Reviewed-by: Milan Zamazal <mzamazal@redhat.com> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
-rw-r--r--src/libcamera/software_isp/debayer_cpu.cpp128
-rw-r--r--src/libcamera/software_isp/debayer_cpu.h13
2 files changed, 141 insertions, 0 deletions
diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp
index 6bc4b167..82163458 100644
--- a/src/libcamera/software_isp/debayer_cpu.cpp
+++ b/src/libcamera/software_isp/debayer_cpu.cpp
@@ -61,6 +61,11 @@ DebayerCpu::~DebayerCpu()
free(lineBuffers_[i]);
}
+#define DECLARE_SRC_POINTERS(pixel_t) \
+ const pixel_t *prev = (const pixel_t *)src[0] + xShift_; \
+ const pixel_t *curr = (const pixel_t *)src[1] + xShift_; \
+ const pixel_t *next = (const pixel_t *)src[2] + xShift_;
+
/*
* RGR
* GBG
@@ -105,6 +110,70 @@ DebayerCpu::~DebayerCpu()
*dst++ = red_[curr[x] / (div)]; \
x++;
+void DebayerCpu::debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])
+{
+ DECLARE_SRC_POINTERS(uint8_t)
+
+ for (int x = 0; x < (int)window_.width;) {
+ BGGR_BGR888(1, 1, 1)
+ GBRG_BGR888(1, 1, 1)
+ }
+}
+
+void DebayerCpu::debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])
+{
+ DECLARE_SRC_POINTERS(uint8_t)
+
+ for (int x = 0; x < (int)window_.width;) {
+ GRBG_BGR888(1, 1, 1)
+ RGGB_BGR888(1, 1, 1)
+ }
+}
+
+void DebayerCpu::debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])
+{
+ DECLARE_SRC_POINTERS(uint16_t)
+
+ for (int x = 0; x < (int)window_.width;) {
+ /* divide values by 4 for 10 -> 8 bpp value */
+ BGGR_BGR888(1, 1, 4)
+ GBRG_BGR888(1, 1, 4)
+ }
+}
+
+void DebayerCpu::debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])
+{
+ DECLARE_SRC_POINTERS(uint16_t)
+
+ for (int x = 0; x < (int)window_.width;) {
+ /* divide values by 4 for 10 -> 8 bpp value */
+ GRBG_BGR888(1, 1, 4)
+ RGGB_BGR888(1, 1, 4)
+ }
+}
+
+void DebayerCpu::debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])
+{
+ DECLARE_SRC_POINTERS(uint16_t)
+
+ for (int x = 0; x < (int)window_.width;) {
+ /* divide values by 16 for 12 -> 8 bpp value */
+ BGGR_BGR888(1, 1, 16)
+ GBRG_BGR888(1, 1, 16)
+ }
+}
+
+void DebayerCpu::debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])
+{
+ DECLARE_SRC_POINTERS(uint16_t)
+
+ for (int x = 0; x < (int)window_.width;) {
+ /* divide values by 16 for 12 -> 8 bpp value */
+ GRBG_BGR888(1, 1, 16)
+ RGGB_BGR888(1, 1, 16)
+ }
+}
+
void DebayerCpu::debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])
{
const int widthInBytes = window_.width * 5 / 4;
@@ -206,6 +275,16 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf
BayerFormat bayerFormat =
BayerFormat::fromPixelFormat(inputFormat);
+ if ((bayerFormat.bitDepth == 8 || bayerFormat.bitDepth == 10 || bayerFormat.bitDepth == 12) &&
+ bayerFormat.packing == BayerFormat::Packing::None &&
+ isStandardBayerOrder(bayerFormat.order)) {
+ config.bpp = (bayerFormat.bitDepth + 7) & ~7;
+ config.patternSize.width = 2;
+ config.patternSize.height = 2;
+ config.outputFormats = std::vector<PixelFormat>({ formats::RGB888 });
+ return 0;
+ }
+
if (bayerFormat.bitDepth == 10 &&
bayerFormat.packing == BayerFormat::Packing::CSI2 &&
isStandardBayerOrder(bayerFormat.order)) {
@@ -233,6 +312,32 @@ int DebayerCpu::getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &c
return -EINVAL;
}
+/*
+ * Check for standard Bayer orders and set xShift_ and swap debayer0/1, so that
+ * a single pair of BGGR debayer functions can be used for all 4 standard orders.
+ */
+int DebayerCpu::setupStandardBayerOrder(BayerFormat::Order order)
+{
+ switch (order) {
+ case BayerFormat::BGGR:
+ break;
+ case BayerFormat::GBRG:
+ xShift_ = 1; /* BGGR -> GBRG */
+ break;
+ case BayerFormat::GRBG:
+ std::swap(debayer0_, debayer1_); /* BGGR -> GRBG */
+ break;
+ case BayerFormat::RGGB:
+ xShift_ = 1; /* BGGR -> GBRG */
+ std::swap(debayer0_, debayer1_); /* GBRG -> RGGB */
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/* \todo This ignores outputFormat since there is only 1 supported outputFormat
for now */
int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, [[maybe_unused]] PixelFormat outputFormat)
@@ -240,6 +345,29 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, [[maybe_unused]] Pi
BayerFormat bayerFormat =
BayerFormat::fromPixelFormat(inputFormat);
+ xShift_ = 0;
+
+ if ((bayerFormat.bitDepth == 8 || bayerFormat.bitDepth == 10 || bayerFormat.bitDepth == 12) &&
+ bayerFormat.packing == BayerFormat::Packing::None &&
+ isStandardBayerOrder(bayerFormat.order)) {
+ switch (bayerFormat.bitDepth) {
+ case 8:
+ debayer0_ = &DebayerCpu::debayer8_BGBG_BGR888;
+ debayer1_ = &DebayerCpu::debayer8_GRGR_BGR888;
+ break;
+ case 10:
+ debayer0_ = &DebayerCpu::debayer10_BGBG_BGR888;
+ debayer1_ = &DebayerCpu::debayer10_GRGR_BGR888;
+ break;
+ case 12:
+ debayer0_ = &DebayerCpu::debayer12_BGBG_BGR888;
+ debayer1_ = &DebayerCpu::debayer12_GRGR_BGR888;
+ break;
+ }
+ setupStandardBayerOrder(bayerFormat.order);
+ return 0;
+ }
+
if (bayerFormat.bitDepth == 10 &&
bayerFormat.packing == BayerFormat::Packing::CSI2) {
switch (bayerFormat.order) {
diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h
index 1b5ad984..598fe021 100644
--- a/src/libcamera/software_isp/debayer_cpu.h
+++ b/src/libcamera/software_isp/debayer_cpu.h
@@ -17,6 +17,8 @@
#include <libcamera/base/object.h>
+#include "libcamera/internal/bayer_format.h"
+
#include "debayer.h"
#include "swstats_cpu.h"
@@ -82,6 +84,15 @@ private:
*/
using debayerFn = void (DebayerCpu::*)(uint8_t *dst, const uint8_t *src[]);
+ /* 8-bit raw bayer format */
+ void debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);
+ void debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);
+ /* unpacked 10-bit raw bayer format */
+ void debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);
+ void debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);
+ /* unpacked 12-bit raw bayer format */
+ void debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);
+ void debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);
/* CSI-2 packed 10-bit raw bayer format (all the 4 orders) */
void debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);
void debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);
@@ -103,6 +114,7 @@ private:
int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config);
int getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config);
+ int setupStandardBayerOrder(BayerFormat::Order order);
int setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat);
void setupInputMemcpy(const uint8_t *linePointers[]);
void shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src);
@@ -131,6 +143,7 @@ private:
unsigned int lineBufferLength_;
unsigned int lineBufferPadding_;
unsigned int lineBufferIndex_;
+ unsigned int xShift_; /* Offset of 0/1 applied to window_.x */
bool enableInputMemcpy_;
float gammaCorrection_;
unsigned int measuredFrames_;