From patchwork Mon Nov 23 07:37:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Plowman X-Patchwork-Id: 10464 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 E0683BE08A for ; Mon, 23 Nov 2020 07:38:37 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 91BFC632EE; Mon, 23 Nov 2020 08:38:37 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="GSQ6mQRn"; dkim-atps=neutral Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 230C760332 for ; Mon, 23 Nov 2020 08:38:35 +0100 (CET) Received: by mail-wr1-x434.google.com with SMTP id l1so17534141wrb.9 for ; Sun, 22 Nov 2020 23:38:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=V8Nsaokvnt+3p3VR7LiNfq4cMjAbzSycTM1hXK3GrGw=; b=GSQ6mQRncupg35/N1SMZdUxl0Dtl1n5vsMLy2Kw8sPspXOc/MK16OlUWrkzcwN4hBw xeGNntViTck3j+ENpyuEe12cEwVTJTZpJCYKw7dwLYnJsNW/aRboi2WcBAKc8eVDTRPQ 1HJOkv9qEyPoqh9KEotPwH45PYo3U2q9d/o1lkrHYo56BrrjWRC743ihWssLWKJJZmZf SMvoCpXY6EBu3WOZtXmAfyoH+cB35111uUxQOMVZ771x7ZD9v0YGIl1t9AokO3aV2OfH Y3yvsOjgLELqGNb3p8V9qAYIqiIO8RE1hC6tmxgB98P4nTMThztrd3HQFidKa5ODj+Q+ O/YQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=V8Nsaokvnt+3p3VR7LiNfq4cMjAbzSycTM1hXK3GrGw=; b=W2S6rDJHwLwn49hQC0ccg/h87HwLMGNnIfa79psyPajvXCBfnCe023MbCvZ/6Nk9Mb dkAOQUo+jbJP4OpbfKuh8pHot89n/D3/brC/pA4oAqr+2dYGUCn1wPIDPQ5p7Ra75PMv YlfJo79o3iLarLgM7viYKf89k0jSFUXsjNOAPZTQe8045PFD4KnOUKHPhZWrJS1YSyLq oaoZQjefUSpG00+eZvISvZTYo1JPfnk73ajiwkjALYJ81EBROtxRZgjfef3PWMBIMChL Atnz7r6zWx0FLd6cxkhVrF/YmFjFsGLVzwoOw9wDtuvV1mUK4e5PDApCYjq8CXKpuOR1 UsoA== X-Gm-Message-State: AOAM533fTB3B1+Pkt5kq7R4dH6kgJI1bQ8Hg+Tn6UWFgLCMG3udkGsIY NoKtiR5SeyCfJU12yJczYpejh4CIrGjIog26 X-Google-Smtp-Source: ABdhPJwjXCMsbm0hPZwqQLY5NgPXcOY3OFyNdvm7Vhw0hCmN3CLVTkF6EpwbTSLSw+T0Lg0B0rIhXA== X-Received: by 2002:a5d:69d1:: with SMTP id s17mr30048175wrw.104.1606117114547; Sun, 22 Nov 2020 23:38:34 -0800 (PST) Received: from pi4-davidp.lan (plowpeople3.plus.com. [80.229.223.72]) by smtp.gmail.com with ESMTPSA id h15sm17841822wrw.15.2020.11.22.23.38.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 22 Nov 2020 23:38:34 -0800 (PST) From: David Plowman To: libcamera-devel@lists.libcamera.org Date: Mon, 23 Nov 2020 07:37:59 +0000 Message-Id: <20201123073804.3125-6-david.plowman@raspberrypi.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201123073804.3125-1-david.plowman@raspberrypi.com> References: <20201123073804.3125-1-david.plowman@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 05/10] libcamera: ipa: raspberrypi: agc: Fetch AWB status only once 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" Introduce a function to fetch the AwbStatus (fetchAwbStatus), and call it unconditionally at the top of Prepare so that both Prepare and Process know thereafter that it's been done. Signed-off-by: David Plowman Reviewed-by: Naushir Patuck --- src/ipa/raspberrypi/controller/rpi/agc.cpp | 35 +++++++++++----------- src/ipa/raspberrypi/controller/rpi/agc.hpp | 5 ++-- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp b/src/ipa/raspberrypi/controller/rpi/agc.cpp index f0c70a0a..4cf98e66 100644 --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp @@ -235,6 +235,8 @@ void Agc::Prepare(Metadata *image_metadata) int lock_count = lock_count_; lock_count_ = 0; status_.digital_gain = 1.0; + fetchAwbStatus(image_metadata); // always fetch it so that Process knows it's been done + if (status_.total_exposure_value) { // Process has run, so we have meaningful values. DeviceStatus device_status; @@ -300,7 +302,7 @@ void Agc::Process(StatisticsPtr &stats, Metadata *image_metadata) // Some of the exposure has to be applied as digital gain, so work out // what that is. This function also tells us whether it's decided to // "desaturate" the image more quickly. - bool desaturate = applyDigitalGain(image_metadata, gain, target_Y); + bool desaturate = applyDigitalGain(gain, target_Y); // The results have to be filtered so as not to change too rapidly. filterExposure(desaturate); // The last thing is to divide up the exposure value into a shutter time @@ -377,14 +379,19 @@ void Agc::fetchCurrentExposure(Metadata *image_metadata) current_.total_exposure_no_dg = current_.shutter * current_.analogue_gain; } -static double compute_initial_Y(bcm2835_isp_stats *stats, Metadata *image_metadata, +void Agc::fetchAwbStatus(Metadata *image_metadata) +{ + awb_.gain_r = 1.0; // in case not found in metadata + awb_.gain_g = 1.0; + awb_.gain_b = 1.0; + if (image_metadata->Get("awb.status", awb_) != 0) + LOG(RPiAgc, Warning) << "Agc: no AWB status found"; +} + +static double compute_initial_Y(bcm2835_isp_stats *stats, AwbStatus const &awb, double weights[]) { bcm2835_isp_stats_region *regions = stats->agc_stats; - struct AwbStatus awb; - awb.gain_r = awb.gain_g = awb.gain_b = 1.0; // in case no metadata - if (image_metadata->Get("awb.status", awb) != 0) - LOG(RPiAgc, Warning) << "Agc: no AWB status found"; // Note how the calculation below means that equal weights give you // "average" metering (i.e. all pixels equally important). double R_sum = 0, G_sum = 0, B_sum = 0, pixel_sum = 0; @@ -436,7 +443,7 @@ void Agc::computeGain(bcm2835_isp_stats *statistics, Metadata *image_metadata, target_Y = config_.Y_target.Eval(config_.Y_target.Domain().Clip(lux.lux)); target_Y = std::min(EV_GAIN_Y_TARGET_LIMIT, target_Y * ev_gain); - double initial_Y = compute_initial_Y(statistics, image_metadata, + double initial_Y = compute_initial_Y(statistics, awb_, metering_mode_->weights); gain = std::min(10.0, target_Y / (initial_Y + .001)); LOG(RPiAgc, Debug) << "Initially Y " << initial_Y << " target " << target_Y @@ -482,19 +489,13 @@ void Agc::computeTargetExposure(double gain) LOG(RPiAgc, Debug) << "Target total_exposure " << target_.total_exposure; } -bool Agc::applyDigitalGain(Metadata *image_metadata, double gain, - double target_Y) +bool Agc::applyDigitalGain(double gain, double target_Y) { - double dg = 1.0; + double min_colour_gain = std::min({ awb_.gain_r, awb_.gain_g, awb_.gain_b, 1.0 }); + ASSERT(min_colour_gain != 0.0); + double dg = 1.0 / min_colour_gain; // I think this pipeline subtracts black level and rescales before we // get the stats, so no need to worry about it. - struct AwbStatus awb; - if (image_metadata->Get("awb.status", awb) == 0) { - double min_gain = std::min(awb.gain_r, - std::min(awb.gain_g, awb.gain_b)); - dg *= std::max(1.0, 1.0 / min_gain); - } else - LOG(RPiAgc, Warning) << "Agc: no AWB status found"; LOG(RPiAgc, Debug) << "after AWB, target dg " << dg << " gain " << gain << " target_Y " << target_Y; // Finally, if we're trying to reduce exposure but the target_Y is diff --git a/src/ipa/raspberrypi/controller/rpi/agc.hpp b/src/ipa/raspberrypi/controller/rpi/agc.hpp index 2442fc03..e7ac480f 100644 --- a/src/ipa/raspberrypi/controller/rpi/agc.hpp +++ b/src/ipa/raspberrypi/controller/rpi/agc.hpp @@ -83,11 +83,11 @@ private: AgcConfig config_; void housekeepConfig(); void fetchCurrentExposure(Metadata *image_metadata); + void fetchAwbStatus(Metadata *image_metadata); void computeGain(bcm2835_isp_stats *statistics, Metadata *image_metadata, double &gain, double &target_Y); void computeTargetExposure(double gain); - bool applyDigitalGain(Metadata *image_metadata, double gain, - double target_Y); + bool applyDigitalGain(double gain, double target_Y); void filterExposure(bool desaturate); void divideUpExposure(); void writeAndFinish(Metadata *image_metadata, bool desaturate); @@ -95,6 +95,7 @@ private: AgcExposureMode *exposure_mode_; AgcConstraintMode *constraint_mode_; uint64_t frame_count_; + AwbStatus awb_; struct ExposureValues { ExposureValues() : shutter(0), analogue_gain(0), total_exposure(0), total_exposure_no_dg(0) {}