From patchwork Fri Mar 6 18:46:41 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Javier Tia X-Patchwork-Id: 26268 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 C9E49BE086 for ; Fri, 6 Mar 2026 18:47:26 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7ED6162633; Fri, 6 Mar 2026 19:47:26 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=jetm.me header.i=@jetm.me header.b="qOKeJDgj"; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="bOVksbR2"; dkim-atps=neutral Received: from fout-b3-smtp.messagingengine.com (fout-b3-smtp.messagingengine.com [202.12.124.146]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 815686261B for ; Fri, 6 Mar 2026 19:47:25 +0100 (CET) Received: from phl-compute-02.internal (phl-compute-02.internal [10.202.2.42]) by mailfout.stl.internal (Postfix) with ESMTP id 8EC401D00128; Fri, 6 Mar 2026 13:47:24 -0500 (EST) Received: from phl-imap-07 ([10.202.2.97]) by phl-compute-02.internal (MEProxy); Fri, 06 Mar 2026 13:47:24 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=jetm.me; h=cc:cc :content-transfer-encoding:content-type:content-type:date:date :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:subject:subject:to:to; s=fm3; t=1772822844; x=1772909244; bh=fFQMfRVX4SXJwh9RbOEBdeIDJ6/usq4wS8mkK6iJZ/4=; b= qOKeJDgjFyeXmQxKn+HXG57pp9CnvSjhVY7uW9tTsGQPSqRHjY64PvtaLAI9x5Et MqTpVImSye4CeA1hiJeB7zw1QStbpP4rf/q0kbobrzM6+oORUkaEETGFZRJ1bVfa 76RLcZQfFlJ95gEqGeUSFAEN0fnN/AwvL62VMjU/sReWcDB/j/TCqmR0OxjJUP53 nIi7gxRlO34x4u6CLxLfdyZ0xZE/RY2qdtUEFcxbYY65u8svdPG49rfFypx7CpDU b3wQQaw1XHRb9lhThEpoc9N14fU5RmSlfP5GUapeSbVWwYty6q8gz0X7J2s7MGng KfQtLR2raO8HyQOilrGoMA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:feedback-id:feedback-id :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:subject:subject:to:to:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t=1772822844; x= 1772909244; bh=fFQMfRVX4SXJwh9RbOEBdeIDJ6/usq4wS8mkK6iJZ/4=; b=b OVksbR2c2ujL1cim2h1R2XJR2of872s2Qwgt1O3QJYAkba0F20zX07wzidS1mHYK cBgw/8vfrap8cwU0u1ZWsGk9x+niIle4QIxvwSj1WAtK4IRAjbyveDH9hej/ldNI 38eABC0l/CVqFbnYT+gtKJz7jrC37ZVnyrLBpnaKdR4yA8j1Uj9b6Y1W9GhvmClq ivqXhtLZNjCOGN98HUbl2HL+oTenu+xb+AW+cy+AzXaJbEMPQqvZiRKScnTv8CKp Zrh9uyA9Gh91i6B2DxegCEfBB50/DlOa8sFeuWvtZVc2LHdqQsMSfS1TVznQ1m1+ 4HTgf8gprtMa7oJjyOs7w== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefgedrtddtgddvjedttdegucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceu rghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujf gurhepoffhfffugggtgffkvfevofgjfhesthekredtredtjeenucfhrhhomheplfgrvhhi vghrucfvihgruceofhhlohhsshesjhgvthhmrdhmvgeqnecuggftrfgrthhtvghrnhepve ektdfhffevuddtgfetieevtddvheduhfeggfekveejlefhleefieevueefiefhnecuvehl uhhsthgvrhfuihiivgepudenucfrrghrrghmpehmrghilhhfrhhomhepfhhlohhsshesjh gvthhmrdhmvgdpnhgspghrtghpthhtohepgedpmhhouggvpehsmhhtphhouhhtpdhrtghp thhtohepsggrrhhnrggsrghsrdhpohgtiigvsehiuggvrghsohhnsghorghrugdrtghomh dprhgtphhtthhopehflhhoshhssehjvghtmhdrmhgvpdhrtghpthhtoheplhhisggtrghm vghrrgdquggvvhgvlheslhhishhtshdrlhhisggtrghmvghrrgdrohhrghdprhgtphhtth hopehmiigrmhgriigrlhesrhgvughhrghtrdgtohhm X-ME-Proxy: Feedback-ID: i9dde48b3:Fastmail Received: by mailuser.phl.internal (Postfix, from userid 501) id 4CD991EA006B; Fri, 6 Mar 2026 13:47:24 -0500 (EST) X-Mailer: MessagingEngine.com Webmail Interface From: Javier Tia Date: Fri, 06 Mar 2026 12:46:41 -0600 Subject: [PATCH v4 2/3] libcamera: software_isp: Normalize statistics sums to 8-bit MIME-Version: 1.0 Message-Id: <20260306-agc-proportional-v4-2-e87c7e0d837a@jetm.me> To: libcamera-devel@lists.libcamera.org Cc: Javier Tia , Milan Zamazal , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=3262; i=floss@jetm.me; h=from:subject:message-id; bh=LPdCiSDd3MA8NAdHMsUrfV6hJzO9wW24ssL+LcTrfSg=; b=owEB7QES/pANAwAKAbXuwwuoZ3cfAcsmYgBpqyEPM0DYOvoMGOjeah2y0sdaHWmcMOG/wzKEq OmSLOmMOZyJAbMEAAEKAB0WIQSbE7ILzw7eI0VKk8m17sMLqGd3HwUCaashDwAKCRC17sMLqGd3 HyFDDACbwlLXhgrHH3oYsJfyvDmsJhZH9uK8XpvVjFAK7LDYGWHy+2v9Or3k574Cut7XRAmIV3L dvE8W1DH2nQmIUlFL9xdGzaGbyjtXss2xcpZvw1DL4mT4QYyZxhXVCHWXGfTv98AsgfFIWgLAT3 1m0yd5Y+DDzsvVGafZl2JOMm1Kjzd/RGCN1OTSPdSTUGLLoAg++SfBIpQ6ogMeIfSKcA5kX3nGy v3sg31YLf5kEZHPPwLHGqFG5fCx//x6qyM9/JrLXDmg0qruRaEm95wAFefMTvgGzU0JFC78HEVZ sfJl+i6cQpVH8VCY0YTTatqLQ1tJxjjyCTBNMRnX5QSGa/UA4sM6OvBwwl1goolYdJAlpS65331 ITMcTliQJJtSxVY5VyAPZH7g5xTV0RldRgCnjYwCOQVIDx20eB7M2Ml3C6Q3YZ5P8Me4z1Dx7No GZ5wWqvDi2jt0M+Ph1ybCZZxcfSZlCxcw4+13OSm944/EIgq0GXlrxanOuy5rQmKOYjng= X-Developer-Key: i=floss@jetm.me; a=openpgp; fpr=9B13B20BCF0EDE23454A93C9B5EEC30BA867771F In-Reply-To: <20260306-agc-proportional-v4-0-e87c7e0d837a@jetm.me> References: <20260306-agc-proportional-v4-0-e87c7e0d837a@jetm.me> 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 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. This mismatch between the AWB's gain calculation (using incorrectly BLC-subtracted sums) and the debayer's correct normalized BLC subtraction produces a visible color cast. For example, with the OV2740 sensor (10-bit, BLC=16), the under-subtraction skews R/G gain by ~9%. 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 --- 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 64b3e23f..37bfde53 100644 --- a/include/libcamera/internal/software_isp/swstats_cpu.h +++ b/include/libcamera/internal/software_isp/swstats_cpu.h @@ -115,6 +115,7 @@ private: unsigned int xShift_; unsigned int stride_; + unsigned int sumShift_; SharedMemObject sharedStats_; SwIspStats stats_; diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp index 1cedcfbc..744a7560 100644 --- a/src/libcamera/software_isp/swstats_cpu.cpp +++ b/src/libcamera/software_isp/swstats_cpu.cpp @@ -346,6 +346,11 @@ void SwStatsCpu::startFrame(uint32_t frame) void SwStatsCpu::finishFrame(uint32_t frame, uint32_t bufferId) { stats_.valid = frame % kStatPerNumFrames == 0; + if (stats_.valid && sumShift_) { + stats_.sum_.r() >>= sumShift_; + stats_.sum_.g() >>= sumShift_; + stats_.sum_.b() >>= sumShift_; + } *sharedStats_ = stats_; statsReady.emit(frame, bufferId); } @@ -402,6 +407,7 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg) 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; @@ -422,6 +428,7 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg) /* Skip every 3th and 4th line, sample every other 2x2 block */ ySkipMask_ = 0x02; xShift_ = 0; + sumShift_ = 0; processFrame_ = &SwStatsCpu::processBayerFrame2; switch (bayerFormat.order) {