From 93802f600cf4c3bf15c9d044b980927615e800f4 Mon Sep 17 00:00:00 2001 From: Jean-Michel Hautbois Date: Wed, 18 Aug 2021 17:54:03 +0200 Subject: ipa: ipu3: Move IPU3 agc into algorithms Now that the interface is properly used by the AGC class, move it into ipa::ipu3::algorithms and let the loops do the calls. As we need to exchange the exposure_ and gain_ by passing them through the FrameContext, use the calculated values in setControls() function to ease the reading. Signed-off-by: Jean-Michel Hautbois Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/ipa/ipu3/algorithms/agc.cpp | 200 ++++++++++++++++++++++++++++++++++++ src/ipa/ipu3/algorithms/agc.h | 60 +++++++++++ src/ipa/ipu3/algorithms/meson.build | 1 + src/ipa/ipu3/ipu3.cpp | 20 ++-- src/ipa/ipu3/ipu3_agc.cpp | 200 ------------------------------------ src/ipa/ipu3/ipu3_agc.h | 60 ----------- src/ipa/ipu3/meson.build | 1 - 7 files changed, 269 insertions(+), 273 deletions(-) create mode 100644 src/ipa/ipu3/algorithms/agc.cpp create mode 100644 src/ipa/ipu3/algorithms/agc.h delete mode 100644 src/ipa/ipu3/ipu3_agc.cpp delete mode 100644 src/ipa/ipu3/ipu3_agc.h (limited to 'src/ipa') diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp new file mode 100644 index 00000000..e4598b2e --- /dev/null +++ b/src/ipa/ipu3/algorithms/agc.cpp @@ -0,0 +1,200 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Ideas On Board + * + * ipu3_agc.cpp - AGC/AEC control algorithm + */ + +#include "agc.h" + +#include +#include +#include + +#include + +#include + +#include "libipa/histogram.h" + +namespace libcamera { + +using namespace std::literals::chrono_literals; + +namespace ipa::ipu3::algorithms { + +LOG_DEFINE_CATEGORY(IPU3Agc) + +/* Number of frames to wait before calculating stats on minimum exposure */ +static constexpr uint32_t kInitialFrameMinAECount = 4; +/* Number of frames to wait between new gain/exposure estimations */ +static constexpr uint32_t kFrameSkipCount = 6; + +/* Maximum ISO value for analogue gain */ +static constexpr uint32_t kMinISO = 100; +static constexpr uint32_t kMaxISO = 1500; + +/* Maximum analogue gain value + * \todo grab it from a camera helper */ +static constexpr uint32_t kMinGain = kMinISO / 100; +static constexpr uint32_t kMaxGain = kMaxISO / 100; + +/* \todo use calculated value based on sensor */ +static constexpr uint32_t kMinExposure = 1; +static constexpr uint32_t kMaxExposure = 1976; + +/* Histogram constants */ +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), + currentExposure_(0s), currentExposureNoDg_(0s) +{ +} + +int Agc::configure(IPAContext &context, const IPAConfigInfo &configInfo) +{ + aeGrid_ = context.configuration.grid.bdsGrid; + + lineDuration_ = configInfo.sensorInfo.lineLength * 1.0s + / configInfo.sensorInfo.pixelRate; + maxExposureTime_ = kMaxExposure * lineDuration_; + + return 0; +} + +void Agc::processBrightness(const ipu3_uapi_stats_3a *stats) +{ + 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 >> aeGrid_.block_width_log2; + int topleftY = topleft.y >> aeGrid_.block_height_log2; + + /* Align to the grid cell width and height */ + uint32_t startX = topleftX << aeGrid_.block_width_log2; + uint32_t startY = topleftY * aeGrid_.width << aeGrid_.block_width_log2; + uint32_t endX = (startX + (aeRegion.size().width >> aeGrid_.block_width_log2)) << aeGrid_.block_width_log2; + uint32_t i, j; + uint32_t count = 0; + + uint32_t hist[knumHistogramBins] = { 0 }; + for (j = topleftY; + j < topleftY + (aeRegion.size().height >> aeGrid_.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 * aeGrid_.width] == 0) { + uint8_t Gr = stats->awb_raw_buffer.meta_data[i + 0 + j * aeGrid_.width]; + uint8_t Gb = stats->awb_raw_buffer.meta_data[i + 3 + j * aeGrid_.width]; + hist[(Gr + Gb) / 2]++; + count++; + } + } + } + + /* Estimate the quantile mean of the top 2% of the histogram */ + iqMean_ = Histogram(Span(hist)).interQuantileMean(0.98, 1.0); +} + +void Agc::filterExposure() +{ + double speed = 0.2; + if (prevExposure_ == 0s) { + /* DG stands for digital gain.*/ + prevExposure_ = currentExposure_; + prevExposureNoDg_ = currentExposureNoDg_; + } else { + /* + * If we are close to the desired result, go faster to avoid making + * multiple micro-adjustments. + * \ todo: Make this customisable? + */ + if (prevExposure_ < 1.2 * currentExposure_ && + prevExposure_ > 0.8 * currentExposure_) + speed = sqrt(speed); + + prevExposure_ = speed * currentExposure_ + + prevExposure_ * (1.0 - speed); + prevExposureNoDg_ = speed * currentExposureNoDg_ + + prevExposureNoDg_ * (1.0 - speed); + } + /* + * We can't let the no_dg exposure deviate too far below the + * total exposure, as there might not be enough digital gain available + * in the ISP to hide it (which will cause nasty oscillation). + */ + double fastReduceThreshold = 0.4; + if (prevExposureNoDg_ < + prevExposure_ * fastReduceThreshold) + prevExposureNoDg_ = prevExposure_ * fastReduceThreshold; + LOG(IPU3Agc, Debug) << "After filtering, total_exposure " << prevExposure_; +} + +void Agc::lockExposureGain(uint32_t &exposure, double &gain) +{ + /* Algorithm initialization should wait for first valid frames */ + /* \todo - have a number of frames given by DelayedControls ? + * - implement a function for IIR */ + if ((frameCount_ < kInitialFrameMinAECount) || (frameCount_ - lastFrame_ < kFrameSkipCount)) + return; + + /* Are we correctly exposed ? */ + if (std::abs(iqMean_ - kEvGainTarget * knumHistogramBins) <= 1) { + LOG(IPU3Agc, Debug) << "!!! Good exposure with iqMean = " << iqMean_; + } else { + double newGain = kEvGainTarget * knumHistogramBins / iqMean_; + + /* extracted from Rpi::Agc::computeTargetExposure */ + libcamera::utils::Duration currentShutter = exposure * lineDuration_; + currentExposureNoDg_ = currentShutter * gain; + LOG(IPU3Agc, Debug) << "Actual total exposure " << currentExposureNoDg_ + << " Shutter speed " << currentShutter + << " Gain " << gain; + currentExposure_ = currentExposureNoDg_ * newGain; + libcamera::utils::Duration maxTotalExposure = maxExposureTime_ * kMaxGain; + currentExposure_ = std::min(currentExposure_, maxTotalExposure); + LOG(IPU3Agc, Debug) << "Target total exposure " << currentExposure_; + + /* \todo: estimate if we need to desaturate */ + filterExposure(); + + libcamera::utils::Duration newExposure = 0.0s; + if (currentShutter < maxExposureTime_) { + exposure = std::clamp(static_cast(exposure * currentExposure_ / currentExposureNoDg_), kMinExposure, kMaxExposure); + newExposure = currentExposure_ / exposure; + gain = std::clamp(static_cast(gain * currentExposure_ / newExposure), kMinGain, kMaxGain); + } else if (currentShutter >= maxExposureTime_) { + gain = std::clamp(static_cast(gain * currentExposure_ / currentExposureNoDg_), kMinGain, kMaxGain); + newExposure = currentExposure_ / gain; + exposure = std::clamp(static_cast(exposure * currentExposure_ / newExposure), kMinExposure, kMaxExposure); + } + LOG(IPU3Agc, Debug) << "Adjust exposure " << exposure * lineDuration_ << " and gain " << gain; + } + lastFrame_ = frameCount_; +} + +void Agc::process(IPAContext &context, const ipu3_uapi_stats_3a *stats) +{ + uint32_t &exposure = context.frameContext.agc.exposure; + double &gain = context.frameContext.agc.gain; + processBrightness(stats); + lockExposureGain(exposure, gain); + frameCount_++; +} + +} /* namespace ipa::ipu3::algorithms */ + +} /* namespace libcamera */ diff --git a/src/ipa/ipu3/algorithms/agc.h b/src/ipa/ipu3/algorithms/agc.h new file mode 100644 index 00000000..1739d2fd --- /dev/null +++ b/src/ipa/ipu3/algorithms/agc.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Ideas On Board + * + * agc.h - IPU3 AGC/AEC control algorithm + */ +#ifndef __LIBCAMERA_IPU3_ALGORITHMS_AGC_H__ +#define __LIBCAMERA_IPU3_ALGORITHMS_AGC_H__ + +#include + +#include + +#include + +#include "algorithm.h" + +namespace libcamera { + +struct IPACameraSensorInfo; + +namespace ipa::ipu3::algorithms { + +using utils::Duration; + +class Agc : public Algorithm +{ +public: + Agc(); + ~Agc() = default; + + int configure(IPAContext &context, const IPAConfigInfo &configInfo) override; + void process(IPAContext &context, const ipu3_uapi_stats_3a *stats) override; + +private: + void processBrightness(const ipu3_uapi_stats_3a *stats); + void filterExposure(); + void lockExposureGain(uint32_t &exposure, double &gain); + + struct ipu3_uapi_grid_config aeGrid_; + + uint64_t frameCount_; + uint64_t lastFrame_; + + double iqMean_; + + Duration lineDuration_; + Duration maxExposureTime_; + + Duration prevExposure_; + Duration prevExposureNoDg_; + Duration currentExposure_; + Duration currentExposureNoDg_; +}; + +} /* namespace ipa::ipu3::algorithms */ + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_IPU3_ALGORITHMS_AGC_H__ */ diff --git a/src/ipa/ipu3/algorithms/meson.build b/src/ipa/ipu3/algorithms/meson.build index fa004df4..deae225b 100644 --- a/src/ipa/ipu3/algorithms/meson.build +++ b/src/ipa/ipu3/algorithms/meson.build @@ -1,6 +1,7 @@ # SPDX-License-Identifier: CC0-1.0 ipu3_ipa_algorithms = files([ + 'agc.cpp', 'algorithm.cpp', 'awb.cpp', 'tone_mapping.cpp', diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp index 5fc358fa..0ed0a6f1 100644 --- a/src/ipa/ipu3/ipu3.cpp +++ b/src/ipa/ipu3/ipu3.cpp @@ -29,10 +29,10 @@ #include "libcamera/internal/mapped_framebuffer.h" +#include "algorithms/agc.h" #include "algorithms/algorithm.h" #include "algorithms/awb.h" #include "algorithms/tone_mapping.h" -#include "ipu3_agc.h" #include "libipa/camera_sensor_helper.h" /** @@ -187,8 +187,6 @@ private: uint32_t minGain_; uint32_t maxGain_; - /* Interface to the AEC/AGC algorithm */ - std::unique_ptr agcAlgo_; /* Interface to the Camera Helper */ std::unique_ptr camHelper_; @@ -268,6 +266,7 @@ int IPAIPU3::init(const IPASettings &settings, *ipaControls = ControlInfoMap(std::move(controls), controls::controls); /* Construct our Algorithms */ + algorithms_.push_back(std::make_unique()); algorithms_.push_back(std::make_unique()); algorithms_.push_back(std::make_unique()); @@ -386,9 +385,6 @@ int IPAIPU3::configure(const IPAConfigInfo &configInfo) return ret; } - agcAlgo_ = std::make_unique(); - agcAlgo_->configure(context_, configInfo); - return 0; } @@ -476,15 +472,12 @@ void IPAIPU3::parseStatistics(unsigned int frame, { ControlList ctrls(controls::controls); - for (auto const &algo : algorithms_) - algo->process(context_, stats); - /* \todo These fields should not be written by the IPAIPU3 layer */ context_.frameContext.agc.gain = camHelper_->gain(gain_); context_.frameContext.agc.exposure = exposure_; - agcAlgo_->process(context_, stats); - exposure_ = context_.frameContext.agc.exposure; - gain_ = camHelper_->gainCode(context_.frameContext.agc.gain); + + for (auto const &algo : algorithms_) + algo->process(context_, stats); setControls(frame); @@ -505,6 +498,9 @@ void IPAIPU3::setControls(unsigned int frame) IPU3Action op; op.op = ActionSetSensorControls; + exposure_ = context_.frameContext.agc.exposure; + gain_ = camHelper_->gainCode(context_.frameContext.agc.gain); + ControlList ctrls(ctrls_); ctrls.set(V4L2_CID_EXPOSURE, static_cast(exposure_)); ctrls.set(V4L2_CID_ANALOGUE_GAIN, static_cast(gain_)); diff --git a/src/ipa/ipu3/ipu3_agc.cpp b/src/ipa/ipu3/ipu3_agc.cpp deleted file mode 100644 index 1c156b89..00000000 --- a/src/ipa/ipu3/ipu3_agc.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2021, Ideas On Board - * - * ipu3_agc.cpp - AGC/AEC control algorithm - */ - -#include "ipu3_agc.h" - -#include -#include -#include - -#include - -#include - -#include "libipa/histogram.h" - -namespace libcamera { - -using namespace std::literals::chrono_literals; - -namespace ipa::ipu3 { - -LOG_DEFINE_CATEGORY(IPU3Agc) - -/* Number of frames to wait before calculating stats on minimum exposure */ -static constexpr uint32_t kInitialFrameMinAECount = 4; -/* Number of frames to wait between new gain/exposure estimations */ -static constexpr uint32_t kFrameSkipCount = 6; - -/* Maximum ISO value for analogue gain */ -static constexpr uint32_t kMinISO = 100; -static constexpr uint32_t kMaxISO = 1500; - -/* Maximum analogue gain value - * \todo grab it from a camera helper */ -static constexpr uint32_t kMinGain = kMinISO / 100; -static constexpr uint32_t kMaxGain = kMaxISO / 100; - -/* \todo use calculated value based on sensor */ -static constexpr uint32_t kMinExposure = 1; -static constexpr uint32_t kMaxExposure = 1976; - -/* Histogram constants */ -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; - -IPU3Agc::IPU3Agc() - : frameCount_(0), lastFrame_(0), iqMean_(0.0), lineDuration_(0s), - maxExposureTime_(0s), prevExposure_(0s), prevExposureNoDg_(0s), - currentExposure_(0s), currentExposureNoDg_(0s) -{ -} - -int IPU3Agc::configure(IPAContext &context, const IPAConfigInfo &configInfo) -{ - aeGrid_ = context.configuration.grid.bdsGrid; - - lineDuration_ = configInfo.sensorInfo.lineLength * 1.0s - / configInfo.sensorInfo.pixelRate; - maxExposureTime_ = kMaxExposure * lineDuration_; - - return 0; -} - -void IPU3Agc::processBrightness(const ipu3_uapi_stats_3a *stats) -{ - 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 >> aeGrid_.block_width_log2; - int topleftY = topleft.y >> aeGrid_.block_height_log2; - - /* Align to the grid cell width and height */ - uint32_t startX = topleftX << aeGrid_.block_width_log2; - uint32_t startY = topleftY * aeGrid_.width << aeGrid_.block_width_log2; - uint32_t endX = (startX + (aeRegion.size().width >> aeGrid_.block_width_log2)) << aeGrid_.block_width_log2; - uint32_t i, j; - uint32_t count = 0; - - uint32_t hist[knumHistogramBins] = { 0 }; - for (j = topleftY; - j < topleftY + (aeRegion.size().height >> aeGrid_.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 * aeGrid_.width] == 0) { - uint8_t Gr = stats->awb_raw_buffer.meta_data[i + 0 + j * aeGrid_.width]; - uint8_t Gb = stats->awb_raw_buffer.meta_data[i + 3 + j * aeGrid_.width]; - hist[(Gr + Gb) / 2]++; - count++; - } - } - } - - /* Estimate the quantile mean of the top 2% of the histogram */ - iqMean_ = Histogram(Span(hist)).interQuantileMean(0.98, 1.0); -} - -void IPU3Agc::filterExposure() -{ - double speed = 0.2; - if (prevExposure_ == 0s) { - /* DG stands for digital gain.*/ - prevExposure_ = currentExposure_; - prevExposureNoDg_ = currentExposureNoDg_; - } else { - /* - * If we are close to the desired result, go faster to avoid making - * multiple micro-adjustments. - * \ todo: Make this customisable? - */ - if (prevExposure_ < 1.2 * currentExposure_ && - prevExposure_ > 0.8 * currentExposure_) - speed = sqrt(speed); - - prevExposure_ = speed * currentExposure_ + - prevExposure_ * (1.0 - speed); - prevExposureNoDg_ = speed * currentExposureNoDg_ + - prevExposureNoDg_ * (1.0 - speed); - } - /* - * We can't let the no_dg exposure deviate too far below the - * total exposure, as there might not be enough digital gain available - * in the ISP to hide it (which will cause nasty oscillation). - */ - double fastReduceThreshold = 0.4; - if (prevExposureNoDg_ < - prevExposure_ * fastReduceThreshold) - prevExposureNoDg_ = prevExposure_ * fastReduceThreshold; - LOG(IPU3Agc, Debug) << "After filtering, total_exposure " << prevExposure_; -} - -void IPU3Agc::lockExposureGain(uint32_t &exposure, double &gain) -{ - /* Algorithm initialization should wait for first valid frames */ - /* \todo - have a number of frames given by DelayedControls ? - * - implement a function for IIR */ - if ((frameCount_ < kInitialFrameMinAECount) || (frameCount_ - lastFrame_ < kFrameSkipCount)) - return; - - /* Are we correctly exposed ? */ - if (std::abs(iqMean_ - kEvGainTarget * knumHistogramBins) <= 1) { - LOG(IPU3Agc, Debug) << "!!! Good exposure with iqMean = " << iqMean_; - } else { - double newGain = kEvGainTarget * knumHistogramBins / iqMean_; - - /* extracted from Rpi::Agc::computeTargetExposure */ - libcamera::utils::Duration currentShutter = exposure * lineDuration_; - currentExposureNoDg_ = currentShutter * gain; - LOG(IPU3Agc, Debug) << "Actual total exposure " << currentExposureNoDg_ - << " Shutter speed " << currentShutter - << " Gain " << gain; - currentExposure_ = currentExposureNoDg_ * newGain; - libcamera::utils::Duration maxTotalExposure = maxExposureTime_ * kMaxGain; - currentExposure_ = std::min(currentExposure_, maxTotalExposure); - LOG(IPU3Agc, Debug) << "Target total exposure " << currentExposure_; - - /* \todo: estimate if we need to desaturate */ - filterExposure(); - - libcamera::utils::Duration newExposure = 0.0s; - if (currentShutter < maxExposureTime_) { - exposure = std::clamp(static_cast(exposure * currentExposure_ / currentExposureNoDg_), kMinExposure, kMaxExposure); - newExposure = currentExposure_ / exposure; - gain = std::clamp(static_cast(gain * currentExposure_ / newExposure), kMinGain, kMaxGain); - } else if (currentShutter >= maxExposureTime_) { - gain = std::clamp(static_cast(gain * currentExposure_ / currentExposureNoDg_), kMinGain, kMaxGain); - newExposure = currentExposure_ / gain; - exposure = std::clamp(static_cast(exposure * currentExposure_ / newExposure), kMinExposure, kMaxExposure); - } - LOG(IPU3Agc, Debug) << "Adjust exposure " << exposure * lineDuration_ << " and gain " << gain; - } - lastFrame_ = frameCount_; -} - -void IPU3Agc::process(IPAContext &context, const ipu3_uapi_stats_3a *stats) -{ - uint32_t &exposure = context.frameContext.agc.exposure; - double &gain = context.frameContext.agc.gain; - processBrightness(stats); - lockExposureGain(exposure, gain); - frameCount_++; -} - -} /* namespace ipa::ipu3 */ - -} /* namespace libcamera */ diff --git a/src/ipa/ipu3/ipu3_agc.h b/src/ipa/ipu3/ipu3_agc.h deleted file mode 100644 index 0e922664..00000000 --- a/src/ipa/ipu3/ipu3_agc.h +++ /dev/null @@ -1,60 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2021, Ideas On Board - * - * ipu3_agc.h - IPU3 AGC/AEC control algorithm - */ -#ifndef __LIBCAMERA_IPU3_AGC_H__ -#define __LIBCAMERA_IPU3_AGC_H__ - -#include - -#include - -#include - -#include "algorithms/algorithm.h" - -namespace libcamera { - -struct IPACameraSensorInfo; - -namespace ipa::ipu3 { - -using utils::Duration; - -class IPU3Agc : public Algorithm -{ -public: - IPU3Agc(); - ~IPU3Agc() = default; - - int configure(IPAContext &context, const IPAConfigInfo &configInfo) override; - void process(IPAContext &context, const ipu3_uapi_stats_3a *stats) override; - -private: - void processBrightness(const ipu3_uapi_stats_3a *stats); - void filterExposure(); - void lockExposureGain(uint32_t &exposure, double &gain); - - struct ipu3_uapi_grid_config aeGrid_; - - uint64_t frameCount_; - uint64_t lastFrame_; - - double iqMean_; - - Duration lineDuration_; - Duration maxExposureTime_; - - Duration prevExposure_; - Duration prevExposureNoDg_; - Duration currentExposure_; - Duration currentExposureNoDg_; -}; - -} /* namespace ipa::ipu3 */ - -} /* namespace libcamera */ - -#endif /* __LIBCAMERA_IPU3_AGC_H__ */ diff --git a/src/ipa/ipu3/meson.build b/src/ipa/ipu3/meson.build index d1126947..39320980 100644 --- a/src/ipa/ipu3/meson.build +++ b/src/ipa/ipu3/meson.build @@ -6,7 +6,6 @@ ipa_name = 'ipa_ipu3' ipu3_ipa_sources = files([ 'ipu3.cpp', - 'ipu3_agc.cpp', ]) ipu3_ipa_sources += ipu3_ipa_algorithms -- cgit v1.2.1