From patchwork Fri Feb 3 09:17:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 18240 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 075BFBEFBE for ; Fri, 3 Feb 2023 09:17:44 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id F4158625EE; Fri, 3 Feb 2023 10:17:41 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1675415862; bh=gnjOLxwHnFSU2iGTu7KO1N3RlVXKuSggoauFfbGNjrI=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=TveAgHmL/hZO7OFwSR3Xam2d8PJSz47M5wWQB4VeILCc30vKlRJWDgHAvJdX6ZrZ7 og3Dht7HeGAQGzF2pI+hdqiUDR8X4dxZZMo/xa/4h7fiD2FGM5U5GuYWlFdLBAJ/11 h+5a9NHnwUyur4A/YU6/W36itBEGKzZL9dwy8c0ZwmS40IJ383rZ9YDiP2XW+yI/Hu 9PRY1jGpdcVH+MN6VglAFk3F9DndouxaU+7Yy2Y2FnzC0wvuKrMLRlyVGDiiMl3L2c KGLqbLAdG51sbxfSDsbvtPq/XsXR9gxvi+TB1PQDzoZ8w2XDgCyao2eShLN/z18sDX VEJPyK5JvCVfw== Received: from mail-wm1-x32a.google.com (mail-wm1-x32a.google.com [IPv6:2a00:1450:4864:20::32a]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7728761EF4 for ; Fri, 3 Feb 2023 10:17:40 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="XAjSdPzx"; dkim-atps=neutral Received: by mail-wm1-x32a.google.com with SMTP id m5-20020a05600c4f4500b003db03b2559eso3327931wmq.5 for ; Fri, 03 Feb 2023 01:17:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; 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; bh=cFKCg+ZE+nhe2cGJPAWdDIMNRxjiykJzy0Pv0P4gmyY=; b=XAjSdPzxrRaAYn5n9SnykQbJk04dkhF9ux0jIhrfo/sLHL60V2vbzR47WzYJCNyEYr lM96hZ1DKePJ6MhjI1eYty4VmxtrF7EvtVHHKgScvKfhA02iswi+OapC8zGp/1052Jbh zKvXX/z5p/U4eEwxyqrZEXy8Ea5fAHa7gX9MvPJDTgiMjnU+QKAKqaahX5CpwJbI/Kl9 0qc8Har2pBiSJvyDQY4LEZWgauJ6yTnkbtD8tYhMVWfJ1AAxBgRhxeudl9QXhLvAiiDj MW+BPqVhoX3bpxNGhGL6t8m1xrmDSGtr39cIDwxVyk6I/eKv3e9qtGKddV9xtTrFC0FW rDaA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=cFKCg+ZE+nhe2cGJPAWdDIMNRxjiykJzy0Pv0P4gmyY=; b=ae9T6bLiFdJBb4fxkbMJqT/URW0KAZ3ilC/ysPkt0fFllR6HCrp246uSySOMQpfZim mvdbY8wzQ4nvKyOXLwjZpmma6xEtZ3I9HYyJbSP4fK1P/Iv/m+aHWB2z6Z/CS4aYPu+1 Z/oOyvC6NgILlZ+ipnJGBVIxuPRcqYoW5LVFYEKx9H1wgt5IQ7rAyr03uzBbI46j+AOI e/ifgzXFQ5RAxod48ip/L58EziQID+tivo65LhGXqhroCuPnlpa4fwqnIb4ODZ3EPATH yN41A5lPDEfq5lxY9ptfe1VDM5onVOb8bghHByAum7KbBVLv7qmUNiFJsxB7qCtMPQyt Dp9w== X-Gm-Message-State: AO0yUKXnRI9Wv1gcl1zrAcNtsr7k7jqEQPljDE72jJ8GQvfy+ObVZoJf UiKi23IVGpsm/f+pWbVUR18jIFMLrbK+w9WGvjnMnA== X-Google-Smtp-Source: AK7set/H/+V1VTQR06YTnEHPb5NVNR6CNF6XJkebH+pLS01w/XHD9mhkLm7cc1n2HmutrziY3HoJzQ== X-Received: by 2002:a1c:4c08:0:b0:3de:b1ec:7f95 with SMTP id z8-20020a1c4c08000000b003deb1ec7f95mr8978810wmf.18.1675415859843; Fri, 03 Feb 2023 01:17:39 -0800 (PST) Received: from localhost.localdomain ([93.93.133.154]) by smtp.gmail.com with ESMTPSA id az24-20020a05600c601800b003dc4baaedd3sm7468864wmb.37.2023.02.03.01.17.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 Feb 2023 01:17:39 -0800 (PST) To: libcamera-devel@lists.libcamera.org Date: Fri, 3 Feb 2023 09:17:30 +0000 Message-Id: <20230203091734.22803-2-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230203091734.22803-1-naush@raspberrypi.com> References: <20230203091734.22803-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 1/5] ipa: raspberrypi: Generalise statistics 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: , X-Patchwork-Original-From: Naushir Patuck via libcamera-devel From: Naushir Patuck Reply-To: Naushir Patuck Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" At present, the controller algorithms access the bcm2835_isp_stats structure, which is hardware specific. It would be desirable to abstract out the statistics structure to remove hardware specific headers from the algorithms source files. Define a new templated RegionStats class that encompasses region based statistics generated by the ISP. For the VC4 ISP, this can be used to hold RGB sums and focus FoM values. Define a new Statistics structure that holds all the VC4 ISP statistics output. This includes AGC histograms, AGC/AWB region sums and focus FoM regions. Signed-off-by: Naushir Patuck Reviewed-by: David Plowman Reviewed-by: Kieran Bingham --- src/ipa/raspberrypi/controller/region_stats.h | 123 ++++++++++++++++++ src/ipa/raspberrypi/statistics.h | 76 +++++++++++ 2 files changed, 199 insertions(+) create mode 100644 src/ipa/raspberrypi/controller/region_stats.h create mode 100644 src/ipa/raspberrypi/statistics.h diff --git a/src/ipa/raspberrypi/controller/region_stats.h b/src/ipa/raspberrypi/controller/region_stats.h new file mode 100644 index 000000000000..9aaf3a58a6f7 --- /dev/null +++ b/src/ipa/raspberrypi/controller/region_stats.h @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2022, Raspberry Pi Ltd + * + * region_stats.h - Raspberry Pi region based statistics container + */ +#pragma once + +#include +#include +#include + +#include + +namespace RPiController { + +template +class RegionStats +{ +public: + struct Region { + T val; + uint32_t counted; + uint32_t uncounted; + }; + + RegionStats() + : size_({}), numFloating_(0), default_({}) + { + } + + void init(const libcamera::Size &size, unsigned int numFloating = 0) + { + size_ = size; + numFloating_ = numFloating; + regions_.clear(); + regions_.resize(size_.width * size_.height + numFloating_); + } + + void init(unsigned int num) + { + size_ = libcamera::Size(num, 1); + numFloating_ = 0; + regions_.clear(); + regions_.resize(num); + } + + unsigned int numRegions() const + { + return size_.width * size_.height; + } + + unsigned int numFloatingRegions() const + { + return numFloating_; + } + + libcamera::Size size() const + { + return size_; + } + + void set(unsigned int index, const Region ®ion) + { + if (index >= numRegions()) + return; + set_(index, region); + } + + void set(const libcamera::Point &pos, const Region ®ion) + { + set(pos.y * size_.width + pos.x, region); + } + + void setFloating(unsigned int index, const Region ®ion) + { + if (index >= numFloatingRegions()) + return; + set(numRegions() + index, region); + } + + const Region &get(unsigned int index) const + { + if (index >= numRegions()) + return default_; + return get_(index); + } + + const T &get(const libcamera::Point &pos) const + { + return get(pos.y * size_.width + pos.x); + } + + const T &getFloating(unsigned int index) const + { + if (index >= numFloatingRegions()) + return default_; + return get_(numRegions() + index); + } + + typename std::vector::iterator begin() { return regions_.begin(); } + typename std::vector::iterator end() { return regions_.end(); } + typename std::vector::const_iterator begin() const { return regions_.begin(); } + typename std::vector::const_iterator end() const { return regions_.end(); } + +private: + void set_(unsigned int index, const Region ®ion) + { + regions_[index] = region; + } + + const Region &get_(unsigned int index) const + { + return regions_[index]; + } + + libcamera::Size size_; + unsigned int numFloating_; + std::vector regions_; + Region default_; +}; + +} /* namespace RPiController */ diff --git a/src/ipa/raspberrypi/statistics.h b/src/ipa/raspberrypi/statistics.h new file mode 100644 index 000000000000..ad486534b216 --- /dev/null +++ b/src/ipa/raspberrypi/statistics.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2022, Raspberry Pi Ltd + * + * statistics.h - Raspberry Pi generic statistics structure + */ +#pragma once + +#include +#include +#include + +#include "histogram.h" +#include "region_stats.h" + +namespace RPiController { + +struct RgbySums { + RgbySums(uint64_t _rSum = 0, uint64_t _gSum = 0, uint64_t _bSum = 0, uint64_t _ySum = 0) + : rSum(_rSum), gSum(_gSum), bSum(_bSum), ySum(_ySum) + { + } + uint64_t rSum; + uint64_t gSum; + uint64_t bSum; + uint64_t ySum; +}; + +using RgbyRegions = RegionStats; +using FocusRegions = RegionStats; + +struct Statistics { + /* + * All region based statistics are normalised to 16-bits, giving a + * maximum value of (1 << NormalisationFactorPow2) - 1. + */ + static constexpr unsigned int NormalisationFactorPow2 = 16; + + /* + * Positioning of the AGC statistics gathering in the pipeline: + * Pre-WB correction or post-WB correction. + * Assume this is post-LSC. + */ + enum class AgcStatsPos { PreWb, PostWb }; + const AgcStatsPos agcStatsPos; + + /* + * Positioning of the AWB/ALSC statistics gathering in the pipeline: + * Pre-LSC or post-LSC. + */ + enum class ColourStatsPos { PreLsc, PostLsc }; + const ColourStatsPos colourStatsPos; + + Statistics(AgcStatsPos a, ColourStatsPos c) + : agcStatsPos(a), colourStatsPos(c) + { + } + + /* Histogram statistics. Not all histograms may be populated! */ + Histogram rHist; + Histogram gHist; + Histogram bHist; + Histogram yHist; + + /* Row sums for flicker avoidance. */ + std::vector rowSums; + + /* Region based colour sums. */ + RgbyRegions agcRegions; + RgbyRegions awbRegions; + + /* Region based focus FoM. */ + FocusRegions focusRegions; +}; + +} /* namespace RPiController */ From patchwork Fri Feb 3 09:17:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 18241 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 0790CC3243 for ; Fri, 3 Feb 2023 09:17:45 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9178761EF6; Fri, 3 Feb 2023 10:17:42 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1675415862; bh=0DLpjcoVBgrz4VpzM1CoahUQ97CgrbpdDHhpaKpgEIo=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=0WXWLu1ZTyJmCPsYtTrRYvLgnnxe/R8vF8xN/3S6X8Or5tFXeEY3hh5HT500m5iXr 2OWmE058R908ytEAsln2mF4j9//N0APOteWKx/QNQLoa5gdISaTzPYWzvnn7Ve8Bet U9lHM/qmOftu0vPHsLnnbMT2I8/h85jmYeyxFvu5TPL5jHj0BcPzPYhEo/IcOtgTBf y4aRhZYm0lAnTRQuLRZIS1jA2Etio1WwoSG9pKCcnakch4p5Fjsbas95WZ1FuevZDw Wt7uznn6ZNnxzuVhInvZ3IMznFbbRU7obt50a9awoB/xPKd0mFbWTU5wW4B5I42inx 4aQsNnZLBsvbA== Received: from mail-wm1-x335.google.com (mail-wm1-x335.google.com [IPv6:2a00:1450:4864:20::335]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F0DEC61EF4 for ; Fri, 3 Feb 2023 10:17:40 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="UL8sAqR9"; dkim-atps=neutral Received: by mail-wm1-x335.google.com with SMTP id j32-20020a05600c1c2000b003dc4fd6e61dso5530911wms.5 for ; Fri, 03 Feb 2023 01:17:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; 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; bh=M1N5dqqm7dMXcCpzYGXNUD+d9WKJ+Ysufg73/hJ/cJs=; b=UL8sAqR94giJaFAFKTHFHceEETvplOPHu+QgmikGblD1t5ANphXd/88HhTn711mNzK YxApBqd9mdH3QbdByDnCqazRJ0oSR9kHxyxY68BW7cukjxQ3zkR6uXQ3E0KDIIHW0+y+ nxgi56LymLReP832Oyzj3GpL5bRuTVBBtnoFTxYFxubRrrmsUXyQzSSN8Ay6fD6bzQGq DBFzPuT+pmkEmQKFNELBbF+A0i/GCMeXIKfEbSS8Pbig6yrD3AtCOGZYjCjz9V5QGJag DK7UUrfnESXNbjyk8G0aE8MwS+ygL44hW74LrcTJF7GcYZk1j22sl7v6li6GZtQ+KS3T Yufg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=M1N5dqqm7dMXcCpzYGXNUD+d9WKJ+Ysufg73/hJ/cJs=; b=6V9o6MPul3qcDvoy3fIs9t1uLI/lKKO16ttcYi8IoWY8qqqzLm6NckYFOLlCNryHcn 5ZnCxe090b5D23HFlUIKP72PNWWfjQy1p5V1lFxRauTWYWK0HcPWY3T7LuQbDnkxeotF fBkWTQMH+ZF+lKfMEjdQEdifW4QgYnK/6FiAJkWHHiiJZiasuIUMb16aQWv5dc5vHWRT +SK2xw7/mkvMsyDwP2ShE2/V5UcxrFCPBwmTwSGiQ3rzmTCcdTZ2/Zpy4CnmCepPkNku 4hCcDoOJMTbBQgTIkmB06YnR3mr43fHZF4mv/r+b1OXuJyk+sjEc7I+IUATdlVFqTld6 ddDw== X-Gm-Message-State: AO0yUKVR3WhFKqkTv3cd0h7O5aKlJgvZ7IYuk6zLppMC4aYM7l9TmABW aUkHZjgzJIliswj3uzoz6CR1ULduCOrWJLqEjqQETg== X-Google-Smtp-Source: AK7set8kMGpy2oAV7CvbK2EOUukctTpU6yUdIVLhYMm6xVr5Z4YlJZlIaQ38ro42qLf/U6PTMSZL7w== X-Received: by 2002:a05:600c:4f93:b0:3dc:59c3:9020 with SMTP id n19-20020a05600c4f9300b003dc59c39020mr9191331wmq.8.1675415860509; Fri, 03 Feb 2023 01:17:40 -0800 (PST) Received: from localhost.localdomain ([93.93.133.154]) by smtp.gmail.com with ESMTPSA id az24-20020a05600c601800b003dc4baaedd3sm7468864wmb.37.2023.02.03.01.17.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 Feb 2023 01:17:40 -0800 (PST) To: libcamera-devel@lists.libcamera.org Date: Fri, 3 Feb 2023 09:17:31 +0000 Message-Id: <20230203091734.22803-3-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230203091734.22803-1-naush@raspberrypi.com> References: <20230203091734.22803-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 2/5] ipa: raspberrypi: histogram: Add a constructor for an empty histogram 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: , X-Patchwork-Original-From: Naushir Patuck via libcamera-devel From: Naushir Patuck Reply-To: Naushir Patuck Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add a default constructor to the RPiController::Histogram class that creates an empty histogram. Since this is a cumulative histogram, push a value of 0 into the first (and only) bin to signify this. Signed-off-by: Naushir Patuck Reviewed-by: David Plowman Reviewed-by: Kieran Bingham --- src/ipa/raspberrypi/controller/histogram.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ipa/raspberrypi/controller/histogram.h b/src/ipa/raspberrypi/controller/histogram.h index 66a68b087964..6b3e3a9e68e4 100644 --- a/src/ipa/raspberrypi/controller/histogram.h +++ b/src/ipa/raspberrypi/controller/histogram.h @@ -20,6 +20,11 @@ namespace RPiController { class Histogram { public: + Histogram() + { + cumulative_.push_back(0); + } + template Histogram(T *histogram, int num) { assert(num); From patchwork Fri Feb 3 09:17:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 18242 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 BDAC7BEFBE for ; Fri, 3 Feb 2023 09:17:45 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 348BE625E8; Fri, 3 Feb 2023 10:17:45 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1675415865; bh=P6j9Xio4hdEWygeIAu/eoLHX89q5TgOrG8h3SAAUOR4=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=N7hL6TsBPFJF47je1tRnMxQ3XdPaWR2Ee9Qx/kwzMRtlSi+ZZa48a+CwC1z7ZafXF 2XWOS/InPH8aMUudkiC7eCynZDhpnLm0Hh+LZx1gqM1za2VpsIOABPXvRVb36OaEVO 5LX2Z2Grij6kW6+ZonzTc+OhY5rafA2saKyevcipoFboY+qtXz9VWnpHLoB3JJrGRU wFq8KkiM7QId904jDT7wuug+L7sUbtMk0uQBVvqjVQr/5WE3THFWAmYt7vY1Gp0X5Y /zH8WVLEh4UWtGfDUmV1oOhL/CPtwDDknf+yTtnemGAddQJBruhWSsZjdUZFBno4yb L2v9ZakaOM4Og== Received: from mail-wm1-x32a.google.com (mail-wm1-x32a.google.com [IPv6:2a00:1450:4864:20::32a]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 87CC6625EB for ; Fri, 3 Feb 2023 10:17:41 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="NH4CUexy"; dkim-atps=neutral Received: by mail-wm1-x32a.google.com with SMTP id m5-20020a05600c4f4500b003db03b2559eso3327973wmq.5 for ; Fri, 03 Feb 2023 01:17:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; 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; bh=G/JQb0uBfrwIRQcYwTAsXOw+rV9FlpM8/tfxdtjycqg=; b=NH4CUexyNLwTVYcM5RtjFvaLs88lfFt4Y08W73mZ4tVj1AyPQ3IkEhJ9RX/Rkoc4+U SN6II599cc85CzBZnLEhl6RL/xyVX9nhSP7FtHb7EdPpZDktklYtAjhqnuagDo1h5LD8 0J6jc8EyFGs9R//eFlg5y621/mmLAr/yyv9ritJGb/4jBfTi5XcPFHcC15WEgbLfrHNH NzEKROo+riTNPaQnsrV/QFE3uX4zorU24SvFisilNUUhckPttaK9nkklwxfDC3FJ0Cz4 Z9OTOoMTf5B/vyKzWxSwpAq8ARK6ADS7uiNIx1OyHaHd11iBk8i8jBZTlES07FJxjGvp p0/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=G/JQb0uBfrwIRQcYwTAsXOw+rV9FlpM8/tfxdtjycqg=; b=2oy6qiBvi3cjMHGqtfFzvD9KorOaxkppc7OSbizD/etwAkaTvLrnKWBC31WRePDqUa +MP3C7/d77wtCg3GiW/c06iAYxXYKUgHa3h0id6Gmb2YECx0HXCtyHc4VYUFAzrLtFSj 3g2DAwHRv8mjlu46bxIqLvoWG0ALWaU7Td8qvLUHCVd6uuERwBnXzYI/jg9qZwXRs7aI Gim3ln/IX76bvifNVdE7JB2vUeBc0pGzkcSaCXT60twoNw3IGQC833G+JKywkTdhuzZb eWtvalXPPds4lW1t+IObQWY0u44uG/AZASI0rJqwGaXvnkf35uUpm71Blbg1Igkp4Typ hJzw== X-Gm-Message-State: AO0yUKWLFpXymXfMs5FOv/iRpAJbM8RBeHXH2hW0S+LBfbHlMeSBhPN4 NY11EoPRLTig1IZ4jF81IEd7L0Z9jkq9QDkpcxV67w== X-Google-Smtp-Source: AK7set8edxXxc4tDtIOwvrFXaL/Bh3fdsLuNfji19diTGJXpSPUl8Mr12iIKMhEGYmPpsVvrCGJMDA== X-Received: by 2002:a05:600c:2b46:b0:3dc:4aa6:a8a9 with SMTP id e6-20020a05600c2b4600b003dc4aa6a8a9mr8517781wmf.7.1675415861068; Fri, 03 Feb 2023 01:17:41 -0800 (PST) Received: from localhost.localdomain ([93.93.133.154]) by smtp.gmail.com with ESMTPSA id az24-20020a05600c601800b003dc4baaedd3sm7468864wmb.37.2023.02.03.01.17.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 Feb 2023 01:17:40 -0800 (PST) To: libcamera-devel@lists.libcamera.org Date: Fri, 3 Feb 2023 09:17:32 +0000 Message-Id: <20230203091734.22803-4-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230203091734.22803-1-naush@raspberrypi.com> References: <20230203091734.22803-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 3/5] ipa: raspberrypi: awb: Delay release of the statistics buffer 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: , X-Patchwork-Original-From: Naushir Patuck via libcamera-devel From: Naushir Patuck Reply-To: Naushir Patuck Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Release the statistics buffer after running the through the AWB calculations. Only the "counted" statistics are copied out to a local structure, so keeping the statistics buffer allows the algorithm to see the "uncounted" statistics as well. This is currently handled by hard-coding the total number of statistics regions regions based on the structure definition in the bcm2835_isp_stats structure. Signed-off-by: Naushir Patuck Reviewed-by: David Plowman Reviewed-by: Kieran Bingham --- src/ipa/raspberrypi/controller/rpi/awb.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ipa/raspberrypi/controller/rpi/awb.cpp b/src/ipa/raspberrypi/controller/rpi/awb.cpp index 4f6af4ba98dc..04d1c8783654 100644 --- a/src/ipa/raspberrypi/controller/rpi/awb.cpp +++ b/src/ipa/raspberrypi/controller/rpi/awb.cpp @@ -427,11 +427,6 @@ void Awb::prepareStats() */ generateStats(zones_, statistics_->awb_stats, config_.minPixels, config_.minG); - /* - * we're done with these; we may as well relinquish our hold on the - * pointer. - */ - statistics_.reset(); /* * apply sensitivities, so values appear to come from our "canonical" * sensor. @@ -728,6 +723,11 @@ void Awb::doAwb() << " with gains r " << asyncResults_.gainR << " and b " << asyncResults_.gainB; } + /* + * we're done with these; we may as well relinquish our hold on the + * pointer. + */ + statistics_.reset(); } /* Register algorithm with the system. */ From patchwork Fri Feb 3 09:17:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 18243 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 62D92C329C for ; Fri, 3 Feb 2023 09:17:46 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id AACCB625E6; Fri, 3 Feb 2023 10:17:45 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1675415865; bh=3fF12qfXaAoV4729g7w1NrymLzTumDyDGI/x10LBEf4=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=tMlMEsVEjjP2NFXDZvn/0DCeXzAAu9jadD3dz2N2jb/PlilTZ/xp3/olpJxyRNwZu b9ICpmAUWPriGERv4TL7bRjQQIiTMKm9zdw3s0lVkc84yWBtlmGZkY25gW3USFEg3C S2Wb6vbzyldCJaiOoZByVoDCRPp+sWHYMGoiiVrH5aCy8fXJJqY632kXZ3bV5lqu93 s5vPuXIk/jMkNIrw8QztLY86nhIYknKuOYUi9Ep1QSmJNP5CEV0I9l2HXJC+rEygSP M/jBQUm6pXec03NrvHcG3yhmq6qXFrPmu9oSeB4ySSlT62iyBt08BmWCnW2yCpnlq2 TuvhYPQqZrRWA== 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 D0F74625E6 for ; Fri, 3 Feb 2023 10:17:42 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="o+Iq8RAL"; dkim-atps=neutral Received: by mail-wm1-x32e.google.com with SMTP id l37-20020a05600c1d2500b003dfe46a9801so1863765wms.0 for ; Fri, 03 Feb 2023 01:17:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; 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; bh=hcSRKZKVn+WWn/o3x44hx5plyPapJYKIGnhoSAAJTr0=; b=o+Iq8RALG6uzXGYRNkE+mXuge/QvuD9+gg+mPDeOAW7W1lOFmiU1EPC/yB2v0qyh3r mmtegU62g4pCSvO5znBj32F0CJyBulJbTTDPp7Nz/ZTGlTzeUlAichzXa+tpo/KWuQSP kY3EzSqq1v49jTTY/u1otgwKkiq0wKcVtt1BcmPjPVWsmvQIkhvXThX8SJEnQ16d5puH uo/4NTAPlKCX4H76jLWPUL6e+cJOjg351yLnHGN/GfMyaNfZXXQlSuZuCN2qj/uDJ01t kfVSnosohrEGu9foIQwYgM2iQbUxZf+vFcveos6vMd6pbnNeQ0VC3FxHAGLMWFyofuAU crEw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=hcSRKZKVn+WWn/o3x44hx5plyPapJYKIGnhoSAAJTr0=; b=v8zpqPLQFkIsmt03j2c+2M4Fb6oMi88XBeALTWUCHPIpdlbf/9qxXlowTpvknors2x ayAILMklwm2yIgnhCl+sVFmeVzpnY1R2WFIBrLyQxYqpDqe0kTLQY7EDZtTIqCIeh4gf 2H23xK+OONU+hcwdxHCvDi2xOBnIIceGx3y7RKcA5d6Y05vOfVoo5hvTLQ4ReLsYl/Tn rBh1Q+rvY8ktIF6wfgVjlzGCwhI+ltpn8llHtYgE2WPIVyS0trL/AxO0duSHKint2AIA PgS6Reg2ZuFtMG0QGqA6DQ5LgNW+LKMLJcdJRAAvpLFCy+Xs4JY8Ptc0Jm7g2qPFz/d8 eIhg== X-Gm-Message-State: AO0yUKV0qmVJ3gtwWEq5KqBCPYVtp2x1Gt1QnUAV5Wwdn20aV+ORnHKl 7nv1HM5QoN1DzIbfAqqHtIuD4OB+TeU5K3b3KceBdA== X-Google-Smtp-Source: AK7set/0ENuL23ylyxQsDlBKRx5ffS1YLiHG3k8HsgHHfogw0jZU82jXZBYrjVfrq5I7wMjLucaXIA== X-Received: by 2002:a05:600c:4f50:b0:3df:94c3:4725 with SMTP id m16-20020a05600c4f5000b003df94c34725mr6486266wmq.38.1675415861715; Fri, 03 Feb 2023 01:17:41 -0800 (PST) Received: from localhost.localdomain ([93.93.133.154]) by smtp.gmail.com with ESMTPSA id az24-20020a05600c601800b003dc4baaedd3sm7468864wmb.37.2023.02.03.01.17.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 Feb 2023 01:17:41 -0800 (PST) To: libcamera-devel@lists.libcamera.org Date: Fri, 3 Feb 2023 09:17:33 +0000 Message-Id: <20230203091734.22803-5-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230203091734.22803-1-naush@raspberrypi.com> References: <20230203091734.22803-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 4/5] ipa: raspberrypi: Use the generic statistics structure in the algorithms 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: , X-Patchwork-Original-From: Naushir Patuck via libcamera-devel From: Naushir Patuck Reply-To: Naushir Patuck Cc: Nick Hollinghurst Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Repurpose the StatisticsPtr type from being a shared_ptr to shared_ptr. This removes any hardware specific header files and structures from the algorithms source code. Add a new function in the Raspberry Pi IPA to populate the generic statistics structure from the values provided by the hardware in the bcm2835_isp_stats structure. Update the Lux, AWB, AGC, ALSC, Contrast, and Focus algorithms to use the generic statistics structure appropriately in their calculations. Additionally, remove references to any hardware specific headers and defines in these source files. Signed-off-by: Naushir Patuck Reviewed-by: David Plowman Tested-by: Nick Hollinghurst --- src/ipa/raspberrypi/cam_helper_imx708.cpp | 26 ++++++----- src/ipa/raspberrypi/controller/controller.h | 4 +- src/ipa/raspberrypi/controller/rpi/af.cpp | 10 ++--- src/ipa/raspberrypi/controller/rpi/af.h | 8 +++- src/ipa/raspberrypi/controller/rpi/agc.cpp | 27 +++++------- src/ipa/raspberrypi/controller/rpi/agc.h | 2 +- src/ipa/raspberrypi/controller/rpi/alsc.cpp | 32 +++++++------- src/ipa/raspberrypi/controller/rpi/alsc.h | 3 +- src/ipa/raspberrypi/controller/rpi/awb.cpp | 20 ++++----- src/ipa/raspberrypi/controller/rpi/awb.h | 1 + .../raspberrypi/controller/rpi/contrast.cpp | 8 ++-- src/ipa/raspberrypi/controller/rpi/focus.cpp | 7 ++- src/ipa/raspberrypi/controller/rpi/lux.cpp | 14 +----- src/ipa/raspberrypi/raspberrypi.cpp | 44 ++++++++++++++++++- src/ipa/raspberrypi/statistics.h | 2 + 15 files changed, 121 insertions(+), 87 deletions(-) diff --git a/src/ipa/raspberrypi/cam_helper_imx708.cpp b/src/ipa/raspberrypi/cam_helper_imx708.cpp index 4c43c8e7fb7d..f825a7f178e3 100644 --- a/src/ipa/raspberrypi/cam_helper_imx708.cpp +++ b/src/ipa/raspberrypi/cam_helper_imx708.cpp @@ -78,14 +78,14 @@ private: bool parseAEHist(const uint8_t *ptr, size_t len, unsigned bpp); void putAGCStatistics(StatisticsPtr stats); - uint32_t aeHistLinear_[128]; + Histogram aeHistLinear_; uint32_t aeHistAverage_; bool aeHistValid_; }; CamHelperImx708::CamHelperImx708() : CamHelper(std::make_unique(registerList), frameIntegrationDiff), - aeHistLinear_{ 0 }, aeHistAverage_(0), aeHistValid_(false) + aeHistLinear_{}, aeHistAverage_(0), aeHistValid_(false) { } @@ -264,9 +264,11 @@ bool CamHelperImx708::parsePdafData(const uint8_t *ptr, size_t len, bool CamHelperImx708::parseAEHist(const uint8_t *ptr, size_t len, unsigned bpp) { - static const uint32_t ISP_PIPELINE_BITS = 13; + static constexpr unsigned int PipelineBits = Statistics::NormalisationFactorPow2; + uint64_t count = 0, sum = 0; size_t step = bpp >> 1; /* bytes per histogram bin */ + uint32_t hist[128]; if (len < 144 * step) return false; @@ -280,12 +282,12 @@ bool CamHelperImx708::parseAEHist(const uint8_t *ptr, size_t len, unsigned bpp) if (ptr[3] != 0x55) return false; uint32_t c = (ptr[0] << 14) + (ptr[1] << 6) + (ptr[2] >> 2); - aeHistLinear_[i] = c >> 2; /* pixels to quads */ + hist[i] = c >> 2; /* pixels to quads */ if (i != 0) { count += c; sum += c * - (i * (1u << (ISP_PIPELINE_BITS - 7)) + - (1u << (ISP_PIPELINE_BITS - 8))); + (i * (1u << (PipelineBits - 7)) + + (1u << (PipelineBits - 8))); } ptr += step; } @@ -301,15 +303,16 @@ bool CamHelperImx708::parseAEHist(const uint8_t *ptr, size_t len, unsigned bpp) uint32_t c = (ptr[0] << 14) + (ptr[1] << 6) + (ptr[2] >> 2); count += c; sum += c * - ((3u << ISP_PIPELINE_BITS) >> (17 - i)); + ((3u << PipelineBits) >> (17 - i)); ptr += step; } if ((unsigned)((ptr[0] << 12) + (ptr[1] << 4) + (ptr[2] >> 4)) != - aeHistLinear_[1]) { + hist[1]) { LOG(IPARPI, Error) << "Lin/Log histogram mismatch"; return false; } + aeHistLinear_ = std::move(Histogram(hist, 128)); aeHistAverage_ = count ? (sum / count) : 0; return count != 0; @@ -329,13 +332,12 @@ void CamHelperImx708::putAGCStatistics(StatisticsPtr stats) * scaled by a fiddle-factor so that a conventional (non-HDR) y_target * of e.g. 0.17 will map to a suitable level for HDR. */ - memcpy(stats->hist[0].g_hist, aeHistLinear_, sizeof(stats->hist[0].g_hist)); + stats->yHist = aeHistLinear_; constexpr unsigned int HdrHeadroomFactor = 4; uint64_t v = HdrHeadroomFactor * aeHistAverage_; - for (int i = 0; i < AGC_REGIONS; i++) { - struct bcm2835_isp_stats_region &r = stats->agc_stats[i]; - r.r_sum = r.b_sum = r.g_sum = r.counted * v; + for (auto ®ion : stats->agcRegions) { + region.val.rSum = region.val.gSum = region.val.bSum = region.counted * v; } } diff --git a/src/ipa/raspberrypi/controller/controller.h b/src/ipa/raspberrypi/controller/controller.h index 3e1e051703b3..e6c950c3a509 100644 --- a/src/ipa/raspberrypi/controller/controller.h +++ b/src/ipa/raspberrypi/controller/controller.h @@ -15,19 +15,17 @@ #include #include -#include - #include "libcamera/internal/yaml_parser.h" #include "camera_mode.h" #include "device_status.h" #include "metadata.h" +#include "statistics.h" namespace RPiController { class Algorithm; typedef std::unique_ptr AlgorithmPtr; -typedef std::shared_ptr StatisticsPtr; /* * The Controller holds a pointer to some global_metadata, which is how diff --git a/src/ipa/raspberrypi/controller/rpi/af.cpp b/src/ipa/raspberrypi/controller/rpi/af.cpp index 2e72f239fb25..a623651875f2 100644 --- a/src/ipa/raspberrypi/controller/rpi/af.cpp +++ b/src/ipa/raspberrypi/controller/rpi/af.cpp @@ -352,14 +352,12 @@ bool Af::getPhase(PdafData const &data, double &phase, double &conf) const } } -double Af::getContrast(struct bcm2835_isp_stats_focus const focus_stats[FOCUS_REGIONS]) const +double Af::getContrast(const FocusRegions &focusStats) const { uint32_t sumWc = 0; - for (unsigned i = 0; i < FOCUS_REGIONS; ++i) { - unsigned w = contrastWeights_[i]; - sumWc += w * (focus_stats[i].contrast_val[1][1] >> 10); - } + for (unsigned i = 0; i < focusStats.numRegions(); ++i) + sumWc += contrastWeights_[i] * focusStats.get(i).val; return (sumWeights_ == 0) ? 0.0 : (double)sumWc / (double)sumWeights_; } @@ -666,7 +664,7 @@ void Af::prepare(Metadata *imageMetadata) void Af::process(StatisticsPtr &stats, [[maybe_unused]] Metadata *imageMetadata) { (void)imageMetadata; - prevContrast_ = getContrast(stats->focus_stats); + prevContrast_ = getContrast(stats->focusRegions); } /* Controls */ diff --git a/src/ipa/raspberrypi/controller/rpi/af.h b/src/ipa/raspberrypi/controller/rpi/af.h index f7baf8979873..7959371baf64 100644 --- a/src/ipa/raspberrypi/controller/rpi/af.h +++ b/src/ipa/raspberrypi/controller/rpi/af.h @@ -11,6 +11,12 @@ #include "../pdaf_data.h" #include "../pwl.h" +/* + * \todo FOCUS_REGIONS is taken from bcm2835-isp.h, but should be made as a + * generic RegionStats structure. + */ +#define FOCUS_REGIONS 12 + /* * This algorithm implements a hybrid of CDAF and PDAF, favouring PDAF. * @@ -117,7 +123,7 @@ private: void computeWeights(); bool getPhase(PdafData const &data, double &phase, double &conf) const; - double getContrast(struct bcm2835_isp_stats_focus const focus_stats[FOCUS_REGIONS]) const; + double getContrast(const FocusRegions &focusStats) const; void doPDAF(double phase, double conf); bool earlyTerminationByPhase(double phase); double findPeak(unsigned index) const; diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp b/src/ipa/raspberrypi/controller/rpi/agc.cpp index 46dcc81ae14c..868c30f03d66 100644 --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp @@ -9,8 +9,6 @@ #include #include -#include - #include #include "../awb_status.h" @@ -451,7 +449,7 @@ void Agc::process(StatisticsPtr &stats, Metadata *imageMetadata) fetchCurrentExposure(imageMetadata); /* Compute the total gain we require relative to the current exposure. */ double gain, targetY; - computeGain(stats.get(), imageMetadata, gain, targetY); + computeGain(stats, imageMetadata, gain, targetY); /* Now compute the target (final) exposure which we think we want. */ computeTargetExposure(gain); /* @@ -585,24 +583,23 @@ void Agc::fetchAwbStatus(Metadata *imageMetadata) LOG(RPiAgc, Debug) << "No AWB status found"; } -static double computeInitialY(bcm2835_isp_stats *stats, AwbStatus const &awb, +static double computeInitialY(StatisticsPtr &stats, AwbStatus const &awb, double weights[], double gain) { - bcm2835_isp_stats_region *regions = stats->agc_stats; /* * Note how the calculation below means that equal weights give you * "average" metering (i.e. all pixels equally important). */ double rSum = 0, gSum = 0, bSum = 0, pixelSum = 0; - for (unsigned int i = 0; i < AgcStatsSize; i++) { - double counted = regions[i].counted; - double rAcc = std::min(regions[i].r_sum * gain, ((1 << PipelineBits) - 1) * counted); - double gAcc = std::min(regions[i].g_sum * gain, ((1 << PipelineBits) - 1) * counted); - double bAcc = std::min(regions[i].b_sum * gain, ((1 << PipelineBits) - 1) * counted); + for (unsigned int i = 0; i < stats->agcRegions.numRegions(); i++) { + auto ®ion = stats->agcRegions.get(i); + double rAcc = std::min(region.val.rSum * gain, ((1 << PipelineBits) - 1) * region.counted); + double gAcc = std::min(region.val.gSum * gain, ((1 << PipelineBits) - 1) * region.counted); + double bAcc = std::min(region.val.bSum * gain, ((1 << PipelineBits) - 1) * region.counted); rSum += rAcc * weights[i]; gSum += gAcc * weights[i]; bSum += bAcc * weights[i]; - pixelSum += counted * weights[i]; + pixelSum += region.counted * weights[i]; } if (pixelSum == 0.0) { LOG(RPiAgc, Warning) << "computeInitialY: pixelSum is zero"; @@ -624,23 +621,23 @@ static double computeInitialY(bcm2835_isp_stats *stats, AwbStatus const &awb, static constexpr double EvGainYTargetLimit = 0.9; -static double constraintComputeGain(AgcConstraint &c, Histogram &h, double lux, +static double constraintComputeGain(AgcConstraint &c, const Histogram &h, double lux, double evGain, double &targetY) { targetY = c.yTarget.eval(c.yTarget.domain().clip(lux)); targetY = std::min(EvGainYTargetLimit, targetY * evGain); double iqm = h.interQuantileMean(c.qLo, c.qHi); - return (targetY * NUM_HISTOGRAM_BINS) / iqm; + return (targetY * h.bins()) / iqm; } -void Agc::computeGain(bcm2835_isp_stats *statistics, Metadata *imageMetadata, +void Agc::computeGain(StatisticsPtr &statistics, Metadata *imageMetadata, double &gain, double &targetY) { struct LuxStatus lux = {}; lux.lux = 400; /* default lux level to 400 in case no metadata found */ if (imageMetadata->get("lux.status", lux) != 0) LOG(RPiAgc, Warning) << "No lux level found"; - Histogram h(statistics->hist[0].g_hist, NUM_HISTOGRAM_BINS); + const Histogram &h = statistics->yHist; double evGain = status_.ev * config_.baseEv; /* * The initial gain and target_Y come from some of the regions. After diff --git a/src/ipa/raspberrypi/controller/rpi/agc.h b/src/ipa/raspberrypi/controller/rpi/agc.h index cf04da1973f1..f04896ca25ad 100644 --- a/src/ipa/raspberrypi/controller/rpi/agc.h +++ b/src/ipa/raspberrypi/controller/rpi/agc.h @@ -96,7 +96,7 @@ private: void housekeepConfig(); void fetchCurrentExposure(Metadata *imageMetadata); void fetchAwbStatus(Metadata *imageMetadata); - void computeGain(bcm2835_isp_stats *statistics, Metadata *imageMetadata, + void computeGain(StatisticsPtr &statistics, Metadata *imageMetadata, double &gain, double &targetY); void computeTargetExposure(double gain); bool applyDigitalGain(double gain, double targetY); diff --git a/src/ipa/raspberrypi/controller/rpi/alsc.cpp b/src/ipa/raspberrypi/controller/rpi/alsc.cpp index a4afaf841c41..eb4e2f9496e1 100644 --- a/src/ipa/raspberrypi/controller/rpi/alsc.cpp +++ b/src/ipa/raspberrypi/controller/rpi/alsc.cpp @@ -310,19 +310,21 @@ double getCt(Metadata *metadata, double defaultCt) return awbStatus.temperatureK; } -static void copyStats(bcm2835_isp_stats_region regions[XY], StatisticsPtr &stats, +static void copyStats(RgbyRegions ®ions, StatisticsPtr &stats, AlscStatus const &status) { - bcm2835_isp_stats_region *inputRegions = stats->awb_stats; + if (!regions.numRegions()) + regions.init(stats->awbRegions.size()); + double *rTable = (double *)status.r; double *gTable = (double *)status.g; double *bTable = (double *)status.b; - for (int i = 0; i < XY; i++) { - regions[i].r_sum = inputRegions[i].r_sum / rTable[i]; - regions[i].g_sum = inputRegions[i].g_sum / gTable[i]; - regions[i].b_sum = inputRegions[i].b_sum / bTable[i]; - regions[i].counted = inputRegions[i].counted; - /* (don't care about the uncounted value) */ + for (unsigned int i = 0; i < stats->awbRegions.numRegions(); i++) { + auto r = stats->awbRegions.get(i); + r.val.rSum = static_cast(r.val.rSum / rTable[i]); + r.val.gSum = static_cast(r.val.gSum / gTable[i]); + r.val.bSum = static_cast(r.val.bSum / bTable[i]); + regions.set(i, r); } } @@ -512,19 +514,19 @@ void resampleCalTable(double const calTableIn[XY], } /* Calculate chrominance statistics (R/G and B/G) for each region. */ -static_assert(XY == AWB_REGIONS, "ALSC/AWB statistics region mismatch"); -static void calculateCrCb(bcm2835_isp_stats_region *awbRegion, double cr[XY], +static void calculateCrCb(const RgbyRegions &awbRegion, double cr[XY], double cb[XY], uint32_t minCount, uint16_t minG) { for (int i = 0; i < XY; i++) { - bcm2835_isp_stats_region &zone = awbRegion[i]; - if (zone.counted <= minCount || - zone.g_sum / zone.counted <= minG) { + auto s = awbRegion.get(i); + + if (s.counted <= minCount || s.val.gSum / s.counted <= minG) { cr[i] = cb[i] = InsufficientData; continue; } - cr[i] = zone.r_sum / (double)zone.g_sum; - cb[i] = zone.b_sum / (double)zone.g_sum; + + cr[i] = s.val.rSum / (double)s.val.gSum; + cb[i] = s.val.bSum / (double)s.val.gSum; } } diff --git a/src/ipa/raspberrypi/controller/rpi/alsc.h b/src/ipa/raspberrypi/controller/rpi/alsc.h index a858ef5a6551..9167c9ffa2e3 100644 --- a/src/ipa/raspberrypi/controller/rpi/alsc.h +++ b/src/ipa/raspberrypi/controller/rpi/alsc.h @@ -12,6 +12,7 @@ #include "../algorithm.h" #include "../alsc_status.h" +#include "../statistics.h" namespace RPiController { @@ -98,7 +99,7 @@ private: /* copy out the results from the async thread so that it can be restarted */ void fetchAsyncResults(); double ct_; - bcm2835_isp_stats_region statistics_[AlscCellsY * AlscCellsX]; + RgbyRegions statistics_; double asyncResults_[3][AlscCellsY][AlscCellsX]; double asyncLambdaR_[AlscCellsX * AlscCellsY]; double asyncLambdaB_[AlscCellsX * AlscCellsY]; diff --git a/src/ipa/raspberrypi/controller/rpi/awb.cpp b/src/ipa/raspberrypi/controller/rpi/awb.cpp index 04d1c8783654..ef3435d66106 100644 --- a/src/ipa/raspberrypi/controller/rpi/awb.cpp +++ b/src/ipa/raspberrypi/controller/rpi/awb.cpp @@ -21,9 +21,6 @@ LOG_DEFINE_CATEGORY(RPiAwb) #define NAME "rpi.awb" -static constexpr unsigned int AwbStatsSizeX = DEFAULT_AWB_REGIONS_X; -static constexpr unsigned int AwbStatsSizeY = DEFAULT_AWB_REGIONS_Y; - /* * todo - the locking in this algorithm needs some tidying up as has been done * elsewhere (ALSC and AGC). @@ -401,17 +398,16 @@ void Awb::asyncFunc() } static void generateStats(std::vector &zones, - bcm2835_isp_stats_region *stats, double minPixels, + RgbyRegions &stats, double minPixels, double minG) { - for (unsigned int i = 0; i < AwbStatsSizeX * AwbStatsSizeY; i++) { + for (auto const ®ion : stats) { Awb::RGB zone; - double counted = stats[i].counted; - if (counted >= minPixels) { - zone.G = stats[i].g_sum / counted; + if (region.counted >= minPixels) { + zone.G = region.val.gSum / region.counted; if (zone.G >= minG) { - zone.R = stats[i].r_sum / counted; - zone.B = stats[i].b_sum / counted; + zone.R = region.val.rSum / region.counted; + zone.B = region.val.bSum / region.counted; zones.push_back(zone); } } @@ -425,7 +421,7 @@ void Awb::prepareStats() * LSC has already been applied to the stats in this pipeline, so stop * any LSC compensation. We also ignore config_.fast in this version. */ - generateStats(zones_, statistics_->awb_stats, config_.minPixels, + generateStats(zones_, statistics_->awbRegions, config_.minPixels, config_.minG); /* * apply sensitivities, so values appear to come from our "canonical" @@ -641,7 +637,7 @@ void Awb::awbBayes() * valid... not entirely sure about this. */ Pwl prior = interpolatePrior(); - prior *= zones_.size() / (double)(AwbStatsSizeX * AwbStatsSizeY); + prior *= zones_.size() / (double)(statistics_->awbRegions.numRegions()); prior.map([](double x, double y) { LOG(RPiAwb, Debug) << "(" << x << "," << y << ")"; }); diff --git a/src/ipa/raspberrypi/controller/rpi/awb.h b/src/ipa/raspberrypi/controller/rpi/awb.h index 2254c3ed2cc4..e7d49cd8036b 100644 --- a/src/ipa/raspberrypi/controller/rpi/awb.h +++ b/src/ipa/raspberrypi/controller/rpi/awb.h @@ -13,6 +13,7 @@ #include "../awb_algorithm.h" #include "../pwl.h" #include "../awb_status.h" +#include "../statistics.h" namespace RPiController { diff --git a/src/ipa/raspberrypi/controller/rpi/contrast.cpp b/src/ipa/raspberrypi/controller/rpi/contrast.cpp index 5b37edcbd46a..a4f8c4f04fc4 100644 --- a/src/ipa/raspberrypi/controller/rpi/contrast.cpp +++ b/src/ipa/raspberrypi/controller/rpi/contrast.cpp @@ -106,7 +106,7 @@ Pwl computeStretchCurve(Histogram const &histogram, * bit. */ double histLo = histogram.quantile(config.loHistogram) * - (65536 / NUM_HISTOGRAM_BINS); + (65536 / histogram.bins()); double levelLo = config.loLevel * 65536; LOG(RPiContrast, Debug) << "Move histogram point " << histLo << " to " << levelLo; @@ -119,7 +119,7 @@ Pwl computeStretchCurve(Histogram const &histogram, * Keep the mid-point (median) in the same place, though, to limit the * apparent amount of global brightness shift. */ - double mid = histogram.quantile(0.5) * (65536 / NUM_HISTOGRAM_BINS); + double mid = histogram.quantile(0.5) * (65536 / histogram.bins()); enhance.append(mid, mid); /* @@ -127,7 +127,7 @@ Pwl computeStretchCurve(Histogram const &histogram, * there up. */ double histHi = histogram.quantile(config.hiHistogram) * - (65536 / NUM_HISTOGRAM_BINS); + (65536 / histogram.bins()); double levelHi = config.hiLevel * 65536; LOG(RPiContrast, Debug) << "Move histogram point " << histHi << " to " << levelHi; @@ -158,7 +158,7 @@ Pwl applyManualContrast(Pwl const &gammaCurve, double brightness, void Contrast::process(StatisticsPtr &stats, [[maybe_unused]] Metadata *imageMetadata) { - Histogram histogram(stats->hist[0].g_hist, NUM_HISTOGRAM_BINS); + Histogram &histogram = stats->yHist; /* * We look at the histogram and adjust the gamma curve in the following * ways: 1. Adjust the gamma curve so as to pull the start of the diff --git a/src/ipa/raspberrypi/controller/rpi/focus.cpp b/src/ipa/raspberrypi/controller/rpi/focus.cpp index 8c5029bd0e95..ea3cc00e42c3 100644 --- a/src/ipa/raspberrypi/controller/rpi/focus.cpp +++ b/src/ipa/raspberrypi/controller/rpi/focus.cpp @@ -31,10 +31,9 @@ char const *Focus::name() const void Focus::process(StatisticsPtr &stats, Metadata *imageMetadata) { FocusStatus status; - unsigned int i; - for (i = 0; i < FOCUS_REGIONS; i++) - status.focusMeasures[i] = stats->focus_stats[i].contrast_val[1][1] / 1000; - status.num = i; + for (unsigned int i = 0; i < stats->focusRegions.numRegions(); i++) + status.focusMeasures[i] = stats->focusRegions.get(i).val; + status.num = stats->focusRegions.numRegions(); imageMetadata->set("focus.status", status); LOG(RPiFocus, Debug) diff --git a/src/ipa/raspberrypi/controller/rpi/lux.cpp b/src/ipa/raspberrypi/controller/rpi/lux.cpp index 9759186afacf..06625f3a5ea3 100644 --- a/src/ipa/raspberrypi/controller/rpi/lux.cpp +++ b/src/ipa/raspberrypi/controller/rpi/lux.cpp @@ -6,8 +6,6 @@ */ #include -#include - #include #include "../device_status.h" @@ -83,20 +81,12 @@ void Lux::process(StatisticsPtr &stats, Metadata *imageMetadata) if (imageMetadata->get("device.status", deviceStatus) == 0) { double currentGain = deviceStatus.analogueGain; double currentAperture = deviceStatus.aperture.value_or(currentAperture_); - uint64_t sum = 0; - uint32_t num = 0; - uint32_t *bin = stats->hist[0].g_hist; - const int numBins = sizeof(stats->hist[0].g_hist) / - sizeof(stats->hist[0].g_hist[0]); - for (int i = 0; i < numBins; i++) - sum += bin[i] * (uint64_t)i, num += bin[i]; - /* add .5 to reflect the mid-points of bins */ - double currentY = sum / (double)num + .5; + double currentY = stats->yHist.interQuantileMean(0, 1); double gainRatio = referenceGain_ / currentGain; double shutterSpeedRatio = referenceShutterSpeed_ / deviceStatus.shutterSpeed; double apertureRatio = referenceAperture_ / currentAperture; - double yRatio = currentY * (65536 / numBins) / referenceY_; + double yRatio = currentY * (65536 / stats->yHist.bins()) / referenceY_; double estimatedLux = shutterSpeedRatio * gainRatio * apertureRatio * apertureRatio * yRatio * referenceLux_; diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp index 5f7397e2ab21..b8cce51522c0 100644 --- a/src/ipa/raspberrypi/raspberrypi.cpp +++ b/src/ipa/raspberrypi/raspberrypi.cpp @@ -54,6 +54,7 @@ #include "metadata.h" #include "sharpen_algorithm.h" #include "sharpen_status.h" +#include "statistics.h" namespace libcamera { @@ -152,6 +153,7 @@ private: void prepareISP(const ISPConfig &data); void reportMetadata(unsigned int ipaContext); void fillDeviceStatus(const ControlList &sensorControls, unsigned int ipaContext); + RPiController::StatisticsPtr fillStatistics(bcm2835_isp_stats *stats) const; void processStats(unsigned int bufferId, unsigned int ipaContext); void applyFrameDurations(Duration minFrameDuration, Duration maxFrameDuration); void applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls); @@ -1364,6 +1366,46 @@ void IPARPi::fillDeviceStatus(const ControlList &sensorControls, unsigned int ip rpiMetadata_[ipaContext].set("device.status", deviceStatus); } +RPiController::StatisticsPtr IPARPi::fillStatistics(bcm2835_isp_stats *stats) const +{ + using namespace RPiController; + + unsigned int i; + StatisticsPtr statistics = + std::make_unique(Statistics::AgcStatsPos::PreWb, Statistics::ColourStatsPos::PostLsc); + + /* RGB histograms are not used, so do not populate them. */ + statistics->yHist = std::move(RPiController::Histogram(stats->hist[0].g_hist, NUM_HISTOGRAM_BINS)); + + statistics->awbRegions.init({ DEFAULT_AWB_REGIONS_X, DEFAULT_AWB_REGIONS_Y }); + for (i = 0; i < statistics->awbRegions.numRegions(); i++) + statistics->awbRegions.set(i, { { stats->awb_stats[i].r_sum, + stats->awb_stats[i].g_sum, + stats->awb_stats[i].b_sum }, + stats->awb_stats[i].counted, + stats->awb_stats[i].notcounted }); + + /* + * There are only ever 15 regions computed by the firmware due to zoning, + * but the HW defines AGC_REGIONS == 16! + */ + statistics->agcRegions.init(15); + for (i = 0; i < statistics->agcRegions.numRegions(); i++) + statistics->agcRegions.set(i, { { stats->agc_stats[i].r_sum, + stats->agc_stats[i].g_sum, + stats->agc_stats[i].b_sum }, + stats->agc_stats[i].counted, + stats->awb_stats[i].notcounted }); + + statistics->focusRegions.init({ 4, 3 }); + for (i = 0; i < statistics->focusRegions.numRegions(); i++) + statistics->focusRegions.set(i, { stats->focus_stats[i].contrast_val[1][1] / 1000, + stats->focus_stats[i].contrast_val_num[1][1], + stats->focus_stats[i].contrast_val_num[1][0] }); + + return statistics; +} + void IPARPi::processStats(unsigned int bufferId, unsigned int ipaContext) { RPiController::Metadata &rpiMetadata = rpiMetadata_[ipaContext]; @@ -1376,7 +1418,7 @@ void IPARPi::processStats(unsigned int bufferId, unsigned int ipaContext) Span mem = it->second.planes()[0]; bcm2835_isp_stats *stats = reinterpret_cast(mem.data()); - RPiController::StatisticsPtr statistics = std::make_shared(*stats); + RPiController::StatisticsPtr statistics = fillStatistics(stats); helper_->process(statistics, rpiMetadata); controller_.process(statistics, &rpiMetadata); diff --git a/src/ipa/raspberrypi/statistics.h b/src/ipa/raspberrypi/statistics.h index ad486534b216..015d4efc6454 100644 --- a/src/ipa/raspberrypi/statistics.h +++ b/src/ipa/raspberrypi/statistics.h @@ -73,4 +73,6 @@ struct Statistics { FocusRegions focusRegions; }; +using StatisticsPtr = std::shared_ptr; + } /* namespace RPiController */ From patchwork Fri Feb 3 09:17:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 18244 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 D21AFC329D for ; Fri, 3 Feb 2023 09:17:46 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8D87D625F3; Fri, 3 Feb 2023 10:17:46 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1675415866; bh=QiXxWahddJBjH0Y2496EO0ohusMMG86k6EqWrbFoh8I=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=yql4dOgYcTbWGWvoI7H7vd3tyB3El9mErHGwxPcHSUMtAAcCic674KuvivnuUJRSW mIsBzaDbdpJuZ3GH2kKbXi8AZND/n6iUtK9GPqS7ja7rLJudGNpQmyJU9+RrDKMCaX 1IF0CjHna0CqazCA9NB5mkbHHMJhzYRxzEw81szrsBYqf3cs6b86XQiWvAsUo78D8T aRMkgD+5ghrFRwHAs1o44Vz10xp4nGuQeQjnkE9uhgJnNQ1haoErYrdyFFdf+YkVf/ 5wrKPuN55KnIM7s5xUzrrnktsdjrtn6IHh2RegiOAB3SJaBXKfsXr+guTAQr4LmsGd iNu3m19XsNsdA== 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 07FDE625F0 for ; Fri, 3 Feb 2023 10:17:43 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="I8SCHb1P"; dkim-atps=neutral Received: by mail-wm1-x32b.google.com with SMTP id q10-20020a1cf30a000000b003db0edfdb74so5272486wmq.1 for ; Fri, 03 Feb 2023 01:17:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; 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; bh=zPHFslMm2RC6M7HPmlZDZ0wSiz5LyD2fZ96vieBis1Y=; b=I8SCHb1P9P+Yp+2WXSrGR9BqS5Gfmw7UJ6UlJfDuczA3vqjT0Hk7ixTAkcngzeCT8r XDhM90IriRnLlB2V/SAbeGET0hVDGQyiA3YxZse+O/0ZaTAdXNUXBu9Cv8HT9NAhkZhM dlemY/97GeJHDA+PFBn+JxzobKUHkm3XWy+GlNtv1nPWqSgdRRnmXpudxcYpuedOyYAu Rffel6jg16zkxIK/DW4LqGMoIclTGdWKatVNJm3oLobOpYY7v0j3cRSz9WWLPnOkAK+z XNVgfMLGgBnoGbr5MClCIXte7znPKjPI20Vb5TveyBkQ8JMhla8byVXkRFyBxWbCo308 h3lg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zPHFslMm2RC6M7HPmlZDZ0wSiz5LyD2fZ96vieBis1Y=; b=OkMZu1UKktiU/KDGQLRh2wwsGGfodZMxZtMjn8+5/a6nh3eq93hHHWk6FkrZZueHuF J3R09pmUlcFtZ2GWVRakns9Dsa2r7/Wl5VWEQQIXSzt+lBmbPthmLR6z+4UlbaSdJsN6 mUzfZle5sFuo/I9dJMNoM9aswsU26OawAcepoW1gb3B/82EHfAQN68+R2SSDai+GR2S/ Tnxx1o7J5xshiZXL4KuoimYTQ7+iSNgkGKgR2gpeE3g28ddq0JMBpjE/qCaERVmVjLT6 VpPgXuFKpqZkBb033hxXGAEQ/UprdjIDPrCPRNG9YWQfto53x15Lti/gknriy4ycoW0c tvNQ== X-Gm-Message-State: AO0yUKX6jaY2cBYuQWo/piOliLJmtrre/r20+4iKNseYtx8q+d8GuU2Q E7y9YlvlYREu/M7OZmTdgWwnbnO9JiofYC7B/8OiGA== X-Google-Smtp-Source: AK7set/FJWZ9p0v1TEtr5B5AUTKYNEowlB1FKSOO3cNIN6+UZbnG19X0gSeETaznjT2xcaT7ycONdw== X-Received: by 2002:a7b:c388:0:b0:3db:2e6e:7826 with SMTP id s8-20020a7bc388000000b003db2e6e7826mr10717211wmj.5.1675415862272; Fri, 03 Feb 2023 01:17:42 -0800 (PST) Received: from localhost.localdomain ([93.93.133.154]) by smtp.gmail.com with ESMTPSA id az24-20020a05600c601800b003dc4baaedd3sm7468864wmb.37.2023.02.03.01.17.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 Feb 2023 01:17:42 -0800 (PST) To: libcamera-devel@lists.libcamera.org Date: Fri, 3 Feb 2023 09:17:34 +0000 Message-Id: <20230203091734.22803-6-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230203091734.22803-1-naush@raspberrypi.com> References: <20230203091734.22803-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 5/5] ipa: raspberrypi: Normalise region sums to 16-bits 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: , X-Patchwork-Original-From: Naushir Patuck via libcamera-devel From: Naushir Patuck Reply-To: Naushir Patuck Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The VC4 ISP uses a pipeline bit-depth of 13-bits. The AGC algorithm needs to know this bit-depth when computing the Y value for the image. Instead of hardcoding the VC4 bit-depth in the AGC source code, normalise all region sums to 16-bits when filling the Statistics structure. AWB and ALSC are agnostic about pipeline depth, so do not need changing. Signed-off-by: Naushir Patuck Reviewed-by: David Plowman Reviewed-by: Kieran Bingham --- src/ipa/raspberrypi/controller/rpi/agc.cpp | 11 +++++------ src/ipa/raspberrypi/raspberrypi.cpp | 18 ++++++++++++------ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp b/src/ipa/raspberrypi/controller/rpi/agc.cpp index 868c30f03d66..ea0c82b5c4c8 100644 --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp @@ -28,8 +28,6 @@ LOG_DEFINE_CATEGORY(RPiAgc) #define NAME "rpi.agc" -static constexpr unsigned int PipelineBits = 13; /* seems to be a 13-bit pipeline */ - int AgcMeteringMode::read(const libcamera::YamlObject ¶ms) { const YamlObject &yamlWeights = params["weights"]; @@ -586,6 +584,7 @@ void Agc::fetchAwbStatus(Metadata *imageMetadata) static double computeInitialY(StatisticsPtr &stats, AwbStatus const &awb, double weights[], double gain) { + constexpr unsigned int maxVal = 1 << Statistics::NormalisationFactorPow2; /* * Note how the calculation below means that equal weights give you * "average" metering (i.e. all pixels equally important). @@ -593,9 +592,9 @@ static double computeInitialY(StatisticsPtr &stats, AwbStatus const &awb, double rSum = 0, gSum = 0, bSum = 0, pixelSum = 0; for (unsigned int i = 0; i < stats->agcRegions.numRegions(); i++) { auto ®ion = stats->agcRegions.get(i); - double rAcc = std::min(region.val.rSum * gain, ((1 << PipelineBits) - 1) * region.counted); - double gAcc = std::min(region.val.gSum * gain, ((1 << PipelineBits) - 1) * region.counted); - double bAcc = std::min(region.val.bSum * gain, ((1 << PipelineBits) - 1) * region.counted); + double rAcc = std::min(region.val.rSum * gain, (maxVal - 1) * region.counted); + double gAcc = std::min(region.val.gSum * gain, (maxVal - 1) * region.counted); + double bAcc = std::min(region.val.bSum * gain, (maxVal - 1) * region.counted); rSum += rAcc * weights[i]; gSum += gAcc * weights[i]; bSum += bAcc * weights[i]; @@ -608,7 +607,7 @@ static double computeInitialY(StatisticsPtr &stats, AwbStatus const &awb, double ySum = rSum * awb.gainR * .299 + gSum * awb.gainG * .587 + bSum * awb.gainB * .114; - return ySum / pixelSum / (1 << PipelineBits); + return ySum / pixelSum / maxVal; } /* diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp index b8cce51522c0..614b8c6aacdb 100644 --- a/src/ipa/raspberrypi/raspberrypi.cpp +++ b/src/ipa/raspberrypi/raspberrypi.cpp @@ -1377,11 +1377,17 @@ RPiController::StatisticsPtr IPARPi::fillStatistics(bcm2835_isp_stats *stats) co /* RGB histograms are not used, so do not populate them. */ statistics->yHist = std::move(RPiController::Histogram(stats->hist[0].g_hist, NUM_HISTOGRAM_BINS)); + /* + * All region sums are based on a 13-bit pipeline bit-depth. Normalise + * this to 16-bits for the AGC/AWB/ALSC algorithms. + */ + constexpr unsigned int scale = Statistics::NormalisationFactorPow2 - 13; + statistics->awbRegions.init({ DEFAULT_AWB_REGIONS_X, DEFAULT_AWB_REGIONS_Y }); for (i = 0; i < statistics->awbRegions.numRegions(); i++) - statistics->awbRegions.set(i, { { stats->awb_stats[i].r_sum, - stats->awb_stats[i].g_sum, - stats->awb_stats[i].b_sum }, + statistics->awbRegions.set(i, { { stats->awb_stats[i].r_sum << scale, + stats->awb_stats[i].g_sum << scale, + stats->awb_stats[i].b_sum << scale }, stats->awb_stats[i].counted, stats->awb_stats[i].notcounted }); @@ -1391,9 +1397,9 @@ RPiController::StatisticsPtr IPARPi::fillStatistics(bcm2835_isp_stats *stats) co */ statistics->agcRegions.init(15); for (i = 0; i < statistics->agcRegions.numRegions(); i++) - statistics->agcRegions.set(i, { { stats->agc_stats[i].r_sum, - stats->agc_stats[i].g_sum, - stats->agc_stats[i].b_sum }, + statistics->agcRegions.set(i, { { stats->agc_stats[i].r_sum << scale, + stats->agc_stats[i].g_sum << scale, + stats->agc_stats[i].b_sum << scale }, stats->agc_stats[i].counted, stats->awb_stats[i].notcounted });