From patchwork Mon Nov 18 15:05:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 21957 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id BA70CC32EF for ; Mon, 18 Nov 2024 15:05:51 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 54EB2658EC; Mon, 18 Nov 2024 16:05:50 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="DgxcKIju"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0793C658E0 for ; Mon, 18 Nov 2024 16:05:48 +0100 (CET) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:4424:4869:bb88:5c61]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 4B0CDB2B; Mon, 18 Nov 2024 16:05:31 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1731942331; bh=kUh+Xri+YK7SjkWjEl6eR6u0Duu3KJuPqlPpiC1M0Sg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DgxcKIjuDy2OZL/CI5BysACFr1DYzW19W0mkJpbacoPmONneIIqn5ohFggBgZPNTa 41GWmme8RqC7eGVgwJN8WfBtR8S5XN5L0YyVuyeMU6ZDzPI6dGttwiA5I/qmjY3E+N l14CgmEHH7gv+v7YlLf3aVZ7kDOZskihSNPbjNt4= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH 2/4] libcamera: Enable and use matrix implementation from libcamera/internal Date: Mon, 18 Nov 2024 16:05:05 +0100 Message-ID: <20241118150528.1856797-3-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241118150528.1856797-1-stefan.klug@ideasonboard.com> References: <20241118150528.1856797-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The matrix code copied from libipa needs to be adapted to compile and work from the new location. To keep the project buildable at all times, these changes are not split into multiple commits but kept as a single one. The changes are: - Add matrix class to meson.build - Move matrix class from libipa namespace into libcamera - Add std::initializer_list based constructor to be able to replace the Matrix implementation contained in the rpi pipeline - Replace Matrix class in rpi pipeline with the new one to prevent name clashes Signed-off-by: Stefan Klug --- include/libcamera/internal/matrix.h | 20 ++++----- include/libcamera/internal/meson.build | 1 + src/ipa/rpi/controller/rpi/ccm.cpp | 56 +++++++------------------- src/ipa/rpi/controller/rpi/ccm.h | 35 +--------------- src/libcamera/matrix.cpp | 8 +--- src/libcamera/meson.build | 1 + 6 files changed, 32 insertions(+), 89 deletions(-) diff --git a/include/libcamera/internal/matrix.h b/include/libcamera/internal/matrix.h index 5471e6975b74..b82d33f98658 100644 --- a/include/libcamera/internal/matrix.h +++ b/include/libcamera/internal/matrix.h @@ -19,8 +19,6 @@ namespace libcamera { LOG_DECLARE_CATEGORY(Matrix) -namespace ipa { - #ifndef __DOXYGEN__ template> * = nullptr> @@ -35,6 +33,12 @@ public: data_.fill(static_cast(0)); } + Matrix(std::initializer_list data) + { + ASSERT(data.size() == Rows * Cols); + std::copy(data.begin(), data.end(), data_.begin()); + } + Matrix(const std::vector &data) { std::copy(data.begin(), data.end(), data_.begin()); @@ -166,24 +170,22 @@ Matrix operator+(const Matrix &m1, const Matrix -std::ostream &operator<<(std::ostream &out, const ipa::Matrix &m) +std::ostream &operator<<(std::ostream &out, const Matrix &m) { out << m.toString(); return out; } template -struct YamlObject::Getter> { - std::optional> get(const YamlObject &obj) const +struct YamlObject::Getter> { + std::optional> get(const YamlObject &obj) const { - if (!ipa::matrixValidateYaml(obj, Rows * Cols)) + if (!matrixValidateYaml(obj, Rows * Cols)) return std::nullopt; - ipa::Matrix matrix; + Matrix matrix; T *data = &matrix[0][0]; unsigned int i = 0; diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build index 1dddcd50c90b..7d6aa8b72bd7 100644 --- a/include/libcamera/internal/meson.build +++ b/include/libcamera/internal/meson.build @@ -29,6 +29,7 @@ libcamera_internal_headers = files([ 'ipc_pipe.h', 'ipc_unixsocket.h', 'mapped_framebuffer.h', + 'matrix.h', 'media_device.h', 'media_object.h', 'pipeline_handler.h', diff --git a/src/ipa/rpi/controller/rpi/ccm.cpp b/src/ipa/rpi/controller/rpi/ccm.cpp index aefa580c9a4b..418bead56ecd 100644 --- a/src/ipa/rpi/controller/rpi/ccm.cpp +++ b/src/ipa/rpi/controller/rpi/ccm.cpp @@ -29,34 +29,7 @@ LOG_DEFINE_CATEGORY(RPiCcm) #define NAME "rpi.ccm" -Matrix::Matrix() -{ - memset(m, 0, sizeof(m)); -} -Matrix::Matrix(double m0, double m1, double m2, double m3, double m4, double m5, - double m6, double m7, double m8) -{ - m[0][0] = m0, m[0][1] = m1, m[0][2] = m2, m[1][0] = m3, m[1][1] = m4, - m[1][2] = m5, m[2][0] = m6, m[2][1] = m7, m[2][2] = m8; -} -int Matrix::read(const libcamera::YamlObject ¶ms) -{ - double *ptr = (double *)m; - - if (params.size() != 9) { - LOG(RPiCcm, Error) << "Wrong number of values in CCM"; - return -EINVAL; - } - - for (const auto ¶m : params.asList()) { - auto value = param.get(); - if (!value) - return -EINVAL; - *ptr++ = *value; - } - - return 0; -} +using Matrix3x3 = Matrix; Ccm::Ccm(Controller *controller) : CcmAlgorithm(controller), saturation_(1.0) {} @@ -68,8 +41,6 @@ char const *Ccm::name() const int Ccm::read(const libcamera::YamlObject ¶ms) { - int ret; - if (params.contains("saturation")) { config_.saturation = params["saturation"].get(ipa::Pwl{}); if (config_.saturation.empty()) @@ -83,9 +54,12 @@ int Ccm::read(const libcamera::YamlObject ¶ms) CtCcm ctCcm; ctCcm.ct = *value; - ret = ctCcm.ccm.read(p["ccm"]); - if (ret) - return ret; + + auto ccm = p["ccm"].get(); + if (!ccm) + return -EINVAL; + + ctCcm.ccm = *ccm; if (!config_.ccms.empty() && ctCcm.ct <= config_.ccms.back().ct) { LOG(RPiCcm, Error) @@ -125,7 +99,7 @@ bool getLocked(Metadata *metadata, std::string const &tag, T &value) return true; } -Matrix calculateCcm(std::vector const &ccms, double ct) +Matrix3x3 calculateCcm(std::vector const &ccms, double ct) { if (ct <= ccms.front().ct) return ccms.front().ccm; @@ -141,13 +115,13 @@ Matrix calculateCcm(std::vector const &ccms, double ct) } } -Matrix applySaturation(Matrix const &ccm, double saturation) +Matrix3x3 applySaturation(Matrix3x3 const &ccm, double saturation) { - Matrix RGB2Y(0.299, 0.587, 0.114, -0.169, -0.331, 0.500, 0.500, -0.419, - -0.081); - Matrix Y2RGB(1.000, 0.000, 1.402, 1.000, -0.345, -0.714, 1.000, 1.771, - 0.000); - Matrix S(1, 0, 0, 0, saturation, 0, 0, 0, saturation); + Matrix3x3 RGB2Y({ 0.299, 0.587, 0.114, -0.169, -0.331, 0.500, 0.500, + -0.419, -0.081 }); + Matrix3x3 Y2RGB({ 1.000, 0.000, 1.402, 1.000, -0.345, -0.714, 1.000, + 1.771, 0.000 }); + Matrix3x3 S({ 1, 0, 0, 0, saturation, 0, 0, 0, saturation }); return Y2RGB * S * RGB2Y * ccm; } @@ -181,7 +155,7 @@ void Ccm::prepare(Metadata *imageMetadata) for (int j = 0; j < 3; j++) for (int i = 0; i < 3; i++) ccmStatus.matrix[j * 3 + i] = - std::max(-8.0, std::min(7.9999, ccm.m[j][i])); + std::max(-8.0, std::min(7.9999, ccm[j][i])); LOG(RPiCcm, Debug) << "colour temperature " << awb.temperatureK << "K"; LOG(RPiCcm, Debug) diff --git a/src/ipa/rpi/controller/rpi/ccm.h b/src/ipa/rpi/controller/rpi/ccm.h index 4e5b33fefa4e..c05dbb17a264 100644 --- a/src/ipa/rpi/controller/rpi/ccm.h +++ b/src/ipa/rpi/controller/rpi/ccm.h @@ -8,6 +8,7 @@ #include +#include "libcamera/internal/matrix.h" #include #include "../ccm_algorithm.h" @@ -16,41 +17,9 @@ namespace RPiController { /* Algorithm to calculate colour matrix. Should be placed after AWB. */ -struct Matrix { - Matrix(double m0, double m1, double m2, double m3, double m4, double m5, - double m6, double m7, double m8); - Matrix(); - double m[3][3]; - int read(const libcamera::YamlObject ¶ms); -}; -static inline Matrix operator*(double d, Matrix const &m) -{ - return Matrix(m.m[0][0] * d, m.m[0][1] * d, m.m[0][2] * d, - m.m[1][0] * d, m.m[1][1] * d, m.m[1][2] * d, - m.m[2][0] * d, m.m[2][1] * d, m.m[2][2] * d); -} -static inline Matrix operator*(Matrix const &m1, Matrix const &m2) -{ - Matrix m; - for (int i = 0; i < 3; i++) - for (int j = 0; j < 3; j++) - m.m[i][j] = m1.m[i][0] * m2.m[0][j] + - m1.m[i][1] * m2.m[1][j] + - m1.m[i][2] * m2.m[2][j]; - return m; -} -static inline Matrix operator+(Matrix const &m1, Matrix const &m2) -{ - Matrix m; - for (int i = 0; i < 3; i++) - for (int j = 0; j < 3; j++) - m.m[i][j] = m1.m[i][j] + m2.m[i][j]; - return m; -} - struct CtCcm { double ct; - Matrix ccm; + libcamera::Matrix ccm; }; struct CcmConfig { diff --git a/src/libcamera/matrix.cpp b/src/libcamera/matrix.cpp index 8346f0d34160..c3ed54895b22 100644 --- a/src/libcamera/matrix.cpp +++ b/src/libcamera/matrix.cpp @@ -5,7 +5,7 @@ * Matrix and related operations */ -#include "matrix.h" +#include "libcamera/internal/matrix.h" #include @@ -18,8 +18,6 @@ namespace libcamera { LOG_DEFINE_CATEGORY(Matrix) -namespace ipa { - /** * \class Matrix * \brief Matrix class @@ -34,7 +32,7 @@ namespace ipa { */ /** - * \fn Matrix::Matrix(const std::vector &data) + * \fn Matrix::Matrix(const Span &data) * \brief Construct a matrix from supplied data * \param[in] data Data from which to construct a matrix * @@ -144,6 +142,4 @@ bool matrixValidateYaml(const YamlObject &obj, unsigned int size) } #endif /* __DOXYGEN__ */ -} /* namespace ipa */ - } /* namespace libcamera */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 21cae11756d6..57fde8a8fab0 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -40,6 +40,7 @@ libcamera_internal_sources = files([ 'ipc_pipe_unixsocket.cpp', 'ipc_unixsocket.cpp', 'mapped_framebuffer.cpp', + 'matrix.cpp', 'media_device.cpp', 'media_object.cpp', 'pipeline_handler.cpp',