af9a8d372b
This code adds support for the ipu6 webcams via libcamera, based on the work in https://copr.fedorainfracloud.org/coprs/jwrdegoede/ipu6-softisp/. It's supposed to be included in your NixOS configuration imports. Change-Id: Ifb71999ad61161fa23506b97cb449f73fb1270e3 Reviewed-on: https://cl.tvl.fyi/c/depot/+/10709 Tested-by: BuildkiteCI Reviewed-by: flokli <flokli@flokli.de> Autosubmit: flokli <flokli@flokli.de>
237 lines
7.8 KiB
Diff
237 lines
7.8 KiB
Diff
From b7b211eb56d98d5b170bd73a23b55aeb45bde8c5 Mon Sep 17 00:00:00 2001
|
|
From: Hans de Goede <hdegoede@redhat.com>
|
|
Date: Thu, 14 Dec 2023 19:57:15 +0100
|
|
Subject: [PATCH 17/25] 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>
|
|
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
|
|
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
|
---
|
|
.../internal/software_isp/debayer_cpu.h | 13 ++
|
|
src/libcamera/software_isp/debayer_cpu.cpp | 128 ++++++++++++++++++
|
|
2 files changed, 141 insertions(+)
|
|
|
|
diff --git a/include/libcamera/internal/software_isp/debayer_cpu.h b/include/libcamera/internal/software_isp/debayer_cpu.h
|
|
index 78573f44..1147b368 100644
|
|
--- a/include/libcamera/internal/software_isp/debayer_cpu.h
|
|
+++ b/include/libcamera/internal/software_isp/debayer_cpu.h
|
|
@@ -17,6 +17,7 @@
|
|
|
|
#include <libcamera/base/object.h>
|
|
|
|
+#include "libcamera/internal/bayer_format.h"
|
|
#include "libcamera/internal/software_isp/swstats_cpu.h"
|
|
#include "libcamera/internal/software_isp/debayer.h"
|
|
|
|
@@ -75,11 +76,21 @@ public:
|
|
* \return The output frame size.
|
|
*/
|
|
unsigned int frameSize() { return outputConfig_.frameSize; }
|
|
+
|
|
private:
|
|
void initLinePointers(const uint8_t *linePointers[], const uint8_t *src);
|
|
void shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src);
|
|
void process2(const uint8_t *src, uint8_t *dst);
|
|
void process4(const uint8_t *src, uint8_t *dst);
|
|
+ /* 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);
|
|
|
|
uint8_t gamma_[1024];
|
|
@@ -119,6 +131,7 @@ private:
|
|
std::unique_ptr<SwStatsCpu> stats_;
|
|
uint8_t *lineBuffers_[5];
|
|
unsigned int lineBufferIndex_;
|
|
+ unsigned int x_shift_; /* Offset of 0/1 applied to window_.x */
|
|
bool enableInputMemcpy_;
|
|
float gamma_correction_;
|
|
int measuredFrames_;
|
|
diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp
|
|
index e0c3c658..7b7623b7 100644
|
|
--- a/src/libcamera/software_isp/debayer_cpu.cpp
|
|
+++ b/src/libcamera/software_isp/debayer_cpu.cpp
|
|
@@ -45,6 +45,11 @@ DebayerCpu::~DebayerCpu()
|
|
free(lineBuffers_[i]);
|
|
}
|
|
|
|
+#define DECLARE_SRC_POINTERS(pixel_t) \
|
|
+ const pixel_t *prev = (const pixel_t *)src[0] + x_shift_; \
|
|
+ const pixel_t *curr = (const pixel_t *)src[1] + x_shift_; \
|
|
+ const pixel_t *next = (const pixel_t *)src[2] + x_shift_;
|
|
+
|
|
// RGR
|
|
// GBG
|
|
// RGR
|
|
@@ -81,6 +86,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 width_in_bytes = window_.width * 5 / 4;
|
|
@@ -170,6 +239,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)) {
|
|
@@ -197,12 +276,61 @@ int DebayerCpu::getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &c
|
|
return -EINVAL;
|
|
}
|
|
|
|
+/*
|
|
+ * Check for standard Bayer orders and set x_shift_ 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:
|
|
+ x_shift_ = 1; /* BGGR -> GBRG */
|
|
+ break;
|
|
+ case BayerFormat::GRBG:
|
|
+ std::swap(debayer0_, debayer1_); /* BGGR -> GRBG */
|
|
+ break;
|
|
+ case BayerFormat::RGGB:
|
|
+ x_shift_ = 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)
|
|
{
|
|
BayerFormat bayerFormat =
|
|
BayerFormat::fromPixelFormat(inputFormat);
|
|
|
|
+ x_shift_ = 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) {
|
|
--
|
|
2.43.0
|
|
|