From patchwork Thu Sep 10 17:21:19 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "D. Manresa" X-Patchwork-Id: 28226 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 DF670BDCBE for ; Thu, 10 Sep 2026 17:21:12 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9D7F06865E; Thu, 10 Sep 2026 19:21:11 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="rGSX5dJj"; dkim-atps=neutral Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 32BA268615 for ; Thu, 10 Sep 2026 19:21:08 +0200 (CEST) Received: by mail-wr1-x436.google.com with SMTP id ffacd0b85a97d-4843f205a5bso5041707f8f.1 for ; Thu, 10 Sep 2026 10:21:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789060868; x=1789665668; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=se6BENrywLu0mAUaUSqbrUeQSArODb2U+yBezrMFg+M=; b=rGSX5dJjgD8pZzkLD1KANLC8J0dnafK9NzH1xYyQ4U4836tFotNI9E4RWUeL+AoaHr narnVNDWPuvYPk/DwyMnVzt82IsydH8++tm+vlugOURyK7mxu7CUzdTyjdOsI+9ljfsL ywDxGMdR6INLZzA5Szc/v+BqvWBR+0Na7NGmnrZoOja+FirUKaUOWya61Dv0pGZN75Pi U2wZKT+6caGVZNsr4EqQDI4X347fWj6sjBW6G0yW7BESGnQ7umLOH7xMugM5qG9vaakz h/nd4DOzrONwtsjo9kL1tWLNek5W7ZnjpV07alO5YtdUJQOQrR6KpHDG1r+gzoqPFsL3 8qJA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789060868; x=1789665668; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=se6BENrywLu0mAUaUSqbrUeQSArODb2U+yBezrMFg+M=; b=furHI+TAVoEiljHou7QIY/8x0CXVpBpJOlRIpCD8mu6KSbpONyf4MaLWtX02rsvOKt yjADXUaUSC7O4Be/YTGzFU7rR7kVNC40LQ07Yg1y8gQPHqM5IPPGiilhXW2cIeTbtHLR pEHkQhyRtRvRqs+nYyh0V8bNKXmusuN6NDYfb7flrCMSjJbvsIdZmjqQenu0WrtAbmsK qjzTfKwFK+ro95t+2eH3Ky3yT2OGVk0y0ESkB1yJBuZWYTsKHvRpI0qHmZSkp417HWoW cuHjB0Fb49YedZ59xGEbNJJMsoJ5AnsIvYAeL03lrgkS+JgXd+c88VuzHXD2nZ0wM2sa 6uSA== X-Gm-Message-State: AFuF++lOWtXR+YIWihqP/ndN4om5zvrqT/rCFSCrgIdLTzAqtvhCkdiY JZHvkshZEQjoQwi24yHnFwBxZflDMA+om+Mele7PO0JK2XL2hU86T642KvGcZmc= X-Gm-Gg: AYBFou3qqRq5MPeKao4Rq6AFMpgcR98ww3AtRNDxIkNTIVrLKV/mqC6Gy+3hfyWRuvD HOGwMa8IpBXiSyIJW60igCtw4/zP8jDauTY82PIOdim1ZOi175B0jVJqo9mBCcXiSYtnKhjdJUo gYOhyZzkHe/kaIdQ8/Fk4PQNJuCR4v63nVVaDvqIt5JOyH+N5aj4B3V4OHWxEs68IEgboZHTg62 YvLsyckQ1uWCksYbjM8+IqWsz8ath5uaoRPWK/dkiUjgsBqFahFTO5cZIqXVl7ZKkWon1J91Ju/ ynLY3FUmERfkw3hr/OgVUeqbvzV4hJcdnrjMHclARS5Z3e+GMvrdMYWWqVyZfMQ5DzZQUg3cGOT C8ZsLC53GsUqO3SuQXjfAlMVARAUGUV1vEgZZkDjmOi14B+NrejHNYQs0y7u61VZpmWjybNNBTB H3FDs76G94KRBvL4fcoCBX+eN3FdL6Qke5skVQlSlDYhwccT6LcHhs+1NU6BWqGJ7pIfN4y2/pW 2Ml0fnYtYHEEfxfXZthjd2wGV9kbeWc54tRs+R5DVZG8qfl+1bQ9m4xQwU= X-Received: by 2002:a05:6000:490e:b0:485:8a46:b3bc with SMTP id ffacd0b85a97d-4858a46b4b8mr43074943f8f.36.1789060867472; Thu, 10 Sep 2026 10:21:07 -0700 (PDT) Received: from latitude7275 (84.124.213.91.dyn.user.ono.com. [84.124.213.91]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-485883c5bc5sm55236940f8f.24.2026.09.10.10.21.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Sep 2026 10:21:06 -0700 (PDT) From: "D. Manresa" To: libcamera-devel@lists.libcamera.org Cc: Daniel Scally Subject: [PATCH v3 1/2] ipa: libipa: camera_sensor_helper: Add OV5670 black level Date: Thu, 10 Sep 2026 19:21:19 +0200 Message-ID: <20260910172120.73148-2-dmanresa@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260910172120.73148-1-dmanresa@gmail.com> References: <20260908163708.341308-1-dmanresa@gmail.com> <20260910172120.73148-1-dmanresa@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" The OV5670 has a black level of 64 at 10 bits, the sensor's default BLC target. This was confirmed on a Dell Latitude 7275 by reading the ImgU statistics and dark frames with different black level corrections. Provide it in the camera sensor helper so that IPAs can use it instead of hard-coded or tuning-file values. Signed-off-by: D. Manresa --- src/ipa/libipa/camera_sensor_helper.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ipa/libipa/camera_sensor_helper.cpp b/src/ipa/libipa/camera_sensor_helper.cpp index 82bf255..eeb3277 100644 --- a/src/ipa/libipa/camera_sensor_helper.cpp +++ b/src/ipa/libipa/camera_sensor_helper.cpp @@ -802,6 +802,8 @@ class CameraSensorHelperOv5670 : public CameraSensorHelper public: CameraSensorHelperOv5670() { + /* Default BLC target of 64 at 10bits, confirmed by measurement. */ + blackLevel_ = 4096; gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; } }; From patchwork Thu Sep 10 17:21:20 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "D. Manresa" X-Patchwork-Id: 28227 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 D1D50BDCBE for ; Thu, 10 Sep 2026 17:21:15 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8735768663; Thu, 10 Sep 2026 19:21:15 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="bQpaJyrk"; dkim-atps=neutral Received: from mail-wm1-x331.google.com (mail-wm1-x331.google.com [IPv6:2a00:1450:4864:20::331]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9A34D6865E for ; Thu, 10 Sep 2026 19:21:09 +0200 (CEST) Received: by mail-wm1-x331.google.com with SMTP id 5b1f17b1804b1-49b8e527d63so1166255e9.2 for ; Thu, 10 Sep 2026 10:21:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789060869; x=1789665669; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=2ZnnBlDNZzl8FJKEJhrFxfok+bCPkn82A6UfyMgbQeE=; b=bQpaJyrkfo6lkX98yFiIT/2GhquKoS2A2psV57YOUZtmwMrUebrX79li7oBcUL+9P7 vkZhSMsWXooif+4miMucP8xQyJfPaPqFM+xN2HoJwN8vkXFK9WL5gUj94ZhxL7eQGf9W KZ+4dvVMo7Vfsqxz+fpv5+4uJJ2Z8nGjnMlYS6K9h5WtWw/UMO19u1z4zuzZtwjNQUEz d7QE2ymacTsbe7yTZ0aSNNFLCgUtdisiioTgXrfMF7tSFpsX+5eGR82tAxcMQHLJ4ZLy xVTnI7QyjQT4YPUVEPIQTjmDUZj0y/hBQoCllkrsUDrdoAdjJUjQweNpWsK2D7FCfQ8B 3bhA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789060869; x=1789665669; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=2ZnnBlDNZzl8FJKEJhrFxfok+bCPkn82A6UfyMgbQeE=; b=hSfN8C/wuLzFTIQZU1bcPAsMBppzc8LTpKclMeYE+0KrJRY0mUvoD0uYqIGlObf0mH Bujsk3JQK2AVWhfRaJrQfxP++1P950F9iH8KaJx+MJgsOude5TkRtnmwtqQEL0nqOWNw VOv4Xztp92JkHTbV/lG4d0BJiX9sOaYyy7JbIztMHBAhROew2hR8tkOpojEu6mLypkLx dOM1aUfvMmMeI6fyU+l+GtK4TucfB0zOhf/I3Z7YyKZFWotxmkcb8gMYv7Sg381ELQTY ukaXYklLaxS5+6ms+Z0QUR0zHvjf7c0XIbGcA5JNXPqN/NlDMQjDLSFr1oDX70E2eR28 9Ifw== X-Gm-Message-State: AFuF++m0xWMmPI/vzQc6Co4UyhOfUGsAcC1RIrel7pFYomgFpnzK4/sF 8Pz8MMaFPp0aVH7u1GU8GzoGMV8GyqaeybAQFIwqOcVTrXT+7ktyyabSB7b8FrA= X-Gm-Gg: AYBFou2d7TlwAjXQmj7wRXIY1UMxUZ5K6OMvPLlOywcjFLKFBTekN5MH3YKKb7MjSu8 GQKDXgLxX0m+uavtfB3fOkkJrbL2RQacOziPQjc3z78BZVRK7B8zg4lDerKs59t9NfzuM5KAf4b 8aD+T9xRMJryeG3pWPPCpBbi4T9ilqCQvLQhamCIeAXQ46X0qGr+0H48DZ40sfouYX0ESz0WylQ his2oVjiNmdWuT/YsOqL0nHXDpqlxVOq6XuOdDRXIW1YHWI83uSh+hjlqjL4015eQt8nFR17/gM 7qljtupcxFIxoENcJx3lF/pkakmaw0Zwt/ZvbbWRe/OOV6P5uBKvHa3D9flCGuGrg2nJG7/B6ZN pqDjQCAiE6oU4QqcC+tyPSjxMSaPaAkZhK6HQtPJenZ6iTuP7znEvaZSLxX5C/ywZO68TJbU/jl GLzDPo1UUfLwYPdODd6gqeyykYkB7C71RpK1ic5sFNNcQ01u7hH0pXH1XBLptc2KJpEB6Dp3odw 7gtz4kf6eRAI6FlC9SIZpzJOTV3cIAqFbkNAzBWe7AroPOr0xMDL/VwFwRtniHzHX1GNEw= X-Received: by 2002:a05:600c:3115:b0:495:4d88:e630 with SMTP id 5b1f17b1804b1-49e61989e79mr1108965e9.10.1789060868413; Thu, 10 Sep 2026 10:21:08 -0700 (PDT) Received: from latitude7275 (84.124.213.91.dyn.user.ono.com. [84.124.213.91]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-485883c5bc5sm55236940f8f.24.2026.09.10.10.21.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Sep 2026 10:21:07 -0700 (PDT) From: "D. Manresa" To: libcamera-devel@lists.libcamera.org Cc: Daniel Scally Subject: [PATCH v3 2/2] ipa: ipu3: blc: Use the black level from the camera sensor helper Date: Thu, 10 Sep 2026 19:21:20 +0200 Message-ID: <20260910172120.73148-3-dmanresa@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260910172120.73148-1-dmanresa@gmail.com> References: <20260908163708.341308-1-dmanresa@gmail.com> <20260910172120.73148-1-dmanresa@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" The black level correction algorithm hard-codes an optical black level of 64 for the four Bayer channels. Take it from the camera sensor helper instead, like the RkISP1 IPA does, falling back to the historical value with a warning when the helper does not provide one. The helper reports the level as a 16-bit value, while the ImgU OB grid expects units of half a 10-bit LSB: on a Dell Latitude 7275 (OV5670, black level 64 at 10 bits) a correction of 64 leaves a residual pedestal in the AWB statistics and in the image, which the colour gains then amplify into a blue or cyan cast; 128 removes the pedestal and 192 clips dark areas to zero. The 16-bit value is therefore shifted right by 5, giving 128 for the OV5670. Dan Scally independently reached the same conclusion on a Surface Go 2 (OV5693), where the ISP has to be given twice the data pedestal configured in the sensor for a dark image to come out dark. Measured on the same indoor scene with the uncalibrated tuning file (NV12, limited range, black = 16): with 64 the darkest percentile of Y is 32 and its mean chroma is U/V = 132/131; with 128 they are 15 and 128/128. Signed-off-by: D. Manresa --- src/ipa/ipu3/algorithms/blc.cpp | 60 ++++++++++++++++++++++++++++----- src/ipa/ipu3/algorithms/blc.h | 5 +++ 2 files changed, 56 insertions(+), 9 deletions(-) diff --git a/src/ipa/ipu3/algorithms/blc.cpp b/src/ipa/ipu3/algorithms/blc.cpp index 35748fb..f91ea37 100644 --- a/src/ipa/ipu3/algorithms/blc.cpp +++ b/src/ipa/ipu3/algorithms/blc.cpp @@ -7,6 +7,10 @@ #include "blc.h" +#include + +#include "libipa/camera_sensor_helper.h" + /** * \file blc.h * \brief IPU3 Black Level Correction control @@ -30,10 +34,52 @@ namespace ipa::ipu3::algorithms { * isn't currently supported. */ +LOG_DEFINE_CATEGORY(IPU3Blc) + +/* + * Black level used when the camera sensor helper does not provide one, + * expressed in ImgU units (see init()). This is the historical value that + * was hard-coded before the level came from the helper. + */ +static constexpr uint16_t kDefaultBlackLevel = 64; + BlackLevelCorrection::BlackLevelCorrection() + : blackLevel_(kDefaultBlackLevel) { } +/** + * \copydoc libcamera::ipa::Algorithm::init + */ +int BlackLevelCorrection::init(IPAContext &context, + [[maybe_unused]] const ValueNode &tuningData) +{ + std::optional blackLevel = context.camHelper->blackLevel(); + if (!blackLevel) { + LOG(IPU3Blc, Warning) + << "No black level provided by camera sensor helper" + << ", please fix"; + blackLevel_ = kDefaultBlackLevel; + } else { + /* + * The helper reports the black level as a 16-bit value, while + * the ImgU OB grid expects it in units of half a 10-bit LSB. On + * an OV5670 (black level 64 at 10 bits) a correction of 64 + * leaves a residual pedestal of about 9/255 in the AWB + * statistics and in the image, 128 removes it, and 192 clips + * dark areas to zero. Experiments with the configurable data + * pedestal of an OV5693 confirm that the ISP needs twice the + * value programmed in the sensor's black level target. The + * 16-bit value is therefore shifted right by 5. + */ + blackLevel_ = *blackLevel >> 5; + } + + LOG(IPU3Blc, Debug) << "Black level " << blackLevel_; + + return 0; +} + /** * \brief Fill in the parameter structure, and enable black level correction * \param[in] context The shared IPA context @@ -49,15 +95,11 @@ void BlackLevelCorrection::prepare([[maybe_unused]] IPAContext &context, [[maybe_unused]] IPAFrameContext &frameContext, ipu3_uapi_params *params) { - /* - * The Optical Black Level correction values - * \todo The correction values should come from sensor specific - * tuning processes. This is a first rough approximation. - */ - params->obgrid_param.gr = 64; - params->obgrid_param.r = 64; - params->obgrid_param.b = 64; - params->obgrid_param.gb = 64; + /* The Optical Black Level correction values */ + params->obgrid_param.gr = blackLevel_; + params->obgrid_param.r = blackLevel_; + params->obgrid_param.b = blackLevel_; + params->obgrid_param.gb = blackLevel_; /* Enable the custom black level correction processing */ params->use.obgrid = 1; diff --git a/src/ipa/ipu3/algorithms/blc.h b/src/ipa/ipu3/algorithms/blc.h index 6274804..bef756f 100644 --- a/src/ipa/ipu3/algorithms/blc.h +++ b/src/ipa/ipu3/algorithms/blc.h @@ -18,9 +18,14 @@ class BlackLevelCorrection : public Algorithm public: BlackLevelCorrection(); + int init(IPAContext &context, const ValueNode &tuningData) override; + void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, ipu3_uapi_params *params) override; + +private: + uint16_t blackLevel_; }; } /* namespace ipa::ipu3::algorithms */