tvl-depot/users/flokli/ipu6-softisp/libcamera/0016-libcamera-swstats_cpu-Add-support-for-8-10-and-12-bp.patch
Florian Klink af9a8d372b feat(users/flokli/ipu6-softisp): init
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>
2024-01-30 09:54:24 +00:00

199 lines
5.8 KiB
Diff

From 66ef9f32e67a96655d10ba38f7a830b3bbfe50f2 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Thu, 14 Dec 2023 19:09:44 +0100
Subject: [PATCH 16/25] libcamera: swstats_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/swstats_cpu.h | 9 ++
src/libcamera/software_isp/swstats_cpu.cpp | 126 ++++++++++++++++++
2 files changed, 135 insertions(+)
diff --git a/include/libcamera/internal/software_isp/swstats_cpu.h b/include/libcamera/internal/software_isp/swstats_cpu.h
index 8bb86e98..e7abc6bb 100644
--- a/include/libcamera/internal/software_isp/swstats_cpu.h
+++ b/include/libcamera/internal/software_isp/swstats_cpu.h
@@ -11,6 +11,7 @@
#pragma once
+#include "libcamera/internal/bayer_format.h"
#include "libcamera/internal/shared_mem_object.h"
#include "libcamera/internal/software_isp/swisp_stats.h"
#include "libcamera/internal/software_isp/swstats.h"
@@ -31,6 +32,14 @@ public:
const SharedFD &getStatsFD() { return sharedStats_.fd(); }
int configure(const StreamConfiguration &inputCfg);
private:
+ int setupStandardBayerOrder(BayerFormat::Order order);
+ /* Bayer 8 bpp unpacked */
+ void statsBGGR8Line0(const uint8_t *src[]);
+ /* Bayer 10 bpp unpacked */
+ void statsBGGR10Line0(const uint8_t *src[]);
+ /* Bayer 12 bpp unpacked */
+ void statsBGGR12Line0(const uint8_t *src[]);
+ /* Bayer 10 bpp packed */
void statsBGGR10PLine0(const uint8_t *src[]);
void statsGBRG10PLine0(const uint8_t *src[]);
void resetStats(void);
diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp
index 59453d07..87550371 100644
--- a/src/libcamera/software_isp/swstats_cpu.cpp
+++ b/src/libcamera/software_isp/swstats_cpu.cpp
@@ -59,6 +59,83 @@ static const unsigned int BLUE_Y_MUL = 29; /* 0.11 * 256 */
stats_.sumG_ += sumG; \
stats_.sumB_ += sumB;
+void SwStatsCpu::statsBGGR8Line0(const uint8_t *src[])
+{
+ const uint8_t *src0 = src[1] + window_.x;
+ const uint8_t *src1 = src[2] + window_.x;
+
+ SWISP_LINARO_START_LINE_STATS(uint8_t)
+
+ if (swap_lines_)
+ std::swap(src0, src1);
+
+ /* x += 4 sample every other 2x2 block */
+ for (int x = 0; x < (int)window_.width; x += 4) {
+ b = src0[x];
+ g = src0[x + 1];
+ g2 = src1[x];
+ r = src1[x + 1];
+
+ g = (g + g2) / 2;
+
+ SWISP_LINARO_ACCUMULATE_LINE_STATS(1)
+ }
+
+ SWISP_LINARO_FINISH_LINE_STATS()
+}
+
+void SwStatsCpu::statsBGGR10Line0(const uint8_t *src[])
+{
+ const uint16_t *src0 = (const uint16_t *)src[1] + window_.x;
+ const uint16_t *src1 = (const uint16_t *)src[2] + window_.x;
+
+ SWISP_LINARO_START_LINE_STATS(uint16_t)
+
+ if (swap_lines_)
+ std::swap(src0, src1);
+
+ /* x += 4 sample every other 2x2 block */
+ for (int x = 0; x < (int)window_.width; x += 4) {
+ b = src0[x];
+ g = src0[x + 1];
+ g2 = src1[x];
+ r = src1[x + 1];
+
+ g = (g + g2) / 2;
+
+ /* divide Y by 4 for 10 -> 8 bpp value */
+ SWISP_LINARO_ACCUMULATE_LINE_STATS(4)
+ }
+
+ SWISP_LINARO_FINISH_LINE_STATS()
+}
+
+void SwStatsCpu::statsBGGR12Line0(const uint8_t *src[])
+{
+ const uint16_t *src0 = (const uint16_t *)src[1] + window_.x;
+ const uint16_t *src1 = (const uint16_t *)src[2] + window_.x;
+
+ SWISP_LINARO_START_LINE_STATS(uint16_t)
+
+ if (swap_lines_)
+ std::swap(src0, src1);
+
+ /* x += 4 sample every other 2x2 block */
+ for (int x = 0; x < (int)window_.width; x += 4) {
+ b = src0[x];
+ g = src0[x + 1];
+ g2 = src1[x];
+ r = src1[x + 1];
+
+ g = (g + g2) / 2;
+
+ /* divide Y by 16 for 12 -> 8 bpp value */
+ SWISP_LINARO_ACCUMULATE_LINE_STATS(16)
+ }
+
+ SWISP_LINARO_FINISH_LINE_STATS()
+}
+
static inline __attribute__((always_inline)) void
statsBayer10P(const int width, const uint8_t *src0, const uint8_t *src1, bool bggr, SwIspStats &stats_)
{
@@ -124,6 +201,39 @@ void SwStatsCpu::finishStats(void)
statsReady.emit(0);
}
+/*
+ * Check if order is a standard Bayer order and setup x_shift_ and swap_lines_
+ * so that a single BGGR stats function can be used for all 4 standard orders.
+ */
+int SwStatsCpu::setupStandardBayerOrder(BayerFormat::Order order)
+{
+ switch (order) {
+ case BayerFormat::BGGR:
+ x_shift_ = 0;
+ swap_lines_ = false;
+ break;
+ case BayerFormat::GBRG:
+ x_shift_ = 1; /* BGGR -> GBRG */
+ swap_lines_ = false;
+ break;
+ case BayerFormat::GRBG:
+ x_shift_ = 0;
+ swap_lines_ = true; /* BGGR -> GRBG */
+ break;
+ case BayerFormat::RGGB:
+ x_shift_ = 1; /* BGGR -> GBRG */
+ swap_lines_ = true; /* GBRG -> RGGB */
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ patternSize_.height = 2;
+ patternSize_.width = 2;
+ y_skip_mask_ = 0x02; /* Skip every 3th and 4th line */
+ return 0;
+}
+
int SwStatsCpu::configure(const StreamConfiguration &inputCfg)
{
BayerFormat bayerFormat =
@@ -132,6 +242,22 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg)
startFrame_ = (SwStats::statsVoidFn)&SwStatsCpu::resetStats;
finishFrame_ = (SwStats::statsVoidFn)&SwStatsCpu::finishStats;
+ if (bayerFormat.packing == BayerFormat::Packing::None &&
+ setupStandardBayerOrder(bayerFormat.order) == 0) {
+ bpp_ = (bayerFormat.bitDepth + 7) & ~7;
+ switch (bayerFormat.bitDepth) {
+ case 8:
+ stats0_ = (SwStats::statsProcessFn)&SwStatsCpu::statsBGGR8Line0;
+ return 0;
+ case 10:
+ stats0_ = (SwStats::statsProcessFn)&SwStatsCpu::statsBGGR10Line0;
+ return 0;
+ case 12:
+ stats0_ = (SwStats::statsProcessFn)&SwStatsCpu::statsBGGR12Line0;
+ return 0;
+ }
+ }
+
if (bayerFormat.bitDepth == 10 &&
bayerFormat.packing == BayerFormat::Packing::CSI2) {
bpp_ = 10;
--
2.43.0