From patchwork Tue Jun 17 08:29:54 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Plowman X-Patchwork-Id: 23589 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 63987BDE6B for ; Tue, 17 Jun 2025 08:30:19 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B881C68DD4; Tue, 17 Jun 2025 10:30:15 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="ippmbL5n"; dkim-atps=neutral Received: from mail-wr1-x430.google.com (mail-wr1-x430.google.com [IPv6:2a00:1450:4864:20::430]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B7B0D68DD8 for ; Tue, 17 Jun 2025 10:30:06 +0200 (CEST) Received: by mail-wr1-x430.google.com with SMTP id ffacd0b85a97d-3a548a73ff2so4976803f8f.0 for ; Tue, 17 Jun 2025 01:30:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; t=1750149006; x=1750753806; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Ka6w8XlXuyTMARzl8Nb760HyjvSz5j6FevThoPwy1Bo=; b=ippmbL5nQsnxFthvtSSkfZtIyCBhYiLex/J2ISEwnDcDFYcS0Kxz3oOim+MzbgZWX2 BuvZRQkDSdPQMu4fuOiDatVFLaWEPRfgbsCIJCCZ3lnutyF9hgwtDxSd02m8gELqoUvh jIoGr5pojQ7RWG66GG0PkX7mkil+TLvwqx27YEJwxgYel88EbEFu7qvYn1vLUZ2i5iZe GGy1rPHWhCc7MC4vNN/QjA3jHYYYZ/yLXwX4KYUY4v7sWEo0VdT1me80cSr4yhb3AT9T iROV8Qpz4aNPvL0pyXg5dwIfCpYPiWjG+2yTklqntO7NtqFV7nf3awUnF4NCW4iaJV4Z OO7A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750149006; x=1750753806; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Ka6w8XlXuyTMARzl8Nb760HyjvSz5j6FevThoPwy1Bo=; b=JLSCTMRnzT9z9AKoZFKs8wHJUTKoOOVkUzsFYzzypX5UOmZqkyVh0MJnl9fJFNdJfo doNSjeHQYCKJFE8lysEXvyck+MAm2hiHJyJtuf+rCjQv1tgpG6gBoL/NwXEykmHFdC1Z WIEQjWUJwm5kPd97G4zILxXcasEV6U3z9HJ1Uv1f48MQSNnhg2SWbv8+XAthGwS8yrdG d9Arfbqef4FlXMDVaoJkWCNQqLrMk2AE5t6sqcghqxirJ/J0rVmgdlr3Ge/WWmypXNZy EfBWjyVTW4FoQOz9ZemSZhSReeAjcZG1UC0Zayd8wDyWDWqyuUJ0sKyjkCLW7XbTO2Ae XHpw== X-Gm-Message-State: AOJu0YxzxRyp910Pp7qUCL5RBVwBXHw9sUuvh9WgTsp9Po5+NbVtXHy9 P9d+VVLoHq9wwryboD588HXOKIYJL9JFRp07RHEAtZuw29Oq6b2mjlSn1ExLgkhRo3rnTph7rzR AzY8V X-Gm-Gg: ASbGnctZKctboSULaUOjYHxPMessMD8v6AQm4fvMpJS2p7fI5QUhCw+JaVvEF6cor+Y r1pa631c4fo3bihgyGTADQ6uZVzwMNEc/YS8dV8cul48N97SdWYfi5SAzvOMtPnK/Z4I7RNwMBK PG39TqgB9zjMbcJIgqfYrCVqUgvk5kWZp9gkae7NSsBcXs6i+QIJiMjtzugbVdGnw20T5Oiaui3 xOCH2zKmwdrdKDwhYvJa2Lj23m1ue6s3yx8czHmwT6pNg40aGfg1kosbafgmrMLN3R9Udia4MbW mZO/RJQgnsDsGhZp/+/jQ9H/MQ8ADAX1g+BPJfz9hxjvHoWPbYM5y2n1ipOt//Uyqfpy44mLDoZ jO4RWq13/cmU7Xj8VQQ== X-Google-Smtp-Source: AGHT+IGYHsSHGmlki6gW/buxyX97m5rntrA5Bo0C08oXWbswIRROrtJ9wXtFnwzTBJObNc+c4iGkCA== X-Received: by 2002:a05:6000:25eb:b0:3a3:65b5:51d7 with SMTP id ffacd0b85a97d-3a572e2df7bmr11058480f8f.26.1750149005514; Tue, 17 Jun 2025 01:30:05 -0700 (PDT) Received: from raspberrypi.pitowers.org ([2a00:1098:3142:1f:ffc9:aff6:7f7f:893b]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4532e259108sm166062955e9.32.2025.06.17.01.30.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Jun 2025 01:30:05 -0700 (PDT) From: David Plowman To: libcamera-devel@lists.libcamera.org Cc: David Plowman Subject: [PATCH 6/7] ipa: rpi: Update digital gain handling in IPA base and derived classes Date: Tue, 17 Jun 2025 09:29:54 +0100 Message-Id: <20250617082956.5699-7-david.plowman@raspberrypi.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250617082956.5699-1-david.plowman@raspberrypi.com> References: <20250617082956.5699-1-david.plowman@raspberrypi.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" Here we update the digital gain handling to use the value computed by process() in the AgcStatus, not the version that was previously in the AgcPrepareStatus. Because we apply this digital gain directly with no further modification, we have to update it to reflect any exposure/gain quantisation that happens (in IpaBase::applyAGC). We must also run the new platformPrepareAgc() even when we're skipping platformPrepareIsp(), which has been split out of the previous platformPrepareIsp() implementation. Signed-off-by: David Plowman --- src/ipa/rpi/common/ipa_base.cpp | 50 +++++++++++++++++++-------- src/ipa/rpi/common/ipa_base.h | 6 +++- src/ipa/rpi/pisp/pisp.cpp | 61 +++++++++++++++++++++------------ src/ipa/rpi/vc4/vc4.cpp | 28 +++++++++------ 4 files changed, 98 insertions(+), 47 deletions(-) diff --git a/src/ipa/rpi/common/ipa_base.cpp b/src/ipa/rpi/common/ipa_base.cpp index 7af4ea5e..22aadeba 100644 --- a/src/ipa/rpi/common/ipa_base.cpp +++ b/src/ipa/rpi/common/ipa_base.cpp @@ -309,20 +309,23 @@ void IpaBase::start(const ControlList &controls, StartResult *result) frameLengths_.clear(); frameLengths_.resize(FrameLengthsQueueSize, 0s); - /* SwitchMode may supply updated exposure/gain values to use. */ - AgcStatus agcStatus; - agcStatus.exposureTime = 0.0s; - agcStatus.analogueGain = 0.0; + /* + * SwitchMode may supply updated exposure/gain values to use. + * agcStatus_ will store these values for us to use until delayed_status values + * start to appear. + */ + agcStatus_.exposureTime = 0.0s; + agcStatus_.analogueGain = 0.0; - metadata.get("agc.status", agcStatus); - if (agcStatus.exposureTime && agcStatus.analogueGain) { + metadata.get("agc.status", agcStatus_); + if (agcStatus_.exposureTime && agcStatus_.analogueGain) { ControlList ctrls(sensorCtrls_); - applyAGC(&agcStatus, ctrls); + applyAGC(&agcStatus_, ctrls); result->controls = std::move(ctrls); setCameraTimeoutValue(); } /* Make a note of this as it tells us the HDR status of the first few frames. */ - hdrStatus_ = agcStatus.hdr; + hdrStatus_ = agcStatus_.hdr; /* * Initialise frame counts, and decide how many frames must be hidden or @@ -476,7 +479,9 @@ void IpaBase::prepareIsp(const PrepareParams ¶ms) controller_.prepare(&rpiMetadata); /* Actually prepare the ISP parameters for the frame. */ platformPrepareIsp(params, rpiMetadata); - } + platformPrepareAgc(rpiMetadata); + } else + platformPrepareAgc(rpiMetadata); frameCount_++; @@ -528,6 +533,7 @@ void IpaBase::processStats(const ProcessParams ¶ms) if (rpiMetadata.get("agc.status", agcStatus) == 0) { ControlList ctrls(sensorCtrls_); applyAGC(&agcStatus, ctrls, offset); + rpiMetadata.set("agc.status", agcStatus); setDelayedControls.emit(ctrls, ipaContext); setCameraTimeoutValue(); } @@ -1472,9 +1478,6 @@ void IpaBase::reportMetadata(unsigned int ipaContext) } AgcPrepareStatus *agcPrepareStatus = rpiMetadata.getLocked("agc.prepare_status"); - if (agcPrepareStatus) - libcameraMetadata_.set(controls::DigitalGain, agcPrepareStatus->digitalGain); - RPiController::AgcAlgorithm *agc = dynamic_cast( controller_.getAlgorithm("agc")); if (agc) { @@ -1487,6 +1490,13 @@ void IpaBase::reportMetadata(unsigned int ipaContext) : controls::AeStateSearching); } + const AgcStatus *agcStatus = rpiMetadata.getLocked("agc.delayed_status"); + if (agcStatus) + libcameraMetadata_.set(controls::DigitalGain, agcStatus->digitalGain); + else + libcameraMetadata_.set(controls::DigitalGain, agcStatus_.digitalGain); + /* The HDR metadata reporting will use this agcStatus too. */ + LuxStatus *luxStatus = rpiMetadata.getLocked("lux.status"); if (luxStatus) libcameraMetadata_.set(controls::Lux, luxStatus->lux); @@ -1576,7 +1586,6 @@ void IpaBase::reportMetadata(unsigned int ipaContext) * delayed_status to be available, we use the HDR status that came out of the * switchMode call. */ - const AgcStatus *agcStatus = rpiMetadata.getLocked("agc.delayed_status"); const HdrStatus &hdrStatus = agcStatus ? agcStatus->hdr : hdrStatus_; if (!hdrStatus.mode.empty() && hdrStatus.mode != "Off") { int32_t hdrMode = controls::HdrModeOff; @@ -1686,7 +1695,7 @@ void IpaBase::applyFrameDurations(Duration minFrameDuration, Duration maxFrameDu } } -void IpaBase::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls, Duration frameDurationOffset) +void IpaBase::applyAGC(struct AgcStatus *agcStatus, ControlList &ctrls, Duration frameDurationOffset) { const int32_t minGainCode = helper_->gainCode(mode_.minAnalogueGain); const int32_t maxGainCode = helper_->gainCode(mode_.maxAnalogueGain); @@ -1716,6 +1725,19 @@ void IpaBase::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls, Du ctrls.set(V4L2_CID_EXPOSURE, exposureLines); ctrls.set(V4L2_CID_ANALOGUE_GAIN, gainCode); + /* + * We must update the digital gain to make up for any quantisation that happens, and + * communicate that back into the metadata so that it will appear as the "delayed" status. + * (Note that "exposure" is already the "actual" exposure.) + */ + double actualGain = helper_->gain(gainCode); + double ratio = agcStatus->analogueGain / actualGain; + ratio *= agcStatus->exposureTime / exposure; + double newDigitalGain = agcStatus->digitalGain * ratio; + agcStatus->digitalGain = newDigitalGain; + agcStatus->analogueGain = actualGain; + agcStatus->exposureTime = exposure; + /* * At present, there is no way of knowing if a control is read-only. * As a workaround, assume that if the minimum and maximum values of diff --git a/src/ipa/rpi/common/ipa_base.h b/src/ipa/rpi/common/ipa_base.h index ed378f45..943a3c91 100644 --- a/src/ipa/rpi/common/ipa_base.h +++ b/src/ipa/rpi/common/ipa_base.h @@ -73,6 +73,9 @@ protected: /* Remember the HDR status after a mode switch. */ HdrStatus hdrStatus_; + /* Remember the AGC status after a mode switch. */ + AgcStatus agcStatus_; + /* Whether the stitch block (if available) needs to swap buffers. */ bool stitchSwapBuffers_; @@ -86,6 +89,7 @@ private: virtual void platformPrepareIsp(const PrepareParams ¶ms, RPiController::Metadata &rpiMetadata) = 0; + virtual void platformPrepareAgc(RPiController::Metadata &rpiMetadata) = 0; virtual RPiController::StatisticsPtr platformProcessStats(Span mem) = 0; void setMode(const IPACameraSensorInfo &sensorInfo); @@ -98,7 +102,7 @@ private: void fillSyncParams(const PrepareParams ¶ms, unsigned int ipaContext); void reportMetadata(unsigned int ipaContext); void applyFrameDurations(utils::Duration minFrameDuration, utils::Duration maxFrameDuration); - void applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls, + void applyAGC(struct AgcStatus *agcStatus, ControlList &ctrls, utils::Duration frameDurationOffset = utils::Duration(0)); std::map buffers_; diff --git a/src/ipa/rpi/pisp/pisp.cpp b/src/ipa/rpi/pisp/pisp.cpp index e1a804f5..ab70d8f4 100644 --- a/src/ipa/rpi/pisp/pisp.cpp +++ b/src/ipa/rpi/pisp/pisp.cpp @@ -218,13 +218,14 @@ private: void platformPrepareIsp(const PrepareParams ¶ms, RPiController::Metadata &rpiMetadata) override; + void platformPrepareAgc(RPiController::Metadata &rpiMetadata) override; RPiController::StatisticsPtr platformProcessStats(Span mem) override; void handleControls(const ControlList &controls) override; - void applyWBG(const AwbStatus *awbStatus, const AgcPrepareStatus *agcStatus, + void applyWBG(const AwbStatus *awbStatus, double digitalGain, pisp_be_global_config &global); - void applyDgOnly(const AgcPrepareStatus *agcPrepareStatus, pisp_be_global_config &global); + void applyDgOnly(double digitalGain, pisp_be_global_config &global); void applyCAC(const CacStatus *cacStatus, pisp_be_global_config &global); void applyContrast(const ContrastStatus *contrastStatus, pisp_be_global_config &global); @@ -341,7 +342,6 @@ void IpaPiSP::platformPrepareIsp([[maybe_unused]] const PrepareParams ¶ms, PISP_BE_RGB_ENABLE_SHARPEN + PISP_BE_RGB_ENABLE_SAT_CONTROL); NoiseStatus *noiseStatus = rpiMetadata.getLocked("noise.status"); - AgcPrepareStatus *agcPrepareStatus = rpiMetadata.getLocked("agc.prepare_status"); { /* All Frontend config goes first, we do not want to hold the FE lock for long! */ @@ -355,14 +355,6 @@ void IpaPiSP::platformPrepareIsp([[maybe_unused]] const PrepareParams ¶ms, if (blackLevelStatus) applyBlackLevel(blackLevelStatus, global); - AwbStatus *awbStatus = rpiMetadata.getLocked("awb.status"); - if (awbStatus && agcPrepareStatus) { - /* Applies digital gain as well. */ - applyWBG(awbStatus, agcPrepareStatus, global); - } else if (agcPrepareStatus) { - /* Mono sensor fallback for digital gain. */ - applyDgOnly(agcPrepareStatus, global); - } } CacStatus *cacStatus = rpiMetadata.getLocked("cac.status"); @@ -443,6 +435,34 @@ void IpaPiSP::platformPrepareIsp([[maybe_unused]] const PrepareParams ¶ms, } } +void IpaPiSP::platformPrepareAgc(RPiController::Metadata &rpiMetadata) +{ + std::scoped_lock l(rpiMetadata); + + AgcStatus *delayedAgcStatus = rpiMetadata.getLocked("agc.delayed_status"); + /* If no delayed status, use the gain from the last mode switch. */ + double digitalGain = delayedAgcStatus ? delayedAgcStatus->digitalGain : agcStatus_.digitalGain; + AwbStatus *awbStatus = rpiMetadata.getLocked("awb.status"); + + pisp_be_global_config global; + be_->GetGlobal(global); + + { + /* All Frontend config goes first, we do not want to hold the FE lock for long! */ + std::scoped_lock lf(*fe_); + + if (awbStatus) { + /* Applies digital gain as well. */ + applyWBG(awbStatus, digitalGain, global); + } else { + /* Mono sensor fallback for digital gain. */ + applyDgOnly(digitalGain, global); + } + } + + be_->SetGlobal(global); +} + RPiController::StatisticsPtr IpaPiSP::platformProcessStats(Span mem) { using namespace RPiController; @@ -515,12 +535,11 @@ void IpaPiSP::handleControls(const ControlList &controls) } } -void IpaPiSP::applyWBG(const AwbStatus *awbStatus, const AgcPrepareStatus *agcPrepareStatus, +void IpaPiSP::applyWBG(const AwbStatus *awbStatus, double digitalGain, pisp_be_global_config &global) { pisp_wbg_config wbg; pisp_fe_rgby_config rgby = {}; - double dg = agcPrepareStatus ? agcPrepareStatus->digitalGain : 1.0; double minColourGain = std::min({ awbStatus->gainR, awbStatus->gainG, awbStatus->gainB, 1.0 }); /* The 0.1 here doesn't mean much, but just stops arithmetic errors and extreme behaviour. */ double extraGain = 1.0 / std::max({ minColourGain, 0.1 }); @@ -536,9 +555,9 @@ void IpaPiSP::applyWBG(const AwbStatus *awbStatus, const AgcPrepareStatus *agcPr double gainG = awbStatus->gainG * extraGain; double gainB = awbStatus->gainB * extraGain; - wbg.gain_r = clampField(dg * gainR, 14, 10); - wbg.gain_g = clampField(dg * gainG, 14, 10); - wbg.gain_b = clampField(dg * gainB, 14, 10); + wbg.gain_r = clampField(digitalGain * gainR, 14, 10); + wbg.gain_g = clampField(digitalGain * gainG, 14, 10); + wbg.gain_b = clampField(digitalGain * gainB, 14, 10); /* * The YCbCr conversion block should contain the appropriate YCbCr @@ -561,15 +580,15 @@ void IpaPiSP::applyWBG(const AwbStatus *awbStatus, const AgcPrepareStatus *agcPr global.bayer_enables |= PISP_BE_BAYER_ENABLE_WBG; } -void IpaPiSP::applyDgOnly(const AgcPrepareStatus *agcPrepareStatus, pisp_be_global_config &global) +void IpaPiSP::applyDgOnly(double digitalGain, pisp_be_global_config &global) { pisp_wbg_config wbg; - wbg.gain_r = clampField(agcPrepareStatus->digitalGain, 14, 10); - wbg.gain_g = clampField(agcPrepareStatus->digitalGain, 14, 10); - wbg.gain_b = clampField(agcPrepareStatus->digitalGain, 14, 10); + wbg.gain_r = clampField(digitalGain, 14, 10); + wbg.gain_g = clampField(digitalGain, 14, 10); + wbg.gain_b = clampField(digitalGain, 14, 10); - LOG(IPARPI, Debug) << "Applying DG (only) : " << agcPrepareStatus->digitalGain; + LOG(IPARPI, Debug) << "Applying DG (only) : " << digitalGain; be_->SetWbg(wbg); global.bayer_enables |= PISP_BE_BAYER_ENABLE_WBG; diff --git a/src/ipa/rpi/vc4/vc4.cpp b/src/ipa/rpi/vc4/vc4.cpp index 8a7a37c8..b2fec934 100644 --- a/src/ipa/rpi/vc4/vc4.cpp +++ b/src/ipa/rpi/vc4/vc4.cpp @@ -57,14 +57,14 @@ private: int32_t platformConfigure(const ConfigParams ¶ms, ConfigResult *result) override; void platformPrepareIsp(const PrepareParams ¶ms, RPiController::Metadata &rpiMetadata) override; + void platformPrepareAgc([[maybe_unused]] RPiController::Metadata &rpiMetadata) override; RPiController::StatisticsPtr platformProcessStats(Span mem) override; void handleControls(const ControlList &controls) override; bool validateIspControls(); void applyAWB(const struct AwbStatus *awbStatus, ControlList &ctrls); - void applyDG(const struct AgcPrepareStatus *dgStatus, - const struct AwbStatus *awbStatus, ControlList &ctrls); + void applyDG(double digitalGain, const struct AwbStatus *awbStatus, ControlList &ctrls); void applyCCM(const struct CcmStatus *ccmStatus, ControlList &ctrls); void applyBlackLevel(const struct BlackLevelStatus *blackLevelStatus, ControlList &ctrls); void applyGamma(const struct ContrastStatus *contrastStatus, ControlList &ctrls); @@ -78,6 +78,7 @@ private: /* VC4 ISP controls. */ ControlInfoMap ispCtrls_; + ControlList ctrls_; /* LS table allocation passed in from the pipeline handler. */ SharedFD lsTableHandle_; @@ -107,6 +108,7 @@ int32_t IpaVc4::platformStart([[maybe_unused]] const ControlList &controls, int32_t IpaVc4::platformConfigure(const ConfigParams ¶ms, [[maybe_unused]] ConfigResult *result) { ispCtrls_ = params.ispControls; + ctrls_ = ControlList(ispCtrls_); if (!validateIspControls()) { LOG(IPARPI, Error) << "ISP control validation failed."; return -1; @@ -139,7 +141,7 @@ int32_t IpaVc4::platformConfigure(const ConfigParams ¶ms, [[maybe_unused]] C void IpaVc4::platformPrepareIsp([[maybe_unused]] const PrepareParams ¶ms, RPiController::Metadata &rpiMetadata) { - ControlList ctrls(ispCtrls_); + ControlList &ctrls = ctrls_; /* Lock the metadata buffer to avoid constant locks/unlocks. */ std::unique_lock lock(rpiMetadata); @@ -152,9 +154,6 @@ void IpaVc4::platformPrepareIsp([[maybe_unused]] const PrepareParams ¶ms, if (ccmStatus) applyCCM(ccmStatus, ctrls); - AgcPrepareStatus *dgStatus = rpiMetadata.getLocked("agc.prepare_status"); - applyDG(dgStatus, awbStatus, ctrls); - AlscStatus *lsStatus = rpiMetadata.getLocked("alsc.status"); if (lsStatus) applyLS(lsStatus, ctrls); @@ -190,9 +189,18 @@ void IpaVc4::platformPrepareIsp([[maybe_unused]] const PrepareParams ¶ms, if (!lensctrls.empty()) setLensControls.emit(lensctrls); } +} - if (!ctrls.empty()) - setIspControls.emit(ctrls); +void IpaVc4::platformPrepareAgc(RPiController::Metadata &rpiMetadata) +{ + AgcStatus *delayedAgcStatus = rpiMetadata.getLocked("agc.delayed_status"); + double digitalGain = delayedAgcStatus ? delayedAgcStatus->digitalGain : agcStatus_.digitalGain; + AwbStatus *awbStatus = rpiMetadata.getLocked("awb.status"); + + applyDG(digitalGain, awbStatus, ctrls_); + + setIspControls.emit(ctrls_); + ctrls_ = ControlList(ispCtrls_); } RPiController::StatisticsPtr IpaVc4::platformProcessStats(Span mem) @@ -329,11 +337,9 @@ void IpaVc4::applyAWB(const struct AwbStatus *awbStatus, ControlList &ctrls) static_cast(awbStatus->gainB * 1000)); } -void IpaVc4::applyDG(const struct AgcPrepareStatus *dgStatus, +void IpaVc4::applyDG(double digitalGain, const struct AwbStatus *awbStatus, ControlList &ctrls) { - double digitalGain = dgStatus ? dgStatus->digitalGain : 1.0; - if (awbStatus) { /* * We must apply sufficient extra digital gain to stop any of the channel gains being