summaryrefslogtreecommitdiff
path: root/src/ipa
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipa')
-rwxr-xr-xsrc/ipa/ipa-sign-install.sh2
-rwxr-xr-xsrc/ipa/ipa-sign.sh2
-rw-r--r--src/ipa/ipu3/algorithms/af.cpp2
-rw-r--r--src/ipa/ipu3/algorithms/af.h2
-rw-r--r--src/ipa/ipu3/algorithms/agc.cpp294
-rw-r--r--src/ipa/ipu3/algorithms/agc.h29
-rw-r--r--src/ipa/ipu3/algorithms/algorithm.h2
-rw-r--r--src/ipa/ipu3/algorithms/awb.cpp2
-rw-r--r--src/ipa/ipu3/algorithms/awb.h2
-rw-r--r--src/ipa/ipu3/algorithms/blc.cpp2
-rw-r--r--src/ipa/ipu3/algorithms/blc.h2
-rw-r--r--src/ipa/ipu3/algorithms/tone_mapping.cpp2
-rw-r--r--src/ipa/ipu3/algorithms/tone_mapping.h2
-rw-r--r--src/ipa/ipu3/ipa_context.cpp5
-rw-r--r--src/ipa/ipu3/ipa_context.h7
-rw-r--r--src/ipa/ipu3/ipu3.cpp7
-rw-r--r--src/ipa/ipu3/module.h2
-rw-r--r--src/ipa/libipa/agc_mean_luminance.cpp577
-rw-r--r--src/ipa/libipa/agc_mean_luminance.h96
-rw-r--r--src/ipa/libipa/algorithm.cpp2
-rw-r--r--src/ipa/libipa/algorithm.h2
-rw-r--r--src/ipa/libipa/camera_sensor_helper.cpp35
-rw-r--r--src/ipa/libipa/camera_sensor_helper.h2
-rw-r--r--src/ipa/libipa/exposure_mode_helper.cpp246
-rw-r--r--src/ipa/libipa/exposure_mode_helper.h53
-rw-r--r--src/ipa/libipa/fc_queue.cpp2
-rw-r--r--src/ipa/libipa/fc_queue.h2
-rw-r--r--src/ipa/libipa/histogram.cpp28
-rw-r--r--src/ipa/libipa/histogram.h17
-rw-r--r--src/ipa/libipa/meson.build4
-rw-r--r--src/ipa/libipa/module.cpp2
-rw-r--r--src/ipa/libipa/module.h2
-rw-r--r--src/ipa/rkisp1/algorithms/agc.cpp278
-rw-r--r--src/ipa/rkisp1/algorithms/agc.h18
-rw-r--r--src/ipa/rkisp1/algorithms/algorithm.h2
-rw-r--r--src/ipa/rkisp1/algorithms/awb.cpp2
-rw-r--r--src/ipa/rkisp1/algorithms/awb.h2
-rw-r--r--src/ipa/rkisp1/algorithms/blc.cpp2
-rw-r--r--src/ipa/rkisp1/algorithms/blc.h2
-rw-r--r--src/ipa/rkisp1/algorithms/cproc.cpp2
-rw-r--r--src/ipa/rkisp1/algorithms/cproc.h2
-rw-r--r--src/ipa/rkisp1/algorithms/dpcc.cpp2
-rw-r--r--src/ipa/rkisp1/algorithms/dpcc.h2
-rw-r--r--src/ipa/rkisp1/algorithms/dpf.cpp2
-rw-r--r--src/ipa/rkisp1/algorithms/dpf.h2
-rw-r--r--src/ipa/rkisp1/algorithms/filter.cpp2
-rw-r--r--src/ipa/rkisp1/algorithms/filter.h2
-rw-r--r--src/ipa/rkisp1/algorithms/gsl.cpp2
-rw-r--r--src/ipa/rkisp1/algorithms/gsl.h2
-rw-r--r--src/ipa/rkisp1/algorithms/lsc.cpp2
-rw-r--r--src/ipa/rkisp1/algorithms/lsc.h2
-rw-r--r--src/ipa/rkisp1/ipa_context.cpp2
-rw-r--r--src/ipa/rkisp1/ipa_context.h7
-rw-r--r--src/ipa/rkisp1/meson.build1
-rw-r--r--src/ipa/rkisp1/module.h2
-rw-r--r--src/ipa/rkisp1/rkisp1.cpp7
-rw-r--r--src/ipa/rkisp1/utils.cpp42
-rw-r--r--src/ipa/rkisp1/utils.h66
-rw-r--r--src/ipa/rpi/cam_helper/cam_helper.cpp2
-rw-r--r--src/ipa/rpi/cam_helper/cam_helper.h2
-rw-r--r--src/ipa/rpi/cam_helper/cam_helper_imx219.cpp2
-rw-r--r--src/ipa/rpi/cam_helper/cam_helper_imx290.cpp2
-rw-r--r--src/ipa/rpi/cam_helper/cam_helper_imx296.cpp2
-rw-r--r--src/ipa/rpi/cam_helper/cam_helper_imx477.cpp2
-rw-r--r--src/ipa/rpi/cam_helper/cam_helper_imx519.cpp2
-rw-r--r--src/ipa/rpi/cam_helper/cam_helper_imx708.cpp2
-rw-r--r--src/ipa/rpi/cam_helper/cam_helper_ov5647.cpp2
-rw-r--r--src/ipa/rpi/cam_helper/cam_helper_ov64a40.cpp2
-rw-r--r--src/ipa/rpi/cam_helper/cam_helper_ov9281.cpp2
-rw-r--r--src/ipa/rpi/cam_helper/md_parser.h2
-rw-r--r--src/ipa/rpi/cam_helper/md_parser_smia.cpp2
-rw-r--r--src/ipa/rpi/common/ipa_base.cpp86
-rw-r--r--src/ipa/rpi/common/ipa_base.h14
-rw-r--r--src/ipa/rpi/controller/af_status.h2
-rw-r--r--src/ipa/rpi/controller/agc_algorithm.h2
-rw-r--r--src/ipa/rpi/controller/agc_status.h2
-rw-r--r--src/ipa/rpi/controller/algorithm.cpp2
-rw-r--r--src/ipa/rpi/controller/algorithm.h2
-rw-r--r--src/ipa/rpi/controller/alsc_status.h2
-rw-r--r--src/ipa/rpi/controller/awb_algorithm.h2
-rw-r--r--src/ipa/rpi/controller/awb_status.h2
-rw-r--r--src/ipa/rpi/controller/black_level_algorithm.h2
-rw-r--r--src/ipa/rpi/controller/black_level_status.h2
-rw-r--r--src/ipa/rpi/controller/camera_mode.h2
-rw-r--r--src/ipa/rpi/controller/ccm_algorithm.h2
-rw-r--r--src/ipa/rpi/controller/ccm_status.h2
-rw-r--r--src/ipa/rpi/controller/contrast_algorithm.h2
-rw-r--r--src/ipa/rpi/controller/contrast_status.h2
-rw-r--r--src/ipa/rpi/controller/controller.cpp2
-rw-r--r--src/ipa/rpi/controller/controller.h2
-rw-r--r--src/ipa/rpi/controller/denoise_algorithm.h2
-rw-r--r--src/ipa/rpi/controller/denoise_status.h2
-rw-r--r--src/ipa/rpi/controller/device_status.cpp2
-rw-r--r--src/ipa/rpi/controller/device_status.h2
-rw-r--r--src/ipa/rpi/controller/dpc_status.h2
-rw-r--r--src/ipa/rpi/controller/geq_status.h2
-rw-r--r--src/ipa/rpi/controller/hdr_algorithm.h2
-rw-r--r--src/ipa/rpi/controller/hdr_status.h2
-rw-r--r--src/ipa/rpi/controller/histogram.cpp2
-rw-r--r--src/ipa/rpi/controller/histogram.h2
-rw-r--r--src/ipa/rpi/controller/lux_status.h2
-rw-r--r--src/ipa/rpi/controller/metadata.h2
-rw-r--r--src/ipa/rpi/controller/noise_status.h2
-rw-r--r--src/ipa/rpi/controller/pdaf_data.h2
-rw-r--r--src/ipa/rpi/controller/pwl.cpp2
-rw-r--r--src/ipa/rpi/controller/pwl.h2
-rw-r--r--src/ipa/rpi/controller/region_stats.h2
-rw-r--r--src/ipa/rpi/controller/rpi/af.cpp2
-rw-r--r--src/ipa/rpi/controller/rpi/af.h2
-rw-r--r--src/ipa/rpi/controller/rpi/agc.cpp2
-rw-r--r--src/ipa/rpi/controller/rpi/agc.h2
-rw-r--r--src/ipa/rpi/controller/rpi/agc_channel.cpp2
-rw-r--r--src/ipa/rpi/controller/rpi/agc_channel.h2
-rw-r--r--src/ipa/rpi/controller/rpi/alsc.cpp2
-rw-r--r--src/ipa/rpi/controller/rpi/alsc.h2
-rw-r--r--src/ipa/rpi/controller/rpi/awb.cpp2
-rw-r--r--src/ipa/rpi/controller/rpi/awb.h2
-rw-r--r--src/ipa/rpi/controller/rpi/black_level.cpp2
-rw-r--r--src/ipa/rpi/controller/rpi/black_level.h2
-rw-r--r--src/ipa/rpi/controller/rpi/cac.cpp2
-rw-r--r--src/ipa/rpi/controller/rpi/ccm.cpp2
-rw-r--r--src/ipa/rpi/controller/rpi/ccm.h2
-rw-r--r--src/ipa/rpi/controller/rpi/contrast.cpp2
-rw-r--r--src/ipa/rpi/controller/rpi/contrast.h2
-rw-r--r--src/ipa/rpi/controller/rpi/denoise.cpp2
-rw-r--r--src/ipa/rpi/controller/rpi/dpc.cpp2
-rw-r--r--src/ipa/rpi/controller/rpi/dpc.h2
-rw-r--r--src/ipa/rpi/controller/rpi/focus.h2
-rw-r--r--src/ipa/rpi/controller/rpi/geq.cpp2
-rw-r--r--src/ipa/rpi/controller/rpi/geq.h2
-rw-r--r--src/ipa/rpi/controller/rpi/hdr.cpp114
-rw-r--r--src/ipa/rpi/controller/rpi/hdr.h12
-rw-r--r--src/ipa/rpi/controller/rpi/lux.cpp2
-rw-r--r--src/ipa/rpi/controller/rpi/lux.h2
-rw-r--r--src/ipa/rpi/controller/rpi/noise.cpp2
-rw-r--r--src/ipa/rpi/controller/rpi/noise.h2
-rw-r--r--src/ipa/rpi/controller/rpi/saturation.cpp2
-rw-r--r--src/ipa/rpi/controller/rpi/sdn.cpp2
-rw-r--r--src/ipa/rpi/controller/rpi/sdn.h2
-rw-r--r--src/ipa/rpi/controller/rpi/sharpen.cpp2
-rw-r--r--src/ipa/rpi/controller/rpi/sharpen.h2
-rw-r--r--src/ipa/rpi/controller/rpi/tonemap.cpp2
-rw-r--r--src/ipa/rpi/controller/saturation_status.h2
-rw-r--r--src/ipa/rpi/controller/sharpen_algorithm.h2
-rw-r--r--src/ipa/rpi/controller/sharpen_status.h2
-rw-r--r--src/ipa/rpi/controller/statistics.h2
-rw-r--r--src/ipa/rpi/controller/stitch_status.h2
-rw-r--r--src/ipa/rpi/controller/tonemap_status.h2
-rw-r--r--src/ipa/rpi/vc4/data/imx219.json607
-rw-r--r--src/ipa/rpi/vc4/data/imx219_noir.json607
-rw-r--r--src/ipa/rpi/vc4/data/imx290.json15
-rw-r--r--src/ipa/rpi/vc4/data/imx296.json17
-rw-r--r--src/ipa/rpi/vc4/data/imx296_mono.json17
-rw-r--r--src/ipa/rpi/vc4/data/imx378.json15
-rw-r--r--src/ipa/rpi/vc4/data/imx477.json615
-rw-r--r--src/ipa/rpi/vc4/data/imx477_noir.json607
-rw-r--r--src/ipa/rpi/vc4/data/imx477_scientific.json15
-rw-r--r--src/ipa/rpi/vc4/data/imx477_v1.json15
-rw-r--r--src/ipa/rpi/vc4/data/imx519.json15
-rw-r--r--src/ipa/rpi/vc4/data/imx708.json555
-rw-r--r--src/ipa/rpi/vc4/data/imx708_noir.json555
-rw-r--r--src/ipa/rpi/vc4/data/imx708_wide.json555
-rw-r--r--src/ipa/rpi/vc4/data/imx708_wide_noir.json555
-rw-r--r--src/ipa/rpi/vc4/data/ov5647.json611
-rw-r--r--src/ipa/rpi/vc4/data/ov5647_noir.json15
-rw-r--r--src/ipa/rpi/vc4/data/ov9281_mono.json5
-rw-r--r--src/ipa/rpi/vc4/data/se327m12.json15
-rw-r--r--src/ipa/rpi/vc4/data/uncalibrated.json5
-rw-r--r--src/ipa/rpi/vc4/vc4.cpp4
-rw-r--r--src/ipa/simple/black_level.cpp2
-rw-r--r--src/ipa/simple/black_level.h2
-rw-r--r--src/ipa/simple/soft_simple.cpp4
-rw-r--r--src/ipa/vimc/vimc.cpp4
173 files changed, 4545 insertions, 3178 deletions
diff --git a/src/ipa/ipa-sign-install.sh b/src/ipa/ipa-sign-install.sh
index bcedb8b5..71696d5a 100755
--- a/src/ipa/ipa-sign-install.sh
+++ b/src/ipa/ipa-sign-install.sh
@@ -4,7 +4,7 @@
#
# Author: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
#
-# ipa-sign-install.sh - Regenerate IPA module signatures when installing
+# Regenerate IPA module signatures when installing
key=$1
shift
diff --git a/src/ipa/ipa-sign.sh b/src/ipa/ipa-sign.sh
index 8673dad1..69024213 100755
--- a/src/ipa/ipa-sign.sh
+++ b/src/ipa/ipa-sign.sh
@@ -4,7 +4,7 @@
#
# Author: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
#
-# ipa-sign.sh - Generate a signature for an IPA module
+# Generate a signature for an IPA module
key="$1"
input="$2"
diff --git a/src/ipa/ipu3/algorithms/af.cpp b/src/ipa/ipu3/algorithms/af.cpp
index 12927eec..29eb7355 100644
--- a/src/ipa/ipu3/algorithms/af.cpp
+++ b/src/ipa/ipu3/algorithms/af.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021, Red Hat
*
- * af.cpp - IPU3 auto focus algorithm
+ * IPU3 auto focus algorithm
*/
#include "af.h"
diff --git a/src/ipa/ipu3/algorithms/af.h b/src/ipa/ipu3/algorithms/af.h
index c6168e30..68126d46 100644
--- a/src/ipa/ipu3/algorithms/af.h
+++ b/src/ipa/ipu3/algorithms/af.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021, Red Hat
*
- * af.h - IPU3 Af algorithm
+ * IPU3 Af algorithm
*/
#pragma once
diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp
index 606a237a..0e0114f6 100644
--- a/src/ipa/ipu3/algorithms/agc.cpp
+++ b/src/ipa/ipu3/algorithms/agc.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021, Ideas On Board
*
- * ipu3_agc.cpp - AGC/AEC mean-based control algorithm
+ * AGC/AEC mean-based control algorithm
*/
#include "agc.h"
@@ -56,24 +56,32 @@ static constexpr utils::Duration kMaxShutterSpeed = 60ms;
/* Histogram constants */
static constexpr uint32_t knumHistogramBins = 256;
-/* Target value to reach for the top 2% of the histogram */
-static constexpr double kEvGainTarget = 0.5;
-
-/* Number of frames to wait before calculating stats on minimum exposure */
-static constexpr uint32_t kNumStartupFrames = 10;
+Agc::Agc()
+ : minShutterSpeed_(0s), maxShutterSpeed_(0s)
+{
+}
-/*
- * Relative luminance target.
+/**
+ * \brief Initialise the AGC algorithm from tuning files
+ * \param[in] context The shared IPA context
+ * \param[in] tuningData The YamlObject containing Agc tuning data
+ *
+ * This function calls the base class' tuningData parsers to discover which
+ * control values are supported.
*
- * It's a number that's chosen so that, when the camera points at a grey
- * target, the resulting image brightness is considered right.
+ * \return 0 on success or errors from the base class
*/
-static constexpr double kRelativeLuminanceTarget = 0.16;
-
-Agc::Agc()
- : frameCount_(0), minShutterSpeed_(0s),
- maxShutterSpeed_(0s), filteredExposure_(0s)
+int Agc::init(IPAContext &context, const YamlObject &tuningData)
{
+ int ret;
+
+ ret = parseTuningData(tuningData);
+ if (ret)
+ return ret;
+
+ context.ctrlMap.merge(controls());
+
+ return 0;
}
/**
@@ -90,6 +98,7 @@ int Agc::configure(IPAContext &context,
IPAActiveState &activeState = context.activeState;
stride_ = configuration.grid.stride;
+ bdsGrid_ = configuration.grid.bdsGrid;
minShutterSpeed_ = configuration.agc.minShutterSpeed;
maxShutterSpeed_ = std::min(configuration.agc.maxShutterSpeed,
@@ -102,168 +111,53 @@ int Agc::configure(IPAContext &context,
activeState.agc.gain = minAnalogueGain_;
activeState.agc.exposure = 10ms / configuration.sensor.lineDuration;
- frameCount_ = 0;
+ context.activeState.agc.constraintMode = constraintModes().begin()->first;
+ context.activeState.agc.exposureMode = exposureModeHelpers().begin()->first;
+
+ /* \todo Run this again when FrameDurationLimits is passed in */
+ setLimits(minShutterSpeed_, maxShutterSpeed_, minAnalogueGain_,
+ maxAnalogueGain_);
+ resetFrameCount();
+
return 0;
}
-/**
- * \brief Estimate the mean value of the top 2% of the histogram
- * \param[in] stats The statistics computed by the ImgU
- * \param[in] grid The grid used to store the statistics in the IPU3
- * \return The mean value of the top 2% of the histogram
- */
-double Agc::measureBrightness(const ipu3_uapi_stats_3a *stats,
- const ipu3_uapi_grid_config &grid) const
+Histogram Agc::parseStatistics(const ipu3_uapi_stats_3a *stats,
+ const ipu3_uapi_grid_config &grid)
{
- /* Initialise the histogram array */
uint32_t hist[knumHistogramBins] = { 0 };
+ rgbTriples_.clear();
+
for (unsigned int cellY = 0; cellY < grid.height; cellY++) {
for (unsigned int cellX = 0; cellX < grid.width; cellX++) {
uint32_t cellPosition = cellY * stride_ + cellX;
const ipu3_uapi_awb_set_item *cell =
reinterpret_cast<const ipu3_uapi_awb_set_item *>(
- &stats->awb_raw_buffer.meta_data[cellPosition]
- );
+ &stats->awb_raw_buffer.meta_data[cellPosition]);
+
+ rgbTriples_.push_back({
+ cell->R_avg,
+ (cell->Gr_avg + cell->Gb_avg) / 2,
+ cell->B_avg
+ });
- uint8_t gr = cell->Gr_avg;
- uint8_t gb = cell->Gb_avg;
/*
* Store the average green value to estimate the
* brightness. Even the overexposed pixels are
* taken into account.
*/
- hist[(gr + gb) / 2]++;
+ hist[(cell->Gr_avg + cell->Gb_avg) / 2]++;
}
}
- /* Estimate the quantile mean of the top 2% of the histogram. */
- return Histogram(Span<uint32_t>(hist)).interQuantileMean(0.98, 1.0);
-}
-
-/**
- * \brief Apply a filter on the exposure value to limit the speed of changes
- * \param[in] exposureValue The target exposure from the AGC algorithm
- *
- * The speed of the filter is adaptive, and will produce the target quicker
- * during startup, or when the target exposure is within 20% of the most recent
- * filter output.
- *
- * \return The filtered exposure
- */
-utils::Duration Agc::filterExposure(utils::Duration exposureValue)
-{
- double speed = 0.2;
-
- /* Adapt instantly if we are in startup phase. */
- if (frameCount_ < kNumStartupFrames)
- speed = 1.0;
-
- /*
- * If we are close to the desired result, go faster to avoid making
- * multiple micro-adjustments.
- * \todo Make this customisable?
- */
- if (filteredExposure_ < 1.2 * exposureValue &&
- filteredExposure_ > 0.8 * exposureValue)
- speed = sqrt(speed);
-
- filteredExposure_ = speed * exposureValue +
- filteredExposure_ * (1.0 - speed);
-
- LOG(IPU3Agc, Debug) << "After filtering, exposure " << filteredExposure_;
-
- return filteredExposure_;
-}
-
-/**
- * \brief Estimate the new exposure and gain values
- * \param[inout] frameContext The shared IPA frame Context
- * \param[in] yGain The gain calculated based on the relative luminance target
- * \param[in] iqMeanGain The gain calculated based on the relative luminance target
- */
-void Agc::computeExposure(IPAContext &context, IPAFrameContext &frameContext,
- double yGain, double iqMeanGain)
-{
- const IPASessionConfiguration &configuration = context.configuration;
- /* Get the effective exposure and gain applied on the sensor. */
- uint32_t exposure = frameContext.sensor.exposure;
- double analogueGain = frameContext.sensor.gain;
-
- /* Use the highest of the two gain estimates. */
- double evGain = std::max(yGain, iqMeanGain);
-
- /* Consider within 1% of the target as correctly exposed */
- if (utils::abs_diff(evGain, 1.0) < 0.01)
- LOG(IPU3Agc, Debug) << "We are well exposed (evGain = "
- << evGain << ")";
-
- /* extracted from Rpi::Agc::computeTargetExposure */
-
- /* Calculate the shutter time in seconds */
- utils::Duration currentShutter = exposure * configuration.sensor.lineDuration;
-
- /*
- * Update the exposure value for the next computation using the values
- * of exposure and gain really used by the sensor.
- */
- utils::Duration effectiveExposureValue = currentShutter * analogueGain;
-
- LOG(IPU3Agc, Debug) << "Actual total exposure " << currentShutter * analogueGain
- << " Shutter speed " << currentShutter
- << " Gain " << analogueGain
- << " Needed ev gain " << evGain;
-
- /*
- * Calculate the current exposure value for the scene as the latest
- * exposure value applied multiplied by the new estimated gain.
- */
- utils::Duration exposureValue = effectiveExposureValue * evGain;
-
- /* Clamp the exposure value to the min and max authorized */
- utils::Duration maxTotalExposure = maxShutterSpeed_ * maxAnalogueGain_;
- exposureValue = std::min(exposureValue, maxTotalExposure);
- LOG(IPU3Agc, Debug) << "Target total exposure " << exposureValue
- << ", maximum is " << maxTotalExposure;
-
- /*
- * Filter the exposure.
- * \todo estimate if we need to desaturate
- */
- exposureValue = filterExposure(exposureValue);
-
- /*
- * Divide the exposure value as new exposure and gain values.
- *
- * Push the shutter time up to the maximum first, and only then
- * increase the gain.
- */
- utils::Duration shutterTime =
- std::clamp<utils::Duration>(exposureValue / minAnalogueGain_,
- minShutterSpeed_, maxShutterSpeed_);
- double stepGain = std::clamp(exposureValue / shutterTime,
- minAnalogueGain_, maxAnalogueGain_);
- LOG(IPU3Agc, Debug) << "Divided up shutter and gain are "
- << shutterTime << " and "
- << stepGain;
-
- IPAActiveState &activeState = context.activeState;
- /* Update the estimated exposure and gain. */
- activeState.agc.exposure = shutterTime / configuration.sensor.lineDuration;
- activeState.agc.gain = stepGain;
+ return Histogram(Span<uint32_t>(hist));
}
/**
* \brief Estimate the relative luminance of the frame with a given gain
- * \param[in] frameContext The shared IPA frame context
- * \param[in] grid The grid used to store the statistics in the IPU3
- * \param[in] stats The IPU3 statistics and ISP results
- * \param[in] gain The gain to apply to the frame
- * \return The relative luminance
- *
- * This function estimates the average relative luminance of the frame that
- * would be output by the sensor if an additional \a gain was applied.
+ * \param[in] gain The gain to apply in estimating luminance
*
* The estimation is based on the AWB statistics for the current frame. Red,
* green and blue averages for all cells are first multiplied by the gain, and
@@ -278,40 +172,24 @@ void Agc::computeExposure(IPAContext &context, IPAFrameContext &frameContext,
*
* More detailed information can be found in:
* https://en.wikipedia.org/wiki/Relative_luminance
+ *
+ * \return The relative luminance of the frame
*/
-double Agc::estimateLuminance(IPAActiveState &activeState,
- const ipu3_uapi_grid_config &grid,
- const ipu3_uapi_stats_3a *stats,
- double gain)
+double Agc::estimateLuminance(double gain) const
{
double redSum = 0, greenSum = 0, blueSum = 0;
- /* Sum the per-channel averages, saturated to 255. */
- for (unsigned int cellY = 0; cellY < grid.height; cellY++) {
- for (unsigned int cellX = 0; cellX < grid.width; cellX++) {
- uint32_t cellPosition = cellY * stride_ + cellX;
-
- const ipu3_uapi_awb_set_item *cell =
- reinterpret_cast<const ipu3_uapi_awb_set_item *>(
- &stats->awb_raw_buffer.meta_data[cellPosition]
- );
- const uint8_t G_avg = (cell->Gr_avg + cell->Gb_avg) / 2;
-
- redSum += std::min(cell->R_avg * gain, 255.0);
- greenSum += std::min(G_avg * gain, 255.0);
- blueSum += std::min(cell->B_avg * gain, 255.0);
- }
+ for (unsigned int i = 0; i < rgbTriples_.size(); i++) {
+ redSum += std::min(std::get<0>(rgbTriples_[i]) * gain, 255.0);
+ greenSum += std::min(std::get<1>(rgbTriples_[i]) * gain, 255.0);
+ blueSum += std::min(std::get<2>(rgbTriples_[i]) * gain, 255.0);
}
- /*
- * Apply the AWB gains to approximate colours correctly, use the Rec.
- * 601 formula to calculate the relative luminance, and normalize it.
- */
- double ySum = redSum * activeState.awb.gains.red * 0.299
- + greenSum * activeState.awb.gains.green * 0.587
- + blueSum * activeState.awb.gains.blue * 0.114;
+ double ySum = redSum * rGain_ * 0.299
+ + greenSum * gGain_ * 0.587
+ + blueSum * bGain_ * 0.114;
- return ySum / (grid.height * grid.width) / 255;
+ return ySum / (bdsGrid_.height * bdsGrid_.width) / 255;
}
/**
@@ -330,44 +208,36 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame,
const ipu3_uapi_stats_3a *stats,
ControlList &metadata)
{
- /*
- * Estimate the gain needed to have the proportion of pixels in a given
- * desired range. iqMean is the mean value of the top 2% of the
- * cumulative histogram, and we want it to be as close as possible to a
- * configured target.
- */
- double iqMean = measureBrightness(stats, context.configuration.grid.bdsGrid);
- double iqMeanGain = kEvGainTarget * knumHistogramBins / iqMean;
+ Histogram hist = parseStatistics(stats, context.configuration.grid.bdsGrid);
+ rGain_ = context.activeState.awb.gains.red;
+ gGain_ = context.activeState.awb.gains.blue;
+ bGain_ = context.activeState.awb.gains.green;
/*
- * Estimate the gain needed to achieve a relative luminance target. To
- * account for non-linearity caused by saturation, the value needs to be
- * estimated in an iterative process, as multiplying by a gain will not
- * increase the relative luminance by the same factor if some image
- * regions are saturated.
+ * The Agc algorithm needs to know the effective exposure value that was
+ * applied to the sensor when the statistics were collected.
*/
- double yGain = 1.0;
- double yTarget = kRelativeLuminanceTarget;
-
- for (unsigned int i = 0; i < 8; i++) {
- double yValue = estimateLuminance(context.activeState,
- context.configuration.grid.bdsGrid,
- stats, yGain);
- double extraGain = std::min(10.0, yTarget / (yValue + .001));
-
- yGain *= extraGain;
- LOG(IPU3Agc, Debug) << "Y value: " << yValue
- << ", Y target: " << yTarget
- << ", gives gain " << yGain;
- if (extraGain < 1.01)
- break;
- }
-
- computeExposure(context, frameContext, yGain, iqMeanGain);
- frameCount_++;
-
utils::Duration exposureTime = context.configuration.sensor.lineDuration
* frameContext.sensor.exposure;
+ double analogueGain = frameContext.sensor.gain;
+ utils::Duration effectiveExposureValue = exposureTime * analogueGain;
+
+ utils::Duration shutterTime;
+ double aGain, dGain;
+ std::tie(shutterTime, aGain, dGain) =
+ calculateNewEv(context.activeState.agc.constraintMode,
+ context.activeState.agc.exposureMode, hist,
+ effectiveExposureValue);
+
+ LOG(IPU3Agc, Debug)
+ << "Divided up shutter, analogue gain and digital gain are "
+ << shutterTime << ", " << aGain << " and " << dGain;
+
+ IPAActiveState &activeState = context.activeState;
+ /* Update the estimated exposure and gain. */
+ activeState.agc.exposure = shutterTime / context.configuration.sensor.lineDuration;
+ activeState.agc.gain = aGain;
+
metadata.set(controls::AnalogueGain, frameContext.sensor.gain);
metadata.set(controls::ExposureTime, exposureTime.get<std::micro>());
diff --git a/src/ipa/ipu3/algorithms/agc.h b/src/ipa/ipu3/algorithms/agc.h
index 9d6e3ff1..411f4da0 100644
--- a/src/ipa/ipu3/algorithms/agc.h
+++ b/src/ipa/ipu3/algorithms/agc.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021, Ideas On Board
*
- * agc.h - IPU3 AGC/AEC mean-based control algorithm
+ * IPU3 AGC/AEC mean-based control algorithm
*/
#pragma once
@@ -13,6 +13,9 @@
#include <libcamera/geometry.h>
+#include "libipa/agc_mean_luminance.h"
+#include "libipa/histogram.h"
+
#include "algorithm.h"
namespace libcamera {
@@ -21,12 +24,13 @@ struct IPACameraSensorInfo;
namespace ipa::ipu3::algorithms {
-class Agc : public Algorithm
+class Agc : public Algorithm, public AgcMeanLuminance
{
public:
Agc();
~Agc() = default;
+ int init(IPAContext &context, const YamlObject &tuningData) override;
int configure(IPAContext &context, const IPAConfigInfo &configInfo) override;
void process(IPAContext &context, const uint32_t frame,
IPAFrameContext &frameContext,
@@ -34,17 +38,9 @@ public:
ControlList &metadata) override;
private:
- double measureBrightness(const ipu3_uapi_stats_3a *stats,
- const ipu3_uapi_grid_config &grid) const;
- utils::Duration filterExposure(utils::Duration currentExposure);
- void computeExposure(IPAContext &context, IPAFrameContext &frameContext,
- double yGain, double iqMeanGain);
- double estimateLuminance(IPAActiveState &activeState,
- const ipu3_uapi_grid_config &grid,
- const ipu3_uapi_stats_3a *stats,
- double gain);
-
- uint64_t frameCount_;
+ double estimateLuminance(double gain) const override;
+ Histogram parseStatistics(const ipu3_uapi_stats_3a *stats,
+ const ipu3_uapi_grid_config &grid);
utils::Duration minShutterSpeed_;
utils::Duration maxShutterSpeed_;
@@ -52,9 +48,12 @@ private:
double minAnalogueGain_;
double maxAnalogueGain_;
- utils::Duration filteredExposure_;
-
uint32_t stride_;
+ double rGain_;
+ double gGain_;
+ double bGain_;
+ ipu3_uapi_grid_config bdsGrid_;
+ std::vector<std::tuple<uint8_t, uint8_t, uint8_t>> rgbTriples_;
};
} /* namespace ipa::ipu3::algorithms */
diff --git a/src/ipa/ipu3/algorithms/algorithm.h b/src/ipa/ipu3/algorithms/algorithm.h
index ae134a94..c7801f93 100644
--- a/src/ipa/ipu3/algorithms/algorithm.h
+++ b/src/ipa/ipu3/algorithms/algorithm.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021, Ideas On Board
*
- * algorithm.h - IPU3 control algorithm interface
+ * IPU3 control algorithm interface
*/
#pragma once
diff --git a/src/ipa/ipu3/algorithms/awb.cpp b/src/ipa/ipu3/algorithms/awb.cpp
index 5abd4621..4d6e3994 100644
--- a/src/ipa/ipu3/algorithms/awb.cpp
+++ b/src/ipa/ipu3/algorithms/awb.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021, Ideas On Board
*
- * awb.cpp - AWB control algorithm
+ * AWB control algorithm
*/
#include "awb.h"
diff --git a/src/ipa/ipu3/algorithms/awb.h b/src/ipa/ipu3/algorithms/awb.h
index 7a70854e..c0202823 100644
--- a/src/ipa/ipu3/algorithms/awb.h
+++ b/src/ipa/ipu3/algorithms/awb.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021, Ideas On Board
*
- * awb.h - IPU3 AWB control algorithm
+ * IPU3 AWB control algorithm
*/
#pragma once
diff --git a/src/ipa/ipu3/algorithms/blc.cpp b/src/ipa/ipu3/algorithms/blc.cpp
index e838072a..257f40e2 100644
--- a/src/ipa/ipu3/algorithms/blc.cpp
+++ b/src/ipa/ipu3/algorithms/blc.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021, Google inc.
*
- * blc.cpp - IPU3 Black Level Correction control
+ * IPU3 Black Level Correction control
*/
#include "blc.h"
diff --git a/src/ipa/ipu3/algorithms/blc.h b/src/ipa/ipu3/algorithms/blc.h
index 292bf67b..62748045 100644
--- a/src/ipa/ipu3/algorithms/blc.h
+++ b/src/ipa/ipu3/algorithms/blc.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021, Google inc.
*
- * black_correction.h - IPU3 Black Level Correction control
+ * IPU3 Black Level Correction control
*/
#pragma once
diff --git a/src/ipa/ipu3/algorithms/tone_mapping.cpp b/src/ipa/ipu3/algorithms/tone_mapping.cpp
index a169894c..160338c1 100644
--- a/src/ipa/ipu3/algorithms/tone_mapping.cpp
+++ b/src/ipa/ipu3/algorithms/tone_mapping.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021, Google inc.
*
- * tone_mapping.cpp - IPU3 ToneMapping and Gamma control
+ * IPU3 ToneMapping and Gamma control
*/
#include "tone_mapping.h"
diff --git a/src/ipa/ipu3/algorithms/tone_mapping.h b/src/ipa/ipu3/algorithms/tone_mapping.h
index 5ae35da5..b2b38010 100644
--- a/src/ipa/ipu3/algorithms/tone_mapping.h
+++ b/src/ipa/ipu3/algorithms/tone_mapping.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021, Google inc.
*
- * tone_mapping.h - IPU3 ToneMapping and Gamma control
+ * IPU3 ToneMapping and Gamma control
*/
#pragma once
diff --git a/src/ipa/ipu3/ipa_context.cpp b/src/ipa/ipu3/ipa_context.cpp
index 959f314f..917d0654 100644
--- a/src/ipa/ipu3/ipa_context.cpp
+++ b/src/ipa/ipu3/ipa_context.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021, Google Inc.
*
- * ipa_context.cpp - IPU3 IPA Context
+ * IPU3 IPA Context
*/
#include "ipa_context.h"
@@ -47,6 +47,9 @@ namespace libcamera::ipa::ipu3 {
*
* \var IPAContext::activeState
* \brief The current state of IPA algorithms
+ *
+ * \var IPAContext::ctrlMap
+ * \brief A ControlInfoMap::Map of controls populated by the algorithms
*/
/**
diff --git a/src/ipa/ipu3/ipa_context.h b/src/ipa/ipu3/ipa_context.h
index e9a3863b..c85d1e34 100644
--- a/src/ipa/ipu3/ipa_context.h
+++ b/src/ipa/ipu3/ipa_context.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021, Google Inc.
*
- * ipa_context.h - IPU3 IPA Context
+ * IPU3 IPA Context
*
*/
@@ -12,6 +12,7 @@
#include <libcamera/base/utils.h>
+#include <libcamera/controls.h>
#include <libcamera/geometry.h>
#include <libipa/fc_queue.h>
@@ -55,6 +56,8 @@ struct IPAActiveState {
struct {
uint32_t exposure;
double gain;
+ uint32_t constraintMode;
+ uint32_t exposureMode;
} agc;
struct {
@@ -85,6 +88,8 @@ struct IPAContext {
IPAActiveState activeState;
FCQueue<IPAFrameContext> frameContexts;
+
+ ControlInfoMap::Map ctrlMap;
};
} /* namespace ipa::ipu3 */
diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp
index 08ee6eb3..cdcdf1fb 100644
--- a/src/ipa/ipu3/ipu3.cpp
+++ b/src/ipa/ipu3/ipu3.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2020, Google Inc.
*
- * ipu3.cpp - IPU3 Image Processing Algorithms
+ * IPU3 Image Processing Algorithms
*/
#include <algorithm>
@@ -189,7 +189,7 @@ private:
};
IPAIPU3::IPAIPU3()
- : context_({ {}, {}, { kMaxFrameContexts } })
+ : context_({ {}, {}, { kMaxFrameContexts }, {} })
{
}
@@ -287,6 +287,7 @@ void IPAIPU3::updateControls(const IPACameraSensorInfo &sensorInfo,
frameDurations[1],
frameDurations[2]);
+ controls.merge(context_.ctrlMap);
*ipaControls = ControlInfoMap(std::move(controls), controls::controls);
}
@@ -672,7 +673,7 @@ extern "C" {
const struct IPAModuleInfo ipaModuleInfo = {
IPA_MODULE_API_VERSION,
1,
- "PipelineHandlerIPU3",
+ "ipu3",
"ipu3",
};
diff --git a/src/ipa/ipu3/module.h b/src/ipa/ipu3/module.h
index d94fc459..60f65cc4 100644
--- a/src/ipa/ipu3/module.h
+++ b/src/ipa/ipu3/module.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2022, Ideas On Board
*
- * module.h - IPU3 IPA Module
+ * IPU3 IPA Module
*/
#pragma once
diff --git a/src/ipa/libipa/agc_mean_luminance.cpp b/src/ipa/libipa/agc_mean_luminance.cpp
new file mode 100644
index 00000000..271b5ae4
--- /dev/null
+++ b/src/ipa/libipa/agc_mean_luminance.cpp
@@ -0,0 +1,577 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024 Ideas on Board Oy
+ *
+ * Base class for mean luminance AGC algorithms
+ */
+
+#include "agc_mean_luminance.h"
+
+#include <cmath>
+
+#include <libcamera/base/log.h>
+#include <libcamera/control_ids.h>
+
+#include "exposure_mode_helper.h"
+
+using namespace libcamera::controls;
+
+/**
+ * \file agc_mean_luminance.h
+ * \brief Base class implementing mean luminance AEGC
+ */
+
+namespace libcamera {
+
+using namespace std::literals::chrono_literals;
+
+LOG_DEFINE_CATEGORY(AgcMeanLuminance)
+
+namespace ipa {
+
+/*
+ * Number of frames for which to run the algorithm at full speed, before slowing
+ * down to prevent large and jarring changes in exposure from frame to frame.
+ */
+static constexpr uint32_t kNumStartupFrames = 10;
+
+/*
+ * Default relative luminance target
+ *
+ * This value should be chosen so that when the camera points at a grey target,
+ * the resulting image brightness looks "right". Custom values can be passed
+ * as the relativeLuminanceTarget value in sensor tuning files.
+ */
+static constexpr double kDefaultRelativeLuminanceTarget = 0.16;
+
+/**
+ * \struct AgcMeanLuminance::AgcConstraint
+ * \brief The boundaries and target for an AeConstraintMode constraint
+ *
+ * This structure describes an AeConstraintMode constraint for the purposes of
+ * this algorithm. These constraints are expressed as a pair of quantile
+ * boundaries for a histogram, along with a luminance target and a bounds-type.
+ * The algorithm uses the constraints by ensuring that the defined portion of a
+ * luminance histogram (I.E. lying between the two quantiles) is above or below
+ * the given luminance value.
+ */
+
+/**
+ * \enum AgcMeanLuminance::AgcConstraint::Bound
+ * \brief Specify whether the constraint defines a lower or upper bound
+ * \var AgcMeanLuminance::AgcConstraint::lower
+ * \brief The constraint defines a lower bound
+ * \var AgcMeanLuminance::AgcConstraint::upper
+ * \brief The constraint defines an upper bound
+ */
+
+/**
+ * \var AgcMeanLuminance::AgcConstraint::bound
+ * \brief The type of constraint bound
+ */
+
+/**
+ * \var AgcMeanLuminance::AgcConstraint::qLo
+ * \brief The lower quantile to use for the constraint
+ */
+
+/**
+ * \var AgcMeanLuminance::AgcConstraint::qHi
+ * \brief The upper quantile to use for the constraint
+ */
+
+/**
+ * \var AgcMeanLuminance::AgcConstraint::yTarget
+ * \brief The luminance target for the constraint
+ */
+
+/**
+ * \class AgcMeanLuminance
+ * \brief A mean-based auto-exposure algorithm
+ *
+ * This algorithm calculates a shutter time, analogue and digital gain such that
+ * the normalised mean luminance value of an image is driven towards a target,
+ * which itself is discovered from tuning data. The algorithm is a two-stage
+ * process.
+ *
+ * In the first stage, an initial gain value is derived by iteratively comparing
+ * the gain-adjusted mean luminance across the entire image against a target,
+ * and selecting a value which pushes it as closely as possible towards the
+ * target.
+ *
+ * In the second stage we calculate the gain required to drive the average of a
+ * section of a histogram to a target value, where the target and the boundaries
+ * of the section of the histogram used in the calculation are taken from the
+ * values defined for the currently configured AeConstraintMode within the
+ * tuning data. This class provides a helper function to parse those tuning data
+ * to discover the constraints, and so requires a specific format for those
+ * data which is described in \ref parseTuningData(). The gain from the first
+ * stage is then clamped to the gain from this stage.
+ *
+ * The final gain is used to adjust the effective exposure value of the image,
+ * and that new exposure value is divided into shutter time, analogue gain and
+ * digital gain according to the selected AeExposureMode. This class uses the
+ * \ref ExposureModeHelper class to assist in that division, and expects the
+ * data needed to initialise that class to be present in tuning data in a
+ * format described in \ref parseTuningData().
+ *
+ * In order to be able to use this algorithm an IPA module needs to be able to
+ * do the following:
+ *
+ * 1. Provide a luminance estimation across an entire image.
+ * 2. Provide a luminance Histogram for the image to use in calculating
+ * constraint compliance. The precision of the Histogram that is available
+ * will determine the supportable precision of the constraints.
+ *
+ * IPA modules that want to use this class to implement their AEGC algorithm
+ * should derive it and provide an overriding estimateLuminance() function for
+ * this class to use. They must call parseTuningData() in init(), and must also
+ * call setLimits() and resetFrameCounter() in configure(). They may then use
+ * calculateNewEv() in process(). If the limits passed to setLimits() change for
+ * any reason (for example, in response to a FrameDurationLimit control being
+ * passed in queueRequest()) then setLimits() must be called again with the new
+ * values.
+ */
+
+AgcMeanLuminance::AgcMeanLuminance()
+ : frameCount_(0), filteredExposure_(0s), relativeLuminanceTarget_(0)
+{
+}
+
+AgcMeanLuminance::~AgcMeanLuminance() = default;
+
+void AgcMeanLuminance::parseRelativeLuminanceTarget(const YamlObject &tuningData)
+{
+ relativeLuminanceTarget_ =
+ tuningData["relativeLuminanceTarget"].get<double>(kDefaultRelativeLuminanceTarget);
+}
+
+void AgcMeanLuminance::parseConstraint(const YamlObject &modeDict, int32_t id)
+{
+ for (const auto &[boundName, content] : modeDict.asDict()) {
+ if (boundName != "upper" && boundName != "lower") {
+ LOG(AgcMeanLuminance, Warning)
+ << "Ignoring unknown constraint bound '" << boundName << "'";
+ continue;
+ }
+
+ unsigned int idx = static_cast<unsigned int>(boundName == "upper");
+ AgcConstraint::Bound bound = static_cast<AgcConstraint::Bound>(idx);
+ double qLo = content["qLo"].get<double>().value_or(0.98);
+ double qHi = content["qHi"].get<double>().value_or(1.0);
+ double yTarget =
+ content["yTarget"].getList<double>().value_or(std::vector<double>{ 0.5 }).at(0);
+
+ AgcConstraint constraint = { bound, qLo, qHi, yTarget };
+
+ if (!constraintModes_.count(id))
+ constraintModes_[id] = {};
+
+ if (idx)
+ constraintModes_[id].push_back(constraint);
+ else
+ constraintModes_[id].insert(constraintModes_[id].begin(), constraint);
+ }
+}
+
+int AgcMeanLuminance::parseConstraintModes(const YamlObject &tuningData)
+{
+ std::vector<ControlValue> availableConstraintModes;
+
+ const YamlObject &yamlConstraintModes = tuningData[controls::AeConstraintMode.name()];
+ if (yamlConstraintModes.isDictionary()) {
+ for (const auto &[modeName, modeDict] : yamlConstraintModes.asDict()) {
+ if (AeConstraintModeNameValueMap.find(modeName) ==
+ AeConstraintModeNameValueMap.end()) {
+ LOG(AgcMeanLuminance, Warning)
+ << "Skipping unknown constraint mode '" << modeName << "'";
+ continue;
+ }
+
+ if (!modeDict.isDictionary()) {
+ LOG(AgcMeanLuminance, Error)
+ << "Invalid constraint mode '" << modeName << "'";
+ return -EINVAL;
+ }
+
+ parseConstraint(modeDict,
+ AeConstraintModeNameValueMap.at(modeName));
+ availableConstraintModes.push_back(
+ AeConstraintModeNameValueMap.at(modeName));
+ }
+ }
+
+ /*
+ * If the tuning data file contains no constraints then we use the
+ * default constraint that the IPU3/RkISP1 Agc algorithms were adhering
+ * to anyway before centralisation; this constraint forces the top 2% of
+ * the histogram to be at least 0.5.
+ */
+ if (constraintModes_.empty()) {
+ AgcConstraint constraint = {
+ AgcConstraint::Bound::lower,
+ 0.98,
+ 1.0,
+ 0.5
+ };
+
+ constraintModes_[controls::ConstraintNormal].insert(
+ constraintModes_[controls::ConstraintNormal].begin(),
+ constraint);
+ availableConstraintModes.push_back(
+ AeConstraintModeNameValueMap.at("ConstraintNormal"));
+ }
+
+ controls_[&controls::AeConstraintMode] = ControlInfo(availableConstraintModes);
+
+ return 0;
+}
+
+int AgcMeanLuminance::parseExposureModes(const YamlObject &tuningData)
+{
+ std::vector<ControlValue> availableExposureModes;
+
+ const YamlObject &yamlExposureModes = tuningData[controls::AeExposureMode.name()];
+ if (yamlExposureModes.isDictionary()) {
+ for (const auto &[modeName, modeValues] : yamlExposureModes.asDict()) {
+ if (AeExposureModeNameValueMap.find(modeName) ==
+ AeExposureModeNameValueMap.end()) {
+ LOG(AgcMeanLuminance, Warning)
+ << "Skipping unknown exposure mode '" << modeName << "'";
+ continue;
+ }
+
+ if (!modeValues.isDictionary()) {
+ LOG(AgcMeanLuminance, Error)
+ << "Invalid exposure mode '" << modeName << "'";
+ return -EINVAL;
+ }
+
+ std::vector<uint32_t> shutters =
+ modeValues["shutter"].getList<uint32_t>().value_or(std::vector<uint32_t>{});
+ std::vector<double> gains =
+ modeValues["gain"].getList<double>().value_or(std::vector<double>{});
+
+ if (shutters.size() != gains.size()) {
+ LOG(AgcMeanLuminance, Error)
+ << "Shutter and gain array sizes unequal";
+ return -EINVAL;
+ }
+
+ if (shutters.empty()) {
+ LOG(AgcMeanLuminance, Error)
+ << "Shutter and gain arrays are empty";
+ return -EINVAL;
+ }
+
+ std::vector<std::pair<utils::Duration, double>> stages;
+ for (unsigned int i = 0; i < shutters.size(); i++) {
+ stages.push_back({
+ std::chrono::microseconds(shutters[i]),
+ gains[i]
+ });
+ }
+
+ std::shared_ptr<ExposureModeHelper> helper =
+ std::make_shared<ExposureModeHelper>(stages);
+
+ exposureModeHelpers_[AeExposureModeNameValueMap.at(modeName)] = helper;
+ availableExposureModes.push_back(AeExposureModeNameValueMap.at(modeName));
+ }
+ }
+
+ /*
+ * If we don't have any exposure modes in the tuning data we create an
+ * ExposureModeHelper using an empty vector of stages. This will result
+ * in the ExposureModeHelper simply driving the shutter as high as
+ * possible before touching gain.
+ */
+ if (availableExposureModes.empty()) {
+ int32_t exposureModeId = AeExposureModeNameValueMap.at("ExposureNormal");
+ std::vector<std::pair<utils::Duration, double>> stages = { };
+
+ std::shared_ptr<ExposureModeHelper> helper =
+ std::make_shared<ExposureModeHelper>(stages);
+
+ exposureModeHelpers_[exposureModeId] = helper;
+ availableExposureModes.push_back(exposureModeId);
+ }
+
+ controls_[&controls::AeExposureMode] = ControlInfo(availableExposureModes);
+
+ return 0;
+}
+
+/**
+ * \brief Parse tuning data for AeConstraintMode and AeExposureMode controls
+ * \param[in] tuningData the YamlObject representing the tuning data
+ *
+ * This function parses tuning data to build the list of allowed values for the
+ * AeConstraintMode and AeExposureMode controls. Those tuning data must provide
+ * the data in a specific format; the Agc algorithm's tuning data should contain
+ * a dictionary called AeConstraintMode containing per-mode setting dictionaries
+ * with the key being a value from \ref controls::AeConstraintModeNameValueMap.
+ * Each mode dict may contain either a "lower" or "upper" key or both, for
+ * example:
+ *
+ * \code{.unparsed}
+ * algorithms:
+ * - Agc:
+ * AeConstraintMode:
+ * ConstraintNormal:
+ * lower:
+ * qLo: 0.98
+ * qHi: 1.0
+ * yTarget: 0.5
+ * ConstraintHighlight:
+ * lower:
+ * qLo: 0.98
+ * qHi: 1.0
+ * yTarget: 0.5
+ * upper:
+ * qLo: 0.98
+ * qHi: 1.0
+ * yTarget: 0.8
+ *
+ * \endcode
+ *
+ * For the AeExposureMode control the data should contain a dictionary called
+ * AeExposureMode containing per-mode setting dictionaries with the key being a
+ * value from \ref controls::AeExposureModeNameValueMap. Each mode dict should
+ * contain an array of shutter times with the key "shutter" and an array of gain
+ * values with the key "gain", in this format:
+ *
+ * \code{.unparsed}
+ * algorithms:
+ * - Agc:
+ * AeExposureMode:
+ * ExposureNormal:
+ * shutter: [ 100, 10000, 30000, 60000, 120000 ]
+ * gain: [ 2.0, 4.0, 6.0, 8.0, 10.0 ]
+ * ExposureShort:
+ * shutter: [ 100, 10000, 30000, 60000, 120000 ]
+ * gain: [ 2.0, 4.0, 6.0, 8.0, 10.0 ]
+ *
+ * \endcode
+ *
+ * \return 0 on success or a negative error code
+ */
+int AgcMeanLuminance::parseTuningData(const YamlObject &tuningData)
+{
+ int ret;
+
+ parseRelativeLuminanceTarget(tuningData);
+
+ ret = parseConstraintModes(tuningData);
+ if (ret)
+ return ret;
+
+ return parseExposureModes(tuningData);
+}
+
+/**
+ * \brief Set the ExposureModeHelper limits for this class
+ * \param[in] minShutter Minimum shutter time to allow
+ * \param[in] maxShutter Maximum shutter time to allow
+ * \param[in] minGain Minimum gain to allow
+ * \param[in] maxGain Maximum gain to allow
+ *
+ * This function calls \ref ExposureModeHelper::setLimits() for each
+ * ExposureModeHelper that has been created for this class.
+ */
+void AgcMeanLuminance::setLimits(utils::Duration minShutter,
+ utils::Duration maxShutter,
+ double minGain, double maxGain)
+{
+ for (auto &[id, helper] : exposureModeHelpers_)
+ helper->setLimits(minShutter, maxShutter, minGain, maxGain);
+}
+
+/**
+ * \fn AgcMeanLuminance::constraintModes()
+ * \brief Get the constraint modes that have been parsed from tuning data
+ */
+
+/**
+ * \fn AgcMeanLuminance::exposureModeHelpers()
+ * \brief Get the ExposureModeHelpers that have been parsed from tuning data
+ */
+
+/**
+ * \fn AgcMeanLuminance::controls()
+ * \brief Get the controls that have been generated after parsing tuning data
+ */
+
+/**
+ * \fn AgcMeanLuminance::estimateLuminance(const double gain)
+ * \brief Estimate the luminance of an image, adjusted by a given gain
+ * \param[in] gain The gain with which to adjust the luminance estimate
+ *
+ * This function estimates the average relative luminance of the frame that
+ * would be output by the sensor if an additional \a gain was applied. It is a
+ * pure virtual function because estimation of luminance is a hardware-specific
+ * operation, which depends wholly on the format of the stats that are delivered
+ * to libcamera from the ISP. Derived classes must override this function with
+ * one that calculates the normalised mean luminance value across the entire
+ * image.
+ *
+ * \return The normalised relative luminance of the image
+ */
+
+/**
+ * \brief Estimate the initial gain needed to achieve a relative luminance
+ * target
+ * \return The calculated initial gain
+ */
+double AgcMeanLuminance::estimateInitialGain() const
+{
+ double yTarget = relativeLuminanceTarget_;
+ double yGain = 1.0;
+
+ /*
+ * To account for non-linearity caused by saturation, the value needs to
+ * be estimated in an iterative process, as multiplying by a gain will
+ * not increase the relative luminance by the same factor if some image
+ * regions are saturated.
+ */
+ for (unsigned int i = 0; i < 8; i++) {
+ double yValue = estimateLuminance(yGain);
+ double extra_gain = std::min(10.0, yTarget / (yValue + .001));
+
+ yGain *= extra_gain;
+ LOG(AgcMeanLuminance, Debug) << "Y value: " << yValue
+ << ", Y target: " << yTarget
+ << ", gives gain " << yGain;
+
+ if (utils::abs_diff(extra_gain, 1.0) < 0.01)
+ break;
+ }
+
+ return yGain;
+}
+
+/**
+ * \brief Clamp gain within the bounds of a defined constraint
+ * \param[in] constraintModeIndex The index of the constraint to adhere to
+ * \param[in] hist A histogram over which to calculate inter-quantile means
+ * \param[in] gain The gain to clamp
+ *
+ * \return The gain clamped within the constraint bounds
+ */
+double AgcMeanLuminance::constraintClampGain(uint32_t constraintModeIndex,
+ const Histogram &hist,
+ double gain)
+{
+ std::vector<AgcConstraint> &constraints = constraintModes_[constraintModeIndex];
+ for (const AgcConstraint &constraint : constraints) {
+ double newGain = constraint.yTarget * hist.bins() /
+ hist.interQuantileMean(constraint.qLo, constraint.qHi);
+
+ if (constraint.bound == AgcConstraint::Bound::lower &&
+ newGain > gain)
+ gain = newGain;
+
+ if (constraint.bound == AgcConstraint::Bound::upper &&
+ newGain < gain)
+ gain = newGain;
+ }
+
+ return gain;
+}
+
+/**
+ * \brief Apply a filter on the exposure value to limit the speed of changes
+ * \param[in] exposureValue The target exposure from the AGC algorithm
+ *
+ * The speed of the filter is adaptive, and will produce the target quicker
+ * during startup, or when the target exposure is within 20% of the most recent
+ * filter output.
+ *
+ * \return The filtered exposure
+ */
+utils::Duration AgcMeanLuminance::filterExposure(utils::Duration exposureValue)
+{
+ double speed = 0.2;
+
+ /* Adapt instantly if we are in startup phase. */
+ if (frameCount_ < kNumStartupFrames)
+ speed = 1.0;
+
+ /*
+ * If we are close to the desired result, go faster to avoid making
+ * multiple micro-adjustments.
+ * \todo Make this customisable?
+ */
+ if (filteredExposure_ < 1.2 * exposureValue &&
+ filteredExposure_ > 0.8 * exposureValue)
+ speed = sqrt(speed);
+
+ filteredExposure_ = speed * exposureValue +
+ filteredExposure_ * (1.0 - speed);
+
+ return filteredExposure_;
+}
+
+/**
+ * \brief Calculate the new exposure value and splut it between shutter time and gain
+ * \param[in] constraintModeIndex The index of the current constraint mode
+ * \param[in] exposureModeIndex The index of the current exposure mode
+ * \param[in] yHist A Histogram from the ISP statistics to use in constraining
+ * the calculated gain
+ * \param[in] effectiveExposureValue The EV applied to the frame from which the
+ * statistics in use derive
+ *
+ * Calculate a new exposure value to try to obtain the target. The calculated
+ * exposure value is filtered to prevent rapid changes from frame to frame, and
+ * divided into shutter time, analogue and digital gain.
+ *
+ * \return Tuple of shutter time, analogue gain, and digital gain
+ */
+std::tuple<utils::Duration, double, double>
+AgcMeanLuminance::calculateNewEv(uint32_t constraintModeIndex,
+ uint32_t exposureModeIndex,
+ const Histogram &yHist,
+ utils::Duration effectiveExposureValue)
+{
+ /*
+ * The pipeline handler should validate that we have received an allowed
+ * value for AeExposureMode.
+ */
+ std::shared_ptr<ExposureModeHelper> exposureModeHelper =
+ exposureModeHelpers_.at(exposureModeIndex);
+
+ double gain = estimateInitialGain();
+ gain = constraintClampGain(constraintModeIndex, yHist, gain);
+
+ /*
+ * We don't check whether we're already close to the target, because
+ * even if the effective exposure value is the same as the last frame's
+ * we could have switched to an exposure mode that would require a new
+ * pass through the splitExposure() function.
+ */
+
+ utils::Duration newExposureValue = effectiveExposureValue * gain;
+
+ /*
+ * We filter the exposure value to make sure changes are not too jarring
+ * from frame to frame.
+ */
+ newExposureValue = filterExposure(newExposureValue);
+
+ frameCount_++;
+ return exposureModeHelper->splitExposure(newExposureValue);
+}
+
+/**
+ * \fn AgcMeanLuminance::resetFrameCount()
+ * \brief Reset the frame counter
+ *
+ * This function resets the internal frame counter, which exists to help the
+ * algorithm decide whether it should respond instantly or not. The expectation
+ * is for derived classes to call this function before each camera start call in
+ * their configure() function.
+ */
+
+} /* namespace ipa */
+
+} /* namespace libcamera */
diff --git a/src/ipa/libipa/agc_mean_luminance.h b/src/ipa/libipa/agc_mean_luminance.h
new file mode 100644
index 00000000..0a81c6d2
--- /dev/null
+++ b/src/ipa/libipa/agc_mean_luminance.h
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024 Ideas on Board Oy
+ *
+ agc_mean_luminance.h - Base class for mean luminance AGC algorithms
+ */
+
+#pragma once
+
+#include <map>
+#include <memory>
+#include <tuple>
+#include <vector>
+
+#include <libcamera/controls.h>
+
+#include "libcamera/internal/yaml_parser.h"
+
+#include "exposure_mode_helper.h"
+#include "histogram.h"
+
+namespace libcamera {
+
+namespace ipa {
+
+class AgcMeanLuminance
+{
+public:
+ AgcMeanLuminance();
+ virtual ~AgcMeanLuminance();
+
+ struct AgcConstraint {
+ enum class Bound {
+ lower = 0,
+ upper = 1
+ };
+ Bound bound;
+ double qLo;
+ double qHi;
+ double yTarget;
+ };
+
+ int parseTuningData(const YamlObject &tuningData);
+
+ void setLimits(utils::Duration minShutter, utils::Duration maxShutter,
+ double minGain, double maxGain);
+
+ std::map<int32_t, std::vector<AgcConstraint>> constraintModes()
+ {
+ return constraintModes_;
+ }
+
+ std::map<int32_t, std::shared_ptr<ExposureModeHelper>> exposureModeHelpers()
+ {
+ return exposureModeHelpers_;
+ }
+
+ ControlInfoMap::Map controls()
+ {
+ return controls_;
+ }
+
+ std::tuple<utils::Duration, double, double>
+ calculateNewEv(uint32_t constraintModeIndex, uint32_t exposureModeIndex,
+ const Histogram &yHist, utils::Duration effectiveExposureValue);
+
+ void resetFrameCount()
+ {
+ frameCount_ = 0;
+ }
+
+private:
+ virtual double estimateLuminance(const double gain) const = 0;
+
+ void parseRelativeLuminanceTarget(const YamlObject &tuningData);
+ void parseConstraint(const YamlObject &modeDict, int32_t id);
+ int parseConstraintModes(const YamlObject &tuningData);
+ int parseExposureModes(const YamlObject &tuningData);
+ double estimateInitialGain() const;
+ double constraintClampGain(uint32_t constraintModeIndex,
+ const Histogram &hist,
+ double gain);
+ utils::Duration filterExposure(utils::Duration exposureValue);
+
+ uint64_t frameCount_;
+ utils::Duration filteredExposure_;
+ double relativeLuminanceTarget_;
+
+ std::map<int32_t, std::vector<AgcConstraint>> constraintModes_;
+ std::map<int32_t, std::shared_ptr<ExposureModeHelper>> exposureModeHelpers_;
+ ControlInfoMap::Map controls_;
+};
+
+} /* namespace ipa */
+
+} /* namespace libcamera */
diff --git a/src/ipa/libipa/algorithm.cpp b/src/ipa/libipa/algorithm.cpp
index bc1c29a6..201efdfd 100644
--- a/src/ipa/libipa/algorithm.cpp
+++ b/src/ipa/libipa/algorithm.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021, Ideas On Board
*
- * algorithm.cpp - IPA control algorithm interface
+ * IPA control algorithm interface
*/
#include "algorithm.h"
diff --git a/src/ipa/libipa/algorithm.h b/src/ipa/libipa/algorithm.h
index 987e3e4c..9a19dbd6 100644
--- a/src/ipa/libipa/algorithm.h
+++ b/src/ipa/libipa/algorithm.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021, Ideas On Board
*
- * algorithm.h - ISP control algorithm interface
+ * ISP control algorithm interface
*/
#pragma once
diff --git a/src/ipa/libipa/camera_sensor_helper.cpp b/src/ipa/libipa/camera_sensor_helper.cpp
index ce29f423..2cd61fcc 100644
--- a/src/ipa/libipa/camera_sensor_helper.cpp
+++ b/src/ipa/libipa/camera_sensor_helper.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021, Google Inc.
*
- * camera_sensor_helper.cpp - Helper class that performs sensor-specific
+ * Helper class that performs sensor-specific
* parameter computations
*/
#include "camera_sensor_helper.h"
@@ -417,6 +417,17 @@ public:
};
REGISTER_CAMERA_SENSOR_HELPER("imx258", CameraSensorHelperImx258)
+class CameraSensorHelperImx283 : public CameraSensorHelper
+{
+public:
+ CameraSensorHelperImx283()
+ {
+ gainType_ = AnalogueGainLinear;
+ gainConstants_.linear = { 0, 2048, -1, 2048 };
+ }
+};
+REGISTER_CAMERA_SENSOR_HELPER("imx283", CameraSensorHelperImx283)
+
class CameraSensorHelperImx290 : public CameraSensorHelper
{
public:
@@ -444,6 +455,28 @@ class CameraSensorHelperImx327 : public CameraSensorHelperImx290
};
REGISTER_CAMERA_SENSOR_HELPER("imx327", CameraSensorHelperImx327)
+class CameraSensorHelperImx335 : public CameraSensorHelper
+{
+public:
+ CameraSensorHelperImx335()
+ {
+ gainType_ = AnalogueGainExponential;
+ gainConstants_.exp = { 1.0, expGainDb(0.3) };
+ }
+};
+REGISTER_CAMERA_SENSOR_HELPER("imx335", CameraSensorHelperImx335)
+
+class CameraSensorHelperImx415 : public CameraSensorHelper
+{
+public:
+ CameraSensorHelperImx415()
+ {
+ gainType_ = AnalogueGainExponential;
+ gainConstants_.exp = { 1.0, expGainDb(0.3) };
+ }
+};
+REGISTER_CAMERA_SENSOR_HELPER("imx415", CameraSensorHelperImx415)
+
class CameraSensorHelperImx477 : public CameraSensorHelper
{
public:
diff --git a/src/ipa/libipa/camera_sensor_helper.h b/src/ipa/libipa/camera_sensor_helper.h
index 1ca9371b..0d99073b 100644
--- a/src/ipa/libipa/camera_sensor_helper.h
+++ b/src/ipa/libipa/camera_sensor_helper.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021, Google Inc.
*
- * camera_sensor_helper.h - Helper class that performs sensor-specific parameter computations
+ * Helper class that performs sensor-specific parameter computations
*/
#pragma once
diff --git a/src/ipa/libipa/exposure_mode_helper.cpp b/src/ipa/libipa/exposure_mode_helper.cpp
new file mode 100644
index 00000000..683a564a
--- /dev/null
+++ b/src/ipa/libipa/exposure_mode_helper.cpp
@@ -0,0 +1,246 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>
+ *
+ * Helper class that performs computations relating to exposure
+ */
+#include "exposure_mode_helper.h"
+
+#include <algorithm>
+
+#include <libcamera/base/log.h>
+
+/**
+ * \file exposure_mode_helper.h
+ * \brief Helper class that performs computations relating to exposure
+ *
+ * AEGC algorithms have a need to split exposure between shutter time, analogue
+ * and digital gain. Multiple implementations do so based on paired stages of
+ * shutter time and gain limits; provide a helper to avoid duplicating the code.
+ */
+
+namespace libcamera {
+
+using namespace std::literals::chrono_literals;
+
+LOG_DEFINE_CATEGORY(ExposureModeHelper)
+
+namespace ipa {
+
+/**
+ * \class ExposureModeHelper
+ * \brief Class for splitting exposure into shutter time and total gain
+ *
+ * The ExposureModeHelper class provides a standard interface through which an
+ * AEGC algorithm can divide exposure between shutter time and gain. It is
+ * configured with a set of shutter time and gain pairs and works by initially
+ * fixing gain at 1.0 and increasing shutter time up to the shutter time value
+ * from the first pair in the set in an attempt to meet the required exposure
+ * value.
+ *
+ * If the required exposure is not achievable by the first shutter time value
+ * alone it ramps gain up to the value from the first pair in the set. If the
+ * required exposure is still not met it then allows shutter time to ramp up to
+ * the shutter time value from the second pair in the set, and continues in this
+ * vein until either the required exposure time is met, or else the hardware's
+ * shutter time or gain limits are reached.
+ *
+ * This method allows users to strike a balance between a well-exposed image and
+ * an acceptable frame-rate, as opposed to simply maximising shutter time
+ * followed by gain. The same helpers can be used to perform the latter
+ * operation if needed by passing an empty set of pairs to the initialisation
+ * function.
+ *
+ * The gain values may exceed a camera sensor's analogue gain limits if either
+ * it or the IPA is also capable of digital gain. The configure() function must
+ * be called with the hardware's limits to inform the helper of those
+ * constraints. Any gain that is needed will be applied as analogue gain first
+ * until the hardware's limit is reached, following which digital gain will be
+ * used.
+ */
+
+/**
+ * \brief Construct an ExposureModeHelper instance
+ * \param[in] stages The vector of paired shutter time and gain limits
+ *
+ * The input stages are shutter time and _total_ gain pairs; the gain
+ * encompasses both analogue and digital gain.
+ *
+ * The vector of stages may be empty. In that case, the helper will simply use
+ * the runtime limits set through setShutterGainLimits() instead.
+ */
+ExposureModeHelper::ExposureModeHelper(const Span<std::pair<utils::Duration, double>> stages)
+{
+ minShutter_ = 0us;
+ maxShutter_ = 0us;
+ minGain_ = 0;
+ maxGain_ = 0;
+
+ for (const auto &[s, g] : stages) {
+ shutters_.push_back(s);
+ gains_.push_back(g);
+ }
+}
+
+/**
+ * \brief Set the shutter time and gain limits
+ * \param[in] minShutter The minimum shutter time supported
+ * \param[in] maxShutter The maximum shutter time supported
+ * \param[in] minGain The minimum analogue gain supported
+ * \param[in] maxGain The maximum analogue gain supported
+ *
+ * This function configures the shutter time and analogue gain limits that need
+ * to be adhered to as the helper divides up exposure. Note that this function
+ * *must* be called whenever those limits change and before splitExposure() is
+ * used.
+ *
+ * If the algorithm using the helpers needs to indicate that either shutter time
+ * or analogue gain or both should be fixed it can do so by setting both the
+ * minima and maxima to the same value.
+ */
+void ExposureModeHelper::setLimits(utils::Duration minShutter,
+ utils::Duration maxShutter,
+ double minGain, double maxGain)
+{
+ minShutter_ = minShutter;
+ maxShutter_ = maxShutter;
+ minGain_ = minGain;
+ maxGain_ = maxGain;
+}
+
+utils::Duration ExposureModeHelper::clampShutter(utils::Duration shutter) const
+{
+ return std::clamp(shutter, minShutter_, maxShutter_);
+}
+
+double ExposureModeHelper::clampGain(double gain) const
+{
+ return std::clamp(gain, minGain_, maxGain_);
+}
+
+/**
+ * \brief Split exposure time into shutter time and gain
+ * \param[in] exposure Exposure time
+ *
+ * This function divides a given exposure time into shutter time, analogue and
+ * digital gain by iterating through stages of shutter time and gain limits. At
+ * each stage the current stage's shutter time limit is multiplied by the
+ * previous stage's gain limit (or 1.0 initially) to see if the combination of
+ * the two can meet the required exposure time. If they cannot then the current
+ * stage's shutter time limit is multiplied by the same stage's gain limit to
+ * see if that combination can meet the required exposure time. If they cannot
+ * then the function moves to consider the next stage.
+ *
+ * When a combination of shutter time and gain _stage_ limits are found that are
+ * sufficient to meet the required exposure time, the function attempts to
+ * reduce shutter time as much as possible whilst fixing gain and still meeting
+ * the exposure time. If a _runtime_ limit prevents shutter time from being
+ * lowered enough to meet the exposure time with gain fixed at the stage limit,
+ * gain is also lowered to compensate.
+ *
+ * Once the shutter time and gain values are ascertained, gain is assigned as
+ * analogue gain as much as possible, with digital gain only in use if the
+ * maximum analogue gain runtime limit is unable to accommodate the exposure
+ * value.
+ *
+ * If no combination of shutter time and gain limits is found that meets the
+ * required exposure time, the helper falls-back to simply maximising the
+ * shutter time first, followed by analogue gain, followed by digital gain.
+ *
+ * \return Tuple of shutter time, analogue gain, and digital gain
+ */
+std::tuple<utils::Duration, double, double>
+ExposureModeHelper::splitExposure(utils::Duration exposure) const
+{
+ ASSERT(maxShutter_);
+ ASSERT(maxGain_);
+
+ bool gainFixed = minGain_ == maxGain_;
+ bool shutterFixed = minShutter_ == maxShutter_;
+
+ /*
+ * There's no point entering the loop if we cannot change either gain
+ * nor shutter anyway.
+ */
+ if (shutterFixed && gainFixed)
+ return { minShutter_, minGain_, exposure / (minShutter_ * minGain_) };
+
+ utils::Duration shutter;
+ double stageGain;
+ double gain;
+
+ for (unsigned int stage = 0; stage < gains_.size(); stage++) {
+ double lastStageGain = stage == 0 ? 1.0 : clampGain(gains_[stage - 1]);
+ utils::Duration stageShutter = clampShutter(shutters_[stage]);
+ stageGain = clampGain(gains_[stage]);
+
+ /*
+ * We perform the clamping on both shutter and gain in case the
+ * helper has had limits set that prevent those values being
+ * lowered beyond a certain minimum...this can happen at runtime
+ * for various reasons and so would not be known when the stage
+ * limits are initialised.
+ */
+
+ if (stageShutter * lastStageGain >= exposure) {
+ shutter = clampShutter(exposure / clampGain(lastStageGain));
+ gain = clampGain(exposure / shutter);
+
+ return { shutter, gain, exposure / (shutter * gain) };
+ }
+
+ if (stageShutter * stageGain >= exposure) {
+ shutter = clampShutter(exposure / clampGain(stageGain));
+ gain = clampGain(exposure / shutter);
+
+ return { shutter, gain, exposure / (shutter * gain) };
+ }
+ }
+
+ /*
+ * From here on all we can do is max out the shutter time, followed by
+ * the analogue gain. If we still haven't achieved the target we send
+ * the rest of the exposure time to digital gain. If we were given no
+ * stages to use then set stageGain to 1.0 so that shutter time is maxed
+ * before gain touched at all.
+ */
+ if (gains_.empty())
+ stageGain = 1.0;
+
+ shutter = clampShutter(exposure / clampGain(stageGain));
+ gain = clampGain(exposure / shutter);
+
+ return { shutter, gain, exposure / (shutter * gain) };
+}
+
+/**
+ * \fn ExposureModeHelper::minShutter()
+ * \brief Retrieve the configured minimum shutter time limit set through
+ * setShutterGainLimits()
+ * \return The minShutter_ value
+ */
+
+/**
+ * \fn ExposureModeHelper::maxShutter()
+ * \brief Retrieve the configured maximum shutter time set through
+ * setShutterGainLimits()
+ * \return The maxShutter_ value
+ */
+
+/**
+ * \fn ExposureModeHelper::minGain()
+ * \brief Retrieve the configured minimum gain set through
+ * setShutterGainLimits()
+ * \return The minGain_ value
+ */
+
+/**
+ * \fn ExposureModeHelper::maxGain()
+ * \brief Retrieve the configured maximum gain set through
+ * setShutterGainLimits()
+ * \return The maxGain_ value
+ */
+
+} /* namespace ipa */
+
+} /* namespace libcamera */
diff --git a/src/ipa/libipa/exposure_mode_helper.h b/src/ipa/libipa/exposure_mode_helper.h
new file mode 100644
index 00000000..85c665d7
--- /dev/null
+++ b/src/ipa/libipa/exposure_mode_helper.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>
+ *
+ * Helper class that performs computations relating to exposure
+ */
+
+#pragma once
+
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include <libcamera/base/span.h>
+#include <libcamera/base/utils.h>
+
+namespace libcamera {
+
+namespace ipa {
+
+class ExposureModeHelper
+{
+public:
+ ExposureModeHelper(const Span<std::pair<utils::Duration, double>> stages);
+ ~ExposureModeHelper() = default;
+
+ void setLimits(utils::Duration minShutter, utils::Duration maxShutter,
+ double minGain, double maxGain);
+
+ std::tuple<utils::Duration, double, double>
+ splitExposure(utils::Duration exposure) const;
+
+ utils::Duration minShutter() const { return minShutter_; }
+ utils::Duration maxShutter() const { return maxShutter_; }
+ double minGain() const { return minGain_; }
+ double maxGain() const { return maxGain_; }
+
+private:
+ utils::Duration clampShutter(utils::Duration shutter) const;
+ double clampGain(double gain) const;
+
+ std::vector<utils::Duration> shutters_;
+ std::vector<double> gains_;
+
+ utils::Duration minShutter_;
+ utils::Duration maxShutter_;
+ double minGain_;
+ double maxGain_;
+};
+
+} /* namespace ipa */
+
+} /* namespace libcamera */
diff --git a/src/ipa/libipa/fc_queue.cpp b/src/ipa/libipa/fc_queue.cpp
index e812faa5..0365e919 100644
--- a/src/ipa/libipa/fc_queue.cpp
+++ b/src/ipa/libipa/fc_queue.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2022, Google Inc.
*
- * fc_queue.cpp - IPA Frame context queue
+ * IPA Frame context queue
*/
#include "fc_queue.h"
diff --git a/src/ipa/libipa/fc_queue.h b/src/ipa/libipa/fc_queue.h
index a589e7e1..24d9e82b 100644
--- a/src/ipa/libipa/fc_queue.h
+++ b/src/ipa/libipa/fc_queue.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2022, Google Inc.
*
- * fc_queue.h - IPA Frame context queue
+ * IPA Frame context queue
*/
#pragma once
diff --git a/src/ipa/libipa/histogram.cpp b/src/ipa/libipa/histogram.cpp
index 6b5cde8e..5fbfadf5 100644
--- a/src/ipa/libipa/histogram.cpp
+++ b/src/ipa/libipa/histogram.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * histogram.cpp - histogram calculations
+ * histogram calculations
*/
#include "histogram.h"
@@ -29,18 +29,34 @@ namespace ipa {
*/
/**
+ * \fn Histogram::Histogram()
+ * \brief Construct an empty Histogram
+ *
+ * This empty constructor exists largely to allow Histograms to be embedded in
+ * other classes which may be created before the contents of the Histogram are
+ * known.
+ */
+
+/**
* \brief Create a cumulative histogram
- * \param[in] data A pre-sorted histogram to be passed
+ * \param[in] data A (non-cumulative) histogram
*/
Histogram::Histogram(Span<const uint32_t> data)
{
- cumulative_.reserve(data.size());
- cumulative_.push_back(0);
- for (const uint32_t &value : data)
- cumulative_.push_back(cumulative_.back() + value);
+ cumulative_.resize(data.size() + 1);
+ cumulative_[0] = 0;
+ for (const auto &[i, value] : utils::enumerate(data))
+ cumulative_[i + 1] = cumulative_[i] + value;
}
/**
+ * \fn Histogram::Histogram(Span<const uint32_t> data, Transform transform)
+ * \brief Create a cumulative histogram
+ * \param[in] data A (non-cumulative) histogram
+ * \param[in] transform The transformation function to apply to every bin
+ */
+
+/**
* \fn Histogram::bins()
* \brief Retrieve the number of bins currently used by the Histogram
* \return Number of bins
diff --git a/src/ipa/libipa/histogram.h b/src/ipa/libipa/histogram.h
index 05bb4b80..032adca0 100644
--- a/src/ipa/libipa/histogram.h
+++ b/src/ipa/libipa/histogram.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * histogram.h - histogram calculation interface
+ * histogram calculation interface
*/
#pragma once
@@ -10,10 +10,11 @@
#include <assert.h>
#include <limits.h>
#include <stdint.h>
-
+#include <type_traits>
#include <vector>
#include <libcamera/base/span.h>
+#include <libcamera/base/utils.h>
namespace libcamera {
@@ -22,7 +23,19 @@ namespace ipa {
class Histogram
{
public:
+ Histogram() { cumulative_.push_back(0); }
Histogram(Span<const uint32_t> data);
+
+ template<typename Transform,
+ std::enable_if_t<std::is_invocable_v<Transform, uint32_t>> * = nullptr>
+ Histogram(Span<const uint32_t> data, Transform transform)
+ {
+ cumulative_.resize(data.size() + 1);
+ cumulative_[0] = 0;
+ for (const auto &[i, value] : utils::enumerate(data))
+ cumulative_[i + 1] = cumulative_[i] + transform(value);
+ }
+
size_t bins() const { return cumulative_.size() - 1; }
uint64_t total() const { return cumulative_[cumulative_.size() - 1]; }
uint64_t cumulativeFrequency(double bin) const;
diff --git a/src/ipa/libipa/meson.build b/src/ipa/libipa/meson.build
index 016b8e0e..7ce885da 100644
--- a/src/ipa/libipa/meson.build
+++ b/src/ipa/libipa/meson.build
@@ -1,16 +1,20 @@
# SPDX-License-Identifier: CC0-1.0
libipa_headers = files([
+ 'agc_mean_luminance.h',
'algorithm.h',
'camera_sensor_helper.h',
+ 'exposure_mode_helper.h',
'fc_queue.h',
'histogram.h',
'module.h',
])
libipa_sources = files([
+ 'agc_mean_luminance.cpp',
'algorithm.cpp',
'camera_sensor_helper.cpp',
+ 'exposure_mode_helper.cpp',
'fc_queue.cpp',
'histogram.cpp',
'module.cpp',
diff --git a/src/ipa/libipa/module.cpp b/src/ipa/libipa/module.cpp
index ee01f12a..64ca9141 100644
--- a/src/ipa/libipa/module.cpp
+++ b/src/ipa/libipa/module.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2022, Ideas On Board
*
- * module.cpp - IPA Module
+ * IPA Module
*/
#include "module.h"
diff --git a/src/ipa/libipa/module.h b/src/ipa/libipa/module.h
index 4149a353..0fb51916 100644
--- a/src/ipa/libipa/module.h
+++ b/src/ipa/libipa/module.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2022, Ideas On Board
*
- * module.h - IPA module
+ * IPA module
*/
#pragma once
diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp
index 47a6f7b2..50e0690f 100644
--- a/src/ipa/rkisp1/algorithms/agc.cpp
+++ b/src/ipa/rkisp1/algorithms/agc.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021-2022, Ideas On Board
*
- * agc.cpp - AGC/AEC mean-based control algorithm
+ * AGC/AEC mean-based control algorithm
*/
#include "agc.h"
@@ -36,32 +36,32 @@ namespace ipa::rkisp1::algorithms {
LOG_DEFINE_CATEGORY(RkISP1Agc)
-/* Minimum limit for analogue gain value */
-static constexpr double kMinAnalogueGain = 1.0;
-
-/* \todo Honour the FrameDurationLimits control instead of hardcoding a limit */
-static constexpr utils::Duration kMaxShutterSpeed = 60ms;
-
-/* Number of frames to wait before calculating stats on minimum exposure */
-static constexpr uint32_t kNumStartupFrames = 10;
-
-/* Target value to reach for the top 2% of the histogram */
-static constexpr double kEvGainTarget = 0.5;
+Agc::Agc()
+{
+ supportsRaw_ = true;
+}
-/*
- * Relative luminance target.
+/**
+ * \brief Initialise the AGC algorithm from tuning files
+ * \param[in] context The shared IPA context
+ * \param[in] tuningData The YamlObject containing Agc tuning data
*
- * It's a number that's chosen so that, when the camera points at a grey
- * target, the resulting image brightness is considered right.
+ * This function calls the base class' tuningData parsers to discover which
+ * control values are supported.
*
- * \todo Why is the value different between IPU3 and RkISP1 ?
+ * \return 0 on success or errors from the base class
*/
-static constexpr double kRelativeLuminanceTarget = 0.4;
-
-Agc::Agc()
- : frameCount_(0), filteredExposure_(0s)
+int Agc::init(IPAContext &context, const YamlObject &tuningData)
{
- supportsRaw_ = true;
+ int ret;
+
+ ret = parseTuningData(tuningData);
+ if (ret)
+ return ret;
+
+ context.ctrlMap.merge(controls());
+
+ return 0;
}
/**
@@ -81,6 +81,9 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo)
context.activeState.agc.manual.exposure = context.activeState.agc.automatic.exposure;
context.activeState.agc.autoEnabled = !context.configuration.raw;
+ context.activeState.agc.constraintMode = constraintModes().begin()->first;
+ context.activeState.agc.exposureMode = exposureModeHelpers().begin()->first;
+
/*
* Define the measurement window for AGC as a centered rectangle
* covering 3/4 of the image width and height.
@@ -90,11 +93,14 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo)
context.configuration.agc.measureWindow.h_size = 3 * configInfo.outputSize.width / 4;
context.configuration.agc.measureWindow.v_size = 3 * configInfo.outputSize.height / 4;
- /*
- * \todo Use the upcoming per-frame context API that will provide a
- * frame index
- */
- frameCount_ = 0;
+ /* \todo Run this again when FrameDurationLimits is passed in */
+ setLimits(context.configuration.sensor.minShutterSpeed,
+ context.configuration.sensor.maxShutterSpeed,
+ context.configuration.sensor.minAnalogueGain,
+ context.configuration.sensor.maxAnalogueGain);
+
+ resetFrameCount();
+
return 0;
}
@@ -188,127 +194,24 @@ void Agc::prepare(IPAContext &context, const uint32_t frame,
params->module_en_update |= RKISP1_CIF_ISP_MODULE_HST;
}
-/**
- * \brief Apply a filter on the exposure value to limit the speed of changes
- * \param[in] exposureValue The target exposure from the AGC algorithm
- *
- * The speed of the filter is adaptive, and will produce the target quicker
- * during startup, or when the target exposure is within 20% of the most recent
- * filter output.
- *
- * \return The filtered exposure
- */
-utils::Duration Agc::filterExposure(utils::Duration exposureValue)
-{
- double speed = 0.2;
-
- /* Adapt instantly if we are in startup phase. */
- if (frameCount_ < kNumStartupFrames)
- speed = 1.0;
-
- /*
- * If we are close to the desired result, go faster to avoid making
- * multiple micro-adjustments.
- * \todo Make this customisable?
- */
- if (filteredExposure_ < 1.2 * exposureValue &&
- filteredExposure_ > 0.8 * exposureValue)
- speed = sqrt(speed);
-
- filteredExposure_ = speed * exposureValue +
- filteredExposure_ * (1.0 - speed);
-
- LOG(RkISP1Agc, Debug) << "After filtering, exposure " << filteredExposure_;
-
- return filteredExposure_;
-}
-
-/**
- * \brief Estimate the new exposure and gain values
- * \param[inout] context The shared IPA Context
- * \param[in] frameContext The FrameContext for this frame
- * \param[in] yGain The gain calculated on the current brightness level
- * \param[in] iqMeanGain The gain calculated based on the relative luminance target
- */
-void Agc::computeExposure(IPAContext &context, IPAFrameContext &frameContext,
- double yGain, double iqMeanGain)
+void Agc::fillMetadata(IPAContext &context, IPAFrameContext &frameContext,
+ ControlList &metadata)
{
- IPASessionConfiguration &configuration = context.configuration;
- IPAActiveState &activeState = context.activeState;
-
- /* Get the effective exposure and gain applied on the sensor. */
- uint32_t exposure = frameContext.sensor.exposure;
- double analogueGain = frameContext.sensor.gain;
-
- /* Use the highest of the two gain estimates. */
- double evGain = std::max(yGain, iqMeanGain);
-
- utils::Duration minShutterSpeed = configuration.sensor.minShutterSpeed;
- utils::Duration maxShutterSpeed = std::min(configuration.sensor.maxShutterSpeed,
- kMaxShutterSpeed);
-
- double minAnalogueGain = std::max(configuration.sensor.minAnalogueGain,
- kMinAnalogueGain);
- double maxAnalogueGain = configuration.sensor.maxAnalogueGain;
-
- /* Consider within 1% of the target as correctly exposed. */
- if (utils::abs_diff(evGain, 1.0) < 0.01)
- return;
-
- /* extracted from Rpi::Agc::computeTargetExposure. */
-
- /* Calculate the shutter time in seconds. */
- utils::Duration currentShutter = exposure * configuration.sensor.lineDuration;
-
- /*
- * Update the exposure value for the next computation using the values
- * of exposure and gain really used by the sensor.
- */
- utils::Duration effectiveExposureValue = currentShutter * analogueGain;
-
- LOG(RkISP1Agc, Debug) << "Actual total exposure " << currentShutter * analogueGain
- << " Shutter speed " << currentShutter
- << " Gain " << analogueGain
- << " Needed ev gain " << evGain;
-
- /*
- * Calculate the current exposure value for the scene as the latest
- * exposure value applied multiplied by the new estimated gain.
- */
- utils::Duration exposureValue = effectiveExposureValue * evGain;
-
- /* Clamp the exposure value to the min and max authorized. */
- utils::Duration maxTotalExposure = maxShutterSpeed * maxAnalogueGain;
- exposureValue = std::min(exposureValue, maxTotalExposure);
- LOG(RkISP1Agc, Debug) << "Target total exposure " << exposureValue
- << ", maximum is " << maxTotalExposure;
-
- /*
- * Divide the exposure value as new exposure and gain values.
- * \todo estimate if we need to desaturate
- */
- exposureValue = filterExposure(exposureValue);
-
- /*
- * Push the shutter time up to the maximum first, and only then
- * increase the gain.
- */
- utils::Duration shutterTime = std::clamp<utils::Duration>(exposureValue / minAnalogueGain,
- minShutterSpeed, maxShutterSpeed);
- double stepGain = std::clamp(exposureValue / shutterTime,
- minAnalogueGain, maxAnalogueGain);
- LOG(RkISP1Agc, Debug) << "Divided up shutter and gain are "
- << shutterTime << " and "
- << stepGain;
+ utils::Duration exposureTime = context.configuration.sensor.lineDuration
+ * frameContext.sensor.exposure;
+ metadata.set(controls::AnalogueGain, frameContext.sensor.gain);
+ metadata.set(controls::ExposureTime, exposureTime.get<std::micro>());
- /* Update the estimated exposure and gain. */
- activeState.agc.automatic.exposure = shutterTime / configuration.sensor.lineDuration;
- activeState.agc.automatic.gain = stepGain;
+ /* \todo Use VBlank value calculated from each frame exposure. */
+ uint32_t vTotal = context.configuration.sensor.size.height
+ + context.configuration.sensor.defVBlank;
+ utils::Duration frameDuration = context.configuration.sensor.lineDuration
+ * vTotal;
+ metadata.set(controls::FrameDuration, frameDuration.get<std::micro>());
}
/**
* \brief Estimate the relative luminance of the frame with a given gain
- * \param[in] expMeans The mean luminance values, from the RkISP1 statistics
* \param[in] gain The gain to apply to the frame
*
* This function estimates the average relative luminance of the frame that
@@ -322,8 +225,6 @@ void Agc::computeExposure(IPAContext &context, IPAFrameContext &frameContext,
* YUV doesn't take into account the fact that the R, G and B components
* contribute differently to the relative luminance.
*
- * \todo Have a dedicated YUV algorithm ?
- *
* The values are normalized to the [0.0, 1.0] range, where 1.0 corresponds to a
* theoretical perfect reflector of 100% reference white.
*
@@ -332,45 +233,17 @@ void Agc::computeExposure(IPAContext &context, IPAFrameContext &frameContext,
*
* \return The relative luminance
*/
-double Agc::estimateLuminance(Span<const uint8_t> expMeans, double gain)
+double Agc::estimateLuminance(double gain) const
{
double ySum = 0.0;
/* Sum the averages, saturated to 255. */
- for (uint8_t expMean : expMeans)
+ for (uint8_t expMean : expMeans_)
ySum += std::min(expMean * gain, 255.0);
/* \todo Weight with the AWB gains */
- return ySum / expMeans.size() / 255;
-}
-
-/**
- * \brief Estimate the mean value of the top 2% of the histogram
- * \param[in] hist The histogram statistics computed by the RkISP1
- * \return The mean value of the top 2% of the histogram
- */
-double Agc::measureBrightness(Span<const uint32_t> hist) const
-{
- Histogram histogram{ hist };
- /* Estimate the quantile mean of the top 2% of the histogram. */
- return histogram.interQuantileMean(0.98, 1.0);
-}
-
-void Agc::fillMetadata(IPAContext &context, IPAFrameContext &frameContext,
- ControlList &metadata)
-{
- utils::Duration exposureTime = context.configuration.sensor.lineDuration
- * frameContext.sensor.exposure;
- metadata.set(controls::AnalogueGain, frameContext.sensor.gain);
- metadata.set(controls::ExposureTime, exposureTime.get<std::micro>());
-
- /* \todo Use VBlank value calculated from each frame exposure. */
- uint32_t vTotal = context.configuration.sensor.size.height
- + context.configuration.sensor.defVBlank;
- utils::Duration frameDuration = context.configuration.sensor.lineDuration
- * vTotal;
- metadata.set(controls::FrameDuration, frameDuration.get<std::micro>());
+ return ySum / expMeans_.size() / 255;
}
/**
@@ -404,41 +277,38 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame,
const rkisp1_cif_isp_stat *params = &stats->params;
ASSERT(stats->meas_type & RKISP1_CIF_ISP_STAT_AUTOEXP);
- Span<const uint8_t> ae{ params->ae.exp_mean, context.hw->numAeCells };
- Span<const uint32_t> hist{
- params->hist.hist_bins,
- context.hw->numHistogramBins
- };
-
- double iqMean = measureBrightness(hist);
- double iqMeanGain = kEvGainTarget * hist.size() / iqMean;
+ /* The lower 4 bits are fractional and meant to be discarded. */
+ Histogram hist({ params->hist.hist_bins, context.hw->numHistogramBins },
+ [](uint32_t x) { return x >> 4; });
+ expMeans_ = { params->ae.exp_mean, context.hw->numAeCells };
/*
- * Estimate the gain needed to achieve a relative luminance target. To
- * account for non-linearity caused by saturation, the value needs to be
- * estimated in an iterative process, as multiplying by a gain will not
- * increase the relative luminance by the same factor if some image
- * regions are saturated.
+ * The Agc algorithm needs to know the effective exposure value that was
+ * applied to the sensor when the statistics were collected.
*/
- double yGain = 1.0;
- double yTarget = kRelativeLuminanceTarget;
-
- for (unsigned int i = 0; i < 8; i++) {
- double yValue = estimateLuminance(ae, yGain);
- double extra_gain = std::min(10.0, yTarget / (yValue + .001));
-
- yGain *= extra_gain;
- LOG(RkISP1Agc, Debug) << "Y value: " << yValue
- << ", Y target: " << yTarget
- << ", gives gain " << yGain;
- if (extra_gain < 1.01)
- break;
- }
+ utils::Duration exposureTime = context.configuration.sensor.lineDuration
+ * frameContext.sensor.exposure;
+ double analogueGain = frameContext.sensor.gain;
+ utils::Duration effectiveExposureValue = exposureTime * analogueGain;
+
+ utils::Duration shutterTime;
+ double aGain, dGain;
+ std::tie(shutterTime, aGain, dGain) =
+ calculateNewEv(context.activeState.agc.constraintMode,
+ context.activeState.agc.exposureMode,
+ hist, effectiveExposureValue);
- computeExposure(context, frameContext, yGain, iqMeanGain);
- frameCount_++;
+ LOG(RkISP1Agc, Debug)
+ << "Divided up shutter, analogue gain and digital gain are "
+ << shutterTime << ", " << aGain << " and " << dGain;
+
+ IPAActiveState &activeState = context.activeState;
+ /* Update the estimated exposure and gain. */
+ activeState.agc.automatic.exposure = shutterTime / context.configuration.sensor.lineDuration;
+ activeState.agc.automatic.gain = aGain;
fillMetadata(context, frameContext, metadata);
+ expMeans_ = {};
}
REGISTER_IPA_ALGORITHM(Agc, "Agc")
diff --git a/src/ipa/rkisp1/algorithms/agc.h b/src/ipa/rkisp1/algorithms/agc.h
index fb82a33f..04b3247e 100644
--- a/src/ipa/rkisp1/algorithms/agc.h
+++ b/src/ipa/rkisp1/algorithms/agc.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021-2022, Ideas On Board
*
- * agc.h - RkISP1 AGC/AEC mean-based control algorithm
+ * RkISP1 AGC/AEC mean-based control algorithm
*/
#pragma once
@@ -14,18 +14,22 @@
#include <libcamera/geometry.h>
+#include "libipa/agc_mean_luminance.h"
+#include "libipa/histogram.h"
+
#include "algorithm.h"
namespace libcamera {
namespace ipa::rkisp1::algorithms {
-class Agc : public Algorithm
+class Agc : public Algorithm, public AgcMeanLuminance
{
public:
Agc();
~Agc() = default;
+ int init(IPAContext &context, const YamlObject &tuningData) override;
int configure(IPAContext &context, const IPACameraSensorInfo &configInfo) override;
void queueRequest(IPAContext &context,
const uint32_t frame,
@@ -40,17 +44,11 @@ public:
ControlList &metadata) override;
private:
- void computeExposure(IPAContext &Context, IPAFrameContext &frameContext,
- double yGain, double iqMeanGain);
- utils::Duration filterExposure(utils::Duration exposureValue);
- double estimateLuminance(Span<const uint8_t> expMeans, double gain);
- double measureBrightness(Span<const uint32_t> hist) const;
void fillMetadata(IPAContext &context, IPAFrameContext &frameContext,
ControlList &metadata);
+ double estimateLuminance(double gain) const override;
- uint64_t frameCount_;
-
- utils::Duration filteredExposure_;
+ Span<const uint8_t> expMeans_;
};
} /* namespace ipa::rkisp1::algorithms */
diff --git a/src/ipa/rkisp1/algorithms/algorithm.h b/src/ipa/rkisp1/algorithms/algorithm.h
index 9454c9a1..715cfcd8 100644
--- a/src/ipa/rkisp1/algorithms/algorithm.h
+++ b/src/ipa/rkisp1/algorithms/algorithm.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021, Ideas On Board
*
- * algorithm.h - RkISP1 control algorithm interface
+ * RkISP1 control algorithm interface
*/
#pragma once
diff --git a/src/ipa/rkisp1/algorithms/awb.cpp b/src/ipa/rkisp1/algorithms/awb.cpp
index 744f4a38..a01fe5d9 100644
--- a/src/ipa/rkisp1/algorithms/awb.cpp
+++ b/src/ipa/rkisp1/algorithms/awb.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021-2022, Ideas On Board
*
- * awb.cpp - AWB control algorithm
+ * AWB control algorithm
*/
#include "awb.h"
diff --git a/src/ipa/rkisp1/algorithms/awb.h b/src/ipa/rkisp1/algorithms/awb.h
index 9d45a442..06c92896 100644
--- a/src/ipa/rkisp1/algorithms/awb.h
+++ b/src/ipa/rkisp1/algorithms/awb.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021-2022, Ideas On Board
*
- * awb.h - AWB control algorithm
+ * AWB control algorithm
*/
#pragma once
diff --git a/src/ipa/rkisp1/algorithms/blc.cpp b/src/ipa/rkisp1/algorithms/blc.cpp
index 15324fb1..d2e74354 100644
--- a/src/ipa/rkisp1/algorithms/blc.cpp
+++ b/src/ipa/rkisp1/algorithms/blc.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021-2022, Ideas On Board
*
- * blc.cpp - RkISP1 Black Level Correction control
+ * RkISP1 Black Level Correction control
*/
#include "blc.h"
diff --git a/src/ipa/rkisp1/algorithms/blc.h b/src/ipa/rkisp1/algorithms/blc.h
index 0b1a2d43..460ebcc1 100644
--- a/src/ipa/rkisp1/algorithms/blc.h
+++ b/src/ipa/rkisp1/algorithms/blc.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021-2022, Ideas On Board
*
- * blc.h - RkISP1 Black Level Correction control
+ * RkISP1 Black Level Correction control
*/
#pragma once
diff --git a/src/ipa/rkisp1/algorithms/cproc.cpp b/src/ipa/rkisp1/algorithms/cproc.cpp
index eaa56c37..68bb8180 100644
--- a/src/ipa/rkisp1/algorithms/cproc.cpp
+++ b/src/ipa/rkisp1/algorithms/cproc.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021-2022, Ideas On Board
*
- * cproc.cpp - RkISP1 Color Processing control
+ * RkISP1 Color Processing control
*/
#include "cproc.h"
diff --git a/src/ipa/rkisp1/algorithms/cproc.h b/src/ipa/rkisp1/algorithms/cproc.h
index ba6e901a..bafba5cc 100644
--- a/src/ipa/rkisp1/algorithms/cproc.h
+++ b/src/ipa/rkisp1/algorithms/cproc.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021-2022, Ideas On Board
*
- * cproc.h - RkISP1 Color Processing control
+ * RkISP1 Color Processing control
*/
#pragma once
diff --git a/src/ipa/rkisp1/algorithms/dpcc.cpp b/src/ipa/rkisp1/algorithms/dpcc.cpp
index 80a1b734..b5a339e9 100644
--- a/src/ipa/rkisp1/algorithms/dpcc.cpp
+++ b/src/ipa/rkisp1/algorithms/dpcc.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021-2022, Ideas On Board
*
- * dpcc.cpp - RkISP1 Defect Pixel Cluster Correction control
+ * RkISP1 Defect Pixel Cluster Correction control
*/
#include "dpcc.h"
diff --git a/src/ipa/rkisp1/algorithms/dpcc.h b/src/ipa/rkisp1/algorithms/dpcc.h
index b1fac7d1..d39b7bed 100644
--- a/src/ipa/rkisp1/algorithms/dpcc.h
+++ b/src/ipa/rkisp1/algorithms/dpcc.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021-2022, Ideas On Board
*
- * dpcc.h - RkISP1 Defect Pixel Cluster Correction control
+ * RkISP1 Defect Pixel Cluster Correction control
*/
#pragma once
diff --git a/src/ipa/rkisp1/algorithms/dpf.cpp b/src/ipa/rkisp1/algorithms/dpf.cpp
index 5bd7e59f..abf95728 100644
--- a/src/ipa/rkisp1/algorithms/dpf.cpp
+++ b/src/ipa/rkisp1/algorithms/dpf.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021-2022, Ideas On Board
*
- * dpf.cpp - RkISP1 Denoise Pre-Filter control
+ * RkISP1 Denoise Pre-Filter control
*/
#include "dpf.h"
diff --git a/src/ipa/rkisp1/algorithms/dpf.h b/src/ipa/rkisp1/algorithms/dpf.h
index 58f29f74..da0115ba 100644
--- a/src/ipa/rkisp1/algorithms/dpf.h
+++ b/src/ipa/rkisp1/algorithms/dpf.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021-2022, Ideas On Board
*
- * dpf.h - RkISP1 Denoise Pre-Filter control
+ * RkISP1 Denoise Pre-Filter control
*/
#pragma once
diff --git a/src/ipa/rkisp1/algorithms/filter.cpp b/src/ipa/rkisp1/algorithms/filter.cpp
index 4b89c05a..9752248a 100644
--- a/src/ipa/rkisp1/algorithms/filter.cpp
+++ b/src/ipa/rkisp1/algorithms/filter.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021-2022, Ideas On Board
*
- * filter.cpp - RkISP1 Filter control
+ * RkISP1 Filter control
*/
#include "filter.h"
diff --git a/src/ipa/rkisp1/algorithms/filter.h b/src/ipa/rkisp1/algorithms/filter.h
index 3fd882ea..d595811d 100644
--- a/src/ipa/rkisp1/algorithms/filter.h
+++ b/src/ipa/rkisp1/algorithms/filter.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021-2022, Ideas On Board
*
- * filter.h - RkISP1 Filter control
+ * RkISP1 Filter control
*/
#pragma once
diff --git a/src/ipa/rkisp1/algorithms/gsl.cpp b/src/ipa/rkisp1/algorithms/gsl.cpp
index b9f87912..9b056c6e 100644
--- a/src/ipa/rkisp1/algorithms/gsl.cpp
+++ b/src/ipa/rkisp1/algorithms/gsl.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021-2022, Ideas On Board
*
- * gsl.cpp - RkISP1 Gamma Sensor Linearization control
+ * RkISP1 Gamma Sensor Linearization control
*/
#include "gsl.h"
diff --git a/src/ipa/rkisp1/algorithms/gsl.h b/src/ipa/rkisp1/algorithms/gsl.h
index 0f1116a7..c404105e 100644
--- a/src/ipa/rkisp1/algorithms/gsl.h
+++ b/src/ipa/rkisp1/algorithms/gsl.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021-2022, Ideas On Board
*
- * gsl.h - RkISP1 Gamma Sensor Linearization control
+ * RkISP1 Gamma Sensor Linearization control
*/
#pragma once
diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp
index a7ccedb1..161183fc 100644
--- a/src/ipa/rkisp1/algorithms/lsc.cpp
+++ b/src/ipa/rkisp1/algorithms/lsc.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021-2022, Ideas On Board
*
- * lsc.cpp - RkISP1 Lens Shading Correction control
+ * RkISP1 Lens Shading Correction control
*/
#include "lsc.h"
diff --git a/src/ipa/rkisp1/algorithms/lsc.h b/src/ipa/rkisp1/algorithms/lsc.h
index e2a93a56..5baf5927 100644
--- a/src/ipa/rkisp1/algorithms/lsc.h
+++ b/src/ipa/rkisp1/algorithms/lsc.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021-2022, Ideas On Board
*
- * lsc.h - RkISP1 Lens Shading Correction control
+ * RkISP1 Lens Shading Correction control
*/
#pragma once
diff --git a/src/ipa/rkisp1/ipa_context.cpp b/src/ipa/rkisp1/ipa_context.cpp
index 070834fa..283bc131 100644
--- a/src/ipa/rkisp1/ipa_context.cpp
+++ b/src/ipa/rkisp1/ipa_context.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021-2022, Ideas On Board
*
- * ipa_context.cpp - RkISP1 IPA Context
+ * RkISP1 IPA Context
*/
#include "ipa_context.h"
diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h
index 10d8f38c..bd02a7a2 100644
--- a/src/ipa/rkisp1/ipa_context.h
+++ b/src/ipa/rkisp1/ipa_context.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021-2022, Ideas On Board
*
- * ipa_context.h - RkISP1 IPA Context
+ * RkISP1 IPA Context
*
*/
@@ -12,6 +12,7 @@
#include <libcamera/base/utils.h>
+#include <libcamera/controls.h>
#include <libcamera/geometry.h>
#include <libipa/fc_queue.h>
@@ -67,6 +68,8 @@ struct IPAActiveState {
} automatic;
bool autoEnabled;
+ uint32_t constraintMode;
+ uint32_t exposureMode;
} agc;
struct {
@@ -151,6 +154,8 @@ struct IPAContext {
IPAActiveState activeState;
FCQueue<IPAFrameContext> frameContexts;
+
+ ControlInfoMap::Map ctrlMap;
};
} /* namespace ipa::rkisp1 */
diff --git a/src/ipa/rkisp1/meson.build b/src/ipa/rkisp1/meson.build
index e813da53..cf05cdb2 100644
--- a/src/ipa/rkisp1/meson.build
+++ b/src/ipa/rkisp1/meson.build
@@ -8,6 +8,7 @@ ipa_name = 'ipa_rkisp1'
rkisp1_ipa_sources = files([
'ipa_context.cpp',
'rkisp1.cpp',
+ 'utils.cpp',
])
rkisp1_ipa_sources += rkisp1_ipa_algorithms
diff --git a/src/ipa/rkisp1/module.h b/src/ipa/rkisp1/module.h
index 89f83208..16c3e43e 100644
--- a/src/ipa/rkisp1/module.h
+++ b/src/ipa/rkisp1/module.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2022, Ideas On Board
*
- * module.h - RkISP1 IPA Module
+ * RkISP1 IPA Module
*/
#pragma once
diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp
index 9dc5f53c..6687c91e 100644
--- a/src/ipa/rkisp1/rkisp1.cpp
+++ b/src/ipa/rkisp1/rkisp1.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Google Inc.
*
- * rkisp1.cpp - RkISP1 Image Processing Algorithms
+ * RkISP1 Image Processing Algorithms
*/
#include <algorithm>
@@ -119,7 +119,7 @@ const ControlInfoMap::Map rkisp1Controls{
} /* namespace */
IPARkISP1::IPARkISP1()
- : context_({ {}, {}, {}, { kMaxFrameContexts } })
+ : context_({ {}, {}, {}, { kMaxFrameContexts }, {} })
{
}
@@ -427,6 +427,7 @@ void IPARkISP1::updateControls(const IPACameraSensorInfo &sensorInfo,
frameDurations[1],
frameDurations[2]);
+ ctrlMap.merge(context_.ctrlMap);
*ipaControls = ControlInfoMap(std::move(ctrlMap), controls::controls);
}
@@ -458,7 +459,7 @@ extern "C" {
const struct IPAModuleInfo ipaModuleInfo = {
IPA_MODULE_API_VERSION,
1,
- "PipelineHandlerRkISP1",
+ "rkisp1",
"rkisp1",
};
diff --git a/src/ipa/rkisp1/utils.cpp b/src/ipa/rkisp1/utils.cpp
new file mode 100644
index 00000000..960ec64e
--- /dev/null
+++ b/src/ipa/rkisp1/utils.cpp
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>
+ *
+ * Miscellaneous utility functions specific to rkisp1
+ */
+
+#include "utils.h"
+
+/**
+ * \file utils.h
+ */
+
+namespace libcamera {
+
+namespace ipa::rkisp1::utils {
+
+/**
+ * \fn R floatingToFixedPoint(T number)
+ * \brief Convert a floating point number to a fixed-point representation
+ * \tparam I Bit width of the integer part of the fixed-point
+ * \tparam F Bit width of the fractional part of the fixed-point
+ * \tparam R Return type of the fixed-point representation
+ * \tparam T Input type of the floating point representation
+ * \param number The floating point number to convert to fixed point
+ * \return The converted value
+ */
+
+/**
+ * \fn R fixedToFloatingPoint(T number)
+ * \brief Convert a fixed-point number to a floating point representation
+ * \tparam I Bit width of the integer part of the fixed-point
+ * \tparam F Bit width of the fractional part of the fixed-point
+ * \tparam R Return type of the floating point representation
+ * \tparam T Input type of the fixed-point representation
+ * \param number The fixed point number to convert to floating point
+ * \return The converted value
+ */
+
+} /* namespace ipa::rkisp1::utils */
+
+} /* namespace libcamera */
diff --git a/src/ipa/rkisp1/utils.h b/src/ipa/rkisp1/utils.h
new file mode 100644
index 00000000..450f2244
--- /dev/null
+++ b/src/ipa/rkisp1/utils.h
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>
+ *
+ * Miscellaneous utility functions specific to rkisp1
+ */
+
+#pragma once
+
+#include <cmath>
+#include <limits>
+#include <type_traits>
+
+namespace libcamera {
+
+namespace ipa::rkisp1::utils {
+
+#ifndef __DOXYGEN__
+template<unsigned int I, unsigned int F, typename R, typename T,
+ std::enable_if_t<std::is_integral_v<R> &&
+ std::is_floating_point_v<T>> * = nullptr>
+#else
+template<unsigned int I, unsigned int F, typename R, typename T>
+#endif
+constexpr R floatingToFixedPoint(T number)
+{
+ static_assert(sizeof(int) >= sizeof(R));
+ static_assert(I + F <= sizeof(R) * 8);
+
+ /*
+ * The intermediate cast to int is needed on arm platforms to properly
+ * cast negative values. See
+ * https://embeddeduse.com/2013/08/25/casting-a-negative-float-to-an-unsigned-int/
+ */
+ R mask = (1 << (F + I)) - 1;
+ R frac = static_cast<R>(static_cast<int>(std::round(number * (1 << F)))) & mask;
+
+ return frac;
+}
+
+#ifndef __DOXYGEN__
+template<unsigned int I, unsigned int F, typename R, typename T,
+ std::enable_if_t<std::is_floating_point_v<R> &&
+ std::is_integral_v<T>> * = nullptr>
+#else
+template<unsigned int I, unsigned int F, typename R, typename T>
+#endif
+constexpr R fixedToFloatingPoint(T number)
+{
+ static_assert(sizeof(int) >= sizeof(T));
+ static_assert(I + F <= sizeof(T) * 8);
+
+ /*
+ * Recreate the upper bits in case of a negative number by shifting the sign
+ * bit from the fixed point to the first bit of the unsigned and then right shifting
+ * by the same amount which keeps the sign bit in place.
+ * This can be optimized by the compiler quite well.
+ */
+ int remaining_bits = sizeof(int) * 8 - (I + F);
+ int t = static_cast<int>(static_cast<unsigned>(number) << remaining_bits) >> remaining_bits;
+ return static_cast<R>(t) / static_cast<R>(1 << F);
+}
+
+} /* namespace ipa::rkisp1::utils */
+
+} /* namespace libcamera */
diff --git a/src/ipa/rpi/cam_helper/cam_helper.cpp b/src/ipa/rpi/cam_helper/cam_helper.cpp
index ddd5e9a4..ee5d011f 100644
--- a/src/ipa/rpi/cam_helper/cam_helper.cpp
+++ b/src/ipa/rpi/cam_helper/cam_helper.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * cam_helper.cpp - helper information for different sensors
+ * helper information for different sensors
*/
#include <linux/videodev2.h>
diff --git a/src/ipa/rpi/cam_helper/cam_helper.h b/src/ipa/rpi/cam_helper/cam_helper.h
index 58a4b202..4a4ab5e6 100644
--- a/src/ipa/rpi/cam_helper/cam_helper.h
+++ b/src/ipa/rpi/cam_helper/cam_helper.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * cam_helper.h - helper class providing camera information
+ * helper class providing camera information
*/
#pragma once
diff --git a/src/ipa/rpi/cam_helper/cam_helper_imx219.cpp b/src/ipa/rpi/cam_helper/cam_helper_imx219.cpp
index c3337ed0..91461f7a 100644
--- a/src/ipa/rpi/cam_helper/cam_helper_imx219.cpp
+++ b/src/ipa/rpi/cam_helper/cam_helper_imx219.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * cam_helper_imx219.cpp - camera helper for imx219 sensor
+ * camera helper for imx219 sensor
*/
#include <assert.h>
diff --git a/src/ipa/rpi/cam_helper/cam_helper_imx290.cpp b/src/ipa/rpi/cam_helper/cam_helper_imx290.cpp
index d98b51cd..24275e12 100644
--- a/src/ipa/rpi/cam_helper/cam_helper_imx290.cpp
+++ b/src/ipa/rpi/cam_helper/cam_helper_imx290.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021, Raspberry Pi Ltd
*
- * cam_helper_imx290.cpp - camera helper for imx290 sensor
+ * camera helper for imx290 sensor
*/
#include <math.h>
diff --git a/src/ipa/rpi/cam_helper/cam_helper_imx296.cpp b/src/ipa/rpi/cam_helper/cam_helper_imx296.cpp
index ecb845e7..d4a4fa79 100644
--- a/src/ipa/rpi/cam_helper/cam_helper_imx296.cpp
+++ b/src/ipa/rpi/cam_helper/cam_helper_imx296.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2020, Raspberry Pi Ltd
*
- * cam_helper_imx296.cpp - Camera helper for IMX296 sensor
+ * Camera helper for IMX296 sensor
*/
#include <algorithm>
diff --git a/src/ipa/rpi/cam_helper/cam_helper_imx477.cpp b/src/ipa/rpi/cam_helper/cam_helper_imx477.cpp
index bc769ca7..6bd89334 100644
--- a/src/ipa/rpi/cam_helper/cam_helper_imx477.cpp
+++ b/src/ipa/rpi/cam_helper/cam_helper_imx477.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2020, Raspberry Pi Ltd
*
- * cam_helper_imx477.cpp - camera helper for imx477 sensor
+ * camera helper for imx477 sensor
*/
#include <algorithm>
diff --git a/src/ipa/rpi/cam_helper/cam_helper_imx519.cpp b/src/ipa/rpi/cam_helper/cam_helper_imx519.cpp
index c7262aa0..c2de3d40 100644
--- a/src/ipa/rpi/cam_helper/cam_helper_imx519.cpp
+++ b/src/ipa/rpi/cam_helper/cam_helper_imx519.cpp
@@ -3,7 +3,7 @@
* Based on cam_helper_imx477.cpp
* Copyright (C) 2020, Raspberry Pi Ltd
*
- * cam_helper_imx519.cpp - camera helper for imx519 sensor
+ * camera helper for imx519 sensor
* Copyright (C) 2021, Arducam Technology co., Ltd.
*/
diff --git a/src/ipa/rpi/cam_helper/cam_helper_imx708.cpp b/src/ipa/rpi/cam_helper/cam_helper_imx708.cpp
index 906c6fa2..63ddb55e 100644
--- a/src/ipa/rpi/cam_helper/cam_helper_imx708.cpp
+++ b/src/ipa/rpi/cam_helper/cam_helper_imx708.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2022, Raspberry Pi Ltd
*
- * cam_helper_imx708.cpp - camera helper for imx708 sensor
+ * camera helper for imx708 sensor
*/
#include <cmath>
diff --git a/src/ipa/rpi/cam_helper/cam_helper_ov5647.cpp b/src/ipa/rpi/cam_helper/cam_helper_ov5647.cpp
index 5a99083d..c30b017c 100644
--- a/src/ipa/rpi/cam_helper/cam_helper_ov5647.cpp
+++ b/src/ipa/rpi/cam_helper/cam_helper_ov5647.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * cam_helper_ov5647.cpp - camera information for ov5647 sensor
+ * camera information for ov5647 sensor
*/
#include <assert.h>
diff --git a/src/ipa/rpi/cam_helper/cam_helper_ov64a40.cpp b/src/ipa/rpi/cam_helper/cam_helper_ov64a40.cpp
index 27e449b1..a8efd389 100644
--- a/src/ipa/rpi/cam_helper/cam_helper_ov64a40.cpp
+++ b/src/ipa/rpi/cam_helper/cam_helper_ov64a40.cpp
@@ -3,7 +3,7 @@
* Copyright (C) 2021, Raspberry Pi Ltd
* Copyright (C) 2023, Ideas on Board Oy.
*
- * cam_helper_ov64a40.cpp - camera information for ov64a40 sensor
+ * camera information for ov64a40 sensor
*/
#include <assert.h>
diff --git a/src/ipa/rpi/cam_helper/cam_helper_ov9281.cpp b/src/ipa/rpi/cam_helper/cam_helper_ov9281.cpp
index 86c5bc4c..a65c8ac0 100644
--- a/src/ipa/rpi/cam_helper/cam_helper_ov9281.cpp
+++ b/src/ipa/rpi/cam_helper/cam_helper_ov9281.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021, Raspberry Pi Ltd
*
- * cam_helper_ov9281.cpp - camera information for ov9281 sensor
+ * camera information for ov9281 sensor
*/
#include <assert.h>
diff --git a/src/ipa/rpi/cam_helper/md_parser.h b/src/ipa/rpi/cam_helper/md_parser.h
index 77d557aa..227c376c 100644
--- a/src/ipa/rpi/cam_helper/md_parser.h
+++ b/src/ipa/rpi/cam_helper/md_parser.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * md_parser.h - image sensor metadata parser interface
+ * image sensor metadata parser interface
*/
#pragma once
diff --git a/src/ipa/rpi/cam_helper/md_parser_smia.cpp b/src/ipa/rpi/cam_helper/md_parser_smia.cpp
index c5b806d7..c7bdcf94 100644
--- a/src/ipa/rpi/cam_helper/md_parser_smia.cpp
+++ b/src/ipa/rpi/cam_helper/md_parser_smia.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019-2021, Raspberry Pi Ltd
*
- * md_parser_smia.cpp - SMIA specification based embedded data parser
+ * SMIA specification based embedded data parser
*/
#include <libcamera/base/log.h>
diff --git a/src/ipa/rpi/common/ipa_base.cpp b/src/ipa/rpi/common/ipa_base.cpp
index 3c133c55..61490bd6 100644
--- a/src/ipa/rpi/common/ipa_base.cpp
+++ b/src/ipa/rpi/common/ipa_base.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019-2023, Raspberry Pi Ltd
*
- * ipa_base.cpp - Raspberry Pi IPA base class
+ * Raspberry Pi IPA base class
*/
#include "ipa_base.h"
@@ -25,7 +25,6 @@
#include "controller/contrast_algorithm.h"
#include "controller/denoise_algorithm.h"
#include "controller/hdr_algorithm.h"
-#include "controller/hdr_status.h"
#include "controller/lux_status.h"
#include "controller/sharpen_algorithm.h"
#include "controller/statistics.h"
@@ -104,9 +103,8 @@ LOG_DEFINE_CATEGORY(IPARPI)
namespace ipa::RPi {
IpaBase::IpaBase()
- : controller_(), frameLengths_(FrameLengthsQueueSize, 0s), statsMetadataOutput_(false),
- frameCount_(0), mistrustCount_(0), lastRunTimestamp_(0), firstStart_(true),
- flickerState_({ 0, 0s })
+ : controller_(), frameLengths_(FrameLengthsQueueSize, 0s), stitchSwapBuffers_(false), frameCount_(0),
+ mistrustCount_(0), lastRunTimestamp_(0), firstStart_(true), flickerState_({ 0, 0s })
{
}
@@ -299,6 +297,8 @@ void IpaBase::start(const ControlList &controls, StartResult *result)
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;
/*
* Initialise frame counts, and decide how many frames must be hidden or
@@ -402,11 +402,17 @@ void IpaBase::prepareIsp(const PrepareParams &params)
* sensor exposure/gain changes. So fetch it from the metadata list
* indexed by the IPA cookie returned, and put it in the current frame
* metadata.
+ *
+ * Note if the HDR mode has changed, as things like tonemaps may need updating.
*/
AgcStatus agcStatus;
+ bool hdrChange = false;
RPiController::Metadata &delayedMetadata = rpiMetadata_[params.delayContext];
- if (!delayedMetadata.get<AgcStatus>("agc.status", agcStatus))
+ if (!delayedMetadata.get<AgcStatus>("agc.status", agcStatus)) {
rpiMetadata.set("agc.delayed_status", agcStatus);
+ hdrChange = agcStatus.hdr.mode != hdrStatus_.mode;
+ hdrStatus_ = agcStatus.hdr;
+ }
/*
* This may overwrite the DeviceStatus using values from the sensor
@@ -417,7 +423,7 @@ void IpaBase::prepareIsp(const PrepareParams &params)
/* Allow a 10% margin on the comparison below. */
Duration delta = (frameTimestamp - lastRunTimestamp_) * 1.0ns;
if (lastRunTimestamp_ && frameCount_ > dropFrameCount_ &&
- delta < controllerMinFrameDuration * 0.9) {
+ delta < controllerMinFrameDuration * 0.9 && !hdrChange) {
/*
* Ensure we merge the previous frame's metadata with the current
* frame. This will not overwrite exposure/gain values for the
@@ -454,7 +460,7 @@ void IpaBase::prepareIsp(const PrepareParams &params)
reportMetadata(ipaContext);
/* Ready to push the input buffer into the ISP. */
- prepareIspComplete.emit(params.buffers, false);
+ prepareIspComplete.emit(params.buffers, stitchSwapBuffers_);
}
void IpaBase::processStats(const ProcessParams &params)
@@ -586,6 +592,12 @@ void IpaBase::setMode(const IPACameraSensorInfo &sensorInfo)
mode_.minAnalogueGain = helper_->gain(gainCtrl.min().get<int32_t>());
mode_.maxAnalogueGain = helper_->gain(gainCtrl.max().get<int32_t>());
+ /*
+ * We need to give the helper the min/max frame durations so it can calculate
+ * the correct exposure limits below.
+ */
+ helper_->setCameraMode(mode_);
+
/* Shutter speed is calculated based on the limits of the frame durations. */
mode_.minShutter = helper_->exposure(shutterCtrl.min().get<int32_t>(), mode_.minLineLength);
mode_.maxShutter = Duration::max();
@@ -695,14 +707,18 @@ static const std::map<int32_t, RPiController::AfAlgorithm::AfPause> AfPauseTable
static const std::map<int32_t, std::string> HdrModeTable = {
{ controls::HdrModeOff, "Off" },
+ { controls::HdrModeMultiExposureUnmerged, "MultiExposureUnmerged" },
{ controls::HdrModeMultiExposure, "MultiExposure" },
{ controls::HdrModeSingleExposure, "SingleExposure" },
+ { controls::HdrModeNight, "Night" },
};
void IpaBase::applyControls(const ControlList &controls)
{
using RPiController::AgcAlgorithm;
using RPiController::AfAlgorithm;
+ using RPiController::ContrastAlgorithm;
+ using RPiController::DenoiseAlgorithm;
using RPiController::HdrAlgorithm;
/* Clear the return metadata buffer. */
@@ -1194,9 +1210,32 @@ void IpaBase::applyControls(const ControlList &controls)
break;
}
- if (hdr->setMode(mode->second) == 0)
+ if (hdr->setMode(mode->second) == 0) {
agc->setActiveChannels(hdr->getChannels());
- else
+
+ /* We also disable adpative contrast enhancement if HDR is running. */
+ ContrastAlgorithm *contrast =
+ dynamic_cast<ContrastAlgorithm *>(controller_.getAlgorithm("contrast"));
+ if (contrast) {
+ if (mode->second == "Off")
+ contrast->restoreCe();
+ else
+ contrast->enableCe(false);
+ }
+
+ DenoiseAlgorithm *denoise =
+ dynamic_cast<DenoiseAlgorithm *>(controller_.getAlgorithm("denoise"));
+ if (denoise) {
+ /* \todo - make the HDR mode say what denoise it wants? */
+ if (mode->second == "Night")
+ denoise->setConfig("night");
+ else if (mode->second == "SingleExposure")
+ denoise->setConfig("hdr");
+ /* MultiExposure doesn't need extra extra denoise. */
+ else
+ denoise->setConfig("normal");
+ }
+ } else
LOG(IPARPI, Warning)
<< "HDR mode " << mode->second << " not supported";
@@ -1354,12 +1393,31 @@ void IpaBase::reportMetadata(unsigned int ipaContext)
libcameraMetadata_.set(controls::AfPauseState, p);
}
- const HdrStatus *hdrStatus = rpiMetadata.getLocked<HdrStatus>("hdr.status");
- if (hdrStatus) {
- if (hdrStatus->channel == "short")
+ /*
+ * THe HDR algorithm sets the HDR channel into the agc.status at the time that those
+ * AGC parameters were calculated several frames ago, so it comes back to us now in
+ * the delayed_status. If this frame is too soon after a mode switch for the
+ * delayed_status to be available, we use the HDR status that came out of the
+ * switchMode call.
+ */
+ const AgcStatus *agcStatus = rpiMetadata.getLocked<AgcStatus>("agc.delayed_status");
+ const HdrStatus &hdrStatus = agcStatus ? agcStatus->hdr : hdrStatus_;
+ if (!hdrStatus.mode.empty() && hdrStatus.mode != "Off") {
+ int32_t hdrMode = controls::HdrModeOff;
+ for (auto const &[mode, name] : HdrModeTable) {
+ if (hdrStatus.mode == name) {
+ hdrMode = mode;
+ break;
+ }
+ }
+ libcameraMetadata_.set(controls::HdrMode, hdrMode);
+
+ if (hdrStatus.channel == "short")
libcameraMetadata_.set(controls::HdrChannel, controls::HdrChannelShort);
- else if (hdrStatus->channel == "long")
+ else if (hdrStatus.channel == "long")
libcameraMetadata_.set(controls::HdrChannel, controls::HdrChannelLong);
+ else if (hdrStatus.channel == "medium")
+ libcameraMetadata_.set(controls::HdrChannel, controls::HdrChannelMedium);
else
libcameraMetadata_.set(controls::HdrChannel, controls::HdrChannelNone);
}
diff --git a/src/ipa/rpi/common/ipa_base.h b/src/ipa/rpi/common/ipa_base.h
index 4db4411e..1a811beb 100644
--- a/src/ipa/rpi/common/ipa_base.h
+++ b/src/ipa/rpi/common/ipa_base.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2023, Raspberry Pi Ltd
*
- * ipa_base.h - Raspberry Pi IPA base class
+ * Raspberry Pi IPA base class
*/
#pragma once
@@ -22,6 +22,7 @@
#include "controller/agc_status.h"
#include "controller/camera_mode.h"
#include "controller/controller.h"
+#include "controller/hdr_status.h"
#include "controller/metadata.h"
namespace libcamera {
@@ -48,6 +49,11 @@ public:
void processStats(const ProcessParams &params) override;
protected:
+ bool monoSensor() const
+ {
+ return monoSensor_;
+ }
+
/* Raspberry Pi controller specific defines. */
std::unique_ptr<RPiController::CamHelper> helper_;
RPiController::Controller controller_;
@@ -64,6 +70,12 @@ protected:
ControlList libcameraMetadata_;
bool statsMetadataOutput_;
+ /* Remember the HDR status after a mode switch. */
+ HdrStatus hdrStatus_;
+
+ /* Whether the stitch block (if available) needs to swap buffers. */
+ bool stitchSwapBuffers_;
+
private:
/* Number of metadata objects available in the context list. */
static constexpr unsigned int numMetadataContexts = 16;
diff --git a/src/ipa/rpi/controller/af_status.h b/src/ipa/rpi/controller/af_status.h
index 92c08812..c1487cc4 100644
--- a/src/ipa/rpi/controller/af_status.h
+++ b/src/ipa/rpi/controller/af_status.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2022, Raspberry Pi Ltd
*
- * af_status.h - AF control algorithm status
+ * AF control algorithm status
*/
#pragma once
diff --git a/src/ipa/rpi/controller/agc_algorithm.h b/src/ipa/rpi/controller/agc_algorithm.h
index 534e38e2..1132de7e 100644
--- a/src/ipa/rpi/controller/agc_algorithm.h
+++ b/src/ipa/rpi/controller/agc_algorithm.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * agc_algorithm.h - AGC/AEC control algorithm interface
+ * AGC/AEC control algorithm interface
*/
#pragma once
diff --git a/src/ipa/rpi/controller/agc_status.h b/src/ipa/rpi/controller/agc_status.h
index 68f89958..c7c87b83 100644
--- a/src/ipa/rpi/controller/agc_status.h
+++ b/src/ipa/rpi/controller/agc_status.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * agc_status.h - AGC/AEC control algorithm status
+ * AGC/AEC control algorithm status
*/
#pragma once
diff --git a/src/ipa/rpi/controller/algorithm.cpp b/src/ipa/rpi/controller/algorithm.cpp
index a957fde5..beed47a1 100644
--- a/src/ipa/rpi/controller/algorithm.cpp
+++ b/src/ipa/rpi/controller/algorithm.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * algorithm.cpp - ISP control algorithms
+ * ISP control algorithms
*/
#include "algorithm.h"
diff --git a/src/ipa/rpi/controller/algorithm.h b/src/ipa/rpi/controller/algorithm.h
index 4aa814eb..1971bfdc 100644
--- a/src/ipa/rpi/controller/algorithm.h
+++ b/src/ipa/rpi/controller/algorithm.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * algorithm.h - ISP control algorithm interface
+ * ISP control algorithm interface
*/
#pragma once
diff --git a/src/ipa/rpi/controller/alsc_status.h b/src/ipa/rpi/controller/alsc_status.h
index 49a9f4a0..329e8a37 100644
--- a/src/ipa/rpi/controller/alsc_status.h
+++ b/src/ipa/rpi/controller/alsc_status.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * alsc_status.h - ALSC (auto lens shading correction) control algorithm status
+ * ALSC (auto lens shading correction) control algorithm status
*/
#pragma once
diff --git a/src/ipa/rpi/controller/awb_algorithm.h b/src/ipa/rpi/controller/awb_algorithm.h
index 6009bdac..1779b050 100644
--- a/src/ipa/rpi/controller/awb_algorithm.h
+++ b/src/ipa/rpi/controller/awb_algorithm.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * awb_algorithm.h - AWB control algorithm interface
+ * AWB control algorithm interface
*/
#pragma once
diff --git a/src/ipa/rpi/controller/awb_status.h b/src/ipa/rpi/controller/awb_status.h
index dd5a79e3..125df1a0 100644
--- a/src/ipa/rpi/controller/awb_status.h
+++ b/src/ipa/rpi/controller/awb_status.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * awb_status.h - AWB control algorithm status
+ * AWB control algorithm status
*/
#pragma once
diff --git a/src/ipa/rpi/controller/black_level_algorithm.h b/src/ipa/rpi/controller/black_level_algorithm.h
index c2cff2f5..ce044e59 100644
--- a/src/ipa/rpi/controller/black_level_algorithm.h
+++ b/src/ipa/rpi/controller/black_level_algorithm.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2023, Raspberry Pi Ltd
*
- * black_level_algorithm.h - black level control algorithm interface
+ * black level control algorithm interface
*/
#pragma once
diff --git a/src/ipa/rpi/controller/black_level_status.h b/src/ipa/rpi/controller/black_level_status.h
index fd5e4ccb..57a0705a 100644
--- a/src/ipa/rpi/controller/black_level_status.h
+++ b/src/ipa/rpi/controller/black_level_status.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * black_level_status.h - black level control algorithm status
+ * black level control algorithm status
*/
#pragma once
diff --git a/src/ipa/rpi/controller/camera_mode.h b/src/ipa/rpi/controller/camera_mode.h
index 63b11778..4fdb5b85 100644
--- a/src/ipa/rpi/controller/camera_mode.h
+++ b/src/ipa/rpi/controller/camera_mode.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019-2020, Raspberry Pi Ltd
*
- * camera_mode.h - description of a particular operating mode of a sensor
+ * description of a particular operating mode of a sensor
*/
#pragma once
diff --git a/src/ipa/rpi/controller/ccm_algorithm.h b/src/ipa/rpi/controller/ccm_algorithm.h
index e2c4d771..6678ba75 100644
--- a/src/ipa/rpi/controller/ccm_algorithm.h
+++ b/src/ipa/rpi/controller/ccm_algorithm.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * ccm_algorithm.h - CCM (colour correction matrix) control algorithm interface
+ * CCM (colour correction matrix) control algorithm interface
*/
#pragma once
diff --git a/src/ipa/rpi/controller/ccm_status.h b/src/ipa/rpi/controller/ccm_status.h
index 5e28ee7c..c81bcd42 100644
--- a/src/ipa/rpi/controller/ccm_status.h
+++ b/src/ipa/rpi/controller/ccm_status.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * ccm_status.h - CCM (colour correction matrix) control algorithm status
+ * CCM (colour correction matrix) control algorithm status
*/
#pragma once
diff --git a/src/ipa/rpi/controller/contrast_algorithm.h b/src/ipa/rpi/controller/contrast_algorithm.h
index 895b36b0..2e983350 100644
--- a/src/ipa/rpi/controller/contrast_algorithm.h
+++ b/src/ipa/rpi/controller/contrast_algorithm.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * contrast_algorithm.h - contrast (gamma) control algorithm interface
+ * contrast (gamma) control algorithm interface
*/
#pragma once
diff --git a/src/ipa/rpi/controller/contrast_status.h b/src/ipa/rpi/controller/contrast_status.h
index fb9fe4ba..7c67f054 100644
--- a/src/ipa/rpi/controller/contrast_status.h
+++ b/src/ipa/rpi/controller/contrast_status.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * contrast_status.h - contrast (gamma) control algorithm status
+ * contrast (gamma) control algorithm status
*/
#pragma once
diff --git a/src/ipa/rpi/controller/controller.cpp b/src/ipa/rpi/controller/controller.cpp
index 5ca98b98..e0131018 100644
--- a/src/ipa/rpi/controller/controller.cpp
+++ b/src/ipa/rpi/controller/controller.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * controller.cpp - ISP controller
+ * ISP controller
*/
#include <assert.h>
diff --git a/src/ipa/rpi/controller/controller.h b/src/ipa/rpi/controller/controller.h
index 170aea74..eff520bd 100644
--- a/src/ipa/rpi/controller/controller.h
+++ b/src/ipa/rpi/controller/controller.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * controller.h - ISP controller interface
+ * ISP controller interface
*/
#pragma once
diff --git a/src/ipa/rpi/controller/denoise_algorithm.h b/src/ipa/rpi/controller/denoise_algorithm.h
index 444cbc25..b9a2a33c 100644
--- a/src/ipa/rpi/controller/denoise_algorithm.h
+++ b/src/ipa/rpi/controller/denoise_algorithm.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021, Raspberry Pi Ltd
*
- * denoise.h - Denoise control algorithm interface
+ * Denoise control algorithm interface
*/
#pragma once
diff --git a/src/ipa/rpi/controller/denoise_status.h b/src/ipa/rpi/controller/denoise_status.h
index 4d2bd291..eead6086 100644
--- a/src/ipa/rpi/controller/denoise_status.h
+++ b/src/ipa/rpi/controller/denoise_status.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019-2021, Raspberry Pi Ltd
*
- * denoise_status.h - Denoise control algorithm status
+ * Denoise control algorithm status
*/
#pragma once
diff --git a/src/ipa/rpi/controller/device_status.cpp b/src/ipa/rpi/controller/device_status.cpp
index c907efdd..68100137 100644
--- a/src/ipa/rpi/controller/device_status.cpp
+++ b/src/ipa/rpi/controller/device_status.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2021, Raspberry Pi Ltd
*
- * device_status.cpp - device (image sensor) status
+ * device (image sensor) status
*/
#include "device_status.h"
diff --git a/src/ipa/rpi/controller/device_status.h b/src/ipa/rpi/controller/device_status.h
index c45db749..518f15b5 100644
--- a/src/ipa/rpi/controller/device_status.h
+++ b/src/ipa/rpi/controller/device_status.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019-2021, Raspberry Pi Ltd
*
- * device_status.h - device (image sensor) status
+ * device (image sensor) status
*/
#pragma once
diff --git a/src/ipa/rpi/controller/dpc_status.h b/src/ipa/rpi/controller/dpc_status.h
index 46d0cf34..9f30d5d9 100644
--- a/src/ipa/rpi/controller/dpc_status.h
+++ b/src/ipa/rpi/controller/dpc_status.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * dpc_status.h - DPC (defective pixel correction) control algorithm status
+ * DPC (defective pixel correction) control algorithm status
*/
#pragma once
diff --git a/src/ipa/rpi/controller/geq_status.h b/src/ipa/rpi/controller/geq_status.h
index 2d749fc9..cb107a48 100644
--- a/src/ipa/rpi/controller/geq_status.h
+++ b/src/ipa/rpi/controller/geq_status.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * geq_status.h - GEQ (green equalisation) control algorithm status
+ * GEQ (green equalisation) control algorithm status
*/
#pragma once
diff --git a/src/ipa/rpi/controller/hdr_algorithm.h b/src/ipa/rpi/controller/hdr_algorithm.h
index f622e099..b889d8fd 100644
--- a/src/ipa/rpi/controller/hdr_algorithm.h
+++ b/src/ipa/rpi/controller/hdr_algorithm.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2023, Raspberry Pi Ltd
*
- * hdr_algorithm.h - HDR control algorithm interface
+ * HDR control algorithm interface
*/
#pragma once
diff --git a/src/ipa/rpi/controller/hdr_status.h b/src/ipa/rpi/controller/hdr_status.h
index 24b1a935..a4955778 100644
--- a/src/ipa/rpi/controller/hdr_status.h
+++ b/src/ipa/rpi/controller/hdr_status.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2023 Raspberry Pi Ltd
*
- * hdr_status.h - HDR control algorithm status
+ * HDR control algorithm status
*/
#pragma once
diff --git a/src/ipa/rpi/controller/histogram.cpp b/src/ipa/rpi/controller/histogram.cpp
index 78116141..ba5b25dd 100644
--- a/src/ipa/rpi/controller/histogram.cpp
+++ b/src/ipa/rpi/controller/histogram.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * histogram.cpp - histogram calculations
+ * histogram calculations
*/
#include <math.h>
#include <stdio.h>
diff --git a/src/ipa/rpi/controller/histogram.h b/src/ipa/rpi/controller/histogram.h
index e2c5509b..ab4e5e31 100644
--- a/src/ipa/rpi/controller/histogram.h
+++ b/src/ipa/rpi/controller/histogram.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * histogram.h - histogram calculation interface
+ * histogram calculation interface
*/
#pragma once
diff --git a/src/ipa/rpi/controller/lux_status.h b/src/ipa/rpi/controller/lux_status.h
index 5eb9faac..d8729f43 100644
--- a/src/ipa/rpi/controller/lux_status.h
+++ b/src/ipa/rpi/controller/lux_status.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * lux_status.h - Lux control algorithm status
+ * Lux control algorithm status
*/
#pragma once
diff --git a/src/ipa/rpi/controller/metadata.h b/src/ipa/rpi/controller/metadata.h
index a232dcb1..b4650d25 100644
--- a/src/ipa/rpi/controller/metadata.h
+++ b/src/ipa/rpi/controller/metadata.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019-2021, Raspberry Pi Ltd
*
- * metadata.h - general metadata class
+ * general metadata class
*/
#pragma once
diff --git a/src/ipa/rpi/controller/noise_status.h b/src/ipa/rpi/controller/noise_status.h
index da194f71..1919da32 100644
--- a/src/ipa/rpi/controller/noise_status.h
+++ b/src/ipa/rpi/controller/noise_status.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * noise_status.h - Noise control algorithm status
+ * Noise control algorithm status
*/
#pragma once
diff --git a/src/ipa/rpi/controller/pdaf_data.h b/src/ipa/rpi/controller/pdaf_data.h
index 470510f2..779b987d 100644
--- a/src/ipa/rpi/controller/pdaf_data.h
+++ b/src/ipa/rpi/controller/pdaf_data.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2022, Raspberry Pi Ltd
*
- * pdaf_data.h - PDAF Metadata
+ * PDAF Metadata
*/
#pragma once
diff --git a/src/ipa/rpi/controller/pwl.cpp b/src/ipa/rpi/controller/pwl.cpp
index 70c2e24b..e3912376 100644
--- a/src/ipa/rpi/controller/pwl.cpp
+++ b/src/ipa/rpi/controller/pwl.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * pwl.cpp - piecewise linear functions
+ * piecewise linear functions
*/
#include <cassert>
diff --git a/src/ipa/rpi/controller/pwl.h b/src/ipa/rpi/controller/pwl.h
index aacf6039..7d5e7e4d 100644
--- a/src/ipa/rpi/controller/pwl.h
+++ b/src/ipa/rpi/controller/pwl.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * pwl.h - piecewise linear functions interface
+ * piecewise linear functions interface
*/
#pragma once
diff --git a/src/ipa/rpi/controller/region_stats.h b/src/ipa/rpi/controller/region_stats.h
index a8860dc8..c60f7d9a 100644
--- a/src/ipa/rpi/controller/region_stats.h
+++ b/src/ipa/rpi/controller/region_stats.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2022, Raspberry Pi Ltd
*
- * region_stats.h - Raspberry Pi region based statistics container
+ * Raspberry Pi region based statistics container
*/
#pragma once
diff --git a/src/ipa/rpi/controller/rpi/af.cpp b/src/ipa/rpi/controller/rpi/af.cpp
index ed0c8a94..c5fd8482 100644
--- a/src/ipa/rpi/controller/rpi/af.cpp
+++ b/src/ipa/rpi/controller/rpi/af.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2022-2023, Raspberry Pi Ltd
*
- * af.cpp - Autofocus control algorithm
+ * Autofocus control algorithm
*/
#include "af.h"
diff --git a/src/ipa/rpi/controller/rpi/af.h b/src/ipa/rpi/controller/rpi/af.h
index 6d2bae67..2617e2ac 100644
--- a/src/ipa/rpi/controller/rpi/af.h
+++ b/src/ipa/rpi/controller/rpi/af.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2022-2023, Raspberry Pi Ltd
*
- * af.h - Autofocus control algorithm
+ * Autofocus control algorithm
*/
#pragma once
diff --git a/src/ipa/rpi/controller/rpi/agc.cpp b/src/ipa/rpi/controller/rpi/agc.cpp
index 6549dedd..fcf7aec9 100644
--- a/src/ipa/rpi/controller/rpi/agc.cpp
+++ b/src/ipa/rpi/controller/rpi/agc.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * agc.cpp - AGC/AEC control algorithm
+ * AGC/AEC control algorithm
*/
#include "agc.h"
diff --git a/src/ipa/rpi/controller/rpi/agc.h b/src/ipa/rpi/controller/rpi/agc.h
index 7d26bdf6..5d056f02 100644
--- a/src/ipa/rpi/controller/rpi/agc.h
+++ b/src/ipa/rpi/controller/rpi/agc.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * agc.h - AGC/AEC control algorithm
+ * AGC/AEC control algorithm
*/
#pragma once
diff --git a/src/ipa/rpi/controller/rpi/agc_channel.cpp b/src/ipa/rpi/controller/rpi/agc_channel.cpp
index 8116c6c1..a77ccec3 100644
--- a/src/ipa/rpi/controller/rpi/agc_channel.cpp
+++ b/src/ipa/rpi/controller/rpi/agc_channel.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2023, Raspberry Pi Ltd
*
- * agc_channel.cpp - AGC/AEC control algorithm
+ * AGC/AEC control algorithm
*/
#include "agc_channel.h"
diff --git a/src/ipa/rpi/controller/rpi/agc_channel.h b/src/ipa/rpi/controller/rpi/agc_channel.h
index 4cf7233e..99033e23 100644
--- a/src/ipa/rpi/controller/rpi/agc_channel.h
+++ b/src/ipa/rpi/controller/rpi/agc_channel.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2023, Raspberry Pi Ltd
*
- * agc_channel.h - AGC/AEC control algorithm
+ * AGC/AEC control algorithm
*/
#pragma once
diff --git a/src/ipa/rpi/controller/rpi/alsc.cpp b/src/ipa/rpi/controller/rpi/alsc.cpp
index 8a205c60..67029fc3 100644
--- a/src/ipa/rpi/controller/rpi/alsc.cpp
+++ b/src/ipa/rpi/controller/rpi/alsc.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * alsc.cpp - ALSC (auto lens shading correction) control algorithm
+ * ALSC (auto lens shading correction) control algorithm
*/
#include <algorithm>
diff --git a/src/ipa/rpi/controller/rpi/alsc.h b/src/ipa/rpi/controller/rpi/alsc.h
index 0b6d9478..31087982 100644
--- a/src/ipa/rpi/controller/rpi/alsc.h
+++ b/src/ipa/rpi/controller/rpi/alsc.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * alsc.h - ALSC (auto lens shading correction) control algorithm
+ * ALSC (auto lens shading correction) control algorithm
*/
#pragma once
diff --git a/src/ipa/rpi/controller/rpi/awb.cpp b/src/ipa/rpi/controller/rpi/awb.cpp
index dde5785a..abe5906e 100644
--- a/src/ipa/rpi/controller/rpi/awb.cpp
+++ b/src/ipa/rpi/controller/rpi/awb.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * awb.cpp - AWB control algorithm
+ * AWB control algorithm
*/
#include <assert.h>
diff --git a/src/ipa/rpi/controller/rpi/awb.h b/src/ipa/rpi/controller/rpi/awb.h
index cde6a62f..499b4519 100644
--- a/src/ipa/rpi/controller/rpi/awb.h
+++ b/src/ipa/rpi/controller/rpi/awb.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * awb.h - AWB control algorithm
+ * AWB control algorithm
*/
#pragma once
diff --git a/src/ipa/rpi/controller/rpi/black_level.cpp b/src/ipa/rpi/controller/rpi/black_level.cpp
index 2e3db51f..ea991df9 100644
--- a/src/ipa/rpi/controller/rpi/black_level.cpp
+++ b/src/ipa/rpi/controller/rpi/black_level.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * black_level.cpp - black level control algorithm
+ * black level control algorithm
*/
#include <math.h>
diff --git a/src/ipa/rpi/controller/rpi/black_level.h b/src/ipa/rpi/controller/rpi/black_level.h
index d8c41c62..f50729db 100644
--- a/src/ipa/rpi/controller/rpi/black_level.h
+++ b/src/ipa/rpi/controller/rpi/black_level.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * black_level.h - black level control algorithm
+ * black level control algorithm
*/
#pragma once
diff --git a/src/ipa/rpi/controller/rpi/cac.cpp b/src/ipa/rpi/controller/rpi/cac.cpp
index f2c8d282..17779ad5 100644
--- a/src/ipa/rpi/controller/rpi/cac.cpp
+++ b/src/ipa/rpi/controller/rpi/cac.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2023 Raspberry Pi Ltd
*
- * cac.cpp - Chromatic Aberration Correction algorithm
+ * Chromatic Aberration Correction algorithm
*/
#include "cac.h"
diff --git a/src/ipa/rpi/controller/rpi/ccm.cpp b/src/ipa/rpi/controller/rpi/ccm.cpp
index 2e2e6664..c5588029 100644
--- a/src/ipa/rpi/controller/rpi/ccm.cpp
+++ b/src/ipa/rpi/controller/rpi/ccm.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * ccm.cpp - CCM (colour correction matrix) control algorithm
+ * CCM (colour correction matrix) control algorithm
*/
#include <libcamera/base/log.h>
diff --git a/src/ipa/rpi/controller/rpi/ccm.h b/src/ipa/rpi/controller/rpi/ccm.h
index 286d0b33..b3abeddf 100644
--- a/src/ipa/rpi/controller/rpi/ccm.h
+++ b/src/ipa/rpi/controller/rpi/ccm.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * ccm.h - CCM (colour correction matrix) control algorithm
+ * CCM (colour correction matrix) control algorithm
*/
#pragma once
diff --git a/src/ipa/rpi/controller/rpi/contrast.cpp b/src/ipa/rpi/controller/rpi/contrast.cpp
index 4e038a02..9eef792d 100644
--- a/src/ipa/rpi/controller/rpi/contrast.cpp
+++ b/src/ipa/rpi/controller/rpi/contrast.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * contrast.cpp - contrast (gamma) control algorithm
+ * contrast (gamma) control algorithm
*/
#include <stdint.h>
diff --git a/src/ipa/rpi/controller/rpi/contrast.h b/src/ipa/rpi/controller/rpi/contrast.h
index 59aa70dc..a9d9bbc9 100644
--- a/src/ipa/rpi/controller/rpi/contrast.h
+++ b/src/ipa/rpi/controller/rpi/contrast.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * contrast.h - contrast (gamma) control algorithm
+ * contrast (gamma) control algorithm
*/
#pragma once
diff --git a/src/ipa/rpi/controller/rpi/denoise.cpp b/src/ipa/rpi/controller/rpi/denoise.cpp
index 154ee604..ba851658 100644
--- a/src/ipa/rpi/controller/rpi/denoise.cpp
+++ b/src/ipa/rpi/controller/rpi/denoise.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2022 Raspberry Pi Ltd
*
- * Denoise.cpp - Denoise (spatial, colour, temporal) control algorithm
+ * Denoise (spatial, colour, temporal) control algorithm
*/
#include "denoise.h"
diff --git a/src/ipa/rpi/controller/rpi/dpc.cpp b/src/ipa/rpi/controller/rpi/dpc.cpp
index be3871df..8aac03f7 100644
--- a/src/ipa/rpi/controller/rpi/dpc.cpp
+++ b/src/ipa/rpi/controller/rpi/dpc.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * dpc.cpp - DPC (defective pixel correction) control algorithm
+ * DPC (defective pixel correction) control algorithm
*/
#include <libcamera/base/log.h>
diff --git a/src/ipa/rpi/controller/rpi/dpc.h b/src/ipa/rpi/controller/rpi/dpc.h
index 84a05604..9cefb06d 100644
--- a/src/ipa/rpi/controller/rpi/dpc.h
+++ b/src/ipa/rpi/controller/rpi/dpc.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * dpc.h - DPC (defective pixel correction) control algorithm
+ * DPC (defective pixel correction) control algorithm
*/
#pragma once
diff --git a/src/ipa/rpi/controller/rpi/focus.h b/src/ipa/rpi/controller/rpi/focus.h
index 8556039d..ee014be9 100644
--- a/src/ipa/rpi/controller/rpi/focus.h
+++ b/src/ipa/rpi/controller/rpi/focus.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2020, Raspberry Pi Ltd
*
- * focus.h - focus algorithm
+ * focus algorithm
*/
#pragma once
diff --git a/src/ipa/rpi/controller/rpi/geq.cpp b/src/ipa/rpi/controller/rpi/geq.cpp
index 510870e9..fb539d1f 100644
--- a/src/ipa/rpi/controller/rpi/geq.cpp
+++ b/src/ipa/rpi/controller/rpi/geq.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * geq.cpp - GEQ (green equalisation) control algorithm
+ * GEQ (green equalisation) control algorithm
*/
#include <libcamera/base/log.h>
diff --git a/src/ipa/rpi/controller/rpi/geq.h b/src/ipa/rpi/controller/rpi/geq.h
index ee3a52ff..2c8400c2 100644
--- a/src/ipa/rpi/controller/rpi/geq.h
+++ b/src/ipa/rpi/controller/rpi/geq.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * geq.h - GEQ (green equalisation) control algorithm
+ * GEQ (green equalisation) control algorithm
*/
#pragma once
diff --git a/src/ipa/rpi/controller/rpi/hdr.cpp b/src/ipa/rpi/controller/rpi/hdr.cpp
index fb580548..34cf360e 100644
--- a/src/ipa/rpi/controller/rpi/hdr.cpp
+++ b/src/ipa/rpi/controller/rpi/hdr.cpp
@@ -2,11 +2,13 @@
/*
* Copyright (C) 2023 Raspberry Pi Ltd
*
- * hdr.cpp - HDR control algorithm
+ * HDR control algorithm
*/
#include "hdr.h"
+#include <cmath>
+
#include <libcamera/base/log.h>
#include "../agc_status.h"
@@ -39,25 +41,52 @@ void HdrConfig::read(const libcamera::YamlObject &params, const std::string &mod
channelMap[v.get<unsigned int>().value()] = k;
/* Lens shading related parameters. */
- if (params.contains("spatial_gain")) {
- spatialGain.read(params["spatial_gain"]);
- diffusion = params["diffusion"].get<unsigned int>(3);
- /* Clip to an arbitrary limit just to stop typos from killing the system! */
- const unsigned int MAX_DIFFUSION = 15;
- if (diffusion > MAX_DIFFUSION) {
- diffusion = MAX_DIFFUSION;
- LOG(RPiHdr, Warning) << "Diffusion value clipped to " << MAX_DIFFUSION;
- }
+ if (params.contains("spatial_gain_curve")) {
+ spatialGainCurve.read(params["spatial_gain_curve"]);
+ } else if (params.contains("spatial_gain")) {
+ double spatialGain = params["spatial_gain"].get<double>(2.0);
+ spatialGainCurve.append(0.0, spatialGain);
+ spatialGainCurve.append(0.01, spatialGain);
+ spatialGainCurve.append(0.06, 1.0); /* maybe make this programmable? */
+ spatialGainCurve.append(1.0, 1.0);
+ }
+
+ diffusion = params["diffusion"].get<unsigned int>(3);
+ /* Clip to an arbitrary limit just to stop typos from killing the system! */
+ const unsigned int MAX_DIFFUSION = 15;
+ if (diffusion > MAX_DIFFUSION) {
+ diffusion = MAX_DIFFUSION;
+ LOG(RPiHdr, Warning) << "Diffusion value clipped to " << MAX_DIFFUSION;
}
/* Read any tonemap parameters. */
tonemapEnable = params["tonemap_enable"].get<int>(0);
- detailConstant = params["detail_constant"].get<uint16_t>(50);
- detailSlope = params["detail_slope"].get<double>(8.0);
+ detailConstant = params["detail_constant"].get<uint16_t>(0);
+ detailSlope = params["detail_slope"].get<double>(0.0);
iirStrength = params["iir_strength"].get<double>(8.0);
strength = params["strength"].get<double>(1.5);
if (tonemapEnable)
tonemap.read(params["tonemap"]);
+ speed = params["speed"].get<double>(1.0);
+ if (params.contains("hi_quantile_targets")) {
+ hiQuantileTargets = params["hi_quantile_targets"].getList<double>().value();
+ if (hiQuantileTargets.empty() || hiQuantileTargets.size() % 2)
+ LOG(RPiHdr, Fatal) << "hi_quantile_targets much be even and non-empty";
+ } else
+ hiQuantileTargets = { 0.95, 0.65, 0.5, 0.28, 0.3, 0.25 };
+ hiQuantileMaxGain = params["hi_quantile_max_gain"].get<double>(1.6);
+ if (params.contains("quantile_targets")) {
+ quantileTargets = params["quantile_targets"].getList<double>().value();
+ if (quantileTargets.empty() || quantileTargets.size() % 2)
+ LOG(RPiHdr, Fatal) << "quantile_targets much be even and non-empty";
+ } else
+ quantileTargets = { 0.2, 0.03, 1.0, 0.15 };
+ powerMin = params["power_min"].get<double>(0.65);
+ powerMax = params["power_max"].get<double>(1.0);
+ if (params.contains("contrast_adjustments")) {
+ contrastAdjustments = params["contrast_adjustments"].getList<double>().value();
+ } else
+ contrastAdjustments = { 0.5, 0.75 };
/* Read any stitch parameters. */
stitchEnable = params["stitch_enable"].get<int>(0);
@@ -159,7 +188,7 @@ void Hdr::prepare(Metadata *imageMetadata)
}
HdrConfig &config = it->second;
- if (config.spatialGain.empty())
+ if (config.spatialGainCurve.empty())
return;
AlscStatus alscStatus{}; /* some compilers seem to require the braces */
@@ -205,10 +234,61 @@ bool Hdr::updateTonemap([[maybe_unused]] StatisticsPtr &stats, HdrConfig &config
return true;
/*
- * If we wanted to build or adjust tonemaps dynamically, this would be the place
- * to do it. But for now we seem to be getting by without.
+ * Create a tonemap dynamically. We have three ingredients.
+ *
+ * 1. We have a list of "hi quantiles" and "targets". We use these to judge if
+ * the image does seem to be reasonably saturated. If it isn't, we calculate
+ * a gain that we will feed as a linear factor into the tonemap generation.
+ * This prevents unsaturated images from beoming quite so "flat".
+ *
+ * 2. We have a list of quantile/target pairs for the bottom of the histogram.
+ * We use these to calculate how much gain we must apply to the bottom of the
+ * tonemap. We apply this gain as a power curve so as not to blow out the top
+ * end.
+ *
+ * 3. Finally, when we generate the tonemap, we have some contrast adjustments
+ * for the bottom because we know that power curves can start quite steeply and
+ * cause a washed-out look.
*/
+ /* Compute the linear gain from the headroom for saturation at the top. */
+ double gain = 10; /* arbitrary, but hiQuantileMaxGain will clamp it later */
+ for (unsigned int i = 0; i < config.hiQuantileTargets.size(); i += 2) {
+ double quantile = config.hiQuantileTargets[i];
+ double target = config.hiQuantileTargets[i + 1];
+ double value = stats->yHist.interQuantileMean(quantile, 1.0) / 1024.0;
+ double newGain = target / (value + 0.01);
+ gain = std::min(gain, newGain);
+ }
+ gain = std::clamp(gain, 1.0, config.hiQuantileMaxGain);
+
+ /* Compute the power curve from the amount of gain needed at the bottom. */
+ double min_power = 2; /* arbitrary, but config.powerMax will clamp it later */
+ for (unsigned int i = 0; i < config.quantileTargets.size(); i += 2) {
+ double quantile = config.quantileTargets[i];
+ double target = config.quantileTargets[i + 1];
+ double value = stats->yHist.interQuantileMean(0, quantile) / 1024.0;
+ value = std::min(value * gain, 1.0);
+ double power = log(target + 1e-6) / log(value + 1e-6);
+ min_power = std::min(min_power, power);
+ }
+ double power = std::clamp(min_power, config.powerMin, config.powerMax);
+
+ /* Generate the tonemap, including the contrast adjustment factors. */
+ Pwl tonemap;
+ tonemap.append(0, 0);
+ for (unsigned int i = 0; i <= 6; i++) {
+ double x = 1 << (i + 9); /* x loops from 512 to 32768 inclusive */
+ double y = pow(std::min(x * gain, 65535.0) / 65536.0, power) * 65536;
+ if (i < config.contrastAdjustments.size())
+ y *= config.contrastAdjustments[i];
+ if (!tonemap_.empty())
+ y = y * config.speed + tonemap_.eval(x) * (1 - config.speed);
+ tonemap.append(x, y);
+ }
+ tonemap.append(65535, 65535);
+ tonemap_ = tonemap;
+
return true;
}
@@ -255,7 +335,7 @@ static void averageGains(std::vector<double> &src, std::vector<double> &dst, con
void Hdr::updateGains(StatisticsPtr &stats, HdrConfig &config)
{
- if (config.spatialGain.empty())
+ if (config.spatialGainCurve.empty())
return;
/* When alternating exposures, only compute these gains for the short frame. */
@@ -270,7 +350,7 @@ void Hdr::updateGains(StatisticsPtr &stats, HdrConfig &config)
double g = region.val.gSum / counted;
double b = region.val.bSum / counted;
double brightness = std::max({ r, g, b }) / 65535;
- gains_[0][i] = config.spatialGain.eval(brightness);
+ gains_[0][i] = config.spatialGainCurve.eval(brightness);
}
/* Ping-pong between the two gains_ buffers. */
diff --git a/src/ipa/rpi/controller/rpi/hdr.h b/src/ipa/rpi/controller/rpi/hdr.h
index 980aa3d1..9b7327f8 100644
--- a/src/ipa/rpi/controller/rpi/hdr.h
+++ b/src/ipa/rpi/controller/rpi/hdr.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2023, Raspberry Pi Ltd
*
- * hdr.h - HDR control algorithm
+ * HDR control algorithm
*/
#pragma once
@@ -26,7 +26,7 @@ struct HdrConfig {
std::map<unsigned int, std::string> channelMap;
/* Lens shading related parameters. */
- Pwl spatialGain; /* Brightness to gain curve for different image regions. */
+ Pwl spatialGainCurve; /* Brightness to gain curve for different image regions. */
unsigned int diffusion; /* How much to diffuse the gain spatially. */
/* Tonemap related parameters. */
@@ -36,6 +36,14 @@ struct HdrConfig {
double iirStrength;
double strength;
Pwl tonemap;
+ /* These relate to adaptive tonemap calculation. */
+ double speed;
+ std::vector<double> hiQuantileTargets; /* quantiles to check for unsaturated images */
+ double hiQuantileMaxGain; /* the max gain we'll apply when unsaturated */
+ std::vector<double> quantileTargets; /* target values for histogram quantiles */
+ double powerMin; /* minimum tonemap power */
+ double powerMax; /* maximum tonemap power */
+ std::vector<double> contrastAdjustments; /* any contrast adjustment factors */
/* Stitch related parameters. */
bool stitchEnable;
diff --git a/src/ipa/rpi/controller/rpi/lux.cpp b/src/ipa/rpi/controller/rpi/lux.cpp
index 06625f3a..7b31faab 100644
--- a/src/ipa/rpi/controller/rpi/lux.cpp
+++ b/src/ipa/rpi/controller/rpi/lux.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * lux.cpp - Lux control algorithm
+ * Lux control algorithm
*/
#include <math.h>
diff --git a/src/ipa/rpi/controller/rpi/lux.h b/src/ipa/rpi/controller/rpi/lux.h
index 89411a54..89f441fc 100644
--- a/src/ipa/rpi/controller/rpi/lux.h
+++ b/src/ipa/rpi/controller/rpi/lux.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * lux.h - Lux control algorithm
+ * Lux control algorithm
*/
#pragma once
diff --git a/src/ipa/rpi/controller/rpi/noise.cpp b/src/ipa/rpi/controller/rpi/noise.cpp
index bcd8b9ed..3f1c62cf 100644
--- a/src/ipa/rpi/controller/rpi/noise.cpp
+++ b/src/ipa/rpi/controller/rpi/noise.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * noise.cpp - Noise control algorithm
+ * Noise control algorithm
*/
#include <math.h>
diff --git a/src/ipa/rpi/controller/rpi/noise.h b/src/ipa/rpi/controller/rpi/noise.h
index 74c31e64..6deae1f0 100644
--- a/src/ipa/rpi/controller/rpi/noise.h
+++ b/src/ipa/rpi/controller/rpi/noise.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * noise.h - Noise control algorithm
+ * Noise control algorithm
*/
#pragma once
diff --git a/src/ipa/rpi/controller/rpi/saturation.cpp b/src/ipa/rpi/controller/rpi/saturation.cpp
index 813540e5..b83c5887 100644
--- a/src/ipa/rpi/controller/rpi/saturation.cpp
+++ b/src/ipa/rpi/controller/rpi/saturation.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2022 Raspberry Pi Ltd
*
- * saturation.cpp - Saturation control algorithm
+ * Saturation control algorithm
*/
#include "saturation.h"
diff --git a/src/ipa/rpi/controller/rpi/sdn.cpp b/src/ipa/rpi/controller/rpi/sdn.cpp
index 2f777dd7..619178a8 100644
--- a/src/ipa/rpi/controller/rpi/sdn.cpp
+++ b/src/ipa/rpi/controller/rpi/sdn.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019-2021, Raspberry Pi Ltd
*
- * sdn.cpp - SDN (spatial denoise) control algorithm
+ * SDN (spatial denoise) control algorithm
*/
#include <libcamera/base/log.h>
diff --git a/src/ipa/rpi/controller/rpi/sdn.h b/src/ipa/rpi/controller/rpi/sdn.h
index 9dd73c38..cb226de8 100644
--- a/src/ipa/rpi/controller/rpi/sdn.h
+++ b/src/ipa/rpi/controller/rpi/sdn.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * sdn.h - SDN (spatial denoise) control algorithm
+ * SDN (spatial denoise) control algorithm
*/
#pragma once
diff --git a/src/ipa/rpi/controller/rpi/sharpen.cpp b/src/ipa/rpi/controller/rpi/sharpen.cpp
index 4f6f020a..39537f4a 100644
--- a/src/ipa/rpi/controller/rpi/sharpen.cpp
+++ b/src/ipa/rpi/controller/rpi/sharpen.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * sharpen.cpp - sharpening control algorithm
+ * sharpening control algorithm
*/
#include <math.h>
diff --git a/src/ipa/rpi/controller/rpi/sharpen.h b/src/ipa/rpi/controller/rpi/sharpen.h
index 8bb7631e..96ccd609 100644
--- a/src/ipa/rpi/controller/rpi/sharpen.h
+++ b/src/ipa/rpi/controller/rpi/sharpen.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * sharpen.h - sharpening control algorithm
+ * sharpening control algorithm
*/
#pragma once
diff --git a/src/ipa/rpi/controller/rpi/tonemap.cpp b/src/ipa/rpi/controller/rpi/tonemap.cpp
index 5f8b2bf2..0426e972 100644
--- a/src/ipa/rpi/controller/rpi/tonemap.cpp
+++ b/src/ipa/rpi/controller/rpi/tonemap.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2022 Raspberry Pi Ltd
*
- * tonemap.cpp - Tonemap control algorithm
+ * Tonemap control algorithm
*/
#include "tonemap.h"
diff --git a/src/ipa/rpi/controller/saturation_status.h b/src/ipa/rpi/controller/saturation_status.h
index 337b66a3..c7fadc99 100644
--- a/src/ipa/rpi/controller/saturation_status.h
+++ b/src/ipa/rpi/controller/saturation_status.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2022 Raspberry Pi Ltd
*
- * saturation_status.h - Saturation control algorithm status
+ * Saturation control algorithm status
*/
#pragma once
diff --git a/src/ipa/rpi/controller/sharpen_algorithm.h b/src/ipa/rpi/controller/sharpen_algorithm.h
index 3be21c32..abd82cb2 100644
--- a/src/ipa/rpi/controller/sharpen_algorithm.h
+++ b/src/ipa/rpi/controller/sharpen_algorithm.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2020, Raspberry Pi Ltd
*
- * sharpen_algorithm.h - sharpness control algorithm interface
+ * sharpness control algorithm interface
*/
#pragma once
diff --git a/src/ipa/rpi/controller/sharpen_status.h b/src/ipa/rpi/controller/sharpen_status.h
index 106166db..74910199 100644
--- a/src/ipa/rpi/controller/sharpen_status.h
+++ b/src/ipa/rpi/controller/sharpen_status.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Raspberry Pi Ltd
*
- * sharpen_status.h - Sharpen control algorithm status
+ * Sharpen control algorithm status
*/
#pragma once
diff --git a/src/ipa/rpi/controller/statistics.h b/src/ipa/rpi/controller/statistics.h
index 015d4efc..cbd81161 100644
--- a/src/ipa/rpi/controller/statistics.h
+++ b/src/ipa/rpi/controller/statistics.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2022, Raspberry Pi Ltd
*
- * statistics.h - Raspberry Pi generic statistics structure
+ * Raspberry Pi generic statistics structure
*/
#pragma once
diff --git a/src/ipa/rpi/controller/stitch_status.h b/src/ipa/rpi/controller/stitch_status.h
index b17800ed..7812f3e3 100644
--- a/src/ipa/rpi/controller/stitch_status.h
+++ b/src/ipa/rpi/controller/stitch_status.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2023 Raspberry Pi Ltd
*
- * stitch_status.h - stitch control algorithm status
+ * stitch control algorithm status
*/
#pragma once
diff --git a/src/ipa/rpi/controller/tonemap_status.h b/src/ipa/rpi/controller/tonemap_status.h
index 0e639946..41a7bf2f 100644
--- a/src/ipa/rpi/controller/tonemap_status.h
+++ b/src/ipa/rpi/controller/tonemap_status.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2022 Raspberry Pi Ltd
*
- * hdr.h - Tonemap control algorithm status
+ * Tonemap control algorithm status
*/
#pragma once
diff --git a/src/ipa/rpi/vc4/data/imx219.json b/src/ipa/rpi/vc4/data/imx219.json
index 54defc0b..a020b12f 100644
--- a/src/ipa/rpi/vc4/data/imx219.json
+++ b/src/ipa/rpi/vc4/data/imx219.json
@@ -131,282 +131,308 @@
{
"rpi.agc":
{
- "channels":
- [
- {
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 10000, 30000, 60000, 66666 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 33333 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "long":
- {
- "shutter": [ 100, 10000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.5,
- 1000, 0.5
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.5,
- 1000, 0.5
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ],
- "shadows": [
- {
- "bound": "LOWER",
- "q_lo": 0.0,
- "q_hi": 0.5,
- "y_target":
- [
- 0, 0.17,
- 1000, 0.17
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ]
- },
- {
- "base_ev": 0.125,
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 10000, 30000, 60000, 66666 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 33333 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "long":
- {
- "shutter": [ 100, 10000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.5,
- 1000, 0.5
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.5,
- 1000, 0.5
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ],
- "shadows": [
- {
- "bound": "LOWER",
- "q_lo": 0.0,
- "q_hi": 0.5,
- "y_target":
- [
- 0, 0.17,
- 1000, 0.17
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ]
- },
- {
- "base_ev": 1.5,
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 10000, 30000, 60000, 66666 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 33333 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "long":
- {
- "shutter": [ 100, 10000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.5,
- 1000, 0.5
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.5,
- 1000, 0.5
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ],
- "shadows": [
- {
- "bound": "LOWER",
- "q_lo": 0.0,
- "q_hi": 0.5,
- "y_target":
- [
- 0, 0.17,
- 1000, 0.17
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ]
- }
- ]
- }
+ "channels": [
+ {
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 33333 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.5,
+ 1000, 0.5
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.5,
+ 1000, 0.5
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ],
+ "shadows": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.0,
+ "q_hi": 0.5,
+ "y_target":
+ [
+ 0, 0.17,
+ 1000, 0.17
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ]
+ },
+ {
+ "base_ev": 0.125,
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 33333 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.5,
+ 1000, 0.5
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.5,
+ 1000, 0.5
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ],
+ "shadows": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.0,
+ "q_hi": 0.5,
+ "y_target":
+ [
+ 0, 0.17,
+ 1000, 0.17
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ]
+ },
+ {
+ "base_ev": 1.5,
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 33333 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.5,
+ 1000, 0.5
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.5,
+ 1000, 0.5
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ],
+ "shadows": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.0,
+ "q_hi": 0.5,
+ "y_target":
+ [
+ 0, 0.17,
+ 1000, 0.17
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ]
+ }
+ ]
+ }
},
{
"rpi.alsc":
@@ -651,20 +677,19 @@
{
"rpi.sharpen": { }
},
- {
- "rpi.hdr":
- {
- "MultiExposure":
- {
- "cadence": [ 1, 2 ],
- "channel_map": { "short": 1, "long": 2 }
- },
- "SingleExposure":
- {
- "cadence": [ 1 ],
- "channel_map": { "short": 1 }
- }
- }
- }
+ {
+ "rpi.hdr":
+ {
+ "MultiExposureUnmerged":
+ {
+ "cadence": [ 1, 2 ],
+ "channel_map":
+ {
+ "short": 1,
+ "long": 2
+ }
+ }
+ }
+ }
]
}
diff --git a/src/ipa/rpi/vc4/data/imx219_noir.json b/src/ipa/rpi/vc4/data/imx219_noir.json
index e823a90d..d8bc9639 100644
--- a/src/ipa/rpi/vc4/data/imx219_noir.json
+++ b/src/ipa/rpi/vc4/data/imx219_noir.json
@@ -47,282 +47,308 @@
{
"rpi.agc":
{
- "channels":
- [
- {
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 10000, 30000, 60000, 66666 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 33333 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "long":
- {
- "shutter": [ 100, 10000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.5,
- 1000, 0.5
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.5,
- 1000, 0.5
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ],
- "shadows": [
- {
- "bound": "LOWER",
- "q_lo": 0.0,
- "q_hi": 0.5,
- "y_target":
- [
- 0, 0.17,
- 1000, 0.17
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ]
- },
- {
- "base_ev": 0.125,
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 10000, 30000, 60000, 66666 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 33333 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "long":
- {
- "shutter": [ 100, 10000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.5,
- 1000, 0.5
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.5,
- 1000, 0.5
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ],
- "shadows": [
- {
- "bound": "LOWER",
- "q_lo": 0.0,
- "q_hi": 0.5,
- "y_target":
- [
- 0, 0.17,
- 1000, 0.17
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ]
- },
- {
- "base_ev": 1.5,
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 10000, 30000, 60000, 66666 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 33333 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "long":
- {
- "shutter": [ 100, 10000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.5,
- 1000, 0.5
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.5,
- 1000, 0.5
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ],
- "shadows": [
- {
- "bound": "LOWER",
- "q_lo": 0.0,
- "q_hi": 0.5,
- "y_target":
- [
- 0, 0.17,
- 1000, 0.17
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ]
- }
- ]
- }
+ "channels": [
+ {
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 33333 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.5,
+ 1000, 0.5
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.5,
+ 1000, 0.5
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ],
+ "shadows": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.0,
+ "q_hi": 0.5,
+ "y_target":
+ [
+ 0, 0.17,
+ 1000, 0.17
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ]
+ },
+ {
+ "base_ev": 0.125,
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 33333 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.5,
+ 1000, 0.5
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.5,
+ 1000, 0.5
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ],
+ "shadows": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.0,
+ "q_hi": 0.5,
+ "y_target":
+ [
+ 0, 0.17,
+ 1000, 0.17
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ]
+ },
+ {
+ "base_ev": 1.5,
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 33333 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.5,
+ 1000, 0.5
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.5,
+ 1000, 0.5
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ],
+ "shadows": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.0,
+ "q_hi": 0.5,
+ "y_target":
+ [
+ 0, 0.17,
+ 1000, 0.17
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ]
+ }
+ ]
+ }
},
{
"rpi.alsc":
@@ -585,20 +611,19 @@
{
"rpi.sharpen": { }
},
- {
- "rpi.hdr":
- {
- "MultiExposure":
- {
- "cadence": [ 1, 2 ],
- "channel_map": { "short": 1, "long": 2 }
- },
- "SingleExposure":
- {
- "cadence": [ 1 ],
- "channel_map": { "short": 1 }
- }
- }
- }
+ {
+ "rpi.hdr":
+ {
+ "MultiExposureUnmerged":
+ {
+ "cadence": [ 1, 2 ],
+ "channel_map":
+ {
+ "short": 1,
+ "long": 2
+ }
+ }
+ }
+ }
]
}
diff --git a/src/ipa/rpi/vc4/data/imx290.json b/src/ipa/rpi/vc4/data/imx290.json
index 8a7cadba..8f41bf51 100644
--- a/src/ipa/rpi/vc4/data/imx290.json
+++ b/src/ipa/rpi/vc4/data/imx290.json
@@ -52,15 +52,24 @@
{
"matrix":
{
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
},
"centre-weighted":
{
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
},
"spot":
{
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
}
},
"exposure_modes":
diff --git a/src/ipa/rpi/vc4/data/imx296.json b/src/ipa/rpi/vc4/data/imx296.json
index 7621f759..8f24ce5b 100644
--- a/src/ipa/rpi/vc4/data/imx296.json
+++ b/src/ipa/rpi/vc4/data/imx296.json
@@ -135,15 +135,24 @@
{
"centre-weighted":
{
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
},
"spot":
{
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
},
"matrix":
{
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
}
},
"exposure_modes":
@@ -431,4 +440,4 @@
}
}
]
-}
+} \ No newline at end of file
diff --git a/src/ipa/rpi/vc4/data/imx296_mono.json b/src/ipa/rpi/vc4/data/imx296_mono.json
index d4140c81..fe331569 100644
--- a/src/ipa/rpi/vc4/data/imx296_mono.json
+++ b/src/ipa/rpi/vc4/data/imx296_mono.json
@@ -38,15 +38,24 @@
{
"centre-weighted":
{
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
},
"spot":
{
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
},
"matrix":
{
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
}
},
"exposure_modes":
@@ -228,4 +237,4 @@
}
}
]
-}
+} \ No newline at end of file
diff --git a/src/ipa/rpi/vc4/data/imx378.json b/src/ipa/rpi/vc4/data/imx378.json
index f7b68011..363b47e1 100644
--- a/src/ipa/rpi/vc4/data/imx378.json
+++ b/src/ipa/rpi/vc4/data/imx378.json
@@ -133,15 +133,24 @@
{
"centre-weighted":
{
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
},
"spot":
{
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
},
"matrix":
{
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
}
},
"exposure_modes":
diff --git a/src/ipa/rpi/vc4/data/imx477.json b/src/ipa/rpi/vc4/data/imx477.json
index 853bfa67..fa25ee86 100644
--- a/src/ipa/rpi/vc4/data/imx477.json
+++ b/src/ipa/rpi/vc4/data/imx477.json
@@ -115,16 +115,16 @@
"ct_curve":
[
2360.0, 0.6009, 0.3093,
- 2848.0, 0.5071, 0.4000,
+ 2848.0, 0.5071, 0.4,
2903.0, 0.4905, 0.4392,
3628.0, 0.4261, 0.5564,
3643.0, 0.4228, 0.5623,
- 4660.0, 0.3529, 0.6800,
- 5579.0, 0.3227, 0.7000,
- 6125.0, 0.3129, 0.7100,
- 6671.0, 0.3065, 0.7200,
- 7217.0, 0.3014, 0.7300,
- 7763.0, 0.2950, 0.7400,
+ 4660.0, 0.3529, 0.68,
+ 5579.0, 0.3227, 0.7,
+ 6125.0, 0.3129, 0.71,
+ 6671.0, 0.3065, 0.72,
+ 7217.0, 0.3014, 0.73,
+ 7763.0, 0.295, 0.74,
9505.0, 0.2524, 0.7856
],
"sensitivity_r": 1.05,
@@ -136,282 +136,308 @@
{
"rpi.agc":
{
- "channels":
- [
+ "channels": [
{
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 10000, 30000, 60000, 66666 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 33333 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "long":
- {
- "shutter": [ 100, 10000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.3,
- 1000, 0.3
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.3,
- 1000, 0.3
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ],
- "shadows": [
- {
- "bound": "LOWER",
- "q_lo": 0.0,
- "q_hi": 0.5,
- "y_target":
- [
- 0, 0.17,
- 1000, 0.17
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ]
- },
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 33333 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.3,
+ 1000, 0.3
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.3,
+ 1000, 0.3
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ],
+ "shadows": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.0,
+ "q_hi": 0.5,
+ "y_target":
+ [
+ 0, 0.17,
+ 1000, 0.17
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ]
+ },
{
- "base_ev": 0.125,
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 10000, 30000, 60000, 66666 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 33333 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "long":
- {
- "shutter": [ 100, 10000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.3,
- 1000, 0.3
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.3,
- 1000, 0.3
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ],
- "shadows": [
- {
- "bound": "LOWER",
- "q_lo": 0.0,
- "q_hi": 0.5,
- "y_target":
- [
- 0, 0.17,
- 1000, 0.17
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ]
- },
+ "base_ev": 0.125,
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 33333 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.3,
+ 1000, 0.3
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.3,
+ 1000, 0.3
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ],
+ "shadows": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.0,
+ "q_hi": 0.5,
+ "y_target":
+ [
+ 0, 0.17,
+ 1000, 0.17
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ]
+ },
{
- "base_ev": 1.5,
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 10000, 30000, 60000, 66666 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 33333 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "long":
- {
- "shutter": [ 100, 10000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.3,
- 1000, 0.3
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.3,
- 1000, 0.3
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ],
- "shadows": [
- {
- "bound": "LOWER",
- "q_lo": 0.0,
- "q_hi": 0.5,
- "y_target":
- [
- 0, 0.17,
- 1000, 0.17
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ]
- }
- ]
- }
+ "base_ev": 1.5,
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 33333 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.3,
+ 1000, 0.3
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.3,
+ 1000, 0.3
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ],
+ "shadows": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.0,
+ "q_hi": 0.5,
+ "y_target":
+ [
+ 0, 0.17,
+ 1000, 0.17
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ]
+ }
+ ]
+ }
},
{
"rpi.alsc":
@@ -656,20 +682,19 @@
{
"rpi.sharpen": { }
},
- {
- "rpi.hdr":
- {
- "MultiExposure":
- {
- "cadence": [ 1, 2 ],
- "channel_map": { "short": 1, "long": 2 }
- },
- "SingleExposure":
- {
- "cadence": [ 1 ],
- "channel_map": { "short": 1 }
- }
- }
- }
+ {
+ "rpi.hdr":
+ {
+ "MultiExposureUnmerged":
+ {
+ "cadence": [ 1, 2 ],
+ "channel_map":
+ {
+ "short": 1,
+ "long": 2
+ }
+ }
+ }
+ }
]
} \ No newline at end of file
diff --git a/src/ipa/rpi/vc4/data/imx477_noir.json b/src/ipa/rpi/vc4/data/imx477_noir.json
index 143e20bd..472f33fe 100644
--- a/src/ipa/rpi/vc4/data/imx477_noir.json
+++ b/src/ipa/rpi/vc4/data/imx477_noir.json
@@ -47,282 +47,308 @@
{
"rpi.agc":
{
- "channels":
- [
- {
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 10000, 30000, 60000, 66666 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 33333 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "long":
- {
- "shutter": [ 100, 10000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.3,
- 1000, 0.3
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.3,
- 1000, 0.3
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ],
- "shadows": [
- {
- "bound": "LOWER",
- "q_lo": 0.0,
- "q_hi": 0.5,
- "y_target":
- [
- 0, 0.17,
- 1000, 0.17
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ]
- },
- {
- "base_ev": 0.125,
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 10000, 30000, 60000, 66666 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 33333 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "long":
- {
- "shutter": [ 100, 10000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.3,
- 1000, 0.3
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.3,
- 1000, 0.3
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ],
- "shadows": [
- {
- "bound": "LOWER",
- "q_lo": 0.0,
- "q_hi": 0.5,
- "y_target":
- [
- 0, 0.17,
- 1000, 0.17
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ]
- },
- {
- "base_ev": 1.5,
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 10000, 30000, 60000, 66666 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 33333 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "long":
- {
- "shutter": [ 100, 10000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.3,
- 1000, 0.3
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.3,
- 1000, 0.3
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ],
- "shadows": [
- {
- "bound": "LOWER",
- "q_lo": 0.0,
- "q_hi": 0.5,
- "y_target":
- [
- 0, 0.17,
- 1000, 0.17
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ]
- }
- ]
- }
+ "channels": [
+ {
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 33333 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.3,
+ 1000, 0.3
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.3,
+ 1000, 0.3
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ],
+ "shadows": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.0,
+ "q_hi": 0.5,
+ "y_target":
+ [
+ 0, 0.17,
+ 1000, 0.17
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ]
+ },
+ {
+ "base_ev": 0.125,
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 33333 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.3,
+ 1000, 0.3
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.3,
+ 1000, 0.3
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ],
+ "shadows": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.0,
+ "q_hi": 0.5,
+ "y_target":
+ [
+ 0, 0.17,
+ 1000, 0.17
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ]
+ },
+ {
+ "base_ev": 1.5,
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 33333 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.3,
+ 1000, 0.3
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.3,
+ 1000, 0.3
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ],
+ "shadows": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.0,
+ "q_hi": 0.5,
+ "y_target":
+ [
+ 0, 0.17,
+ 1000, 0.17
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ]
+ }
+ ]
+ }
},
{
"rpi.alsc":
@@ -612,20 +638,19 @@
{
"rpi.sharpen": { }
},
- {
- "rpi.hdr":
- {
- "MultiExposure":
- {
- "cadence": [ 1, 2 ],
- "channel_map": { "short": 1, "long": 2 }
- },
- "SingleExposure":
- {
- "cadence": [ 1 ],
- "channel_map": { "short": 1 }
- }
- }
- }
+ {
+ "rpi.hdr":
+ {
+ "MultiExposureUnmerged":
+ {
+ "cadence": [ 1, 2 ],
+ "channel_map":
+ {
+ "short": 1,
+ "long": 2
+ }
+ }
+ }
+ }
]
}
diff --git a/src/ipa/rpi/vc4/data/imx477_scientific.json b/src/ipa/rpi/vc4/data/imx477_scientific.json
index 26c692fd..9dc32eb1 100644
--- a/src/ipa/rpi/vc4/data/imx477_scientific.json
+++ b/src/ipa/rpi/vc4/data/imx477_scientific.json
@@ -148,15 +148,24 @@
{
"centre-weighted":
{
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
},
"spot":
{
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
},
"matrix":
{
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
}
},
"exposure_modes":
diff --git a/src/ipa/rpi/vc4/data/imx477_v1.json b/src/ipa/rpi/vc4/data/imx477_v1.json
index d6402009..55e4adc1 100644
--- a/src/ipa/rpi/vc4/data/imx477_v1.json
+++ b/src/ipa/rpi/vc4/data/imx477_v1.json
@@ -138,15 +138,24 @@
{
"centre-weighted":
{
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
},
"spot":
{
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
},
"matrix":
{
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
}
},
"exposure_modes":
diff --git a/src/ipa/rpi/vc4/data/imx519.json b/src/ipa/rpi/vc4/data/imx519.json
index 1b0a7747..ce194256 100644
--- a/src/ipa/rpi/vc4/data/imx519.json
+++ b/src/ipa/rpi/vc4/data/imx519.json
@@ -133,15 +133,24 @@
{
"centre-weighted":
{
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
},
"spot":
{
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
},
"matrix":
{
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
}
},
"exposure_modes":
diff --git a/src/ipa/rpi/vc4/data/imx708.json b/src/ipa/rpi/vc4/data/imx708.json
index 26aafc95..4de6f079 100644
--- a/src/ipa/rpi/vc4/data/imx708.json
+++ b/src/ipa/rpi/vc4/data/imx708.json
@@ -139,255 +139,281 @@
{
"rpi.agc":
{
- "channels":
- [
- {
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 15000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
- },
- "long":
- {
- "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.2,
- 1000, 0.2
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.2,
- 1000, 0.2
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ],
- "startup_frames": 5,
- "convergence_frames": 6,
- "speed": 0.15
- },
- {
- "base_ev": 0.125,
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 15000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
- },
- "long":
- {
- "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.2,
- 1000, 0.2
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.2,
- 1000, 0.2
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ],
- "startup_frames": 5,
- "convergence_frames": 6,
- "speed": 0.15
- },
- {
- "base_ev": 1.5,
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 15000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
- },
- "long":
- {
- "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.2,
- 1000, 0.2
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.2,
- 1000, 0.2
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ],
- "startup_frames": 5,
- "convergence_frames": 6,
- "speed": 0.15
- }
- ]
- }
+ "channels": [
+ {
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 15000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.2,
+ 1000, 0.2
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.2,
+ 1000, 0.2
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ],
+ "startup_frames": 5,
+ "convergence_frames": 6,
+ "speed": 0.15
+ },
+ {
+ "base_ev": 0.125,
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 15000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.2,
+ 1000, 0.2
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.2,
+ 1000, 0.2
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ],
+ "startup_frames": 5,
+ "convergence_frames": 6,
+ "speed": 0.15
+ },
+ {
+ "base_ev": 1.5,
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 15000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.2,
+ 1000, 0.2
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.2,
+ 1000, 0.2
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ],
+ "startup_frames": 5,
+ "convergence_frames": 6,
+ "speed": 0.15
+ }
+ ]
+ }
},
{
"rpi.alsc":
@@ -627,20 +653,19 @@
"map": [ 0.0, 445, 15.0, 925 ]
}
},
- {
- "rpi.hdr":
- {
- "MultiExposure":
- {
- "cadence": [ 1, 2 ],
- "channel_map": { "short": 1, "long": 2 }
- },
- "SingleExposure":
- {
- "cadence": [ 1 ],
- "channel_map": { "short": 1 }
- }
- }
- }
+ {
+ "rpi.hdr":
+ {
+ "MultiExposureUnmerged":
+ {
+ "cadence": [ 1, 2 ],
+ "channel_map":
+ {
+ "short": 1,
+ "long": 2
+ }
+ }
+ }
+ }
]
-}
+} \ No newline at end of file
diff --git a/src/ipa/rpi/vc4/data/imx708_noir.json b/src/ipa/rpi/vc4/data/imx708_noir.json
index 8259ca4d..7b7ee874 100644
--- a/src/ipa/rpi/vc4/data/imx708_noir.json
+++ b/src/ipa/rpi/vc4/data/imx708_noir.json
@@ -139,255 +139,281 @@
{
"rpi.agc":
{
- "channels":
- [
- {
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 15000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
- },
- "long":
- {
- "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.2,
- 1000, 0.2
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.2,
- 1000, 0.2
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ],
- "startup_frames": 5,
- "convergence_frames": 6,
- "speed": 0.15
- },
- {
- "base_ev": 0.125,
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 15000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
- },
- "long":
- {
- "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.2,
- 1000, 0.2
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.2,
- 1000, 0.2
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ],
- "startup_frames": 5,
- "convergence_frames": 6,
- "speed": 0.15
- },
- {
- "base_ev": 1.5,
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 15000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
- },
- "long":
- {
- "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.2,
- 1000, 0.2
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.2,
- 1000, 0.2
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ],
- "startup_frames": 5,
- "convergence_frames": 6,
- "speed": 0.15
- }
- ]
- }
+ "channels": [
+ {
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 15000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.2,
+ 1000, 0.2
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.2,
+ 1000, 0.2
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ],
+ "startup_frames": 5,
+ "convergence_frames": 6,
+ "speed": 0.15
+ },
+ {
+ "base_ev": 0.125,
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 15000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.2,
+ 1000, 0.2
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.2,
+ 1000, 0.2
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ],
+ "startup_frames": 5,
+ "convergence_frames": 6,
+ "speed": 0.15
+ },
+ {
+ "base_ev": 1.5,
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 15000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.2,
+ 1000, 0.2
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.2,
+ 1000, 0.2
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ],
+ "startup_frames": 5,
+ "convergence_frames": 6,
+ "speed": 0.15
+ }
+ ]
+ }
},
{
"rpi.alsc":
@@ -726,20 +752,19 @@
"map": [ 0.0, 445, 15.0, 925 ]
}
},
- {
- "rpi.hdr":
- {
- "MultiExposure":
- {
- "cadence": [ 1, 2 ],
- "channel_map": { "short": 1, "long": 2 }
- },
- "SingleExposure":
- {
- "cadence": [ 1 ],
- "channel_map": { "short": 1 }
- }
- }
- }
+ {
+ "rpi.hdr":
+ {
+ "MultiExposureUnmerged":
+ {
+ "cadence": [ 1, 2 ],
+ "channel_map":
+ {
+ "short": 1,
+ "long": 2
+ }
+ }
+ }
+ }
]
-}
+} \ No newline at end of file
diff --git a/src/ipa/rpi/vc4/data/imx708_wide.json b/src/ipa/rpi/vc4/data/imx708_wide.json
index 0f846ea2..6f45aafc 100644
--- a/src/ipa/rpi/vc4/data/imx708_wide.json
+++ b/src/ipa/rpi/vc4/data/imx708_wide.json
@@ -129,255 +129,281 @@
{
"rpi.agc":
{
- "channels":
- [
- {
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 15000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
- },
- "long":
- {
- "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.2,
- 1000, 0.2
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.2,
- 1000, 0.2
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ],
- "startup_frames": 5,
- "convergence_frames": 6,
- "speed": 0.15
- },
- {
- "base_ev": 0.125,
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 15000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
- },
- "long":
- {
- "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.2,
- 1000, 0.2
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.2,
- 1000, 0.2
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ],
- "startup_frames": 5,
- "convergence_frames": 6,
- "speed": 0.15
- },
- {
- "base_ev": 1.5,
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 15000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
- },
- "long":
- {
- "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.2,
- 1000, 0.2
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.2,
- 1000, 0.2
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ],
- "startup_frames": 5,
- "convergence_frames": 6,
- "speed": 0.15
- }
- ]
- }
+ "channels": [
+ {
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 15000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.2,
+ 1000, 0.2
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.2,
+ 1000, 0.2
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ],
+ "startup_frames": 5,
+ "convergence_frames": 6,
+ "speed": 0.15
+ },
+ {
+ "base_ev": 0.125,
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 15000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.2,
+ 1000, 0.2
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.2,
+ 1000, 0.2
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ],
+ "startup_frames": 5,
+ "convergence_frames": 6,
+ "speed": 0.15
+ },
+ {
+ "base_ev": 1.5,
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 15000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.2,
+ 1000, 0.2
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.2,
+ 1000, 0.2
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ],
+ "startup_frames": 5,
+ "convergence_frames": 6,
+ "speed": 0.15
+ }
+ ]
+ }
},
{
"rpi.alsc":
@@ -638,20 +664,19 @@
"map": [ 0.0, 420, 35.0, 920 ]
}
},
- {
- "rpi.hdr":
- {
- "MultiExposure":
- {
- "cadence": [ 1, 2 ],
- "channel_map": { "short": 1, "long": 2 }
- },
- "SingleExposure":
- {
- "cadence": [ 1 ],
- "channel_map": { "short": 1 }
- }
- }
- }
+ {
+ "rpi.hdr":
+ {
+ "MultiExposureUnmerged":
+ {
+ "cadence": [ 1, 2 ],
+ "channel_map":
+ {
+ "short": 1,
+ "long": 2
+ }
+ }
+ }
+ }
]
-}
+} \ No newline at end of file
diff --git a/src/ipa/rpi/vc4/data/imx708_wide_noir.json b/src/ipa/rpi/vc4/data/imx708_wide_noir.json
index f12ddbb6..b9a5227e 100644
--- a/src/ipa/rpi/vc4/data/imx708_wide_noir.json
+++ b/src/ipa/rpi/vc4/data/imx708_wide_noir.json
@@ -129,255 +129,281 @@
{
"rpi.agc":
{
- "channels":
- [
- {
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 15000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
- },
- "long":
- {
- "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.2,
- 1000, 0.2
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.2,
- 1000, 0.2
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ],
- "startup_frames": 5,
- "convergence_frames": 6,
- "speed": 0.15
- },
- {
- "base_ev": 0.125,
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 15000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
- },
- "long":
- {
- "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.2,
- 1000, 0.2
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.2,
- 1000, 0.2
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ],
- "startup_frames": 5,
- "convergence_frames": 6,
- "speed": 0.15
- },
- {
- "base_ev": 1.5,
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 15000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
- },
- "long":
- {
- "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.2,
- 1000, 0.2
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.2,
- 1000, 0.2
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ],
- "startup_frames": 5,
- "convergence_frames": 6,
- "speed": 0.15
- }
- ]
- }
+ "channels": [
+ {
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 15000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.2,
+ 1000, 0.2
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.2,
+ 1000, 0.2
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ],
+ "startup_frames": 5,
+ "convergence_frames": 6,
+ "speed": 0.15
+ },
+ {
+ "base_ev": 0.125,
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 15000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.2,
+ 1000, 0.2
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.2,
+ 1000, 0.2
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ],
+ "startup_frames": 5,
+ "convergence_frames": 6,
+ "speed": 0.15
+ },
+ {
+ "base_ev": 1.5,
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 15000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.2,
+ 1000, 0.2
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.2,
+ 1000, 0.2
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ],
+ "startup_frames": 5,
+ "convergence_frames": 6,
+ "speed": 0.15
+ }
+ ]
+ }
},
{
"rpi.alsc":
@@ -629,20 +655,19 @@
"map": [ 0.0, 420, 35.0, 920 ]
}
},
- {
- "rpi.hdr":
- {
- "MultiExposure":
- {
- "cadence": [ 1, 2 ],
- "channel_map": { "short": 1, "long": 2 }
- },
- "SingleExposure":
- {
- "cadence": [ 1 ],
- "channel_map": { "short": 1 }
- }
- }
- }
+ {
+ "rpi.hdr":
+ {
+ "MultiExposureUnmerged":
+ {
+ "cadence": [ 1, 2 ],
+ "channel_map":
+ {
+ "short": 1,
+ "long": 2
+ }
+ }
+ }
+ }
]
-}
+} \ No newline at end of file
diff --git a/src/ipa/rpi/vc4/data/ov5647.json b/src/ipa/rpi/vc4/data/ov5647.json
index 4def9ffc..40c6059c 100644
--- a/src/ipa/rpi/vc4/data/ov5647.json
+++ b/src/ipa/rpi/vc4/data/ov5647.json
@@ -131,285 +131,309 @@
{
"rpi.agc":
{
- "channels":
- [
- {
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 10000, 30000, 60000, 66666 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 33333 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "long":
- {
- "shutter": [ 100, 10000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.5,
- 1000, 0.5
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.5,
- 1000, 0.5
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ],
- "shadows": [
- {
- "bound": "LOWER",
- "q_lo": 0.0,
- "q_hi": 0.5,
- "y_target":
- [
- 0, 0.17,
- 1000, 0.17
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ],
- "base_ev": 1.25
- },
- {
- "base_ev": 0.125,
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 10000, 30000, 60000, 66666 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 33333 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "long":
- {
- "shutter": [ 100, 10000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.5,
- 1000, 0.5
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.5,
- 1000, 0.5
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ],
- "shadows": [
- {
- "bound": "LOWER",
- "q_lo": 0.0,
- "q_hi": 0.5,
- "y_target":
- [
- 0, 0.17,
- 1000, 0.17
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ],
- "base_ev": 1.25
- },
- {
- "base_ev": 1.5,
- "metering_modes":
- {
- "centre-weighted":
- {
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
- },
- "spot":
- {
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- },
- "matrix":
- {
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
- }
- },
- "exposure_modes":
- {
- "normal":
- {
- "shutter": [ 100, 10000, 30000, 60000, 66666 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "short":
- {
- "shutter": [ 100, 5000, 10000, 20000, 33333 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
- },
- "long":
- {
- "shutter": [ 100, 10000, 30000, 60000, 120000 ],
- "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
- }
- },
- "constraint_modes":
- {
- "normal": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.5,
- 1000, 0.5
- ]
- }
- ],
- "highlight": [
- {
- "bound": "LOWER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.5,
- 1000, 0.5
- ]
- },
- {
- "bound": "UPPER",
- "q_lo": 0.98,
- "q_hi": 1.0,
- "y_target":
- [
- 0, 0.8,
- 1000, 0.8
- ]
- }
- ],
- "shadows": [
- {
- "bound": "LOWER",
- "q_lo": 0.0,
- "q_hi": 0.5,
- "y_target":
- [
- 0, 0.17,
- 1000, 0.17
- ]
- }
- ]
- },
- "y_target":
- [
- 0, 0.16,
- 1000, 0.165,
- 10000, 0.17
- ],
- "base_ev": 1.25
- }
- ]
- }
+ "channels": [
+ {
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 33333 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.5,
+ 1000, 0.5
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.5,
+ 1000, 0.5
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ],
+ "shadows": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.0,
+ "q_hi": 0.5,
+ "y_target":
+ [
+ 0, 0.17,
+ 1000, 0.17
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ],
+ "base_ev": 1.25
+ },
+ {
+ "base_ev": 1.25,
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 33333 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.5,
+ 1000, 0.5
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.5,
+ 1000, 0.5
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ],
+ "shadows": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.0,
+ "q_hi": 0.5,
+ "y_target":
+ [
+ 0, 0.17,
+ 1000, 0.17
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ]
+ },
+ {
+ "base_ev": 1.25,
+ "metering_modes":
+ {
+ "centre-weighted":
+ {
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
+ },
+ "spot":
+ {
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
+ },
+ "matrix":
+ {
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
+ }
+ },
+ "exposure_modes":
+ {
+ "normal":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "short":
+ {
+ "shutter": [ 100, 5000, 10000, 20000, 33333 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+ },
+ "long":
+ {
+ "shutter": [ 100, 10000, 30000, 60000, 120000 ],
+ "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+ }
+ },
+ "constraint_modes":
+ {
+ "normal": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.5,
+ 1000, 0.5
+ ]
+ }
+ ],
+ "highlight": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.5,
+ 1000, 0.5
+ ]
+ },
+ {
+ "bound": "UPPER",
+ "q_lo": 0.98,
+ "q_hi": 1.0,
+ "y_target":
+ [
+ 0, 0.8,
+ 1000, 0.8
+ ]
+ }
+ ],
+ "shadows": [
+ {
+ "bound": "LOWER",
+ "q_lo": 0.0,
+ "q_hi": 0.5,
+ "y_target":
+ [
+ 0, 0.17,
+ 1000, 0.17
+ ]
+ }
+ ]
+ },
+ "y_target":
+ [
+ 0, 0.16,
+ 1000, 0.165,
+ 10000, 0.17
+ ]
+ }
+ ]
+ }
},
{
"rpi.alsc":
@@ -654,20 +678,19 @@
{
"rpi.sharpen": { }
},
- {
- "rpi.hdr":
- {
- "MultiExposure":
- {
- "cadence": [ 1, 2 ],
- "channel_map": { "short": 1, "long": 2 }
- },
- "SingleExposure":
- {
- "cadence": [ 1 ],
- "channel_map": { "short": 1 }
- }
- }
- }
+ {
+ "rpi.hdr":
+ {
+ "MultiExposureUnmerged":
+ {
+ "cadence": [ 1, 2 ],
+ "channel_map":
+ {
+ "short": 1,
+ "long": 2
+ }
+ }
+ }
+ }
]
}
diff --git a/src/ipa/rpi/vc4/data/ov5647_noir.json b/src/ipa/rpi/vc4/data/ov5647_noir.json
index a6c6722f..488b7119 100644
--- a/src/ipa/rpi/vc4/data/ov5647_noir.json
+++ b/src/ipa/rpi/vc4/data/ov5647_noir.json
@@ -51,15 +51,24 @@
{
"centre-weighted":
{
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
},
"spot":
{
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
},
"matrix":
{
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
}
},
"exposure_modes":
diff --git a/src/ipa/rpi/vc4/data/ov9281_mono.json b/src/ipa/rpi/vc4/data/ov9281_mono.json
index 2b7292ec..a9d05a01 100644
--- a/src/ipa/rpi/vc4/data/ov9281_mono.json
+++ b/src/ipa/rpi/vc4/data/ov9281_mono.json
@@ -35,7 +35,10 @@
{
"centre-weighted":
{
- "weights": [ 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
+ "weights":
+ [
+ 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
}
},
"exposure_modes":
diff --git a/src/ipa/rpi/vc4/data/se327m12.json b/src/ipa/rpi/vc4/data/se327m12.json
index 8552ed92..948169db 100644
--- a/src/ipa/rpi/vc4/data/se327m12.json
+++ b/src/ipa/rpi/vc4/data/se327m12.json
@@ -133,15 +133,24 @@
{
"centre-weighted":
{
- "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
+ "weights":
+ [
+ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
},
"spot":
{
- "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
+ "weights":
+ [
+ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]
},
"matrix":
{
- "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
+ "weights":
+ [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+ ]
}
},
"exposure_modes":
diff --git a/src/ipa/rpi/vc4/data/uncalibrated.json b/src/ipa/rpi/vc4/data/uncalibrated.json
index 7654defa..cdc56b32 100644
--- a/src/ipa/rpi/vc4/data/uncalibrated.json
+++ b/src/ipa/rpi/vc4/data/uncalibrated.json
@@ -22,7 +22,10 @@
{
"centre-weighted":
{
- "weights": [ 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
+ "weights":
+ [
+ 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+ ]
}
},
"exposure_modes":
diff --git a/src/ipa/rpi/vc4/vc4.cpp b/src/ipa/rpi/vc4/vc4.cpp
index d2159a51..ba43e474 100644
--- a/src/ipa/rpi/vc4/vc4.cpp
+++ b/src/ipa/rpi/vc4/vc4.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019-2021, Raspberry Pi Ltd
*
- * rpi.cpp - Raspberry Pi VC4/BCM2835 ISP IPA.
+ * Raspberry Pi VC4/BCM2835 ISP IPA.
*/
#include <string.h>
@@ -583,7 +583,7 @@ extern "C" {
const struct IPAModuleInfo ipaModuleInfo = {
IPA_MODULE_API_VERSION,
1,
- "PipelineHandlerVc4",
+ "rpi/vc4",
"rpi/vc4",
};
diff --git a/src/ipa/simple/black_level.cpp b/src/ipa/simple/black_level.cpp
index c7e8d8b7..53b4c040 100644
--- a/src/ipa/simple/black_level.cpp
+++ b/src/ipa/simple/black_level.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2024, Red Hat Inc.
*
- * black_level.cpp - black level handling
+ * black level handling
*/
#include "black_level.h"
diff --git a/src/ipa/simple/black_level.h b/src/ipa/simple/black_level.h
index 7e37757e..25094217 100644
--- a/src/ipa/simple/black_level.h
+++ b/src/ipa/simple/black_level.h
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2024, Red Hat Inc.
*
- * black_level.h - black level handling
+ * black level handling
*/
#pragma once
diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp
index b9fb58b5..a5bb2bbf 100644
--- a/src/ipa/simple/soft_simple.cpp
+++ b/src/ipa/simple/soft_simple.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2023, Linaro Ltd
*
- * soft_simple.cpp - Simple Software Image Processing Algorithm module
+ * Simple Software Image Processing Algorithm module
*/
#include <sys/mman.h>
@@ -389,7 +389,7 @@ extern "C" {
const struct IPAModuleInfo ipaModuleInfo = {
IPA_MODULE_API_VERSION,
0,
- "SimplePipelineHandler",
+ "simple",
"simple",
};
diff --git a/src/ipa/vimc/vimc.cpp b/src/ipa/vimc/vimc.cpp
index 2c255778..ebd63fa6 100644
--- a/src/ipa/vimc/vimc.cpp
+++ b/src/ipa/vimc/vimc.cpp
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2019, Google Inc.
*
- * vimc.cpp - Vimc Image Processing Algorithm module
+ * Vimc Image Processing Algorithm module
*/
#include <libcamera/ipa/vimc_ipa_interface.h>
@@ -200,7 +200,7 @@ extern "C" {
const struct IPAModuleInfo ipaModuleInfo = {
IPA_MODULE_API_VERSION,
0,
- "PipelineHandlerVimc",
+ "vimc",
"vimc",
};