From patchwork Mon Nov 16 16:49:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Plowman X-Patchwork-Id: 10434 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 D0303BE082 for ; Mon, 16 Nov 2020 16:49:32 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9EF39632DE; Mon, 16 Nov 2020 17:49:32 +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="NidqvYhV"; dkim-atps=neutral Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A6668632D8 for ; Mon, 16 Nov 2020 17:49:29 +0100 (CET) Received: by mail-wr1-x436.google.com with SMTP id j7so19410086wrp.3 for ; Mon, 16 Nov 2020 08:49:29 -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=3jOTqsdM+5vSReHOduxhhHeWX+jcNQzjs9vGsaKAjj8=; b=NidqvYhVeTQ16nbibmCfTfc8gH3CR+macAriZ0dsfCosr1dbDfzlnANSHKhtRb9x5q QqrSpX6WtBeVHbujcaasWrU9EF9a7v2CZM1HzTdAixVGHo9gRdyIUvAaW1bcjxqf2+Mw 8sJfec3CWnfcABuD3SAWA/NLbBmzLPjB4NevLeD5DUyD89olhpmdRLkYmtfaDtVdwqpu w1mx6LeLpzsgXP3mScAnLLH6kb5KAjAArTUA4axdXehE5EEg7g3kD6FCbJxI6PGsWF5P Fb344FX/E9sKwe9LFkeod99pnB94y12q/RsB26O1QrOb3gCKpHAWRZWVg4/KP8/byIM2 KIcw== 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=3jOTqsdM+5vSReHOduxhhHeWX+jcNQzjs9vGsaKAjj8=; b=PRIOU44nijD2JKVoG/3WvKwDc2k1FLXbpFEufoSArf6LnsQU0xfZPibdfFz1XYUnF0 UUa92j6N/dVI/Js7NancrqfjMhNlqb5UXixu+XPDg5Rzk2vjBCndAyCGBonSH+GRo0QF hDqewKXf33gL9Atodft3mTdHhDpGkKEuPNQjE+caacSBaZcKg/56afbcquRqyeESIute gwU53xOHbTNvOJz0GFN6U052WiyVgfuvvJ28l45bDzIEnJQTRf8g1Tw0xqMibBYxM1qE hqWdrFHXKs956hoA0od9pAZc1ynwUwGo/+LNQn0YOt7FQFCKqz4ME5wr2cLcxc/ujkAq GVMw== X-Gm-Message-State: AOAM533ybtmjC6XXZRn3/xtgdjPt0OTNiWQ1Opk1mBoUw7dUrGYtbSDE vGFAJAWDnTxS+OpFCVPT+FVvTP4rpeYD3w== X-Google-Smtp-Source: ABdhPJwA/o677mH523dHvj34Pah/tT3vRGIqXOvqVLXQj6UMJghFfsr7uWFGGCC+dYOBaD2uZkIpCQ== X-Received: by 2002:adf:e88b:: with SMTP id d11mr19378694wrm.4.1605545369068; Mon, 16 Nov 2020 08:49:29 -0800 (PST) Received: from pi4-davidp.lan (plowpeople3.plus.com. [80.229.223.72]) by smtp.gmail.com with ESMTPSA id q16sm23716973wrn.13.2020.11.16.08.49.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Nov 2020 08:49:28 -0800 (PST) From: David Plowman To: libcamera-devel@lists.libcamera.org Date: Mon, 16 Nov 2020 16:49:13 +0000 Message-Id: <20201116164918.2055-6-david.plowman@raspberrypi.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201116164918.2055-1-david.plowman@raspberrypi.com> References: <20201116164918.2055-1-david.plowman@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 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 | 37 ++++++++++++---------- src/ipa/raspberrypi/controller/rpi/agc.hpp | 5 +-- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp b/src/ipa/raspberrypi/controller/rpi/agc.cpp index ead28398..6de56def 100644 --- a/src/ipa/raspberrypi/controller/rpi/agc.cpp +++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp @@ -5,6 +5,8 @@ * agc.cpp - AGC/AEC control algorithm */ +#include + #include #include "linux/bcm2835-isp.h" @@ -235,6 +237,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; @@ -301,7 +305,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 @@ -378,14 +382,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; @@ -437,7 +446,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 @@ -483,19 +492,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) {}