@@ -190,10 +190,10 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo)
context.activeState.agc.meteringMode =
static_cast<controls::AeMeteringModeEnum>(meteringModes_.begin()->first);
- /* Limit the frame duration to match current initialisation */
- ControlInfo &frameDurationLimits = context.ctrlMap[&controls::FrameDurationLimits];
- context.activeState.agc.minFrameDuration = std::chrono::microseconds(frameDurationLimits.min().get<int64_t>());
- context.activeState.agc.maxFrameDuration = std::chrono::microseconds(frameDurationLimits.max().get<int64_t>());
+ context.activeState.agc.minFrameDuration =
+ context.configuration.sensor.minFrameDuration;
+ context.activeState.agc.maxFrameDuration =
+ context.configuration.sensor.maxFrameDuration;
context.configuration.agc.measureWindow.h_offs = 0;
context.configuration.agc.measureWindow.v_offs = 0;
@@ -320,16 +320,16 @@ void Agc::queueRequest(IPAContext &context,
const auto &frameDurationLimits = controls.get(controls::FrameDurationLimits);
if (frameDurationLimits) {
- /* Limit the control value to the limits in ControlInfo */
- ControlInfo &limits = context.ctrlMap[&controls::FrameDurationLimits];
- int64_t minFrameDuration =
- std::clamp((*frameDurationLimits).front(),
- limits.min().get<int64_t>(),
- limits.max().get<int64_t>());
- int64_t maxFrameDuration =
- std::clamp((*frameDurationLimits).back(),
- limits.min().get<int64_t>(),
- limits.max().get<int64_t>());
+ /* Limit the control value to the sensor constraints. */
+ int64_t sensorMinFrameDuration =
+ context.configuration.sensor.minFrameDuration.get<std::micro>();
+ int64_t sensorMaxFrameDuration =
+ context.configuration.sensor.maxFrameDuration.get<std::micro>();
+
+ int64_t minFrameDuration = std::clamp((*frameDurationLimits).front(),
+ sensorMinFrameDuration, sensorMaxFrameDuration);
+ int64_t maxFrameDuration = std::clamp((*frameDurationLimits).back(),
+ sensorMinFrameDuration, sensorMaxFrameDuration);
agc.minFrameDuration = std::chrono::microseconds(minFrameDuration);
agc.maxFrameDuration = std::chrono::microseconds(maxFrameDuration);
@@ -62,6 +62,8 @@ struct IPASessionConfiguration {
struct {
utils::Duration minExposureTime;
utils::Duration maxExposureTime;
+ utils::Duration minFrameDuration;
+ utils::Duration maxFrameDuration;
double minAnalogueGain;
double maxAnalogueGain;
@@ -227,6 +227,7 @@ int IPARkISP1::configure(const IPAConfigInfo &ipaConfig,
const std::map<uint32_t, IPAStream> &streamConfig,
ControlInfoMap *ipaControls)
{
+ const IPACameraSensorInfo &info = ipaConfig.sensorInfo;
sensorControls_ = ipaConfig.sensorControls;
const auto itExp = sensorControls_.find(V4L2_CID_EXPOSURE);
@@ -237,6 +238,12 @@ int IPARkISP1::configure(const IPAConfigInfo &ipaConfig,
int32_t minGain = itGain->second.min().get<int32_t>();
int32_t maxGain = itGain->second.max().get<int32_t>();
+ const auto itVBlank = sensorControls_.find(V4L2_CID_VBLANK);
+ std::array<uint32_t, 2> frameHeights{
+ itVBlank->second.min().get<int32_t>() + info.outputSize.height,
+ itVBlank->second.max().get<int32_t>() + info.outputSize.height,
+ };
+
LOG(IPARkISP1, Debug)
<< "Exposure: [" << minExposure << ", " << maxExposure
<< "], gain: [" << minGain << ", " << maxGain << "]";
@@ -248,11 +255,10 @@ int IPARkISP1::configure(const IPAConfigInfo &ipaConfig,
context_.configuration.paramFormat = ipaConfig.paramFormat;
- const IPACameraSensorInfo &info = ipaConfig.sensorInfo;
- const ControlInfo vBlank = sensorControls_.find(V4L2_CID_VBLANK)->second;
- context_.configuration.sensor.defVBlank = vBlank.def().get<int32_t>();
+ utils::Duration lineDuration = info.minLineLength * 1.0s / info.pixelRate;
+ context_.configuration.sensor.defVBlank = itVBlank->second.def().get<int32_t>();
context_.configuration.sensor.size = info.outputSize;
- context_.configuration.sensor.lineDuration = info.minLineLength * 1.0s / info.pixelRate;
+ context_.configuration.sensor.lineDuration = lineDuration;
/* Update the camera controls using the new sensor settings. */
updateControls(info, sensorControls_, ipaControls);
@@ -261,17 +267,13 @@ int IPARkISP1::configure(const IPAConfigInfo &ipaConfig,
* When the AGC computes the new exposure values for a frame, it needs
* to know the limits for exposure time and analogue gain. As it depends
* on the sensor, update it with the controls.
- *
- * \todo take VBLANK into account for maximum exposure time
*/
- context_.configuration.sensor.minExposureTime =
- minExposure * context_.configuration.sensor.lineDuration;
- context_.configuration.sensor.maxExposureTime =
- maxExposure * context_.configuration.sensor.lineDuration;
- context_.configuration.sensor.minAnalogueGain =
- context_.camHelper->gain(minGain);
- context_.configuration.sensor.maxAnalogueGain =
- context_.camHelper->gain(maxGain);
+ context_.configuration.sensor.minExposureTime = minExposure * lineDuration;
+ context_.configuration.sensor.maxExposureTime = maxExposure * lineDuration;
+ context_.configuration.sensor.minFrameDuration = frameHeights[0] * lineDuration;
+ context_.configuration.sensor.maxFrameDuration = frameHeights[1] * lineDuration;
+ context_.configuration.sensor.minAnalogueGain = context_.camHelper->gain(minGain);
+ context_.configuration.sensor.maxAnalogueGain = context_.camHelper->gain(maxGain);
context_.configuration.raw = std::any_of(streamConfig.begin(), streamConfig.end(),
[](auto &cfg) -> bool {
@@ -436,12 +438,20 @@ void IPARkISP1::updateControls(const IPACameraSensorInfo &sensorInfo,
uint64_t frameSize = lineLength * frameHeights[i];
frameDurations[i] = frameSize / (sensorInfo.pixelRate / 1000000U);
}
-
- /* \todo Move this (and other agc-related controls) to agc */
- context_.ctrlMap[&controls::FrameDurationLimits] =
+ ctrlMap[&controls::FrameDurationLimits] =
ControlInfo(frameDurations[0], frameDurations[1], frameDurations[2]);
- ctrlMap.insert(context_.ctrlMap.begin(), context_.ctrlMap.end());
+ /*
+ * Store the min/max frame duration in the active context to initialize
+ * the AGC algorithm.
+ *
+ * \todo Move this (and other agc-related controls) to agc
+ */
+ context_.activeState.agc.minFrameDuration = std::chrono::microseconds(frameDurations[0]);
+ context_.activeState.agc.maxFrameDuration = std::chrono::microseconds(frameDurations[1]);
+
+ ctrlMap.merge(context_.ctrlMap);
+
*ipaControls = ControlInfoMap(std::move(ctrlMap), controls::controls);
}
The RkISP1 IPA context stores a control list ctrlMap which is used by the AGC algorithm to initialize controls that are then added to the list of the ones registered by the IPA module. The FrameDurationLimits control is a bit of an outlier, as it's the only control that is registered by the IPA in the context ctrlMap and is then used by the AGC algorithm. As the purpose of the context ctrlMap is to be populated by algorithms for the IPA, do not abuse it by registering a control there in the main IPA module and only store the control limits in the active context. Removing FrameDurationLimits from the ctrlMap requires to store it as a sensor configuration parameter in the IPA context and use it for clamping the FrameDurationLimits control and to initialize the AGC active state. Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> --- src/ipa/rkisp1/algorithms/agc.cpp | 28 ++++++++++++------------ src/ipa/rkisp1/ipa_context.h | 2 ++ src/ipa/rkisp1/rkisp1.cpp | 46 ++++++++++++++++++++++++--------------- 3 files changed, 44 insertions(+), 32 deletions(-)