summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Roth <nicholas@rothemail.net>2022-10-30 18:04:56 -0500
committerJacopo Mondi <jacopo.mondi@ideasonboard.com>2023-10-18 13:06:44 +0000
commita7103ced3a6d9c56df839b1f2eab0780c56674f7 (patch)
treec43a2e01d60aef725baed4391f72c463021b682c
parentbeaffa59a04ebabf17dee7b329ab570da14651b8 (diff)
ipa: workaround libcxx duration limitationjmondi/android/vndk
A bug in libcxx [0] used by clang version 11.0.2 is prevalent when building libcamera for Android SDK30. This has been fixed and integrated upstream with [1]. As a workaround, directly cast libcamera::utils::Duration objects to std::chrono::duration when dividing. Alternatives evaluated: Considered: Enable public inheritance of std::chrono::duration and override operator/ in the class. Outcome: Does not fix the original compiler error. Considered: Enable public inheritance of std::chrono::duration and override operator/ in the libcamera namespace. Outcome: new compiler error: ld.lld: error: duplicate symbol: libcamera::operator/ (libcamera::utils::Duration const&, libcamera::utils::Duration const&) Considered: Use private inheritance of std::chrono::duration and re-implement a pass-through version of each std::chrono::duration operator within libcamera::utils::Duration and use template metaprogramming to fix the division operator. Outcome: Testing shows that this would introduce substantial limitations, i.e. requring the Duration object to be on the LHS of any arithmetic operation with other numeric types. This also substantially increases implementation complexity. Considered: Extract double values from libcamera::utils::Duration objects and use those to divide. Outcome: This creates substantial readability and unit-safety issues. [0] https://github.com/llvm/llvm-project/issues/40475 [1] https://github.com/llvm/llvm-project/commit/efa6d803c624f9251d0ab7881122501bb9d27368 Bug: https://bugs.libcamera.org/show_bug.cgi?id=156 Signed-off-by: Nicholas Roth <nicholas@rothemail.net>
-rw-r--r--src/ipa/ipu3/algorithms/agc.cpp13
-rw-r--r--src/ipa/rkisp1/algorithms/agc.cpp11
-rw-r--r--src/ipa/rpi/cam_helper/cam_helper.cpp6
-rw-r--r--src/ipa/rpi/cam_helper/cam_helper_imx296.cpp3
-rw-r--r--src/ipa/rpi/controller/rpi/agc_channel.cpp11
-rw-r--r--src/ipa/rpi/controller/rpi/lux.cpp3
6 files changed, 28 insertions, 19 deletions
diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp
index 606a237a..632d1fe3 100644
--- a/src/ipa/ipu3/algorithms/agc.cpp
+++ b/src/ipa/ipu3/algorithms/agc.cpp
@@ -240,17 +240,20 @@ void Agc::computeExposure(IPAContext &context, IPAFrameContext &frameContext,
* increase the gain.
*/
utils::Duration shutterTime =
- std::clamp<utils::Duration>(exposureValue / minAnalogueGain_,
- minShutterSpeed_, maxShutterSpeed_);
- double stepGain = std::clamp(exposureValue / shutterTime,
- minAnalogueGain_, maxAnalogueGain_);
+ std::clamp<utils::Duration>(std::chrono::duration(exposureValue) /
+ minAnalogueGain_,
+ minShutterSpeed_, maxShutterSpeed_);
+ double stepGain = std::clamp(std::chrono::duration(exposureValue) /
+ std::chrono::duration(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.exposure = std::chrono::duration(shutterTime) /
+ std::chrono::duration(configuration.sensor.lineDuration);
activeState.agc.gain = stepGain;
}
diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp
index e5aeb342..42f158fc 100644
--- a/src/ipa/rkisp1/algorithms/agc.cpp
+++ b/src/ipa/rkisp1/algorithms/agc.cpp
@@ -76,7 +76,7 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo)
/* Configure the default exposure and gain. */
context.activeState.agc.automatic.gain = context.configuration.sensor.minAnalogueGain;
context.activeState.agc.automatic.exposure =
- 10ms / context.configuration.sensor.lineDuration;
+ 10ms / std::chrono::duration(context.configuration.sensor.lineDuration);
context.activeState.agc.manual.gain = context.activeState.agc.automatic.gain;
context.activeState.agc.manual.exposure = context.activeState.agc.automatic.exposure;
context.activeState.agc.autoEnabled = !context.configuration.raw;
@@ -135,7 +135,7 @@ void Agc::queueRequest(IPAContext &context,
const auto &exposure = controls.get(controls::ExposureTime);
if (exposure && !agc.autoEnabled) {
agc.manual.exposure = *exposure * 1.0us
- / context.configuration.sensor.lineDuration;
+ / std::chrono::duration(context.configuration.sensor.lineDuration);
LOG(RkISP1Agc, Debug)
<< "Set exposure to " << agc.manual.exposure;
@@ -303,16 +303,17 @@ void Agc::computeExposure(IPAContext &context, IPAFrameContext &frameContext,
* Push the shutter time up to the maximum first, and only then
* increase the gain.
*/
- utils::Duration shutterTime = std::clamp<utils::Duration>(exposureValue / minAnalogueGain,
+ utils::Duration shutterTime = std::clamp<utils::Duration>(std::chrono::duration(exposureValue) / minAnalogueGain,
minShutterSpeed, maxShutterSpeed);
- double stepGain = std::clamp(exposureValue / shutterTime,
+ double stepGain = std::clamp(exposureValue / std::chrono::duration(shutterTime),
minAnalogueGain, maxAnalogueGain);
LOG(RkISP1Agc, Debug) << "Divided up shutter and gain are "
<< shutterTime << " and "
<< stepGain;
/* Update the estimated exposure and gain. */
- activeState.agc.automatic.exposure = shutterTime / configuration.sensor.lineDuration;
+ activeState.agc.automatic.exposure = std::chrono::duration(shutterTime) /
+ std::chrono::duration(configuration.sensor.lineDuration);
activeState.agc.automatic.gain = stepGain;
}
diff --git a/src/ipa/rpi/cam_helper/cam_helper.cpp b/src/ipa/rpi/cam_helper/cam_helper.cpp
index ddd5e9a4..7e29373b 100644
--- a/src/ipa/rpi/cam_helper/cam_helper.cpp
+++ b/src/ipa/rpi/cam_helper/cam_helper.cpp
@@ -71,7 +71,7 @@ void CamHelper::process([[maybe_unused]] StatisticsPtr &stats,
uint32_t CamHelper::exposureLines(const Duration exposure, const Duration lineLength) const
{
- return exposure / lineLength;
+ return std::chrono::duration(exposure) / std::chrono::duration(lineLength);
}
Duration CamHelper::exposure(uint32_t exposureLines, const Duration lineLength) const
@@ -93,8 +93,8 @@ std::pair<uint32_t, uint32_t> CamHelper::getBlanking(Duration &exposure,
* frameLengthMax gets calculated on the smallest line length as we do
* not want to extend that unless absolutely necessary.
*/
- frameLengthMin = minFrameDuration / mode_.minLineLength;
- frameLengthMax = maxFrameDuration / mode_.minLineLength;
+ frameLengthMin = std::chrono::duration(minFrameDuration) / std::chrono::duration(mode_.minLineLength);
+ frameLengthMax = std::chrono::duration(maxFrameDuration) / std::chrono::duration(mode_.minLineLength);
/*
* Watch out for (exposureLines + frameIntegrationDiff_) overflowing a
diff --git a/src/ipa/rpi/cam_helper/cam_helper_imx296.cpp b/src/ipa/rpi/cam_helper/cam_helper_imx296.cpp
index ecb845e7..c5180de5 100644
--- a/src/ipa/rpi/cam_helper/cam_helper_imx296.cpp
+++ b/src/ipa/rpi/cam_helper/cam_helper_imx296.cpp
@@ -57,7 +57,8 @@ double CamHelperImx296::gain(uint32_t gainCode) const
uint32_t CamHelperImx296::exposureLines(const Duration exposure,
[[maybe_unused]] const Duration lineLength) const
{
- return std::max<uint32_t>(minExposureLines, (exposure - 14.26us) / timePerLine);
+ return std::max<uint32_t>(minExposureLines, std::chrono::duration(exposure - 14.26us) /
+ std::chrono::duration(timePerLine));
}
Duration CamHelperImx296::exposure(uint32_t exposureLines,
diff --git a/src/ipa/rpi/controller/rpi/agc_channel.cpp b/src/ipa/rpi/controller/rpi/agc_channel.cpp
index 3957dbc3..e856289a 100644
--- a/src/ipa/rpi/controller/rpi/agc_channel.cpp
+++ b/src/ipa/rpi/controller/rpi/agc_channel.cpp
@@ -473,7 +473,8 @@ void AgcChannel::prepare(Metadata *imageMetadata)
Duration actualExposure = deviceStatus.shutterSpeed *
deviceStatus.analogueGain;
if (actualExposure) {
- double digitalGain = totalExposureValue / actualExposure;
+ double digitalGain = std::chrono::duration(totalExposureValue) /
+ std::chrono::duration(actualExposure);
LOG(RPiAgc, Debug) << "Want total exposure " << totalExposureValue;
/*
* Never ask for a gain < 1.0, and also impose
@@ -925,7 +926,8 @@ void AgcChannel::divideUpExposure()
}
if (status_.fixedAnalogueGain == 0.0) {
if (exposureMode_->gain[stage] * shutterTime >= exposureValue) {
- analogueGain = exposureValue / shutterTime;
+ analogueGain = std::chrono::duration(exposureValue) /
+ std::chrono::duration(shutterTime);
break;
}
analogueGain = exposureMode_->gain[stage];
@@ -941,10 +943,11 @@ void AgcChannel::divideUpExposure()
*/
if (!status_.fixedShutter && !status_.fixedAnalogueGain &&
status_.flickerPeriod) {
- int flickerPeriods = shutterTime / status_.flickerPeriod;
+ int flickerPeriods = std::chrono::duration(shutterTime) /
+ std::chrono::duration(status_.flickerPeriod);
if (flickerPeriods) {
Duration newShutterTime = flickerPeriods * status_.flickerPeriod;
- analogueGain *= shutterTime / newShutterTime;
+ analogueGain *= shutterTime / std::chrono::duration(newShutterTime);
/*
* We should still not allow the ag to go over the
* largest value in the exposure mode. Note that this
diff --git a/src/ipa/rpi/controller/rpi/lux.cpp b/src/ipa/rpi/controller/rpi/lux.cpp
index 06625f3a..49a7af00 100644
--- a/src/ipa/rpi/controller/rpi/lux.cpp
+++ b/src/ipa/rpi/controller/rpi/lux.cpp
@@ -84,7 +84,8 @@ void Lux::process(StatisticsPtr &stats, Metadata *imageMetadata)
double currentY = stats->yHist.interQuantileMean(0, 1);
double gainRatio = referenceGain_ / currentGain;
double shutterSpeedRatio =
- referenceShutterSpeed_ / deviceStatus.shutterSpeed;
+ std::chrono::duration(referenceShutterSpeed_) /
+ std::chrono::duration(deviceStatus.shutterSpeed);
double apertureRatio = referenceAperture_ / currentAperture;
double yRatio = currentY * (65536 / stats->yHist.bins()) / referenceY_;
double estimatedLux = shutterSpeedRatio * gainRatio *