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>
272 lines
8 KiB
Diff
272 lines
8 KiB
Diff
From c1c43445cd4408010e500fe9d6b6424c77bcf75d Mon Sep 17 00:00:00 2001
|
|
From: Hans de Goede <hdegoede@redhat.com>
|
|
Date: Fri, 8 Dec 2023 12:50:57 +0100
|
|
Subject: [PATCH 08/25] libcamera: software_isp: Add SwStatsCpu class
|
|
|
|
Add a CPU based SwStats implementation for SoftwareISP / SoftIPA use.
|
|
|
|
Co-authored-by: Andrey Konovalov <andrey.konovalov@linaro.org>
|
|
Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
|
|
Co-authored-by: Pavel Machek <pavel@ucw.cz>
|
|
Signed-off-by: Pavel Machek <pavel@ucw.cz>
|
|
Co-authored-by: Dennis Bonke <admin@dennisbonke.com>
|
|
Signed-off-by: Dennis Bonke <admin@dennisbonke.com>
|
|
Co-authored-by: Marttico <g.martti@gmail.com>
|
|
Signed-off-by: Marttico <g.martti@gmail.com>
|
|
Co-authored-by: Toon Langendam <t.langendam@gmail.com>
|
|
Signed-off-by: Toon Langendam <t.langendam@gmail.com>
|
|
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
|
Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s
|
|
Tested-by: Pavel Machek <pavel@ucw.cz>
|
|
---
|
|
.../internal/software_isp/meson.build | 1 +
|
|
.../internal/software_isp/swstats_cpu.h | 44 +++++
|
|
src/libcamera/software_isp/meson.build | 1 +
|
|
src/libcamera/software_isp/swstats_cpu.cpp | 164 ++++++++++++++++++
|
|
4 files changed, 210 insertions(+)
|
|
create mode 100644 include/libcamera/internal/software_isp/swstats_cpu.h
|
|
create mode 100644 src/libcamera/software_isp/swstats_cpu.cpp
|
|
|
|
diff --git a/include/libcamera/internal/software_isp/meson.build b/include/libcamera/internal/software_isp/meson.build
|
|
index 1c43acc4..1d9e4018 100644
|
|
--- a/include/libcamera/internal/software_isp/meson.build
|
|
+++ b/include/libcamera/internal/software_isp/meson.build
|
|
@@ -3,4 +3,5 @@
|
|
libcamera_internal_headers += files([
|
|
'swisp_stats.h',
|
|
'swstats.h',
|
|
+ 'swstats_cpu.h',
|
|
])
|
|
diff --git a/include/libcamera/internal/software_isp/swstats_cpu.h b/include/libcamera/internal/software_isp/swstats_cpu.h
|
|
new file mode 100644
|
|
index 00000000..8bb86e98
|
|
--- /dev/null
|
|
+++ b/include/libcamera/internal/software_isp/swstats_cpu.h
|
|
@@ -0,0 +1,44 @@
|
|
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
+/*
|
|
+ * Copyright (C) 2023, Linaro Ltd
|
|
+ * Copyright (C) 2023, Red Hat Inc.
|
|
+ *
|
|
+ * Authors:
|
|
+ * Hans de Goede <hdegoede@redhat.com>
|
|
+ *
|
|
+ * swstats_cpu.h - CPU based software statistics implementation
|
|
+ */
|
|
+
|
|
+#pragma once
|
|
+
|
|
+#include "libcamera/internal/shared_mem_object.h"
|
|
+#include "libcamera/internal/software_isp/swisp_stats.h"
|
|
+#include "libcamera/internal/software_isp/swstats.h"
|
|
+
|
|
+namespace libcamera {
|
|
+
|
|
+/**
|
|
+ * \class SwStatsCpu
|
|
+ * \brief Implementation for the Software statistics on the CPU.
|
|
+ */
|
|
+class SwStatsCpu : public SwStats
|
|
+{
|
|
+public:
|
|
+ SwStatsCpu();
|
|
+ ~SwStatsCpu() { }
|
|
+
|
|
+ bool isValid() const { return sharedStats_.fd().isValid(); }
|
|
+ const SharedFD &getStatsFD() { return sharedStats_.fd(); }
|
|
+ int configure(const StreamConfiguration &inputCfg);
|
|
+private:
|
|
+ void statsBGGR10PLine0(const uint8_t *src[]);
|
|
+ void statsGBRG10PLine0(const uint8_t *src[]);
|
|
+ void resetStats(void);
|
|
+ void finishStats(void);
|
|
+
|
|
+ SharedMemObject<SwIspStats> sharedStats_;
|
|
+ SwIspStats stats_;
|
|
+ bool swap_lines_;
|
|
+};
|
|
+
|
|
+} /* namespace libcamera */
|
|
diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build
|
|
index 9359075d..d31c6217 100644
|
|
--- a/src/libcamera/software_isp/meson.build
|
|
+++ b/src/libcamera/software_isp/meson.build
|
|
@@ -2,4 +2,5 @@
|
|
|
|
libcamera_sources += files([
|
|
'swstats.cpp',
|
|
+ 'swstats_cpu.cpp',
|
|
])
|
|
diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp
|
|
new file mode 100644
|
|
index 00000000..59453d07
|
|
--- /dev/null
|
|
+++ b/src/libcamera/software_isp/swstats_cpu.cpp
|
|
@@ -0,0 +1,164 @@
|
|
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
+/*
|
|
+ * Copyright (C) 2023, Linaro Ltd
|
|
+ * Copyright (C) 2023, Red Hat Inc.
|
|
+ *
|
|
+ * Authors:
|
|
+ * Hans de Goede <hdegoede@redhat.com>
|
|
+ *
|
|
+ * swstats_cpu.cpp - CPU based software statistics implementation
|
|
+ */
|
|
+
|
|
+#include "libcamera/internal/software_isp/swstats_cpu.h"
|
|
+
|
|
+#include <libcamera/base/log.h>
|
|
+
|
|
+#include <libcamera/stream.h>
|
|
+
|
|
+#include "libcamera/internal/bayer_format.h"
|
|
+
|
|
+namespace libcamera {
|
|
+
|
|
+SwStatsCpu::SwStatsCpu()
|
|
+ : SwStats()
|
|
+{
|
|
+ sharedStats_ = SharedMemObject<SwIspStats>("softIsp_stats");
|
|
+ if (!sharedStats_.fd().isValid())
|
|
+ LOG(SwStats, Error)
|
|
+ << "Failed to create shared memory for statistics";
|
|
+}
|
|
+
|
|
+/* for brightness values in the 0 to 255 range: */
|
|
+static const unsigned int BRIGHT_LVL = 200U << 8;
|
|
+static const unsigned int TOO_BRIGHT_LVL = 240U << 8;
|
|
+
|
|
+static const unsigned int RED_Y_MUL = 77; /* 0.30 * 256 */
|
|
+static const unsigned int GREEN_Y_MUL = 150; /* 0.59 * 256 */
|
|
+static const unsigned int BLUE_Y_MUL = 29; /* 0.11 * 256 */
|
|
+
|
|
+#define SWISP_LINARO_START_LINE_STATS(pixel_t) \
|
|
+ pixel_t r, g, g2, b; \
|
|
+ unsigned int y_val; \
|
|
+ \
|
|
+ unsigned int sumR = 0; \
|
|
+ unsigned int sumG = 0; \
|
|
+ unsigned int sumB = 0;
|
|
+
|
|
+#define SWISP_LINARO_ACCUMULATE_LINE_STATS(div) \
|
|
+ sumR += r; \
|
|
+ sumG += g; \
|
|
+ sumB += b; \
|
|
+ \
|
|
+ y_val = r * RED_Y_MUL; \
|
|
+ y_val += g * GREEN_Y_MUL; \
|
|
+ y_val += b * BLUE_Y_MUL; \
|
|
+ stats_.y_histogram[y_val / (256 * 16 * (div))]++;
|
|
+
|
|
+#define SWISP_LINARO_FINISH_LINE_STATS() \
|
|
+ stats_.sumR_ += sumR; \
|
|
+ stats_.sumG_ += sumG; \
|
|
+ stats_.sumB_ += sumB;
|
|
+
|
|
+static inline __attribute__((always_inline)) void
|
|
+statsBayer10P(const int width, const uint8_t *src0, const uint8_t *src1, bool bggr, SwIspStats &stats_)
|
|
+{
|
|
+ const int width_in_bytes = width * 5 / 4;
|
|
+
|
|
+ SWISP_LINARO_START_LINE_STATS(uint8_t)
|
|
+
|
|
+ for (int x = 0; x < width_in_bytes; x += 5) {
|
|
+ if (bggr) {
|
|
+ /* BGGR */
|
|
+ b = src0[x];
|
|
+ g = src0[x + 1];
|
|
+ g2 = src1[x];
|
|
+ r = src1[x + 1];
|
|
+ } else {
|
|
+ /* GBRG */
|
|
+ g = src0[x];
|
|
+ b = src0[x + 1];
|
|
+ r = src1[x];
|
|
+ g2 = src1[x + 1];
|
|
+ }
|
|
+ g = (g + g2) / 2;
|
|
+
|
|
+ SWISP_LINARO_ACCUMULATE_LINE_STATS(1)
|
|
+ }
|
|
+
|
|
+ SWISP_LINARO_FINISH_LINE_STATS()
|
|
+}
|
|
+
|
|
+void SwStatsCpu::statsBGGR10PLine0(const uint8_t *src[])
|
|
+{
|
|
+ const uint8_t *src0 = src[1] + window_.x * 5 / 4;
|
|
+ const uint8_t *src1 = src[2] + window_.x * 5 / 4;
|
|
+
|
|
+ if (swap_lines_)
|
|
+ std::swap(src0, src1);
|
|
+
|
|
+ statsBayer10P(window_.width, src0, src1, true, stats_);
|
|
+}
|
|
+
|
|
+void SwStatsCpu::statsGBRG10PLine0(const uint8_t *src[])
|
|
+{
|
|
+ const uint8_t *src0 = src[1] + window_.x * 5 / 4;
|
|
+ const uint8_t *src1 = src[2] + window_.x * 5 / 4;
|
|
+
|
|
+ if (swap_lines_)
|
|
+ std::swap(src0, src1);
|
|
+
|
|
+ statsBayer10P(window_.width, src0, src1, false, stats_);
|
|
+}
|
|
+
|
|
+void SwStatsCpu::resetStats(void)
|
|
+{
|
|
+ stats_.sumR_ = 0;
|
|
+ stats_.sumB_ = 0;
|
|
+ stats_.sumG_ = 0;
|
|
+ std::fill_n(stats_.y_histogram, 16, 0);
|
|
+}
|
|
+
|
|
+void SwStatsCpu::finishStats(void)
|
|
+{
|
|
+ *sharedStats_ = stats_;
|
|
+ statsReady.emit(0);
|
|
+}
|
|
+
|
|
+int SwStatsCpu::configure(const StreamConfiguration &inputCfg)
|
|
+{
|
|
+ BayerFormat bayerFormat =
|
|
+ BayerFormat::fromPixelFormat(inputCfg.pixelFormat);
|
|
+
|
|
+ startFrame_ = (SwStats::statsVoidFn)&SwStatsCpu::resetStats;
|
|
+ finishFrame_ = (SwStats::statsVoidFn)&SwStatsCpu::finishStats;
|
|
+
|
|
+ if (bayerFormat.bitDepth == 10 &&
|
|
+ bayerFormat.packing == BayerFormat::Packing::CSI2) {
|
|
+ bpp_ = 10;
|
|
+ patternSize_.height = 2;
|
|
+ patternSize_.width = 4; /* 5 bytes per *4* pixels */
|
|
+ y_skip_mask_ = 0x02; /* Skip every 3th and 4th line */
|
|
+ x_shift_ = 0;
|
|
+
|
|
+ switch (bayerFormat.order) {
|
|
+ case BayerFormat::BGGR:
|
|
+ case BayerFormat::GRBG:
|
|
+ stats0_ = (SwStats::statsProcessFn)&SwStatsCpu::statsBGGR10PLine0;
|
|
+ swap_lines_ = bayerFormat.order == BayerFormat::GRBG;
|
|
+ return 0;
|
|
+ case BayerFormat::GBRG:
|
|
+ case BayerFormat::RGGB:
|
|
+ stats0_ = (SwStats::statsProcessFn)&SwStatsCpu::statsGBRG10PLine0;
|
|
+ swap_lines_ = bayerFormat.order == BayerFormat::RGGB;
|
|
+ return 0;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ LOG(SwStats, Info)
|
|
+ << "Unsupported input format " << inputCfg.pixelFormat.toString();
|
|
+ return -EINVAL;
|
|
+}
|
|
+
|
|
+} /* namespace libcamera */
|
|
--
|
|
2.43.0
|
|
|