From patchwork Wed Mar 26 08:00:31 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 23029 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 AD5D5C323E for ; Wed, 26 Mar 2025 08:00:48 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5510B68959; Wed, 26 Mar 2025 09:00:48 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="XeyGQwBJ"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4A64568951 for ; Wed, 26 Mar 2025 09:00:46 +0100 (CET) Received: from neptunite.flets-east.jp (unknown [IPv6:2404:7a81:160:2100:7402:917d:ea0c:6d4c]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 3654F3A4; Wed, 26 Mar 2025 08:58:56 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1742975938; bh=9f8CxV7HK71qH7/DEgQ17GHKGX+TekOXbGOs5iwFBuE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XeyGQwBJWW3zXx1AfA45qJ/f5f9prPuDx5EPpHaF74ey8dQhUkgAGlwLOEWWPUoFy yTp2G9nizFue5RglXrY7u22/Lx2QbKFY8Na9dDV/kEUmrqPZ4GTxN/LjQD6a1irqyO KwyyVV2Y42iyimGAFXy2I7jhyGir1z66sa1itmWU= From: Paul Elder To: libcamera-devel@lists.libcamera.org Cc: Kieran Bingham , Paul Elder Subject: [PATCH v2 1/3] ipa: libipa: Allow retrieving the name of a CameraSensorHelperFactory Date: Wed, 26 Mar 2025 17:00:31 +0900 Message-ID: <20250326080034.1733385-2-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250326080034.1733385-1-paul.elder@ideasonboard.com> References: <20250326080034.1733385-1-paul.elder@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" From: Kieran Bingham Support the test suite iterating the factories by exposing a const retriever of the factory name. Signed-off-by: Kieran Bingham Signed-off-by: Paul Elder --- Changes in v2: - recover from bitrot --- src/ipa/libipa/camera_sensor_helper.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ipa/libipa/camera_sensor_helper.h b/src/ipa/libipa/camera_sensor_helper.h index a9300a64f1e7..92f527108137 100644 --- a/src/ipa/libipa/camera_sensor_helper.h +++ b/src/ipa/libipa/camera_sensor_helper.h @@ -60,6 +60,8 @@ public: static std::vector &factories(); + const std::string &name() const { return name_; }; + private: LIBCAMERA_DISABLE_COPY_AND_MOVE(CameraSensorHelperFactoryBase) From patchwork Wed Mar 26 08:00:32 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 23030 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 8D387C323E for ; Wed, 26 Mar 2025 08:00:50 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 36FA86895E; Wed, 26 Mar 2025 09:00:50 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Q/GJGGEZ"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 145B968952 for ; Wed, 26 Mar 2025 09:00:48 +0100 (CET) Received: from neptunite.flets-east.jp (unknown [IPv6:2404:7a81:160:2100:7402:917d:ea0c:6d4c]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 2992E99F; Wed, 26 Mar 2025 08:58:58 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1742975940; bh=ZLlCj5BtvNnBwa3s/U1+UcbUZDL7OgMTE+FlKyPtWdY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Q/GJGGEZXX/j/Di9oXw8CNKuTHK0QbBbIOmQ+mEeGtckFiJuVVTNzGrX0KGQrx8OO 0aeRwpO/RogPhBBg4Dq3mgN5DO0xX3rr6m2We2rAz2dtH8oR30dtvyQKkfZfHk8yTY DhL+fMoLmARdWiqGZ91ExaEqGvxN8AQmCxjLvziw= From: Paul Elder To: libcamera-devel@lists.libcamera.org Cc: Kieran Bingham , Paul Elder Subject: [PATCH v2 2/3] test: ipa: libipa: Add CameraSensorHelper Gain Model tests Date: Wed, 26 Mar 2025 17:00:32 +0900 Message-ID: <20250326080034.1733385-3-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250326080034.1733385-1-paul.elder@ideasonboard.com> References: <20250326080034.1733385-1-paul.elder@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" From: Kieran Bingham Introduce a test that validates conversion of the gain model in each CameraSensorHelper. It should be expected that if a gainCode produces a given gain value, then converting that gain back should produce the same result. This test fails on the following CameraSensorHelpers: - imx219 imx258 imx283 imx290 imx296 imx327 imx335 imx477 Signed-off-by: Kieran Bingham Signed-off-by: Paul Elder --- Discussion points: - Should we duplicate the min/max gain values for all the sensors in the CameraSensorHelpers? (instead of using 0~240 that comes from the imx283) Is it fine to duplicate it anyway because we're already duplicating a lot of other sensor propery values? - Should we restrict the test to a specific set of sensors so that we don't have to deal with breaking tests from, for example, sensors that use gains of different Q formats or non-continuous ranges etc? Or should we test everything and diligently fix the test for every new sensor so that we're sure that nothing breaks? Changes in v2: - recover from bitrot --- test/ipa/camera_sensor_helper.cpp | 69 +++++++++++++++++++++++++++++++ test/ipa/meson.build | 1 + 2 files changed, 70 insertions(+) create mode 100644 test/ipa/camera_sensor_helper.cpp diff --git a/test/ipa/camera_sensor_helper.cpp b/test/ipa/camera_sensor_helper.cpp new file mode 100644 index 000000000000..2d37628f87c4 --- /dev/null +++ b/test/ipa/camera_sensor_helper.cpp @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2024, Ideas on Board Oy. + */ + +#include "libipa/camera_sensor_helper.h" + +#include +#include + +#include "test.h" + +using namespace std; +using namespace libcamera; +using namespace libcamera::ipa; + +class CameraSensorHelperTest : public Test +{ +protected: + int testGainModel(std::string model) + { + int ret = TestPass; + + std::unique_ptr camHelper_; + + camHelper_ = CameraSensorHelperFactoryBase::create(model); + if (!camHelper_) { + std::cout + << "Failed to create camera sensor helper for " + << model; + return TestFail; + } + + for (unsigned int i = 0; i < 240; i++) { + float gain = camHelper_->gain(i); + uint32_t gainCode = camHelper_->gainCode(gain); + + if (i != gainCode) { + std::cout << model << ": Gain conversions failed: " + << i << " : " << gain << " : " + << gainCode << std::endl; + + ret = TestFail; + } + }; + + return ret; + } + + int run() override + { + unsigned int failures = 0; + + std::vector factories; + + for (auto factory : CameraSensorHelperFactoryBase::factories()) { + const std::string &model = factory->name(); + + cout << "Testing CameraSensorHelper for " << model << endl; + + if (testGainModel(factory->name()) == TestFail) + failures++; + } + + return failures ? TestFail : TestPass; + } +}; + +TEST_REGISTER(CameraSensorHelperTest) diff --git a/test/ipa/meson.build b/test/ipa/meson.build index ceed15ba660a..98aff58b8a1a 100644 --- a/test/ipa/meson.build +++ b/test/ipa/meson.build @@ -3,6 +3,7 @@ subdir('libipa') ipa_test = [ + {'name': 'camera_sensor_helper', 'sources': ['camera_sensor_helper.cpp']}, {'name': 'ipa_module_test', 'sources': ['ipa_module_test.cpp']}, {'name': 'ipa_interface_test', 'sources': ['ipa_interface_test.cpp']}, ] From patchwork Wed Mar 26 08:00:33 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 23031 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 19D1AC323E for ; Wed, 26 Mar 2025 08:00:53 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C08C268951; Wed, 26 Mar 2025 09:00:52 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="juz7gufD"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 14AB768951 for ; Wed, 26 Mar 2025 09:00:50 +0100 (CET) Received: from neptunite.flets-east.jp (unknown [IPv6:2404:7a81:160:2100:7402:917d:ea0c:6d4c]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 224C23A4; Wed, 26 Mar 2025 08:59:00 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1742975942; bh=xflUdtGNRSQk3YX26MXTAQ20Q9y4NH0GeFwii+zNx74=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=juz7gufDvKLDfUTNTncvjzM1WrDJg00l6J1nkTlzib/JX58LyvwEOZ3FT588884Pq cyQrvrO9i+W57n/nSj+38+KKQYgQKXzkETnir94c/VZ7m2/tLjHuFEp/ay0uwRVRh+ rSNILWghfcAVo6gtAu7dxtkSgKXgEvg1R7Qg+KyI= From: Paul Elder To: libcamera-devel@lists.libcamera.org Cc: Kieran Bingham , Paul Elder Subject: [PATCH v2 3/3] libipa: camera_sensor_helper: Fix rounding of gainCode Date: Wed, 26 Mar 2025 17:00:33 +0900 Message-ID: <20250326080034.1733385-4-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250326080034.1733385-1-paul.elder@ideasonboard.com> References: <20250326080034.1733385-1-paul.elder@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" From: Kieran Bingham The implementation of gainCode for both Exponential and Linear gain models does not generate a gainCode that matches the result of the reverse operation. This can be seen by converting sequential gainCodes to a gain and converting that back to the gainCode. The values do not translate back due to rounding errors. Correct the rounding error and ensure that gainCode translation produces accurate bi-directional conversions from the perspective of the gainCode. This fixes the IMX290, IMX296, IMX327 and IMX335 which use the Exponential gain model helpers, as well as IMX219 IMX258 and IMX477 which use the Linear gain model helpers. Signed-off-by: Kieran Bingham Signed-off-by: Paul Elder --- Changes in v2: - recover from bitrot --- src/ipa/libipa/camera_sensor_helper.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ipa/libipa/camera_sensor_helper.cpp b/src/ipa/libipa/camera_sensor_helper.cpp index 7c66cd57d685..5645dd14fda3 100644 --- a/src/ipa/libipa/camera_sensor_helper.cpp +++ b/src/ipa/libipa/camera_sensor_helper.cpp @@ -90,12 +90,12 @@ uint32_t CameraSensorHelper::gainCode(double gain) const if (auto *l = std::get_if(&gain_)) { ASSERT(l->m0 == 0 || l->m1 == 0); - return (l->c0 - l->c1 * gain) / - (l->m1 * gain - l->m0); + return std::round((l->c0 - l->c1 * gain) / + (l->m1 * gain - l->m0)); } else if (auto *e = std::get_if(&gain_)) { ASSERT(e->a != 0 && e->m != 0); - return std::log2(gain / e->a) / e->m; + return std::round(std::log2(gain / e->a) / e->m); } else { ASSERT(false); return 0;