From patchwork Fri Apr 5 14:47:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 19851 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 6D6C6C327C for ; Fri, 5 Apr 2024 14:47:49 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B5E5F61C31; Fri, 5 Apr 2024 16:47:47 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="tB4/bgeY"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BDD1E61C2F for ; Fri, 5 Apr 2024 16:47:46 +0200 (CEST) Received: from pyrite.hamster-moth.ts.net (h175-177-049-156.catv02.itscom.jp [175.177.49.156]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 0092C63B; Fri, 5 Apr 2024 16:47:06 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1712328428; bh=uEiZ9XUT64hX3kGNRz2krIRJMyJCutWL38psNEuR+Yo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=tB4/bgeYp3fMkA5kxax9Haqv7hTZym2K6VqSNtvajcOORI5aUJeBraze+NLI/lutz 8J+m1hZUvBY8bLKsTgXD36tfpN7q+ZtnZrHaS6cMv+wOpm2vpSfwb6zHmqzCSbuJsX gMNdU7Fpd6uJcjAHoWcGgqRuJZVFSy7MZxaLaswU= From: Paul Elder To: libcamera-devel@lists.libcamera.org Cc: Paul Elder Subject: [PATCH 1/5] ipa: rkisp1: agc: Read histogram weights from tuning file Date: Fri, 5 Apr 2024 23:47:25 +0900 Message-Id: <20240405144729.2992219-2-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240405144729.2992219-1-paul.elder@ideasonboard.com> References: <20240405144729.2992219-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add support to the rkisp1 AGC to read histogram weights from the tuning file. As controls for selecting the metering mode are not yet supported, for now hardcode the matrix metering mode, which is the same as what the AGC previously hardcoded. Signed-off-by: Paul Elder --- src/ipa/rkisp1/algorithms/agc.cpp | 80 +++++++++++++++++++++++++++++-- src/ipa/rkisp1/algorithms/agc.h | 6 +++ 2 files changed, 83 insertions(+), 3 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp index 1cd977a0..fd47ba4e 100644 --- a/src/ipa/rkisp1/algorithms/agc.cpp +++ b/src/ipa/rkisp1/algorithms/agc.cpp @@ -17,6 +17,8 @@ #include #include +#include "libcamera/internal/yaml_parser.h" + #include "libipa/histogram.h" /** @@ -42,6 +44,62 @@ static constexpr double kMinAnalogueGain = 1.0; /* \todo Honour the FrameDurationLimits control instead of hardcoding a limit */ static constexpr utils::Duration kMaxShutterSpeed = 60ms; +int Agc::parseMeteringModes(IPAContext &context, const YamlObject &tuningData, + const char *prop) +{ + const YamlObject &yamlMeteringModes = tuningData[prop]; + if (!yamlMeteringModes.isDictionary()) { + LOG(RkISP1Agc, Error) + << "'" << prop << "' parameter not found in tuning file"; + return -EINVAL; + } + + for (const auto &[key, value] : yamlMeteringModes.asDict()) { + if (controls::AeMeteringModeNameValueMap.find(key) == + controls::AeMeteringModeNameValueMap.end()) { + LOG(RkISP1Agc, Warning) + << "Skipping unknown metering mode '" << key << "'"; + continue; + } + + std::vector weights = + value.getList().value_or(std::vector{}); + if (weights.size() != context.hw->numHistogramWeights) { + LOG(RkISP1Agc, Error) + << "Invalid '" << key << "' values: expected " + << context.hw->numHistogramWeights + << " elements, got " << weights.size(); + return -ENODATA; + } + + meteringModes_[controls::AeMeteringModeNameValueMap.at(key)] = weights; + } + + return 0; +} + +uint8_t Agc::predivider(Size &size) +{ + static const std::vector> + pixelCountThresholds = { + { 640 * 480, 3 }, + { 800 * 600, 4 }, + { 1024 * 768, 5 }, + { 1280 * 960, 6 }, + { 1600 * 1200, 8 }, + { 2048 * 1536, 10 }, + { 2600 * 1950, 12 }, + { 4096 * 3072, 16 }, + }; + + unsigned long pixels = size.width * size.height; + for (auto &pair : pixelCountThresholds) + if (pixels < pair.first) + return pair.second; + + return 24; +} + Agc::Agc() { supportsRaw_ = true; @@ -72,6 +130,10 @@ int Agc::init(IPAContext &context, const YamlObject &tuningData) if (ret) return ret; + ret = parseMeteringModes(context, tuningData, "AeMeteringMode"); + if (ret) + return ret; + context.ctrlMap.merge(controls()); return 0; @@ -177,6 +239,7 @@ void Agc::prepare(IPAContext &context, const uint32_t frame, frameContext.agc.gain = context.activeState.agc.automatic.gain; } + /* \todo Remove this when we can set the below with controls */ if (frame > 0) return; @@ -195,14 +258,25 @@ void Agc::prepare(IPAContext &context, const uint32_t frame, params->meas.hst_config.meas_window = context.configuration.agc.measureWindow; /* Produce the luminance histogram. */ params->meas.hst_config.mode = RKISP1_CIF_ISP_HISTOGRAM_MODE_Y_HISTOGRAM; + /* Set an average weighted histogram. */ Span weights{ params->meas.hst_config.hist_weight, context.hw->numHistogramWeights }; - std::fill(weights.begin(), weights.end(), 1); - /* Step size can't be less than 3. */ - params->meas.hst_config.histogram_predivider = 4; + /* \todo Get this from control */ + std::vector &modeWeights = meteringModes_.at(controls::MeteringMatrix); + std::copy(modeWeights.begin(), modeWeights.end(), weights.begin()); + + std::stringstream str; + str << "Histogram weights : "; + for (size_t i = 0; i < context.hw->numHistogramWeights; i++) + str << (int)params->meas.hst_config.hist_weight[i] << " "; + LOG(RkISP1Agc, Debug) << str.str(); + + /* \todo Add a control for this? */ + params->meas.hst_config.histogram_predivider = + predivider(context.configuration.sensor.size); /* Update the configuration for histogram. */ params->module_cfg_update |= RKISP1_CIF_ISP_MODULE_HST; diff --git a/src/ipa/rkisp1/algorithms/agc.h b/src/ipa/rkisp1/algorithms/agc.h index 311d4e94..43e3d5b2 100644 --- a/src/ipa/rkisp1/algorithms/agc.h +++ b/src/ipa/rkisp1/algorithms/agc.h @@ -44,6 +44,10 @@ public: ControlList &metadata) override; private: + int parseMeteringModes(IPAContext &context, const YamlObject &tuningData, + const char *prop); + uint8_t predivider(Size &size); + void fillMetadata(IPAContext &context, IPAFrameContext &frameContext, ControlList &metadata); void parseStatistics(const rkisp1_stat_buffer *stats, @@ -52,6 +56,8 @@ private: Histogram hist_; Span expMeans_; + + std::map> meteringModes_; }; } /* namespace ipa::rkisp1::algorithms */