From patchwork Wed May 6 23:06:40 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: devve X-Patchwork-Id: 26652 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 8DC94C32F6 for ; Wed, 6 May 2026 23:06:56 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 42E876302F; Thu, 7 May 2026 01:06:54 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="W4095VUw"; dkim-atps=neutral Received: from mail-wm1-x32b.google.com (mail-wm1-x32b.google.com [IPv6:2a00:1450:4864:20::32b]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 09DF762DC4 for ; Thu, 7 May 2026 01:06:51 +0200 (CEST) Received: by mail-wm1-x32b.google.com with SMTP id 5b1f17b1804b1-488e1a8ac40so2099615e9.2 for ; Wed, 06 May 2026 16:06:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778108810; x=1778713610; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=LaTrKnaEFSG6R1dixgnlxJZEG75nGFBB6KtmVy+2B9E=; b=W4095VUwJCQ63Qd9qMZO5BAvhdxSu4f+gVoeLvm+n8leLmS9XecbiDX2fhevY3YQzQ 6Md9wc1WA44qIjEj9vIqn11tZ3qk78kRX972A49fBzxBGQygWh2cTwmAoI/XEya0oNJS pAQVvoVU2qfEjS3xPlgoEHi0mxR6qQ6v7Y3pdHl74M6f99bMFMsEsZBdyDOVHsAcO9Uz SjMEQGdJLfvANdLmckNkoGHJgZghlSJM8jv0KhOaILvcNbUmQ/hmuEKGiuMr7PmTJGMc u4zuFutt597hyClfVSa/qjxMe1Vh5plFGP/jsEE8NaWKHrGdSmExP883g2fjTiuGEChf UBBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778108810; x=1778713610; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=LaTrKnaEFSG6R1dixgnlxJZEG75nGFBB6KtmVy+2B9E=; b=Gd24tNi58rZWPYOL8uyEfkj5GwwV1h3xHYGj0GV1qQvIYx4zVwzSx3CDupjilGYCQG DP7oSylNWB4DFmkZd8Tye4yu9si4UV6LHELxw1EmNYgc8nYoXcVvEWZAbHs8+Y8TGhCl 8rwdgOR4rbjYCJL8pERrwLj2y0R7zhUkOmrCkCcocwkTaFmO1R2mKOdUwUPtCt/+9ag2 sfmQ8FSfzhf21N704vd+jhmeHxPZorLJKqOkKoMuYM4SsfXk6arLiFLMugta6UpiPt0R bEkJ7b2gSva/QTlqCRqkzF+0GE1KPl9hchL+wHc3CKzeBvW9F8Rmi/7qkO1x7iONV4Tl Pq3w== X-Gm-Message-State: AOJu0Yz6BmfhiLasiXNgt5d2S8Aoyo1BWAeNfqk96ExC6glBc2TAatTM ZF5r1AVH1v6T8nr83cUXM9SKOoU6BJ+K5Jev5jjGvgYVUzMn2KnXPjuBsfTaBg== X-Gm-Gg: AeBDievgEk++udSVO32M1jZXT8Pd/oEYkZ2NzKhCBGqGkIhDbKSB/7fGdZpiX3HNks1 GxEiaOIaPGFhdYaCusCOWBLWYkoAYGaKKKrub3Q33Fys7xwg8n87bpAd7KurslbTdMeLtRyzejn 2tkxjA8nXn7MLEuurvwRJZ99ZEOIFuQRd9sw0/9qLn93t20d570YEWo1V31zJ6e6q9EpDZd+Dpr 8VTRHc/owUaauEWMm3h3NnJQye59FOzKGqQoUr3SO9kCSBd4nwugQ1eaoBxltA+Mslk0C4rppvT LbDx5oM2MB4zKZYnKRuYAWON1ooCxQp7hyqBbTBCJQ/Hviqhb8ZPIMwPd/MZepOlFBbf0lndKk5 XZkHqo4LmdWWXcSgJJFoL4HhoIrQKhet0QOhVXApoNgT6tv7bQ5M23QzTDRMZxp4SyTLp1g3dB7 zIMWx0RwRf9dpJixWbZHXy0sgPV9iz33nO/E8VY4J0CQNdyvClgM2F+py6jaktRWn4WuUx//smH b5G8njHmFhx+UlEpYhaU3tjUL0HTJWNvzuh8orGemqy1PtC4hnw4Q== X-Received: by 2002:a05:600c:8906:b0:488:ffad:6728 with SMTP id 5b1f17b1804b1-48e51f46d7bmr69113445e9.19.1778108810517; Wed, 06 May 2026 16:06:50 -0700 (PDT) Received: from dexps.speedport.ip (p200300eda74453cf3cf3f7929e513b94.dip0.t-ipconnect.de. [2003:ed:a744:53cf:3cf3:f792:9e51:3b94]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48e538a547bsm85951935e9.5.2026.05.06.16.06.50 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 06 May 2026 16:06:50 -0700 (PDT) From: d3vv3 To: libcamera-devel@lists.libcamera.org Subject: [PATCH v2 01/10] ipa: libipa: camera_sensor_helper: Add OV01A10 Date: Thu, 7 May 2026 01:06:40 +0200 Message-ID: <20260506230649.1040794-2-devve.3@gmail.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260506230649.1040794-1-devve.3@gmail.com> References: <20260506230649.1040794-1-devve.3@gmail.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: Stuart J Mackintosh Add a CameraSensorHelper for the OmniVision OV01A10 image sensor, used in Dell XPS 13 and other laptops with the Intel IPU6 camera subsystem. The analogue gain register (0x3508) uses a Q6.8 fixed-point format, with the minimum value OV01A10_ANAL_GAIN_MIN = 0x100 representing unity gain. This gives the linear model: gain = code / 256 Hans de Goede confirmed linear behaviour by monitoring the 18% grey patch of a Macbeth chart under controlled lighting while stepping the gain control. The black level of 0x40 at 10 bits (4096 scaled to 16 bits) was confirmed by dark frame measurement with the lens covered. Without this helper, libcamera's AGC algorithm cannot convert between gain codes and real gain values, causing auto-exposure oscillation and the following warning: IPASoft: Failed to create camera sensor helper for ov01a10 Signed-off-by: Stuart J Mackintosh --- src/ipa/libipa/camera_sensor_helper.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/ipa/libipa/camera_sensor_helper.cpp b/src/ipa/libipa/camera_sensor_helper.cpp index e3e3e535..72466867 100644 --- a/src/ipa/libipa/camera_sensor_helper.cpp +++ b/src/ipa/libipa/camera_sensor_helper.cpp @@ -653,6 +653,18 @@ public: }; REGISTER_CAMERA_SENSOR_HELPER("imx708", CameraSensorHelperImx708) +class CameraSensorHelperOv01a10 : public CameraSensorHelper +{ +public: + CameraSensorHelperOv01a10() + { + /* From dark frame measurement: 0x40 at 10bits. */ + blackLevel_ = 4096; + gain_ = AnalogueGainLinear{ 1, 0, 0, 256 }; + } +}; +REGISTER_CAMERA_SENSOR_HELPER("ov01a10", CameraSensorHelperOv01a10) + class CameraSensorHelperOv2685 : public CameraSensorHelper { public: From patchwork Wed May 6 23:06:41 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: devve X-Patchwork-Id: 26653 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 10D0AC32F7 for ; Wed, 6 May 2026 23:06:57 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 546AB6302D; Thu, 7 May 2026 01:06:57 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="CsnUkxWx"; dkim-atps=neutral Received: from mail-wm1-x32d.google.com (mail-wm1-x32d.google.com [IPv6:2a00:1450:4864:20::32d]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 090A36301E for ; Thu, 7 May 2026 01:06:51 +0200 (CEST) Received: by mail-wm1-x32d.google.com with SMTP id 5b1f17b1804b1-48d102471a4so1771885e9.2 for ; Wed, 06 May 2026 16:06:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778108811; x=1778713611; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=vpT2omGvrrBC/UWz9mRqAkO01quAcHHbvl8N34ZIhJU=; b=CsnUkxWxTOKysjUu84w1+oJ5RWQRZambNaeSw7vogpsyoke0dzLYbwSOhX0yRQZy7Z CaiXeii6CiUbVivYjqua1M58ZDnIZnrpzrhiGL4ZglzlFv4HaRXu1rHGPyqinL/VqbKz 6PAt93QvYfzizOb5YpgGTHNI4gtRtJBb0d+S1TfrQCyvR9nm6Z9JtvIR0DOfvEkS4MeU /bedNH3V34QnmyCRXErDah4YnzKQmGCbhvwY+UHj2hw0Zb3gUnLmqCu6xfq3czIE7+KP Azs6mP0YamkfuqnQamWoz45Yh7lkCOBbfyv7z+m5ufryxRtMGo6OfsMzXkOdEtPDPrnl ggCA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778108811; x=1778713611; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=vpT2omGvrrBC/UWz9mRqAkO01quAcHHbvl8N34ZIhJU=; b=OF/Z2yP6rIZPFulxhRoMxNUxiimfATifqRlI9PS5vqp+ncNlBCX12iSAbEa15D1REf wUNn7TE7g78hCgA/CZDvCOuO56F6zyEGFGrRHBKixUIpWUKM9OXympVrd8mHIpG7BFJM 1oaZib+A0tKwDKDBl604Kfjy9mcP4VRlxD+vweb5T9n6hQWYR+Wo5q1ovXV0+74GF8Qz 9EzRnG+7Hjky0mhOpm7K4M/3DIVoS1pAWFr0iVVDQHB1iwW9drBFoZEFPxKVATc9o8R6 D8+7F8PyVZLgWwZlafrS28dS/SQhBY5vSfwzGSrT3hIF2uECJlXZrI7BvDVmL3uKphV9 Y0fQ== X-Gm-Message-State: AOJu0YzGwr0PYawcyY6Mh9arFL1OP8vc/15Thhb8izARdX2oFP8x3xoP u9l42wLCFgGFKJgMFryBi3D8ryh+r2axroY/Ry+xJDZPRNykeS+BwJvWqRo1LQ== X-Gm-Gg: AeBDieuKqVn5UTgPNyAw0W8HYITSZsad0elYRmfgIiw1HTFrE00aDq7AfKqHdhDTrRR gfpWlsZeiQpbtjBS4A08uT17FMA68UxUBQ1qqAGore4+9wClT0NaO4ZxPNa8ZD091mfMlSnHvKG dp2Djr32okxU4L6V8iMnsgZhgGsZLL3MYE7wy4GqpasO2vQgy7jPKQbE0HotDsVAkROdfx0LmRW j4apAM2I9zSV4+6DcdANSv58QJi2M6yVUUTajqfC5uAzbBk3KAbpyQQoENzkjEcF8/iYuJPSq7I WXEHbod3RmjywqXLuW7+XMoE6M6soxXUqYN7xJVf5Zka3tRwZgqq37hZsyKOpjAHc2aAwMTYssf huenGcc7uGaXzY6fEc6OQmf8OxXP2S9Vm51no3Pa5MIlHZbZumWSwRVrxyWaueQEyPZQ8SD/m/R JsWo8zahfE78O/WkYFc/JpikNo+AyrMPvdpTKVquAougna3z/dr+ibKS9wQZb+mAwj1CsOqU0o3 HjL7tDsS/zRNErkSRy9YWboGbB6Ie2x X-Received: by 2002:a05:600c:c094:b0:48a:592c:e63d with SMTP id 5b1f17b1804b1-48e51f3fab1mr64868415e9.14.1778108810930; Wed, 06 May 2026 16:06:50 -0700 (PDT) Received: from dexps.speedport.ip (p200300eda74453cf3cf3f7929e513b94.dip0.t-ipconnect.de. [2003:ed:a744:53cf:3cf3:f792:9e51:3b94]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48e538a547bsm85951935e9.5.2026.05.06.16.06.50 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 06 May 2026 16:06:50 -0700 (PDT) From: d3vv3 To: libcamera-devel@lists.libcamera.org Subject: [PATCH v2 02/10] ipa: simple: awb: Add temporal smoothing and per-channel gain limits Date: Thu, 7 May 2026 01:06:41 +0200 Message-ID: <20260506230649.1040794-3-devve.3@gmail.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260506230649.1040794-1-devve.3@gmail.com> References: <20260506230649.1040794-1-devve.3@gmail.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" Add configurable YAML parameters maxGainR, maxGainB, and speed to AWB. Replace the single hardcoded max gain (4.0x) with per-channel limits, and apply exponential moving average smoothing to reduce colour temperature oscillation between frames. Signed-off-by: d3vv3 --- src/ipa/simple/algorithms/awb.cpp | 34 ++++++++++++++++++++++++++----- src/ipa/simple/algorithms/awb.h | 6 ++++++ 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/ipa/simple/algorithms/awb.cpp b/src/ipa/simple/algorithms/awb.cpp index f5c88ea6..937aabc8 100644 --- a/src/ipa/simple/algorithms/awb.cpp +++ b/src/ipa/simple/algorithms/awb.cpp @@ -14,6 +14,8 @@ #include +#include "libcamera/internal/yaml_parser.h" + #include "libipa/colours.h" #include "simple/ipa_context.h" @@ -23,6 +25,21 @@ LOG_DEFINE_CATEGORY(IPASoftAwb) namespace ipa::soft::algorithms { +int Awb::init([[maybe_unused]] IPAContext &context, + const ValueNode &tuningData) +{ + maxGainR_ = tuningData["maxGainR"].get().value_or(4.0f); + maxGainB_ = tuningData["maxGainB"].get().value_or(4.0f); + speed_ = tuningData["speed"].get().value_or(1.0f); + + LOG(IPASoftAwb, Debug) + << "AWB: maxGainR " << maxGainR_ + << ", maxGainB " << maxGainB_ + << ", speed " << speed_; + + return 0; +} + int Awb::configure(IPAContext &context, [[maybe_unused]] const IPAConfigInfo &configInfo) { @@ -84,14 +101,21 @@ void Awb::process(IPAContext &context, const RGB sum = stats->sum_.max(offset + minValid) - offset; /* - * Calculate red and blue gains for AWB. - * Clamp max gain at 4.0, this also avoids 0 division. + * Calculate red and blue gains for AWB. Clamp max gain to avoid + * division by zero and extreme color casts. */ auto &gains = context.activeState.awb.gains; + float rawRGain = sum.r() <= sum.g() / maxGainR_ ? maxGainR_ : + static_cast(sum.g()) / sum.r(); + float rawBGain = sum.b() <= sum.g() / maxGainB_ ? maxGainB_ : + static_cast(sum.g()) / sum.b(); + + /* Apply temporal smoothing to avoid rapid white balance changes. */ + float alpha = std::clamp(speed_, 0.01f, 1.0f); gains = { { - sum.r() <= sum.g() / 4 ? 4.0f : static_cast(sum.g()) / sum.r(), - 1.0, - sum.b() <= sum.g() / 4 ? 4.0f : static_cast(sum.g()) / sum.b(), + gains.r() * (1.0f - alpha) + rawRGain * alpha, + 1.0f, + gains.b() * (1.0f - alpha) + rawBGain * alpha, } }; RGB rgbGains{ { 1 / gains.r(), 1 / gains.g(), 1 / gains.b() } }; diff --git a/src/ipa/simple/algorithms/awb.h b/src/ipa/simple/algorithms/awb.h index ad993f39..0aedc1d1 100644 --- a/src/ipa/simple/algorithms/awb.h +++ b/src/ipa/simple/algorithms/awb.h @@ -19,6 +19,7 @@ public: Awb() = default; ~Awb() = default; + int init(IPAContext &context, const ValueNode &tuningData) override; int configure(IPAContext &context, const IPAConfigInfo &configInfo) override; void prepare(IPAContext &context, const uint32_t frame, @@ -29,6 +30,11 @@ public: IPAFrameContext &frameContext, const SwIspStats *stats, ControlList &metadata) override; + +private: + float maxGainR_; + float maxGainB_; + float speed_; }; } /* namespace ipa::soft::algorithms */ From patchwork Wed May 6 23:06:45 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: devve X-Patchwork-Id: 26656 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 E237EC32FB for ; Wed, 6 May 2026 23:07:08 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 635116302F; Thu, 7 May 2026 01:07:02 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="YpC9thUs"; dkim-atps=neutral Received: from mail-wm1-x32e.google.com (mail-wm1-x32e.google.com [IPv6:2a00:1450:4864:20::32e]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 33BC363025 for ; Thu, 7 May 2026 01:06:53 +0200 (CEST) Received: by mail-wm1-x32e.google.com with SMTP id 5b1f17b1804b1-488a8ca4aadso2087445e9.3 for ; Wed, 06 May 2026 16:06:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778108813; x=1778713613; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=ANVPg7VR/jgoiN08fPKUsvHJnWWyqQ90OtjRAf9XFxo=; b=YpC9thUsGro8sLSmKRWLMYPstbZmHs1D2nJ6VZNjNn07Mwr3Px28b2lVzjYQ5OpaBJ JHmR7Ins111cX2NFDhav5MiktIhNFAoaNKc2ZDkbw2+NGH3rkmolaBdOj0oPFVLDQ7R4 37z10eYhFpLqGpQPdqKTNyDY0tiP9ebUTsOPmXYPtPyM0456ztjxsvCsPRr9q6rnBRuM KU+xTjmxaia+YAClXzioXhwpsSirycK5kh/axwZNyW9wXMoV+yURhmL63yxEjCAUBUTk Gj3R5cvojsiDUoZDwCijUv4+3YM8lIgnJzmN3AlX1uGZfAS8MxruqlI24QEjImRTzvNC i9Yw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778108813; x=1778713613; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=ANVPg7VR/jgoiN08fPKUsvHJnWWyqQ90OtjRAf9XFxo=; b=PsiHexaxQ/gHGyTPeF7pq0Em41BlEB2Zza31MAYpJ05llBhlESm0fp+gID08CfJL1r 3QaPyKFn46dEc4UCIcrLTRkKhQCkLnT7hhU4RC4DL4scqrP03cECymp3CwLfW+gPFDVs w2BEz8VlZbvVdtQqgFfXhJWOYTIyYdOvPpIrvP+y1/b/AT62PzNu/cmDSyNbuJ8yoSj1 2Nw8LJu/waluS10nxZSFMZiq6U86sEvH9pFLL8v8Z/NjZPQ9J+mMBiY72J3cm3WGNeRC O27ynpc2+U+/9EusqvvaG0aCpy7fSRl1IZaklcoGAYzY5OmnJv7BdU9kLNnQqnnOJL9P npUw== X-Gm-Message-State: AOJu0YyJy3yHcjc90ryIwLwrYQb1kO2IMIz4NeuypCJzkX+RbRkSW8tH HxE5U8fVBD3aeuf2mJWqgy3X8A3Myu8aOiMSqAjwFZZvTi/rU4n1qpM6hyYwfQ== X-Gm-Gg: AeBDiesi4gcZAnzHRJYIXzcS0RlewMx/goLbFH95TDaOreCJ7d2yrgF6hRgtpQp8OwA Iag+IxpBlLDwcUugOqMMaJILphhaYa1cyTfqInJgKDZv65LtalwOtlKxOfG5ZjPmRODAZZ358Rh Xt5cChnC1rVhFKxY7WwA/m0IgJ0qiicYM0xySx47g9ureFWtBcUVjcE8L3fMbHrMFWHLbvHeq+s TtkMEk4I5POLTQQpmw59KY312xGzpWhYlr5jF9Dd0gbJGEaud3NWEN33Sd34093sluMJ72OkfxT tCgAFRb51BEqyWT5/Yry/QSILtLBcA3xYuHkgpx5Da/uHwmXloqm63v6c3tQ30CIsYzvVseXnys x6mp378cWjCyiwAXelMHBQ03H9QRNIZVMMsvLzJU6TItwTCfUA/ThezqnGlUEVgjm3z7WPqJJjX jn+kVmPkpGaT6mVT9mM3hscf7uhivehVTdyUmL7xXYlkl9KeDQwPrrb4tzrCnXI+ZbEYaIPsnAQ 9Dpq3x4zcXCxb8afpXCS/nd5KLuFAsa X-Received: by 2002:a05:600c:c094:b0:487:5c0:671f with SMTP id 5b1f17b1804b1-48e51e1a7c4mr66305185e9.9.1778108812642; Wed, 06 May 2026 16:06:52 -0700 (PDT) Received: from dexps.speedport.ip (p200300eda74453cf3cf3f7929e513b94.dip0.t-ipconnect.de. [2003:ed:a744:53cf:3cf3:f792:9e51:3b94]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48e538a547bsm85951935e9.5.2026.05.06.16.06.52 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 06 May 2026 16:06:52 -0700 (PDT) From: d3vv3 To: libcamera-devel@lists.libcamera.org Subject: [PATCH v2 06/10] libcamera: software_isp: Normalize statistics sums to 8-bit Date: Thu, 7 May 2026 01:06:45 +0200 Message-ID: <20260506230649.1040794-7-devve.3@gmail.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260506230649.1040794-1-devve.3@gmail.com> References: <20260506230649.1040794-1-devve.3@gmail.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: Javier Tia The SWSTATS_ACCUMULATE_LINE_STATS() macro divides the luminance value for the histogram to normalize it to 8-bit range, but does not apply the same normalization to the RGB sums. For 10-bit and 12-bit unpacked Bayer formats this means the sums are accumulated at native bit depth (0-1023 or 0-4095 per pixel) while the AWB algorithm subtracts an 8-bit black level from them, under-correcting by 4x or 16x respectively. Fix this by right-shifting the RGB sums in finishFrame() to normalize them to 8-bit scale, matching the histogram and the 8-bit black level used by AWB. A per-format sumShift_ value is set in configure(): 0 for 8-bit and CSI-2 packed formats (already 8-bit), 2 for 10-bit, and 4 for 12-bit unpacked formats. Signed-off-by: Javier Tia Reviewed-by: Milan Zamazal Tested-by: Milan Zamazal Reviewed-by: Barnabás Pőcze Tested-by: Barnabás Pőcze Signed-off-by: d3vv3 --- include/libcamera/internal/software_isp/swstats_cpu.h | 1 + src/libcamera/software_isp/swstats_cpu.cpp | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/include/libcamera/internal/software_isp/swstats_cpu.h b/include/libcamera/internal/software_isp/swstats_cpu.h index 802370bd..2dac6945 100644 --- a/include/libcamera/internal/software_isp/swstats_cpu.h +++ b/include/libcamera/internal/software_isp/swstats_cpu.h @@ -116,6 +116,7 @@ private: unsigned int xShift_; unsigned int stride_; + unsigned int sumShift_; std::vector stats_; SharedMemObject sharedStats_; diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp index 5366e019..2ed906e1 100644 --- a/src/libcamera/software_isp/swstats_cpu.cpp +++ b/src/libcamera/software_isp/swstats_cpu.cpp @@ -362,6 +362,11 @@ void SwStatsCpu::finishFrame(uint32_t frame, uint32_t bufferId) for (unsigned int j = 0; j < SwIspStats::kYHistogramSize; j++) sharedStats_->yHistogram[j] += s.yHistogram[j]; } + if (sumShift_) { + sharedStats_->sum_.r() >>= sumShift_; + sharedStats_->sum_.g() >>= sumShift_; + sharedStats_->sum_.b() >>= sumShift_; + } } sharedStats_->valid = valid; @@ -422,6 +427,7 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg, unsigned int stat if (bayerFormat.packing == BayerFormat::Packing::None && setupStandardBayerOrder(bayerFormat.order) == 0) { processFrame_ = &SwStatsCpu::processBayerFrame2; + sumShift_ = bayerFormat.bitDepth - 8; switch (bayerFormat.bitDepth) { case 8: stats0_ = &SwStatsCpu::statsBGGR8Line0; @@ -442,6 +448,7 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg, unsigned int stat /* Skip every 3th and 4th line, sample every other 2x2 block */ ySkipMask_ = 0x02; xShift_ = 0; + sumShift_ = 0; processFrame_ = &SwStatsCpu::processBayerFrame2; switch (bayerFormat.order) {