From patchwork Wed Oct 6 14:00:31 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: 14055 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 9F29AC3243 for ; Wed, 6 Oct 2021 14:01:04 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7AB94691C3; Wed, 6 Oct 2021 16:01:02 +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="H1+jjFvc"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 13BD86023D for ; Wed, 6 Oct 2021 16:01:01 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:843b:c831:54de:6e8c]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id B5A23FFD; Wed, 6 Oct 2021 16:01:00 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1633528860; bh=7iFuYX5Jd9uTHPDAF6PKzCxzUB+2rJANmHloS45ic+M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=H1+jjFvc53r78uWn6kzh4dYrjg6uSlxNfex0+f5qZ1IclLkzYmjdsdWS5pp8yUnL8 odqgGci4tW2tS3GuU94UeYOZnqlsq0H0MxrGGnbsTy7c7nQL8zVIb4wY9BLn++eOS2 qkzwd58X8H3mQrPLcAJP5RIzgydeGLuDsyWSc3w0= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Wed, 6 Oct 2021 16:00:31 +0200 Message-Id: <20211006140041.964542-2-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211006140041.964542-1-jeanmichel.hautbois@ideasonboard.com> References: <20211006140041.964542-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 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 Wed Oct 6 14:00:32 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: 14056 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 1CD4BC324C for ; Wed, 6 Oct 2021 14:01:06 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 337EB691BF; Wed, 6 Oct 2021 16:01:05 +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="FWkTXnZb"; 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 5E03E6023D for ; Wed, 6 Oct 2021 16:01:01 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:843b:c831:54de:6e8c]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id ED33B14D4; Wed, 6 Oct 2021 16:01:00 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1633528861; bh=F9P7sqj743BTrdujHRyPtqe8IfA6wP7KBE7jyNjKHfo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FWkTXnZbaaas0VgGz7TxxJHfyR8ZaEcHabmbauCjDhbNldED4qu4Tx4o+Lrslixml prG0w5Kx1V8Aip5VmbnLLYGmHV5BEa9iE1X0c/2L+ui8Ui/SNliRPW7UwOWB1/PnkQ K8L0h7000AVAkXg8h1RFgUX3/+Q2CbNykJ8DEehU= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Wed, 6 Oct 2021 16:00:32 +0200 Message-Id: <20211006140041.964542-3-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211006140041.964542-1-jeanmichel.hautbois@ideasonboard.com> References: <20211006140041.964542-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 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 | 78 +++++++++++++++++++++++++-------- src/ipa/ipu3/algorithms/awb.h | 5 +-- 2 files changed, 62 insertions(+), 21 deletions(-) diff --git a/src/ipa/ipu3/algorithms/awb.cpp b/src/ipa/ipu3/algorithms/awb.cpp index e05647c9..964d6995 100644 --- a/src/ipa/ipu3/algorithms/awb.cpp +++ b/src/ipa/ipu3/algorithms/awb.cpp @@ -21,26 +21,69 @@ 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 * - * \var IspStatsRegion::gSum - * \brief Sum of the green 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::bSum - * \brief Sum of the blue values in the region + * Each statistics cell represents the average value of the pixels in that cell + * split by colour components. + * + * 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 +200,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 +217,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 +258,6 @@ void Awb::clearAwbStats() awbStats_[i].rSum = 0; awbStats_[i].gSum = 0; awbStats_[i].counted = 0; - awbStats_[i].uncounted = 0; } } @@ -304,7 +346,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 Wed Oct 6 14:00:33 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: 14057 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 F0922C324D for ; Wed, 6 Oct 2021 14:01:06 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id CCFCE691D4; Wed, 6 Oct 2021 16:01:05 +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="L/tBlpbj"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 93A986918C for ; Wed, 6 Oct 2021 16:01:01 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:843b:c831:54de:6e8c]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 308DDFFD; Wed, 6 Oct 2021 16:01:01 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1633528861; bh=qWNIXtj6ph9rvZm64o/MT1At1Cny11I2GXi1xJLOmHg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=L/tBlpbj07Cjw3bWWqrdnSgNCzGeeOJc78b0vPfScluBrEIVa0tY9Wi/iT8p1NMLV 2BYreXOErLud2aFGz4cs2qzEatN5ejSLHJ+/Kz/1fjQkoVUVQTD8Ob+Sj/TnEIaNce U7zwueGVGKjslJy/7mGLSDkDKj2aqyLz9JOmNctM= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Wed, 6 Oct 2021 16:00:33 +0200 Message-Id: <20211006140041.964542-4-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211006140041.964542-1-jeanmichel.hautbois@ideasonboard.com> References: <20211006140041.964542-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 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 | 27 +++++++++++++++------------ src/ipa/ipu3/algorithms/awb.h | 8 +++++--- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/ipa/ipu3/algorithms/awb.cpp b/src/ipa/ipu3/algorithms/awb.cpp index 964d6995..c1a303e2 100644 --- a/src/ipa/ipu3/algorithms/awb.cpp +++ b/src/ipa/ipu3/algorithms/awb.cpp @@ -76,13 +76,16 @@ static constexpr uint32_t kMinGreenLevelInZone = 32; * \var Accumulator::counted * \brief Number of unsaturated cells used to calculate the sums * - * \var Accumulator::rSum + * \var Accumulator::sum + * \brief A structure containing the average red, green and blue sums + * + * \var Accumulator::sum.red * \brief Sum of the average red values of each unsaturated cell in the zone * - * \var Accumulator::gSum + * \var Accumulator::sum.green * \brief Sum of the average green values of each unsaturated cell in the zone * - * \var Accumulator::bSum + * \var Accumulator::sum.blue * \brief Sum of the average blue values of each unsaturated cell in the zone */ @@ -207,10 +210,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); } } @@ -243,9 +246,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; } } } @@ -254,9 +257,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 Wed Oct 6 14:00:34 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: 14058 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 20D7EC323E for ; Wed, 6 Oct 2021 14:01:08 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3AD54691D7; Wed, 6 Oct 2021 16:01:06 +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="wXSjydVN"; 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 CD0CE691BE for ; Wed, 6 Oct 2021 16:01:01 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:843b:c831:54de:6e8c]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 677A51909; Wed, 6 Oct 2021 16:01:01 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1633528861; bh=/1nqqv7d8EaT3GEaQLgVYmBWxVQ86adJo9s6N7mQRmA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=wXSjydVNPkaZ8SCT1rwKti+R0n9UcXTNCcJ4toMmetgZumsyY8E/pzVrrQRt1lJB1 m+WSuAaL4v4/slKxCVnKgPkWgR0jEsZNFFxSHIt8L0LvZfvMZxPEl6+/P9yEPnHcuP k6gWxDQVVsM/kTA2nRHHuaf1BP0Q4WeyCRBZIOKM= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Wed, 6 Oct 2021 16:00:34 +0200 Message-Id: <20211006140041.964542-5-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211006140041.964542-1-jeanmichel.hautbois@ideasonboard.com> References: <20211006140041.964542-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 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 c1a303e2..dba7cec3 100644 --- a/src/ipa/ipu3/algorithms/awb.cpp +++ b/src/ipa/ipu3/algorithms/awb.cpp @@ -224,31 +224,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 Wed Oct 6 14:00:35 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: 14059 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 F2CD1C3243 for ; Wed, 6 Oct 2021 14:01:08 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id EF0C0691D0; Wed, 6 Oct 2021 16:01:06 +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="IsPspLvF"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0EF78691BF for ; Wed, 6 Oct 2021 16:01:02 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:843b:c831:54de:6e8c]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 9B9EF14D4; Wed, 6 Oct 2021 16:01:01 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1633528861; bh=aDIEbCQIZBRLcK5OnUXvXCc8H+HYmCpFIvAIBJhYTok=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=IsPspLvFLyZ/oyQ9tnFfpZHVZ9H1BjCzcvwLj69xUmoCDX+ypZ3Tiw2UydWjjtX9n 3AM57JnycX4nuaUgwrxVQJp+71cscnpkzhK0K6J1a96rV+LSYIPAbfYNH10Bw3q3Mo y3p7Rs+B1ibJSs24R8ZnStX7HvPxvl4tflg2CMvY= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Wed, 6 Oct 2021 16:00:35 +0200 Message-Id: <20211006140041.964542-6-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211006140041.964542-1-jeanmichel.hautbois@ideasonboard.com> References: <20211006140041.964542-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 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 Wed Oct 6 14:00:36 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: 14060 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 96002C323E for ; Wed, 6 Oct 2021 14:01:09 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8B9CB691DB; Wed, 6 Oct 2021 16:01:07 +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="BFM1ioNR"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 29493691C0 for ; Wed, 6 Oct 2021 16:01:02 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:843b:c831:54de:6e8c]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id D038FFFD; Wed, 6 Oct 2021 16:01:01 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1633528861; bh=MtJBvRXCFscX6hWXAb7jb+FkwKKBQ7Qsxg/siVeKt/w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BFM1ioNRQnH8rOh+ulB9G/FOc6qptHMLSPPiDjAXY6Z2m3cEkFxBCjOCYSpb9i1+c yfd1yMqWX2rgo0M3aZ7HzaYEbn5p6dv6S9d6n51SDJeIivKVrKvPU5G7xLNww2voZu BNAHegTDTXZYwPkkkqTP4LkF3813c8eIBiDCRfmE= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Wed, 6 Oct 2021 16:00:36 +0200 Message-Id: <20211006140041.964542-7-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211006140041.964542-1-jeanmichel.hautbois@ideasonboard.com> References: <20211006140041.964542-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 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 Wed Oct 6 14:00:37 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: 14061 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 E3E51C323E for ; Wed, 6 Oct 2021 14:01:10 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A33F4691BF; Wed, 6 Oct 2021 16:01:10 +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="fPkpxKOL"; 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 60136691C2 for ; Wed, 6 Oct 2021 16:01:02 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:843b:c831:54de:6e8c]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 1161E1909; Wed, 6 Oct 2021 16:01:02 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1633528862; bh=xoWuOp6/4P9/LAbzl7B9GMLLcrfZ/5bjwLZ3tnhnxGo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fPkpxKOLsqMY4imnE1QUo2W+4/h8T+2d2i9D2KGxRVZmiZmighYX3Uo04wZJ8gRVw EazXdAyDBKfGKeyFJ+rku4I5SnJbDkSN8bWi6Gztfhj3EBVNYwx6G6n9za1VbOgk9i /da7jTqhe5BAKG/JKiKLIcvUV6+N5STzpRfJweSA= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Wed, 6 Oct 2021 16:00:37 +0200 Message-Id: <20211006140041.964542-8-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211006140041.964542-1-jeanmichel.hautbois@ideasonboard.com> References: <20211006140041.964542-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 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 dba7cec3..1c294f31 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; /** @@ -173,6 +172,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. @@ -209,7 +226,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; @@ -224,19 +241,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 Wed Oct 6 14:00:38 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: 14065 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 83BABC323E for ; Wed, 6 Oct 2021 14:01:13 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 39D08691C9; Wed, 6 Oct 2021 16:01:13 +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="OG1X8AWO"; 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 D435E691C5 for ; Wed, 6 Oct 2021 16:01:02 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:843b:c831:54de:6e8c]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 46F25FFD; Wed, 6 Oct 2021 16:01:02 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1633528862; bh=3jseKx07R09HLzRif7yei3tfCVJt/so1W8hVpvcQ2Sw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=OG1X8AWOqc3ZDywxVwd5bQ3Q3tfuS/rLYoyBx1cy79deySJUgVsnFNWWxc64z3ABJ IExyHGdgBqVM2zoo0ckoPUcWKEKSP0wYpsOZ5dtWYkWOc952WryqMyzslYL9fePR5C y6g5JYwNm5kdQkgWq38Ywz56a4pHCwthnJtnVOKU= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Wed, 6 Oct 2021 16:00:38 +0200 Message-Id: <20211006140041.964542-9-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211006140041.964542-1-jeanmichel.hautbois@ideasonboard.com> References: <20211006140041.964542-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 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 1c294f31..2d875d0b 100644 --- a/src/ipa/ipu3/algorithms/awb.cpp +++ b/src/ipa/ipu3/algorithms/awb.cpp @@ -317,6 +317,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; } @@ -380,15 +381,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 Wed Oct 6 14:00:39 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: 14062 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 56F8EC323E for ; Wed, 6 Oct 2021 14:01:11 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id F2EEB691DE; Wed, 6 Oct 2021 16:01:10 +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="btt/qmd5"; 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 029AA691C6 for ; Wed, 6 Oct 2021 16:01:02 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:843b:c831:54de:6e8c]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 7DA0214D4; Wed, 6 Oct 2021 16:01:02 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1633528862; bh=gRHZ6MrYLBs6TF+k9pT9sLZTUjZaZtXT97+shNdrPPs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=btt/qmd5w6G5OftW+JFK8qxoNuzI/Nh77KU70L0es5FMGUnJinrQJiYBbUEoCojmQ E/ZsON7zxKhqv3YIxAkX/CBEJNUxsMIsImmDfbcuDdwgOlI3BJfIuErXPNIVUqAJaS uD1ceV3opQTfVafXb36YignPZHMo497XCK/xMlcM= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Wed, 6 Oct 2021 16:00:39 +0200 Message-Id: <20211006140041.964542-10-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211006140041.964542-1-jeanmichel.hautbois@ideasonboard.com> References: <20211006140041.964542-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 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 no longer 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 | 6 ++++++ 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/ipa/ipu3/algorithms/awb.cpp b/src/ipa/ipu3/algorithms/awb.cpp index 2d875d0b..3cff9aa4 100644 --- a/src/ipa/ipu3/algorithms/awb.cpp +++ b/src/ipa/ipu3/algorithms/awb.cpp @@ -176,6 +176,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)); @@ -238,8 +239,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 @@ -247,7 +247,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_; @@ -322,13 +322,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) { @@ -340,7 +339,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..06f53fbe 100644 --- a/src/ipa/ipu3/ipu3.cpp +++ b/src/ipa/ipu3/ipu3.cpp @@ -91,6 +91,9 @@ * * \var IPASessionConfiguration::grid::bdsOutputSize * \brief BDS output size configured by the pipeline handler + * + * \var IPASessionConfiguration::grid::stride + * \brief Number of cells on one line including the ImgU padding */ /** @@ -352,6 +355,9 @@ void IPAIPU3::calculateBdsGrid(const Size &bdsOutputSize) bdsGrid.height = best.height >> bestLog2.height; bdsGrid.block_height_log2 = bestLog2.height; + /* The ImgU pads the lines to a multiple of 4 cells. */ + 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 Wed Oct 6 14:00:40 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: 14064 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 A839EC323E for ; Wed, 6 Oct 2021 14:01:12 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5C868691E3; Wed, 6 Oct 2021 16:01:12 +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="HfXZ/lio"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3CB9B691B9 for ; Wed, 6 Oct 2021 16:01:03 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:843b:c831:54de:6e8c]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id B584C1909; Wed, 6 Oct 2021 16:01:02 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1633528862; bh=2YCuR9APHq6A/RiU6Vp0nBlesxn1903OFYld5uk3tyU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HfXZ/liosrXbCnBktz+xdeqNQ581hff3yloUzEhGHNCq+EGVBe5dnpolMESKzB1sS H90/XOJRuadxTmKt3+uNvAxmpNekoinXz2ieOsj+eH4MNiB+zr8KEH8iMuSn9IF9pG SrNhX3i+B2/ZcB3mUYp5izb3Y1B9QmQhxh2USs3E= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Wed, 6 Oct 2021 16:00:40 +0200 Message-Id: <20211006140041.964542-11-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211006140041.964542-1-jeanmichel.hautbois@ideasonboard.com> References: <20211006140041.964542-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 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 resulting 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/blc.cpp | 66 +++++++++++++++++++++++++++++ src/ipa/ipu3/algorithms/blc.h | 28 ++++++++++++ src/ipa/ipu3/algorithms/meson.build | 1 + src/ipa/ipu3/ipu3.cpp | 2 + 4 files changed, 97 insertions(+) create mode 100644 src/ipa/ipu3/algorithms/blc.cpp create mode 100644 src/ipa/ipu3/algorithms/blc.h diff --git a/src/ipa/ipu3/algorithms/blc.cpp b/src/ipa/ipu3/algorithms/blc.cpp new file mode 100644 index 00000000..df56e292 --- /dev/null +++ b/src/ipa/ipu3/algorithms/blc.cpp @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Google inc. + * + * blc.cpp - IPU3 Black Level Correction control + */ + +#include "blc.h" + +#include + +/** + * \file blc.h + */ + +namespace libcamera { + +namespace ipa::ipu3::algorithms { + +/** + * \class BlackLevelCorrection + * \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. To achieve that, the ImgU BLC + * algorithm subtracts a configurable offset from all pixels. + * + * The black level can be measured at runtime from an optical dark region of the + * camera sensor, or measured during the camera tuning process. The first option + * isn't currently supported. + */ + +BlackLevelCorrection::BlackLevelCorrection() +{ +} + +/** + * \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 BlackLevelCorrection::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 rough 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/blc.h b/src/ipa/ipu3/algorithms/blc.h new file mode 100644 index 00000000..4b7cb483 --- /dev/null +++ b/src/ipa/ipu3/algorithms/blc.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Google inc. + * + * black_correction.h - IPU3 Black Level Correction control + */ +#ifndef __LIBCAMERA_IPU3_ALGORITHMS_BLC_H__ +#define __LIBCAMERA_IPU3_ALGORITHMS_BLC_H__ + +#include "algorithm.h" + +namespace libcamera { + +namespace ipa::ipu3::algorithms { + +class BlackLevelCorrection : public Algorithm +{ +public: + BlackLevelCorrection(); + + void prepare(IPAContext &context, ipu3_uapi_params *params) override; +}; + +} /* namespace ipa::ipu3::algorithms */ + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_IPU3_ALGORITHMS_BLC_H__ */ diff --git a/src/ipa/ipu3/algorithms/meson.build b/src/ipa/ipu3/algorithms/meson.build index deae225b..3ec42f72 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', + 'blc.cpp', 'tone_mapping.cpp', ]) diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp index 06f53fbe..6d9bbf39 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/blc.h" #include "algorithms/tone_mapping.h" #include "libipa/camera_sensor_helper.h" @@ -282,6 +283,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 Wed Oct 6 14:00:41 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: 14063 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 03A21C323E for ; Wed, 6 Oct 2021 14:01:12 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C53D8691BD; Wed, 6 Oct 2021 16:01:11 +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="F1HD3mKl"; 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 7455C691C8 for ; Wed, 6 Oct 2021 16:01:03 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:843b:c831:54de:6e8c]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id EBCF51B40; Wed, 6 Oct 2021 16:01:02 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1633528863; bh=RCQm71BtPRF8XwombeKR8j13lqIYjNbSGR++XWfr/cM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=F1HD3mKl+zgmy5YatsennODyxWDBQK2q6zASi7Z63OYpvE6ICHFEsWdk0+lNP2Hm6 2g6c/Y85zLyZI7tD46pI1fMMQRq349tWV/HfkxJkeHN0lRxlgMZDUq463fn4XXTVkz OTKd505kI1QogNAsKUUDZXYTvo4DHEWu6hGXimgY= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Wed, 6 Oct 2021 16:00:41 +0200 Message-Id: <20211006140041.964542-12-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211006140041.964542-1-jeanmichel.hautbois@ideasonboard.com> References: <20211006140041.964542-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 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 | 54 ++++++++++++--------------------- src/ipa/ipu3/algorithms/agc.h | 2 ++ 2 files changed, 21 insertions(+), 35 deletions(-) diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp index 5ff50f4a..4f0d16c6 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,22 @@ 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); + + 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 Wed Oct 6 14:00:42 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: 14066 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 08115C323E for ; Wed, 6 Oct 2021 14:01:14 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B8C3D691E8; Wed, 6 Oct 2021 16:01:13 +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="R7lOa3OS"; 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 AA88A691C9 for ; Wed, 6 Oct 2021 16:01:03 +0200 (CEST) Received: from tatooine.ideasonboard.com (unknown [IPv6:2a01:e0a:169:7140:843b:c831:54de:6e8c]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 2EFF714D4; Wed, 6 Oct 2021 16:01:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1633528863; bh=agiHXjCTwpFN0x9X3XAlg4m4a+YmxpMnOpxleBwCk7Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=R7lOa3OSXS3CVVmVWG4IxKvcuiDQGb41pJg4EseY9Dm77ISF4pAxjGltgUZlF/x1u 68DF2x8H0iOoYJGv/EmXaOPXo10QE07mfv89jdJyMDaV4lmUNA83CxEm02OWyul49C mOk1gIID19i1yFHhGw1Y1agNYTjMRF7ivympxqjI= From: Jean-Michel Hautbois To: libcamera-devel@lists.libcamera.org Date: Wed, 6 Oct 2021 16:00:42 +0200 Message-Id: <20211006140041.964542-13-jeanmichel.hautbois@ideasonboard.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211006140041.964542-1-jeanmichel.hautbois@ideasonboard.com> References: <20211006140041.964542-1-jeanmichel.hautbois@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 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/20211005202019.253353-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 | 32 +++++++++++++++++++++---- 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(+), 57 deletions(-) diff --git a/include/linux/intel-ipu3.h b/include/linux/intel-ipu3.h index ee0e6d0e..b18b28a0 100644 --- a/include/linux/intel-ipu3.h +++ b/include/linux/intel-ipu3.h @@ -59,17 +59,39 @@ 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: Percentage of pixels over a given threshold set in + * ipu3_uapi_awb_config_s, coded from 0 to 255. + * @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. */ #define IPU3_UAPI_AWB_MAX_SETS 60 /* Based on grid size 80 * 60 and cell size 16 x 16 */ -#define IPU3_UAPI_AWB_SET_SIZE 1280 -#define IPU3_UAPI_AWB_MD_ITEM_SIZE 8 +#define IPU3_UAPI_AWB_SET_SIZE 160 #define IPU3_UAPI_AWB_SPARE_FOR_BUBBLES \ - (IPU3_UAPI_MAX_BUBBLE_SIZE * IPU3_UAPI_MAX_STRIPES * \ - IPU3_UAPI_AWB_MD_ITEM_SIZE) + (IPU3_UAPI_MAX_BUBBLE_SIZE * IPU3_UAPI_MAX_STRIPES) #define IPU3_UAPI_AWB_MAX_BUFFER_SIZE \ (IPU3_UAPI_AWB_MAX_SETS * \ (IPU3_UAPI_AWB_SET_SIZE + IPU3_UAPI_AWB_SPARE_FOR_BUBBLES)) @@ -82,7 +104,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 4f0d16c6..5eafe82c 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,17 +72,16 @@ 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; - 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 3cff9aa4..e2b18336 100644 --- a/src/ipa/ipu3/algorithms/awb.cpp +++ b/src/ipa/ipu3/algorithms/awb.cpp @@ -108,32 +108,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 }, @@ -247,25 +221,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 {