From patchwork Thu Sep 30 09:37:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Michel Hautbois X-Patchwork-Id: 13984 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 84702BDC71 for ; Thu, 30 Sep 2021 09:37:24 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3E982691BC; Thu, 30 Sep 2021 11:37:23 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="iPJpHIzj"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id CB5D9691A3 for ; Thu, 30 Sep 2021 11:37:19 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:bab4:22c5:662d:e478]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 69201B2B; Thu, 30 Sep 2021 11:37:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1632994639; bh=7iFuYX5Jd9uTHPDAF6PKzCxzUB+2rJANmHloS45ic+M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=iPJpHIzjJYK/o+6wDy0PxUw6IGeoYFmZvdbqz9aDpF4Ehm7707FrB4ubSfC9v/Ghc 0ewHPDOjc9eh9daqkCe7NIuBzTfn7CSf4t79PEUbR46ijSPwE1wVn7ojSQPJWQIYdz 2OCSRrqKuuoNtQSeYf5WVmTLrD12W1sI6iFAFhGI= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Sep 2021 11:37:04 +0200 Message-Id: <20210930093715.73293-2-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210930093715.73293-1-jeanmichel.hautbois@ideasonboard.com> References: <20210930093715.73293-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 01/12] ipa: ipu3: Move the AWB stats structures 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 structure Ipu3AwbCell describes the AWB stats layout on the kernel side. We will need it to be used by the AGC algorithm to be introduced later, so let's make it visible from ipa::ipu3::algorithms and not only for the AWB class. The IspStatsRegion will be needed by AGC too, so let's move it in the same namespace too. Signed-off-by: Jean-Michel Hautbois Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/ipa/ipu3/algorithms/awb.h | 37 ++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/ipa/ipu3/algorithms/awb.h b/src/ipa/ipu3/algorithms/awb.h index a16dd68d..cc848060 100644 --- a/src/ipa/ipu3/algorithms/awb.h +++ b/src/ipa/ipu3/algorithms/awb.h @@ -23,6 +23,24 @@ namespace ipa::ipu3::algorithms { static constexpr uint32_t kAwbStatsSizeX = 16; static constexpr uint32_t kAwbStatsSizeY = 12; +/* \todo Move the cell layout into intel-ipu3.h kernel header */ +struct Ipu3AwbCell { + unsigned char greenRedAvg; + unsigned char redAvg; + unsigned char blueAvg; + unsigned char greenBlueAvg; + unsigned char satRatio; + unsigned char padding[3]; +} __attribute__((packed)); + +struct IspStatsRegion { + unsigned int counted; + unsigned int uncounted; + unsigned long long rSum; + unsigned long long gSum; + unsigned long long bSum; +}; + class Awb : public Algorithm { public: @@ -32,16 +50,7 @@ public: void prepare(IPAContext &context, ipu3_uapi_params *params) override; void process(IPAContext &context, const ipu3_uapi_stats_3a *stats) override; - struct Ipu3AwbCell { - unsigned char greenRedAvg; - unsigned char redAvg; - unsigned char blueAvg; - unsigned char greenBlueAvg; - unsigned char satRatio; - unsigned char padding[3]; - } __attribute__((packed)); - - /* \todo Make these three structs available to all the ISPs ? */ + /* \todo Make these structs available to all the ISPs ? */ struct RGB { RGB(double _R = 0, double _G = 0, double _B = 0) : R(_R), G(_G), B(_B) @@ -55,14 +64,6 @@ public: } }; - struct IspStatsRegion { - unsigned int counted; - unsigned int uncounted; - unsigned long long rSum; - unsigned long long gSum; - unsigned long long bSum; - }; - struct AwbStatus { double temperatureK; double redGain; From patchwork Thu Sep 30 09:37:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jean-Michel Hautbois X-Patchwork-Id: 13985 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 A8F87BDC71 for ; Thu, 30 Sep 2021 09:37:26 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 42034691C1; Thu, 30 Sep 2021 11:37:26 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="WVwoaz1h"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0FC4C691AA for ; Thu, 30 Sep 2021 11:37:20 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:bab4:22c5:662d:e478]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id A3DA818BF; Thu, 30 Sep 2021 11:37:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1632994639; bh=NwR6vJY2XYrUoukkjWBbCNEXUlJ2jjq0iP8h7BaWQ1o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WVwoaz1hO0UYX+SWNi3S0JePyOzAeFeVwa/h/9qC5AC9M7V0EboQGKCDcC+teySbw Iqb+zxzTuMi3NN0GgJvkQ0j0Wnchnba3beO1+87XrfIQtUbPIgi5PV3zva6V6Tk2MY 2aa4fGMh6ym/Bgx7VhsZ8N1fgkBv3BKpS1QKu06s= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Sep 2021 11:37:05 +0200 Message-Id: <20210930093715.73293-3-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210930093715.73293-1-jeanmichel.hautbois@ideasonboard.com> References: <20210930093715.73293-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 02/12] ipa: ipu3: Rename IspStatsRegion to Accumulator 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 IspStatsRegion structure was introduced as an attempt to prepare for a generic AWB algorithm structure. The structure name by itself is not explicit and it is too optimistic to try and make a generic one for now. Its role is to accumulate the pixels in a given zone. Rename it to accumulator, and remove the uncounted field at the same time. It is always possible to know how many pixels are not relevant for the algorithm by calculating total-counted. The uncounted field was only declared and not used. Amend the documentation accordingly. Signed-off-by: Jean-Michel Hautbois Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/ipa/ipu3/algorithms/awb.cpp | 77 +++++++++++++++++++++++++-------- src/ipa/ipu3/algorithms/awb.h | 5 +-- 2 files changed, 61 insertions(+), 21 deletions(-) diff --git a/src/ipa/ipu3/algorithms/awb.cpp b/src/ipa/ipu3/algorithms/awb.cpp index e05647c9..fd2f12ca 100644 --- a/src/ipa/ipu3/algorithms/awb.cpp +++ b/src/ipa/ipu3/algorithms/awb.cpp @@ -21,26 +21,68 @@ static constexpr uint32_t kMinZonesCounted = 16; static constexpr uint32_t kMinGreenLevelInZone = 32; /** - * \struct IspStatsRegion - * \brief RGB statistics for a given region + * \struct Accumulator + * \brief RGB statistics for a given zone * - * The IspStatsRegion structure is intended to abstract the ISP specific - * statistics and use an agnostic algorithm to compute AWB. + * - Cells are defined in Pixels + * - Zones are defined in Cells * - * \var IspStatsRegion::counted - * \brief Number of pixels used to calculate the sums + * 80 cells + * /───────────── 1280 pixels ───────────\ + * 16 zones + * 16 + * ┌────┬────┬────┬────┬────┬─ ──────┬────┐ \ + * │Cell│ │ │ │ │ | │ │ │ + * 16 │ px │ │ │ │ │ | │ │ │ + * ├────┼────┼────┼────┼────┼─ ──────┼────┤ │ + * │ │ │ │ │ │ | │ │ + * │ │ │ │ │ │ | │ │ 7 + * │ ── │ ── │ ── │ ── │ ── │ ── ── ─┤ ── │ 1 2 4 + * │ │ │ │ │ │ | │ │ 2 0 5 * - * \var IspStatsRegion::uncounted - * \brief Remaining number of pixels in the region + * │ │ │ │ │ │ | │ │ z p c + * ├────┼────┼────┼────┼────┼─ ──────┼────┤ o i e + * │ │ │ │ │ │ | │ │ n x l + * │ │ | │ │ e e l + * ├─── ───┼─ ──────┼────┤ s l s + * │ │ | │ │ s + * │ │ | │ │ + * ├─── Zone of Cells ───┼─ ──────┼────┤ │ + * │ (5 x 4) │ | │ │ │ + * │ │ | │ │ │ + * ├── ───┼─ ──────┼────┤ │ + * │ │ │ | │ │ │ + * │ │ │ │ │ │ | │ │ │ + * └────┴────┴────┴────┴────┴─ ──────┴────┘ / * - * \var IspStatsRegion::rSum - * \brief Sum of the red values in the region + * The algorithm works with a fixed number of zones \a kAwbStatsSizeX x + * \a kAwbStatsSizeY. For example, a frame of 1280x720 is divided into 80x45 + * cells of [16x16] pixels. In the case of \a kAwbStatsSizeX=16 and + * \a kAwbStatsSizeY=12 the zones are made of [5x4] cells. The cells are + * left-aligned and calculated by IPAIPU3::calculateBdsGrid(). * - * \var IspStatsRegion::gSum - * \brief Sum of the green values in the region + * Each statistics cell represents the average value of the pixels in that cell + * split by colour components. * - * \var IspStatsRegion::bSum - * \brief Sum of the blue values in the region + * The Accumulator structure stores the sum of the average of each cell in a + * zone of the image, as well as the number of cells which were unsaturated and + * therefore included in the average. + * \todo move this description and structure into a common header + * + * Cells which are saturated beyond the threshold defined in + * ipu3_uapi_awb_config_s are not included in the average. + * + * \var Accumulator::counted + * \brief Number of unsaturated cells used to calculate the sums + * + * \var Accumulator::rSum + * \brief Sum of the average red values of each unsaturated cell in the zone + * + * \var Accumulator::gSum + * \brief Sum of the average green values of each unsaturated cell in the zone + * + * \var Accumulator::bSum + * \brief Sum of the average blue values of each unsaturated cell in the zone */ /** @@ -157,7 +199,7 @@ uint32_t Awb::estimateCCT(double red, double green, double blue) return 449 * n * n * n + 3525 * n * n + 6823.3 * n + 5520.33; } -/* Generate an RGB vector with the average values for each region */ +/* Generate an RGB vector with the average values for each zone */ void Awb::generateZones(std::vector &zones) { for (unsigned int i = 0; i < kAwbStatsSizeX * kAwbStatsSizeY; i++) { @@ -174,7 +216,7 @@ void Awb::generateZones(std::vector &zones) } } -/* Translate the IPU3 statistics into the default statistics region array */ +/* Translate the IPU3 statistics into the default statistics zone array */ void Awb::generateAwbStats(const ipu3_uapi_stats_3a *stats, const ipu3_uapi_grid_config &grid) { @@ -215,7 +257,6 @@ void Awb::clearAwbStats() awbStats_[i].rSum = 0; awbStats_[i].gSum = 0; awbStats_[i].counted = 0; - awbStats_[i].uncounted = 0; } } @@ -304,7 +345,7 @@ void Awb::prepare(IPAContext &context, ipu3_uapi_params *params) /* * Optical center is column start (respectively row start) of the - * region of interest minus its X center (respectively Y center). + * cell of interest minus its X center (respectively Y center). * * For the moment use BDS as a first approximation, but it should * be calculated based on Shading (SHD) parameters. diff --git a/src/ipa/ipu3/algorithms/awb.h b/src/ipa/ipu3/algorithms/awb.h index cc848060..ac8ccc84 100644 --- a/src/ipa/ipu3/algorithms/awb.h +++ b/src/ipa/ipu3/algorithms/awb.h @@ -33,9 +33,8 @@ struct Ipu3AwbCell { unsigned char padding[3]; } __attribute__((packed)); -struct IspStatsRegion { +struct Accumulator { unsigned int counted; - unsigned int uncounted; unsigned long long rSum; unsigned long long gSum; unsigned long long bSum; @@ -82,7 +81,7 @@ private: uint32_t estimateCCT(double red, double green, double blue); std::vector zones_; - IspStatsRegion awbStats_[kAwbStatsSizeX * kAwbStatsSizeY]; + Accumulator awbStats_[kAwbStatsSizeX * kAwbStatsSizeY]; AwbStatus asyncResults_; }; From patchwork Thu Sep 30 09:37:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Michel Hautbois X-Patchwork-Id: 13986 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 50B0FBDC71 for ; Thu, 30 Sep 2021 09:37:28 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3AD1A691B1; Thu, 30 Sep 2021 11:37:27 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="CWPO+dtD"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 38C92691AC for ; Thu, 30 Sep 2021 11:37:20 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:bab4:22c5:662d:e478]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id DC0772A8; Thu, 30 Sep 2021 11:37:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1632994640; bh=aKPj5VLdOHgTuWeQ78ZlMjDcaD1mvuLIR7m092DaGFw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CWPO+dtD30wVDL613Di2UyuniZ0uQ9SqVQ9ClZqx0ECOzY3wUVP0cZ18KZ4QhjO40 iNv4uZ+HOLExjMbimKZP9N/jgCL4737r/hptR6dFxqlHfNUWiIIYT1Km7sNCAzbrex mHtumMq7S2gvED2t5YA70qWXEIt/JPFTHsY73YIs= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Sep 2021 11:37:06 +0200 Message-Id: <20210930093715.73293-4-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210930093715.73293-1-jeanmichel.hautbois@ideasonboard.com> References: <20210930093715.73293-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 03/12] ipa: ipu3: Change Accumulator structure layout 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 pixel component sums for the Accumulator are inconsistent with other similar structures such as the IPAFrameContext::awb::gains. Group the red, green, and blue sums together in a struct and store them as uint64_t to reduce potential architectural differences. Signed-off-by: Jean-Michel Hautbois Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/ipa/ipu3/algorithms/awb.cpp | 24 ++++++++++++------------ src/ipa/ipu3/algorithms/awb.h | 8 +++++--- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/ipa/ipu3/algorithms/awb.cpp b/src/ipa/ipu3/algorithms/awb.cpp index fd2f12ca..5f61cb89 100644 --- a/src/ipa/ipu3/algorithms/awb.cpp +++ b/src/ipa/ipu3/algorithms/awb.cpp @@ -75,13 +75,13 @@ static constexpr uint32_t kMinGreenLevelInZone = 32; * \var Accumulator::counted * \brief Number of unsaturated cells used to calculate the sums * - * \var Accumulator::rSum + * \var Accumulator::red * \brief Sum of the average red values of each unsaturated cell in the zone * - * \var Accumulator::gSum + * \var Accumulator::green * \brief Sum of the average green values of each unsaturated cell in the zone * - * \var Accumulator::bSum + * \var Accumulator::blue * \brief Sum of the average blue values of each unsaturated cell in the zone */ @@ -206,10 +206,10 @@ void Awb::generateZones(std::vector &zones) RGB zone; double counted = awbStats_[i].counted; if (counted >= kMinZonesCounted) { - zone.G = awbStats_[i].gSum / counted; + zone.G = awbStats_[i].sum.green / counted; if (zone.G >= kMinGreenLevelInZone) { - zone.R = awbStats_[i].rSum / counted; - zone.B = awbStats_[i].bSum / counted; + zone.R = awbStats_[i].sum.red / counted; + zone.B = awbStats_[i].sum.blue / counted; zones.push_back(zone); } } @@ -242,9 +242,9 @@ void Awb::generateAwbStats(const ipu3_uapi_stats_3a *stats, /* The cell is not saturated, use the current cell */ awbStats_[awbRegionPosition].counted++; uint32_t greenValue = currentCell->greenRedAvg + currentCell->greenBlueAvg; - awbStats_[awbRegionPosition].gSum += greenValue / 2; - awbStats_[awbRegionPosition].rSum += currentCell->redAvg; - awbStats_[awbRegionPosition].bSum += currentCell->blueAvg; + awbStats_[awbRegionPosition].sum.green += greenValue / 2; + awbStats_[awbRegionPosition].sum.red += currentCell->redAvg; + awbStats_[awbRegionPosition].sum.blue += currentCell->blueAvg; } } } @@ -253,9 +253,9 @@ void Awb::generateAwbStats(const ipu3_uapi_stats_3a *stats, void Awb::clearAwbStats() { for (unsigned int i = 0; i < kAwbStatsSizeX * kAwbStatsSizeY; i++) { - awbStats_[i].bSum = 0; - awbStats_[i].rSum = 0; - awbStats_[i].gSum = 0; + awbStats_[i].sum.blue = 0; + awbStats_[i].sum.red = 0; + awbStats_[i].sum.green = 0; awbStats_[i].counted = 0; } } diff --git a/src/ipa/ipu3/algorithms/awb.h b/src/ipa/ipu3/algorithms/awb.h index ac8ccc84..3385ebe7 100644 --- a/src/ipa/ipu3/algorithms/awb.h +++ b/src/ipa/ipu3/algorithms/awb.h @@ -35,9 +35,11 @@ struct Ipu3AwbCell { struct Accumulator { unsigned int counted; - unsigned long long rSum; - unsigned long long gSum; - unsigned long long bSum; + struct { + uint64_t red; + uint64_t green; + uint64_t blue; + } sum; }; class Awb : public Algorithm From patchwork Thu Sep 30 09:37:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Michel Hautbois X-Patchwork-Id: 13987 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 72241BDC71 for ; Thu, 30 Sep 2021 09:37:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 40BEB691C5; Thu, 30 Sep 2021 11:37:30 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Gp7fM1BG"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7FDFC691B1 for ; Thu, 30 Sep 2021 11:37:20 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:bab4:22c5:662d:e478]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 20977B2B; Thu, 30 Sep 2021 11:37:20 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1632994640; bh=v/oM/rWOrvppzh/ZwWNwhMJsa/uAcrkmnebDRaqgQS0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Gp7fM1BGozT9WjGhBCGdLZ2p6RzqBHpFq71gbDtboRqXPK0dGLnOYY6F7HM/lJKhv Zb/i4UCO3Wz21I0M2ROeuZKx7Br2TNEmCLEfQ0GcE+CAzLjcTJBqchjkBYOsBSv0Dx 6kr5hJktE0jomHRrLv98jMpkSJAkGgcZYSh3raeY= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Sep 2021 11:37:07 +0200 Message-Id: <20210930093715.73293-5-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210930093715.73293-1-jeanmichel.hautbois@ideasonboard.com> References: <20210930093715.73293-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 04/12] ipa: ipu3: awb: Make the naming consistent 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 variables mix the terms cell, region and zone. It can confuse the reader, and make the algorithm more difficult to follow. Rename the local variables to be consistent with their definitions: - Cells are defined in Pixels - Zones are defined in Cells There is no "region" as such, so replace it with the correct term. Signed-off-by: Jean-Michel Hautbois Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/ipa/ipu3/algorithms/awb.cpp | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/ipa/ipu3/algorithms/awb.cpp b/src/ipa/ipu3/algorithms/awb.cpp index 5f61cb89..2ba6f9e6 100644 --- a/src/ipa/ipu3/algorithms/awb.cpp +++ b/src/ipa/ipu3/algorithms/awb.cpp @@ -220,31 +220,34 @@ void Awb::generateZones(std::vector &zones) void Awb::generateAwbStats(const ipu3_uapi_stats_3a *stats, const ipu3_uapi_grid_config &grid) { - uint32_t regionWidth = round(grid.width / static_cast(kAwbStatsSizeX)); - uint32_t regionHeight = round(grid.height / static_cast(kAwbStatsSizeY)); + uint32_t cellsPerZoneX = round(grid.width / static_cast(kAwbStatsSizeX)); + uint32_t cellsPerZoneY = round(grid.height / static_cast(kAwbStatsSizeY)); /* * Generate a (kAwbStatsSizeX x kAwbStatsSizeY) array from the IPU3 grid which is * (grid.width x grid.height). */ - for (unsigned int j = 0; j < kAwbStatsSizeY * regionHeight; j++) { - for (unsigned int i = 0; i < kAwbStatsSizeX * regionWidth; i++) { - uint32_t cellPosition = j * grid.width + i; - uint32_t cellX = (cellPosition / regionWidth) % kAwbStatsSizeX; - uint32_t cellY = ((cellPosition / grid.width) / regionHeight) % kAwbStatsSizeY; + for (unsigned int cellY = 0; cellY < kAwbStatsSizeY * cellsPerZoneY; cellY++) { + for (unsigned int cellX = 0; cellX < kAwbStatsSizeX * cellsPerZoneX; cellX++) { + uint32_t cellPosition = (cellY * grid.width + cellX) + * sizeof(Ipu3AwbCell); + uint32_t zoneX = cellX / cellsPerZoneX; + uint32_t zoneY = cellY / cellsPerZoneY; - uint32_t awbRegionPosition = cellY * kAwbStatsSizeX + cellX; - cellPosition *= 8; + uint32_t awbZonePosition = zoneY * kAwbStatsSizeX + zoneX; /* Cast the initial IPU3 structure to simplify the reading */ - Ipu3AwbCell *currentCell = reinterpret_cast(const_cast(&stats->awb_raw_buffer.meta_data[cellPosition])); + const Ipu3AwbCell *currentCell = + reinterpret_cast( + &stats->awb_raw_buffer.meta_data[cellPosition] + ); if (currentCell->satRatio == 0) { /* The cell is not saturated, use the current cell */ - awbStats_[awbRegionPosition].counted++; + awbStats_[awbZonePosition].counted++; uint32_t greenValue = currentCell->greenRedAvg + currentCell->greenBlueAvg; - awbStats_[awbRegionPosition].sum.green += greenValue / 2; - awbStats_[awbRegionPosition].sum.red += currentCell->redAvg; - awbStats_[awbRegionPosition].sum.blue += currentCell->blueAvg; + awbStats_[awbZonePosition].sum.green += greenValue / 2; + awbStats_[awbZonePosition].sum.red += currentCell->redAvg; + awbStats_[awbZonePosition].sum.blue += currentCell->blueAvg; } } } From patchwork Thu Sep 30 09:37:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Michel Hautbois X-Patchwork-Id: 13988 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 11820BDC71 for ; Thu, 30 Sep 2021 09:37:31 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B5427691C9; Thu, 30 Sep 2021 11:37:30 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="O/neG4H+"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B5004691B3 for ; Thu, 30 Sep 2021 11:37:20 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:bab4:22c5:662d:e478]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 590D118BF; Thu, 30 Sep 2021 11:37:20 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1632994640; bh=aDIEbCQIZBRLcK5OnUXvXCc8H+HYmCpFIvAIBJhYTok=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=O/neG4H+0SpUywC5k+jDOlbY4+UtgmgtbGkzZuZ1D0XQFX6sd04eJ1AK94gLnKtI8 FMzo2iivCP3WxQjAhp2Nu4nFdz+Riu51xtmNoN2jJl4ZzQfa0YerdHqzRqX1kc6a3i TxI2nu3ThKDpfZahofXzPHr9AeZw4JTUtu27yGBo= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Sep 2021 11:37:08 +0200 Message-Id: <20210930093715.73293-6-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210930093715.73293-1-jeanmichel.hautbois@ideasonboard.com> References: <20210930093715.73293-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 05/12] ipa: ipu3: Change the limits of the AWB stats 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" Until now, the limits used to calculate the grid based on the Bayer Down Scaler configuration where taken from the kernel documentation [0]. While testing and understanding the format of the ImgU statistics, it appears that the ones defined in CrOS [1] are the correct ones. Use those. [0] https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/pixfmt-meta-intel-ipu3.html?highlight=v4l2_meta_fmt_ipu3_params#intel-ipu3-imgu-uapi-data-types [1] https://chromium.googlesource.com/chromiumos/platform/arc-camera/+/refs/heads/master/hal/intel/include/ia_imaging/awb_public.h Signed-off-by: Jean-Michel Hautbois Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/ipa/ipu3/ipu3.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp index ac98a86b..b3ac96ed 100644 --- a/src/ipa/ipu3/ipu3.cpp +++ b/src/ipa/ipu3/ipu3.cpp @@ -136,8 +136,8 @@ * struct ipu3_uapi_gamma_corr_lut for further details. */ -static constexpr uint32_t kMaxCellWidthPerSet = 160; -static constexpr uint32_t kMaxCellHeightPerSet = 56; +static constexpr uint32_t kMaxCellWidthPerSet = 80; +static constexpr uint32_t kMaxCellHeightPerSet = 60; namespace libcamera { @@ -300,11 +300,11 @@ void IPAIPU3::calculateBdsGrid(const Size &bdsOutputSize) /* Set the BDS output size in the IPAConfiguration structure */ context_.configuration.grid.bdsOutputSize = bdsOutputSize; - for (uint32_t widthShift = 3; widthShift <= 7; ++widthShift) { + for (uint32_t widthShift = 3; widthShift <= 6; ++widthShift) { uint32_t width = std::min(kMaxCellWidthPerSet, bdsOutputSize.width >> widthShift); width = width << widthShift; - for (uint32_t heightShift = 3; heightShift <= 7; ++heightShift) { + for (uint32_t heightShift = 3; heightShift <= 6; ++heightShift) { int32_t height = std::min(kMaxCellHeightPerSet, bdsOutputSize.height >> heightShift); height = height << heightShift; From patchwork Thu Sep 30 09:37:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Michel Hautbois X-Patchwork-Id: 13989 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 E0FE5BDC71 for ; Thu, 30 Sep 2021 09:37:31 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 68146691CE; Thu, 30 Sep 2021 11:37:31 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="eEzPCG/6"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E8436691B6 for ; Thu, 30 Sep 2021 11:37:20 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:bab4:22c5:662d:e478]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 94E0C2A8; Thu, 30 Sep 2021 11:37:20 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1632994640; bh=y0J9HLzYTe1+uA6GRWu6M/vctdJ+OqQCQ/fUe0fFy2Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=eEzPCG/6jD7/ij/fuWnnFNsMl2nZ5vl+exhpB/IXPknIKuFoWaX9+VsbM5/FG7Xp9 /nutRTjHe4odA3Vc+APlfa+PwG0on/97w8cTj2YJw9CxwLGJ+n5J9I9ZVXcc5w9ASw /scI22ybFMO5lRMEC5wiWh1Vbbulhd92VuvvD2FM= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Sep 2021 11:37:09 +0200 Message-Id: <20210930093715.73293-7-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210930093715.73293-1-jeanmichel.hautbois@ideasonboard.com> References: <20210930093715.73293-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 06/12] ipa: ipu3: Change limits and split loops in calculateBdsGrid() 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 loops over the width and height of the image when calculating the BDS grid parameters are nested, but they're actually independent. Split them to reduce the complexity. While at it, split out the constants to documented const expressions for the grid sizes. Signed-off-by: Laurent Pinchart Signed-off-by: Jean-Michel Hautbois Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/ipa/ipu3/ipu3.cpp | 70 ++++++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 24 deletions(-) diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp index b3ac96ed..757a5d50 100644 --- a/src/ipa/ipu3/ipu3.cpp +++ b/src/ipa/ipu3/ipu3.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -136,8 +137,18 @@ * struct ipu3_uapi_gamma_corr_lut for further details. */ -static constexpr uint32_t kMaxCellWidthPerSet = 80; -static constexpr uint32_t kMaxCellHeightPerSet = 60; +/* Minimum grid width, expressed as a number of cells */ +static constexpr uint32_t kMinGridWidth = 16; +/* Maximum grid width, expressed as a number of cells */ +static constexpr uint32_t kMaxGridWidth = 80; +/* Minimum grid height, expressed as a number of cells */ +static constexpr uint32_t kMinGridHeight = 16; +/* Maximum grid height, expressed as a number of cells */ +static constexpr uint32_t kMaxGridHeight = 60; +/* log2 of the minimum grid cell width and height, in pixels */ +static constexpr uint32_t kMinCellSizeLog2 = 3; +/* log2 of the maximum grid cell width and height, in pixels */ +static constexpr uint32_t kMaxCellSizeLog2 = 6; namespace libcamera { @@ -281,45 +292,56 @@ int IPAIPU3::start() } /** + * \brief Calculate a grid for the AWB statistics + * * This function calculates a grid for the AWB algorithm in the IPU3 firmware. * Its input is the BDS output size calculated in the ImgU. * It is limited for now to the simplest method: find the lesser error * with the width/height and respective log2 width/height of the cells. * - * \todo The frame is divided into cells which can be 8x8 => 128x128. + * \todo The frame is divided into cells which can be 8x8 => 64x64. * As a smaller cell improves the algorithm precision, adapting the * x_start and y_start parameters of the grid would provoke a loss of * some pixels but would also result in more accurate algorithms. */ void IPAIPU3::calculateBdsGrid(const Size &bdsOutputSize) { - uint32_t minError = std::numeric_limits::max(); Size best; Size bestLog2; /* Set the BDS output size in the IPAConfiguration structure */ context_.configuration.grid.bdsOutputSize = bdsOutputSize; - for (uint32_t widthShift = 3; widthShift <= 6; ++widthShift) { - uint32_t width = std::min(kMaxCellWidthPerSet, - bdsOutputSize.width >> widthShift); - width = width << widthShift; - for (uint32_t heightShift = 3; heightShift <= 6; ++heightShift) { - int32_t height = std::min(kMaxCellHeightPerSet, - bdsOutputSize.height >> heightShift); - height = height << heightShift; - uint32_t error = std::abs(static_cast(width - bdsOutputSize.width)) - + std::abs(static_cast(height - bdsOutputSize.height)); - - if (error > minError) - continue; - - minError = error; - best.width = width; - best.height = height; - bestLog2.width = widthShift; - bestLog2.height = heightShift; - } + uint32_t minError = std::numeric_limits::max(); + for (uint32_t shift = kMinCellSizeLog2; shift <= kMaxCellSizeLog2; ++shift) { + uint32_t width = std::clamp(bdsOutputSize.width >> shift, + kMinGridWidth, + kMaxGridWidth); + + width = width << shift; + uint32_t error = std::abs(static_cast(width - bdsOutputSize.width)); + if (error >= minError) + continue; + + minError = error; + best.width = width; + bestLog2.width = shift; + } + + minError = std::numeric_limits::max(); + for (uint32_t shift = kMinCellSizeLog2; shift <= kMaxCellSizeLog2; ++shift) { + uint32_t height = std::clamp(bdsOutputSize.height >> shift, + kMinGridHeight, + kMaxGridHeight); + + height = height << shift; + uint32_t error = std::abs(static_cast(height - bdsOutputSize.height)); + if (error >= minError) + continue; + + minError = error; + best.height = height; + bestLog2.height = shift; } struct ipu3_uapi_grid_config &bdsGrid = context_.configuration.grid.bdsGrid; From patchwork Thu Sep 30 09:37:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Michel Hautbois X-Patchwork-Id: 13990 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 81E2BBDC71 for ; Thu, 30 Sep 2021 09:37:32 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 40BF2691AF; Thu, 30 Sep 2021 11:37:32 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="LyIw803V"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 23CCE691B7 for ; Thu, 30 Sep 2021 11:37:21 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:bab4:22c5:662d:e478]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id CD06AB2B; Thu, 30 Sep 2021 11:37:20 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1632994640; bh=JAO5iq2Ud3SWuURjRkOgMfD7lKFl5Ikr93rqyXQi9L0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LyIw803VMp03crVUdsKGvN5g92UVn+r5Dchk5u7xZ866Xv7P3lAqDpVqonEtOouDc eu/VtlmnSLDFd+fMKQjFTwqf8ij5j9fW0aLk3S4bMpQSrAhiIVFGa/ocb3lsJmiUmP axk7UQN7oRSnVuDlYmhp9DdenvdsJRmpPt3egWLo= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Sep 2021 11:37:10 +0200 Message-Id: <20210930093715.73293-8-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210930093715.73293-1-jeanmichel.hautbois@ideasonboard.com> References: <20210930093715.73293-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 07/12] ipa: ipu3: awb: Correct the relevant zones proportion 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 algorithm uses the statistics of a cell only if there is not too much saturated pixels in it. The grey world algorithm works fine when there are a limited number of outliers. Consider a valid zone to be at least 80% of unsaturated cells in it. This value could very well be configurable, and make the algorithm more or less tolerant. While at it, implement it in a configure() call as it will not change during execution, and cache the cellsPerZone values estimated with std::round as we are using cmath. Signed-off-by: Jean-Michel Hautbois Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/ipa/ipu3/algorithms/awb.cpp | 32 +++++++++++++++++++++++--------- src/ipa/ipu3/algorithms/awb.h | 5 +++++ 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/ipa/ipu3/algorithms/awb.cpp b/src/ipa/ipu3/algorithms/awb.cpp index 2ba6f9e6..be764c79 100644 --- a/src/ipa/ipu3/algorithms/awb.cpp +++ b/src/ipa/ipu3/algorithms/awb.cpp @@ -17,7 +17,6 @@ namespace ipa::ipu3::algorithms { LOG_DEFINE_CATEGORY(IPU3Awb) -static constexpr uint32_t kMinZonesCounted = 16; static constexpr uint32_t kMinGreenLevelInZone = 32; /** @@ -169,6 +168,24 @@ Awb::Awb() Awb::~Awb() = default; +int Awb::configure(IPAContext &context, + [[maybe_unused]] const IPAConfigInfo &configInfo) +{ + const ipu3_uapi_grid_config &grid = context.configuration.grid.bdsGrid; + + cellsPerZoneX_ = std::round(grid.width / static_cast(kAwbStatsSizeX)); + cellsPerZoneY_ = std::round(grid.height / static_cast(kAwbStatsSizeY)); + + /* + * Configure the minimum proportion of cells counted within a zone + * for it to be relevant for the grey world algorithm. + * \todo This proportion could be configured. + */ + cellsPerZoneThreshold_ = cellsPerZoneX_ * cellsPerZoneY_ * 80 / 100; + + return 0; +} + /** * The function estimates the correlated color temperature using * from RGB color space input. @@ -205,7 +222,7 @@ void Awb::generateZones(std::vector &zones) for (unsigned int i = 0; i < kAwbStatsSizeX * kAwbStatsSizeY; i++) { RGB zone; double counted = awbStats_[i].counted; - if (counted >= kMinZonesCounted) { + if (counted >= cellsPerZoneThreshold_) { zone.G = awbStats_[i].sum.green / counted; if (zone.G >= kMinGreenLevelInZone) { zone.R = awbStats_[i].sum.red / counted; @@ -220,19 +237,16 @@ void Awb::generateZones(std::vector &zones) void Awb::generateAwbStats(const ipu3_uapi_stats_3a *stats, const ipu3_uapi_grid_config &grid) { - uint32_t cellsPerZoneX = round(grid.width / static_cast(kAwbStatsSizeX)); - uint32_t cellsPerZoneY = round(grid.height / static_cast(kAwbStatsSizeY)); - /* * Generate a (kAwbStatsSizeX x kAwbStatsSizeY) array from the IPU3 grid which is * (grid.width x grid.height). */ - for (unsigned int cellY = 0; cellY < kAwbStatsSizeY * cellsPerZoneY; cellY++) { - for (unsigned int cellX = 0; cellX < kAwbStatsSizeX * cellsPerZoneX; cellX++) { + for (unsigned int cellY = 0; cellY < kAwbStatsSizeY * cellsPerZoneY_; cellY++) { + for (unsigned int cellX = 0; cellX < kAwbStatsSizeX * cellsPerZoneX_; cellX++) { uint32_t cellPosition = (cellY * grid.width + cellX) * sizeof(Ipu3AwbCell); - uint32_t zoneX = cellX / cellsPerZoneX; - uint32_t zoneY = cellY / cellsPerZoneY; + uint32_t zoneX = cellX / cellsPerZoneX_; + uint32_t zoneY = cellY / cellsPerZoneY_; uint32_t awbZonePosition = zoneY * kAwbStatsSizeX + zoneX; diff --git a/src/ipa/ipu3/algorithms/awb.h b/src/ipa/ipu3/algorithms/awb.h index 3385ebe7..681d8c2b 100644 --- a/src/ipa/ipu3/algorithms/awb.h +++ b/src/ipa/ipu3/algorithms/awb.h @@ -48,6 +48,7 @@ public: Awb(); ~Awb(); + int configure(IPAContext &context, const IPAConfigInfo &configInfo) override; void prepare(IPAContext &context, ipu3_uapi_params *params) override; void process(IPAContext &context, const ipu3_uapi_stats_3a *stats) override; @@ -85,6 +86,10 @@ private: std::vector zones_; Accumulator awbStats_[kAwbStatsSizeX * kAwbStatsSizeY]; AwbStatus asyncResults_; + + uint32_t cellsPerZoneX_; + uint32_t cellsPerZoneY_; + uint32_t cellsPerZoneThreshold_; }; } /* namespace ipa::ipu3::algorithms */ From patchwork Thu Sep 30 09:37:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Michel Hautbois X-Patchwork-Id: 13991 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 31D77BDC71 for ; Thu, 30 Sep 2021 09:37:33 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E070D691B9; Thu, 30 Sep 2021 11:37:32 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="f+Bb21Sy"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 637F5691B0 for ; Thu, 30 Sep 2021 11:37:21 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:bab4:22c5:662d:e478]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 11C1118BF; Thu, 30 Sep 2021 11:37:21 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1632994641; bh=hTYVctuaF+pMj6hu1k5c6avySlIXZDjiMZOFYuOGD5g=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=f+Bb21SynJ8ewebnSGbNY4+OqSXckw8+jyeuebBCLtpMVuJ+DEk7hmqW7XLXDKclg I3rnTQZij7IPQMUWJq0AUJnzWx9t23FEi+jnjqUsEZiJc0/0+bNq2nXMw74R9Us1kD 4H9rc0u/qCtd3fS/DQBcpG0PUtpKEIKZTuZalB0w= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Sep 2021 11:37:11 +0200 Message-Id: <20210930093715.73293-9-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210930093715.73293-1-jeanmichel.hautbois@ideasonboard.com> References: <20210930093715.73293-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 08/12] ipa: ipu3: awb: Correct the gain multipliers 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 gains have a precision u3.13, range [0, 8[ which means that a gain multiplier value of 1.0 is represented as a multiplication by 8192 in the ImgU. Correct the gains as this was misunderstood in the first place. Signed-off-by: Jean-Michel Hautbois Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/ipa/ipu3/algorithms/awb.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/ipa/ipu3/algorithms/awb.cpp b/src/ipa/ipu3/algorithms/awb.cpp index be764c79..c1ff9450 100644 --- a/src/ipa/ipu3/algorithms/awb.cpp +++ b/src/ipa/ipu3/algorithms/awb.cpp @@ -313,6 +313,7 @@ void Awb::awbGreyWorld() /* Color temperature is not relevant in Grey world but still useful to estimate it :-) */ asyncResults_.temperatureK = estimateCCT(sumRed.R, sumRed.G, sumBlue.B); asyncResults_.redGain = redGain; + /*Hardcode the green gain to 1.0. */ asyncResults_.greenGain = 1.0; asyncResults_.blueGain = blueGain; } @@ -376,15 +377,11 @@ void Awb::prepare(IPAContext &context, ipu3_uapi_params *params) * params->acc_param.bnr.opt_center.x_reset; params->acc_param.bnr.opt_center_sqr.y_sqr_reset = params->acc_param.bnr.opt_center.y_reset * params->acc_param.bnr.opt_center.y_reset; - /* - * Green gains should not be touched and considered 1. - * Default is 16, so do not change it at all. - * 4096 is the value for a gain of 1.0 - */ - params->acc_param.bnr.wb_gains.gr = 16 * context.frameContext.awb.gains.green; - params->acc_param.bnr.wb_gains.r = 4096 * context.frameContext.awb.gains.red; - params->acc_param.bnr.wb_gains.b = 4096 * context.frameContext.awb.gains.blue; - params->acc_param.bnr.wb_gains.gb = 16 * context.frameContext.awb.gains.green; + /* Convert to u3.13 fixed point values */ + params->acc_param.bnr.wb_gains.gr = 8192 * context.frameContext.awb.gains.green; + params->acc_param.bnr.wb_gains.r = 8192 * context.frameContext.awb.gains.red; + params->acc_param.bnr.wb_gains.b = 8192 * context.frameContext.awb.gains.blue; + params->acc_param.bnr.wb_gains.gb = 8192 * context.frameContext.awb.gains.green; LOG(IPU3Awb, Debug) << "Color temperature estimated: " << asyncResults_.temperatureK; From patchwork Thu Sep 30 09:37:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Michel Hautbois X-Patchwork-Id: 13992 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 B8926BDC71 for ; Thu, 30 Sep 2021 09:37:33 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7FEA8691C1; Thu, 30 Sep 2021 11:37:33 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="KcMrLLol"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9E0A6691AB for ; Thu, 30 Sep 2021 11:37:21 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:bab4:22c5:662d:e478]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 4BA6E2A8; Thu, 30 Sep 2021 11:37:21 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1632994641; bh=ZLFmS98jA8/xD2N95JpMrotLaquSujewNAr3ohOfz5o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KcMrLLolGO+nHBNCWJ9OZNR0gwNgALG8usowq62DRiqoyaeqVVtotNxGzi1CtN82u 2eDR54zKDHtIc8hfFBLqAHqKLWMiYKmyLE8Agn6cKFbGfwLZXt8FQxk1EHbaLOhF87 0NS2ZhHyNb9GNWDdRfGiexfbXdHBc0gnCL105S+k= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Sep 2021 11:37:12 +0200 Message-Id: <20210930093715.73293-10-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210930093715.73293-1-jeanmichel.hautbois@ideasonboard.com> References: <20210930093715.73293-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 09/12] ipa: ipu3: awb: Use the line stride for the stats 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 statistics buffer 'ipu3_uapi_awb_raw_buffer' stores the ImgU calculation results in a buffer aligned horizontally to a multiple of 4 cells. The AWB loop should take care of it to add the proper offset between lines and avoid any staircase effect. It is now no more required to pass the grid configuration context to the private functions called from process() which simplifies the code flow. Signed-off-by: Jean-Michel Hautbois Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/ipa/ipu3/algorithms/awb.cpp | 13 ++++++------- src/ipa/ipu3/algorithms/awb.h | 7 +++---- src/ipa/ipu3/ipa_context.h | 1 + src/ipa/ipu3/ipu3.cpp | 3 +++ 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/ipa/ipu3/algorithms/awb.cpp b/src/ipa/ipu3/algorithms/awb.cpp index c1ff9450..fcd1469f 100644 --- a/src/ipa/ipu3/algorithms/awb.cpp +++ b/src/ipa/ipu3/algorithms/awb.cpp @@ -172,6 +172,7 @@ int Awb::configure(IPAContext &context, [[maybe_unused]] const IPAConfigInfo &configInfo) { const ipu3_uapi_grid_config &grid = context.configuration.grid.bdsGrid; + stride_ = context.configuration.grid.stride; cellsPerZoneX_ = std::round(grid.width / static_cast(kAwbStatsSizeX)); cellsPerZoneY_ = std::round(grid.height / static_cast(kAwbStatsSizeY)); @@ -234,8 +235,7 @@ void Awb::generateZones(std::vector &zones) } /* Translate the IPU3 statistics into the default statistics zone array */ -void Awb::generateAwbStats(const ipu3_uapi_stats_3a *stats, - const ipu3_uapi_grid_config &grid) +void Awb::generateAwbStats(const ipu3_uapi_stats_3a *stats) { /* * Generate a (kAwbStatsSizeX x kAwbStatsSizeY) array from the IPU3 grid which is @@ -243,7 +243,7 @@ void Awb::generateAwbStats(const ipu3_uapi_stats_3a *stats, */ for (unsigned int cellY = 0; cellY < kAwbStatsSizeY * cellsPerZoneY_; cellY++) { for (unsigned int cellX = 0; cellX < kAwbStatsSizeX * cellsPerZoneX_; cellX++) { - uint32_t cellPosition = (cellY * grid.width + cellX) + uint32_t cellPosition = (cellY * stride_ + cellX) * sizeof(Ipu3AwbCell); uint32_t zoneX = cellX / cellsPerZoneX_; uint32_t zoneY = cellY / cellsPerZoneY_; @@ -318,13 +318,12 @@ void Awb::awbGreyWorld() asyncResults_.blueGain = blueGain; } -void Awb::calculateWBGains(const ipu3_uapi_stats_3a *stats, - const ipu3_uapi_grid_config &grid) +void Awb::calculateWBGains(const ipu3_uapi_stats_3a *stats) { ASSERT(stats->stats_3a_status.awb_en); zones_.clear(); clearAwbStats(); - generateAwbStats(stats, grid); + generateAwbStats(stats); generateZones(zones_); LOG(IPU3Awb, Debug) << "Valid zones: " << zones_.size(); if (zones_.size() > 10) { @@ -336,7 +335,7 @@ void Awb::calculateWBGains(const ipu3_uapi_stats_3a *stats, void Awb::process(IPAContext &context, const ipu3_uapi_stats_3a *stats) { - calculateWBGains(stats, context.configuration.grid.bdsGrid); + calculateWBGains(stats); /* * Gains are only recalculated if enough zones were detected. diff --git a/src/ipa/ipu3/algorithms/awb.h b/src/ipa/ipu3/algorithms/awb.h index 681d8c2b..b3e0ad82 100644 --- a/src/ipa/ipu3/algorithms/awb.h +++ b/src/ipa/ipu3/algorithms/awb.h @@ -74,11 +74,9 @@ public: }; private: - void calculateWBGains(const ipu3_uapi_stats_3a *stats, - const ipu3_uapi_grid_config &grid); + void calculateWBGains(const ipu3_uapi_stats_3a *stats); void generateZones(std::vector &zones); - void generateAwbStats(const ipu3_uapi_stats_3a *stats, - const ipu3_uapi_grid_config &grid); + void generateAwbStats(const ipu3_uapi_stats_3a *stats); void clearAwbStats(); void awbGreyWorld(); uint32_t estimateCCT(double red, double green, double blue); @@ -87,6 +85,7 @@ private: Accumulator awbStats_[kAwbStatsSizeX * kAwbStatsSizeY]; AwbStatus asyncResults_; + uint32_t stride_; uint32_t cellsPerZoneX_; uint32_t cellsPerZoneY_; uint32_t cellsPerZoneThreshold_; diff --git a/src/ipa/ipu3/ipa_context.h b/src/ipa/ipu3/ipa_context.h index 9d9444dc..5bab684c 100644 --- a/src/ipa/ipu3/ipa_context.h +++ b/src/ipa/ipu3/ipa_context.h @@ -20,6 +20,7 @@ struct IPASessionConfiguration { struct { ipu3_uapi_grid_config bdsGrid; Size bdsOutputSize; + uint32_t stride; } grid; }; diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp index 757a5d50..b33e8c77 100644 --- a/src/ipa/ipu3/ipu3.cpp +++ b/src/ipa/ipu3/ipu3.cpp @@ -352,6 +352,9 @@ void IPAIPU3::calculateBdsGrid(const Size &bdsOutputSize) bdsGrid.height = best.height >> bestLog2.height; bdsGrid.block_height_log2 = bestLog2.height; + /* The grid width is aligned to the next multiple of 4 */ + context_.configuration.grid.stride = utils::alignUp(bdsGrid.width, 4); + LOG(IPAIPU3, Debug) << "Best grid found is: (" << (int)bdsGrid.width << " << " << (int)bdsGrid.block_width_log2 << ") x (" << (int)bdsGrid.height << " << " << (int)bdsGrid.block_height_log2 << ")"; From patchwork Thu Sep 30 09:37:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Michel Hautbois X-Patchwork-Id: 13994 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 07993BDC71 for ; Thu, 30 Sep 2021 09:37:35 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B365A691C7; Thu, 30 Sep 2021 11:37:34 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="i/KmHXxM"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DCC5B691B8 for ; Thu, 30 Sep 2021 11:37:21 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:bab4:22c5:662d:e478]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 7E6C0B2B; Thu, 30 Sep 2021 11:37:21 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1632994641; bh=Hz82vcBRtJaofUifx/6e1lRt2lFJ5rNpThsTC2zIwKU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=i/KmHXxMQwp+aQVZi8dVTd2+dSudbAzsRnJglWsmRT33rB0qUEX2CO7hvb3z5wsH0 XeUFi3HVy5ehXr+Sa/rdWHQ0cOy9yiYK05nvy34EVzUxqHwjZjp8DwpQgSJFM9/tzJ E2IoW+6QVBCBWm13fzLQJ5KcxRpQtuvFiDFmxMOw= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Sep 2021 11:37:13 +0200 Message-Id: <20210930093715.73293-11-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210930093715.73293-1-jeanmichel.hautbois@ideasonboard.com> References: <20210930093715.73293-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 10/12] ipa: ipu3: awb: Introduce Black Level Correction 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 pixels output by the camera normally include a black level, because sensors do not always report a signal level of '0' for black. Pixels at or below this level should be considered black and to achieve that, we need to substract an offset to all the pixels. This can be taken into account by reading the lowest value of a special region on sensors which is not exposed to light. This provides a substracting factor to be able to adjust the expected black levels in the resultant images. For a camera outputting 10-bit pixel values (in the range 0 to 1023) a typical black level might be 64. It is a fixed value, obtained by capturing a raw frame with minimum exposure and gain fixed to 1.0 while covering the sensor (the darker the better). We consider it good enough as a very first approximation, until we measure it during a tuning process and include it in a configuration file Signed-off-by: Jean-Michel Hautbois Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/ipa/ipu3/algorithms/black_correction.cpp | 67 ++++++++++++++++++++ src/ipa/ipu3/algorithms/black_correction.h | 28 ++++++++ src/ipa/ipu3/algorithms/meson.build | 1 + src/ipa/ipu3/ipu3.cpp | 2 + 4 files changed, 98 insertions(+) create mode 100644 src/ipa/ipu3/algorithms/black_correction.cpp create mode 100644 src/ipa/ipu3/algorithms/black_correction.h diff --git a/src/ipa/ipu3/algorithms/black_correction.cpp b/src/ipa/ipu3/algorithms/black_correction.cpp new file mode 100644 index 00000000..5b5b5d31 --- /dev/null +++ b/src/ipa/ipu3/algorithms/black_correction.cpp @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Google inc. + * + * black_correction.cpp - IPU3 Optical Black Correction control + */ + +#include "black_correction.h" + +#include + +/** + * \file black_correction.h + */ + +namespace libcamera { + +namespace ipa::ipu3::algorithms { + +/** + * \class BlackCorrection + * \brief A class to handle optical black correction + * + * The pixels output by the camera normally include a black level, because + * sensors do not always report a signal level of '0' for black. Pixels at or + * below this level should be considered black and to achieve that, we need to + * substract an offset to all the pixels. + * + * This can be taken into account by reading the lowest value of a special + * region on sensors which is not exposed to light. This provides a substracting + * factor to be able to adjust the expected black levels in the resultant + * images. + */ + +BlackCorrection::BlackCorrection() +{ +} + +/** + * \brief Fill in the parameter structure, and enable optical black correction + * \param context The shared IPA context + * \param params The IPU3 parameters + * + * Populate the IPU3 parameter structure with the correction values for each + * channel and enable the corresponding ImgU block processing. + */ +void BlackCorrection::prepare([[maybe_unused]] IPAContext &context, + 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 approximation + */ + params->obgrid_param.gr = 64; + params->obgrid_param.r = 64; + params->obgrid_param.b = 64; + params->obgrid_param.gb = 64; + + /* Enable the custom optical black correction processing */ + params->use.obgrid = 1; + params->use.obgrid_param = 1; +} + +} /* namespace ipa::ipu3::algorithms */ + +} /* namespace libcamera */ diff --git a/src/ipa/ipu3/algorithms/black_correction.h b/src/ipa/ipu3/algorithms/black_correction.h new file mode 100644 index 00000000..6486ac5b --- /dev/null +++ b/src/ipa/ipu3/algorithms/black_correction.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Google inc. + * + * black_correction.h - IPU3 Optical Black Correction control + */ +#ifndef __LIBCAMERA_IPU3_ALGORITHMS_BLACK_CORRECTION_H__ +#define __LIBCAMERA_IPU3_ALGORITHMS_BLACK_CORRECTION_H__ + +#include "algorithm.h" + +namespace libcamera { + +namespace ipa::ipu3::algorithms { + +class BlackCorrection : public Algorithm +{ +public: + BlackCorrection(); + + void prepare(IPAContext &context, ipu3_uapi_params *params) override; +}; + +} /* namespace ipa::ipu3::algorithms */ + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_IPU3_ALGORITHMS_BLACK_CORRECTION_H__ */ diff --git a/src/ipa/ipu3/algorithms/meson.build b/src/ipa/ipu3/algorithms/meson.build index deae225b..66877c1b 100644 --- a/src/ipa/ipu3/algorithms/meson.build +++ b/src/ipa/ipu3/algorithms/meson.build @@ -4,5 +4,6 @@ ipu3_ipa_algorithms = files([ 'agc.cpp', 'algorithm.cpp', 'awb.cpp', + 'black_correction.cpp', 'tone_mapping.cpp', ]) diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp index b33e8c77..7cc0fb89 100644 --- a/src/ipa/ipu3/ipu3.cpp +++ b/src/ipa/ipu3/ipu3.cpp @@ -33,6 +33,7 @@ #include "algorithms/agc.h" #include "algorithms/algorithm.h" #include "algorithms/awb.h" +#include "algorithms/black_correction.h" #include "algorithms/tone_mapping.h" #include "libipa/camera_sensor_helper.h" @@ -279,6 +280,7 @@ int IPAIPU3::init(const IPASettings &settings, /* Construct our Algorithms */ algorithms_.push_back(std::make_unique()); algorithms_.push_back(std::make_unique()); + algorithms_.push_back(std::make_unique()); algorithms_.push_back(std::make_unique()); return 0; From patchwork Thu Sep 30 09:37:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Michel Hautbois X-Patchwork-Id: 13993 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 675EBBDC71 for ; Thu, 30 Sep 2021 09:37:34 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 29161691C3; Thu, 30 Sep 2021 11:37:34 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="dC7MMKU8"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0C97A691B9 for ; Thu, 30 Sep 2021 11:37:22 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:bab4:22c5:662d:e478]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id B2F6018BF; Thu, 30 Sep 2021 11:37:21 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1632994641; bh=6XvCGCc2wwMTxdrkPYkCjYBi+jhlZP0I0O+8681ZiIU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=dC7MMKU8ILEVHEDuidndyyPzVKOqmxB3Kvr5ejp4w25+M8MPYFqD3JvxsW/Y1FLVN OyMSEgI+DDQ7mhlEKmLWUHRr3aqLUl2daNz5XP6j2lve4HBLkxugWgRwYHFGBn8cXn 4cjPurB8qwq2aGIwjWAavy66Wt5rqYchE1ksWkOA= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Sep 2021 11:37:14 +0200 Message-Id: <20210930093715.73293-12-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210930093715.73293-1-jeanmichel.hautbois@ideasonboard.com> References: <20210930093715.73293-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 11/12] ipa: ipu3: agc: Rewrite and simplify the brightness loop 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" Now that we know how the AWB statistics are formatted, use a simplified loop in processBrightness() to parse the green values and get the histogram. Signed-off-by: Jean-Michel Hautbois Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/ipa/ipu3/algorithms/agc.cpp | 55 ++++++++++++--------------------- src/ipa/ipu3/algorithms/agc.h | 2 ++ 2 files changed, 22 insertions(+), 35 deletions(-) diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp index 5ff50f4a..46e01fc4 100644 --- a/src/ipa/ipu3/algorithms/agc.cpp +++ b/src/ipa/ipu3/algorithms/agc.cpp @@ -6,6 +6,7 @@ */ #include "agc.h" +#include "awb.h" #include #include @@ -47,9 +48,6 @@ static constexpr uint32_t kMaxExposure = 1976; static constexpr uint32_t knumHistogramBins = 256; static constexpr double kEvGainTarget = 0.5; -/* A cell is 8 bytes and contains averages for RGB values and saturation ratio */ -static constexpr uint8_t kCellSize = 8; - Agc::Agc() : frameCount_(0), lastFrame_(0), iqMean_(0.0), lineDuration_(0s), maxExposureTime_(0s), prevExposure_(0s), prevExposureNoDg_(0s), @@ -57,9 +55,10 @@ Agc::Agc() { } -int Agc::configure([[maybe_unused]] IPAContext &context, - const IPAConfigInfo &configInfo) +int Agc::configure(IPAContext &context, const IPAConfigInfo &configInfo) { + stride_ = context.configuration.grid.stride; + lineDuration_ = configInfo.sensorInfo.lineLength * 1.0s / configInfo.sensorInfo.pixelRate; maxExposureTime_ = kMaxExposure * lineDuration_; @@ -70,37 +69,23 @@ int Agc::configure([[maybe_unused]] IPAContext &context, void Agc::processBrightness(const ipu3_uapi_stats_3a *stats, const ipu3_uapi_grid_config &grid) { - const struct ipu3_uapi_grid_config statsAeGrid = stats->stats_4a_config.awb_config.grid; - Rectangle aeRegion = { statsAeGrid.x_start, - statsAeGrid.y_start, - static_cast(statsAeGrid.x_end - statsAeGrid.x_start) + 1, - static_cast(statsAeGrid.y_end - statsAeGrid.y_start) + 1 }; - Point topleft = aeRegion.topLeft(); - int topleftX = topleft.x >> grid.block_width_log2; - int topleftY = topleft.y >> grid.block_height_log2; - - /* Align to the grid cell width and height */ - uint32_t startX = topleftX << grid.block_width_log2; - uint32_t startY = topleftY * grid.width << grid.block_width_log2; - uint32_t endX = (startX + (aeRegion.size().width >> grid.block_width_log2)) << grid.block_width_log2; - uint32_t i, j; - uint32_t count = 0; - uint32_t hist[knumHistogramBins] = { 0 }; - for (j = topleftY; - j < topleftY + (aeRegion.size().height >> grid.block_height_log2); - j++) { - for (i = startX + startY; i < endX + startY; i += kCellSize) { - /* - * The grid width (and maybe height) is not reliable. - * We observed a bit shift which makes the value 160 to be 32 in the stats grid. - * Use the one passed at init time. - */ - if (stats->awb_raw_buffer.meta_data[i + 4 + j * grid.width] == 0) { - uint8_t Gr = stats->awb_raw_buffer.meta_data[i + 0 + j * grid.width]; - uint8_t Gb = stats->awb_raw_buffer.meta_data[i + 3 + j * grid.width]; - hist[(Gr + Gb) / 2]++; - count++; + + for (unsigned int cellY = 0; cellY < grid.height; cellY++) { + for (unsigned int cellX = 0; cellX < grid.width; cellX++) { + uint32_t cellPosition = cellY * stride_ + cellX + * sizeof(Ipu3AwbCell); + + /* Cast the initial IPU3 structure to simplify the reading */ + const Ipu3AwbCell *cell = + reinterpret_cast( + &stats->awb_raw_buffer.meta_data[cellPosition] + ); + + if (cell->satRatio == 0) { + uint8_t gr = cell->greenRedAvg; + uint8_t gb = cell->greenBlueAvg; + hist[(gr + gb) / 2]++; } } } diff --git a/src/ipa/ipu3/algorithms/agc.h b/src/ipa/ipu3/algorithms/agc.h index e36797d3..64b71c65 100644 --- a/src/ipa/ipu3/algorithms/agc.h +++ b/src/ipa/ipu3/algorithms/agc.h @@ -50,6 +50,8 @@ private: Duration prevExposureNoDg_; Duration currentExposure_; Duration currentExposureNoDg_; + + uint32_t stride_; }; } /* namespace ipa::ipu3::algorithms */ From patchwork Thu Sep 30 09:37:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Michel Hautbois X-Patchwork-Id: 13995 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 AE0C7BDC71 for ; Thu, 30 Sep 2021 09:37:35 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5ACCA691CB; Thu, 30 Sep 2021 11:37:35 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="gJKBOIX8"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 48BBE691BB for ; Thu, 30 Sep 2021 11:37:22 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:bab4:22c5:662d:e478]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id E28032A8; Thu, 30 Sep 2021 11:37:21 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1632994642; bh=7n3rwwG5p25+iqHFrc0LOPVWXaqyLkZ7Kf2dfKGbQQ8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gJKBOIX8uiVvmVJnzImztUbB8n2t2+wkr5lYdp1pO65LcBzFw/3uJzPYxdFerrfKA YKGcNmoe+XOUoDIWsc0xe1E26xAu/pSKEn3gq033R0/1zf6sgnpI95ZQq1THiRVqcL fvtQhjR5Lm//D0rSruZL+5vT6HcNUtUcOvbmAC8o= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Sep 2021 11:37:15 +0200 Message-Id: <20210930093715.73293-13-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210930093715.73293-1-jeanmichel.hautbois@ideasonboard.com> References: <20210930093715.73293-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 12/12] ipa: ipu3: Replace ipa::ipu3::algorithms::Ipu3AwbCell 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 intel-ipu3.h public interface from the kernel does not define how to parse the statistics for a cell. This had to be identified by a process of reverse engineering, and later identifying the structures from [0] leading to our custom definition of struct Ipu3AwbCell. [0] https://chromium.googlesource.com/chromiumos/platform/arc-camera/+/refs/heads/master/hal/intel/include/ia_imaging/awb_public.h To improve the kernel interface, a proposal has been made to the linux-kernel [1] to incorporate the memory layout for each cell into the intel-ipu3 header directly. [1] https://lore.kernel.org/linux-media/20210930092021.65741-1-jeanmichel.hautbois@ideasonboard.com/ Update our local copy of the intel-ipu3.h to match the proposal and change the AGC and AWB algorithms to reference that structure directly, allowing us to remove the deprecated custom Ipu3AwbCell definition. Signed-off-by: Jean-Michel Hautbois Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- include/linux/intel-ipu3.h | 31 +++++++++++++++++++++---- src/ipa/ipu3/algorithms/agc.cpp | 14 +++++------ src/ipa/ipu3/algorithms/awb.cpp | 41 ++++++--------------------------- src/ipa/ipu3/algorithms/awb.h | 10 -------- 4 files changed, 40 insertions(+), 56 deletions(-) diff --git a/include/linux/intel-ipu3.h b/include/linux/intel-ipu3.h index ee0e6d0e..a5a71ca8 100644 --- a/include/linux/intel-ipu3.h +++ b/include/linux/intel-ipu3.h @@ -59,6 +59,29 @@ struct ipu3_uapi_grid_config { __u16 y_end; } __attribute__((packed)); +/** + * struct ipu3_uapi_awb_set_item - Memory layout for each cell in AWB + * + * @Gr_avg: Green average for red lines in the cell. + * @R_avg: Red average in the cell. + * @B_avg: Blue average in the cell. + * @Gb_avg: Green average for blue lines in the cell. + * @sat_ratio: Saturation ratio in the cell. + * @padding0: Unused byte for padding. + * @padding1: Unused byte for padding. + * @padding2: Unused byte for padding. + */ +struct ipu3_uapi_awb_set_item { + unsigned char Gr_avg; + unsigned char R_avg; + unsigned char B_avg; + unsigned char Gb_avg; + unsigned char sat_ratio; + unsigned char padding0; + unsigned char padding1; + unsigned char padding2; +} __attribute__((packed)); + /* * The grid based data is divided into "slices" called set, each slice of setX * refers to ipu3_uapi_grid_config width * height_per_slice. @@ -71,9 +94,9 @@ struct ipu3_uapi_grid_config { (IPU3_UAPI_MAX_BUBBLE_SIZE * IPU3_UAPI_MAX_STRIPES * \ IPU3_UAPI_AWB_MD_ITEM_SIZE) #define IPU3_UAPI_AWB_MAX_BUFFER_SIZE \ - (IPU3_UAPI_AWB_MAX_SETS * \ - (IPU3_UAPI_AWB_SET_SIZE + IPU3_UAPI_AWB_SPARE_FOR_BUBBLES)) - + ((IPU3_UAPI_AWB_MAX_SETS * \ + (IPU3_UAPI_AWB_SET_SIZE + IPU3_UAPI_AWB_SPARE_FOR_BUBBLES)) / \ + sizeof(struct ipu3_uapi_awb_set_item)) /** * struct ipu3_uapi_awb_raw_buffer - AWB raw buffer @@ -82,7 +105,7 @@ struct ipu3_uapi_grid_config { * the average values for each color channel. */ struct ipu3_uapi_awb_raw_buffer { - __u8 meta_data[IPU3_UAPI_AWB_MAX_BUFFER_SIZE] + struct ipu3_uapi_awb_set_item meta_data[IPU3_UAPI_AWB_MAX_BUFFER_SIZE] __attribute__((aligned(32))); } __attribute__((packed)); diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp index 46e01fc4..44008632 100644 --- a/src/ipa/ipu3/algorithms/agc.cpp +++ b/src/ipa/ipu3/algorithms/agc.cpp @@ -6,7 +6,6 @@ */ #include "agc.h" -#include "awb.h" #include #include @@ -73,18 +72,17 @@ void Agc::processBrightness(const ipu3_uapi_stats_3a *stats, for (unsigned int cellY = 0; cellY < grid.height; cellY++) { for (unsigned int cellX = 0; cellX < grid.width; cellX++) { - uint32_t cellPosition = cellY * stride_ + cellX - * sizeof(Ipu3AwbCell); + uint32_t cellPosition = cellY * stride_ + cellX; /* Cast the initial IPU3 structure to simplify the reading */ - const Ipu3AwbCell *cell = - reinterpret_cast( + const ipu3_uapi_awb_set_item *cell = + reinterpret_cast( &stats->awb_raw_buffer.meta_data[cellPosition] ); - if (cell->satRatio == 0) { - uint8_t gr = cell->greenRedAvg; - uint8_t gb = cell->greenBlueAvg; + if (cell->sat_ratio == 0) { + uint8_t gr = cell->Gr_avg; + uint8_t gb = cell->Gb_avg; hist[(gr + gb) / 2]++; } } diff --git a/src/ipa/ipu3/algorithms/awb.cpp b/src/ipa/ipu3/algorithms/awb.cpp index fcd1469f..4558f85a 100644 --- a/src/ipa/ipu3/algorithms/awb.cpp +++ b/src/ipa/ipu3/algorithms/awb.cpp @@ -104,32 +104,6 @@ static constexpr uint32_t kMinGreenLevelInZone = 32; * \brief Gain calculated for the blue channel */ -/** - * \struct Ipu3AwbCell - * \brief Memory layout for each cell in AWB metadata - * - * The Ipu3AwbCell structure is used to get individual values - * such as red average or saturation ratio in a particular cell. - * - * \var Ipu3AwbCell::greenRedAvg - * \brief Green average for red lines in the cell - * - * \var Ipu3AwbCell::redAvg - * \brief Red average in the cell - * - * \var Ipu3AwbCell::blueAvg - * \brief blue average in the cell - * - * \var Ipu3AwbCell::greenBlueAvg - * \brief Green average for blue lines - * - * \var Ipu3AwbCell::satRatio - * \brief Saturation ratio in the cell - * - * \var Ipu3AwbCell::padding - * \brief array of unused bytes for padding - */ - /* Default settings for Bayer noise reduction replicated from the Kernel */ static const struct ipu3_uapi_bnr_static_config imguCssBnrDefaults = { .wb_gains = { 16, 16, 16, 16 }, @@ -243,25 +217,24 @@ void Awb::generateAwbStats(const ipu3_uapi_stats_3a *stats) */ for (unsigned int cellY = 0; cellY < kAwbStatsSizeY * cellsPerZoneY_; cellY++) { for (unsigned int cellX = 0; cellX < kAwbStatsSizeX * cellsPerZoneX_; cellX++) { - uint32_t cellPosition = (cellY * stride_ + cellX) - * sizeof(Ipu3AwbCell); + uint32_t cellPosition = cellY * stride_ + cellX; uint32_t zoneX = cellX / cellsPerZoneX_; uint32_t zoneY = cellY / cellsPerZoneY_; uint32_t awbZonePosition = zoneY * kAwbStatsSizeX + zoneX; /* Cast the initial IPU3 structure to simplify the reading */ - const Ipu3AwbCell *currentCell = - reinterpret_cast( + const ipu3_uapi_awb_set_item *currentCell = + reinterpret_cast( &stats->awb_raw_buffer.meta_data[cellPosition] ); - if (currentCell->satRatio == 0) { + if (currentCell->sat_ratio == 0) { /* The cell is not saturated, use the current cell */ awbStats_[awbZonePosition].counted++; - uint32_t greenValue = currentCell->greenRedAvg + currentCell->greenBlueAvg; + uint32_t greenValue = currentCell->Gr_avg + currentCell->Gb_avg; awbStats_[awbZonePosition].sum.green += greenValue / 2; - awbStats_[awbZonePosition].sum.red += currentCell->redAvg; - awbStats_[awbZonePosition].sum.blue += currentCell->blueAvg; + awbStats_[awbZonePosition].sum.red += currentCell->R_avg; + awbStats_[awbZonePosition].sum.blue += currentCell->B_avg; } } } diff --git a/src/ipa/ipu3/algorithms/awb.h b/src/ipa/ipu3/algorithms/awb.h index b3e0ad82..677384ed 100644 --- a/src/ipa/ipu3/algorithms/awb.h +++ b/src/ipa/ipu3/algorithms/awb.h @@ -23,16 +23,6 @@ namespace ipa::ipu3::algorithms { static constexpr uint32_t kAwbStatsSizeX = 16; static constexpr uint32_t kAwbStatsSizeY = 12; -/* \todo Move the cell layout into intel-ipu3.h kernel header */ -struct Ipu3AwbCell { - unsigned char greenRedAvg; - unsigned char redAvg; - unsigned char blueAvg; - unsigned char greenBlueAvg; - unsigned char satRatio; - unsigned char padding[3]; -} __attribute__((packed)); - struct Accumulator { unsigned int counted; struct {