summaryrefslogtreecommitdiff
path: root/src/ipa/rpi/common/ipa_base.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipa/rpi/common/ipa_base.cpp')
-rw-r--r--src/ipa/rpi/common/ipa_base.cpp201
1 files changed, 143 insertions, 58 deletions
diff --git a/src/ipa/rpi/common/ipa_base.cpp b/src/ipa/rpi/common/ipa_base.cpp
index 468f36a8..6734c32e 100644
--- a/src/ipa/rpi/common/ipa_base.cpp
+++ b/src/ipa/rpi/common/ipa_base.cpp
@@ -55,9 +55,19 @@ constexpr Duration controllerMinFrameDuration = 1.0s / 30.0;
/* List of controls handled by the Raspberry Pi IPA */
const ControlInfoMap::Map ipaControls{
- { &controls::AeEnable, ControlInfo(false, true) },
- { &controls::ExposureTime, ControlInfo(0, 66666) },
- { &controls::AnalogueGain, ControlInfo(1.0f, 16.0f) },
+ /* \todo Move this to the Camera class */
+ { &controls::AeEnable, ControlInfo(false, true, true) },
+ { &controls::ExposureTimeMode,
+ ControlInfo(static_cast<int32_t>(controls::ExposureTimeModeAuto),
+ static_cast<int32_t>(controls::ExposureTimeModeManual),
+ static_cast<int32_t>(controls::ExposureTimeModeAuto)) },
+ { &controls::ExposureTime,
+ ControlInfo(1, 66666, static_cast<int32_t>(defaultExposureTime.get<std::micro>())) },
+ { &controls::AnalogueGainMode,
+ ControlInfo(static_cast<int32_t>(controls::AnalogueGainModeAuto),
+ static_cast<int32_t>(controls::AnalogueGainModeManual),
+ static_cast<int32_t>(controls::AnalogueGainModeAuto)) },
+ { &controls::AnalogueGain, ControlInfo(1.0f, 16.0f, 1.0f) },
{ &controls::AeMeteringMode, ControlInfo(controls::AeMeteringModeValues) },
{ &controls::AeConstraintMode, ControlInfo(controls::AeConstraintModeValues) },
{ &controls::AeExposureMode, ControlInfo(controls::AeExposureModeValues) },
@@ -71,7 +81,9 @@ const ControlInfoMap::Map ipaControls{
{ &controls::HdrMode, ControlInfo(controls::HdrModeValues) },
{ &controls::Sharpness, ControlInfo(0.0f, 16.0f, 1.0f) },
{ &controls::ScalerCrop, ControlInfo(Rectangle{}, Rectangle(65535, 65535, 65535, 65535), Rectangle{}) },
- { &controls::FrameDurationLimits, ControlInfo(INT64_C(33333), INT64_C(120000)) },
+ { &controls::FrameDurationLimits,
+ ControlInfo(INT64_C(33333), INT64_C(120000),
+ static_cast<int64_t>(defaultMinFrameDuration.get<std::micro>())) },
{ &controls::draft::NoiseReductionMode, ControlInfo(controls::draft::NoiseReductionModeValues) },
{ &controls::rpi::StatsOutputEnable, ControlInfo(false, true, false) },
};
@@ -81,6 +93,7 @@ const ControlInfoMap::Map ipaColourControls{
{ &controls::AwbEnable, ControlInfo(false, true) },
{ &controls::AwbMode, ControlInfo(controls::AwbModeValues) },
{ &controls::ColourGains, ControlInfo(0.0f, 32.0f) },
+ { &controls::ColourTemperature, ControlInfo(100, 100000) },
{ &controls::Saturation, ControlInfo(0.0f, 32.0f, 1.0f) },
};
@@ -134,18 +147,8 @@ int32_t IpaBase::init(const IPASettings &settings, const InitParams &params, Ini
return -EINVAL;
}
- /*
- * Pass out the sensor config to the pipeline handler in order
- * to setup the staggered writer class.
- */
- int gainDelay, exposureDelay, vblankDelay, hblankDelay, sensorMetadata;
- helper_->getDelays(exposureDelay, gainDelay, vblankDelay, hblankDelay);
- sensorMetadata = helper_->sensorEmbeddedDataPresent();
-
- result->sensorConfig.gainDelay = gainDelay;
- result->sensorConfig.exposureDelay = exposureDelay;
- result->sensorConfig.vblankDelay = vblankDelay;
- result->sensorConfig.hblankDelay = hblankDelay;
+ /* Pass out the sensor metadata to the pipeline handler */
+ int sensorMetadata = helper_->sensorEmbeddedDataPresent();
result->sensorConfig.sensorMetadata = sensorMetadata;
/* Load the tuning file for this sensor. */
@@ -160,6 +163,7 @@ int32_t IpaBase::init(const IPASettings &settings, const InitParams &params, Ini
lensPresent_ = params.lensPresent;
controller_.initialise();
+ helper_->setHwConfig(controller_.getHardwareConfig());
/* Return the controls handled by the IPA */
ControlInfoMap::Map ctrlMap = ipaControls;
@@ -224,7 +228,7 @@ int32_t IpaBase::configure(const IPACameraSensorInfo &sensorInfo, const ConfigPa
/* Supply initial values for gain and exposure. */
AgcStatus agcStatus;
- agcStatus.shutterTime = defaultExposureTime;
+ agcStatus.exposureTime = defaultExposureTime;
agcStatus.analogueGain = defaultAnalogueGain;
applyAGC(&agcStatus, ctrls);
@@ -258,15 +262,18 @@ int32_t IpaBase::configure(const IPACameraSensorInfo &sensorInfo, const ConfigPa
ControlInfoMap::Map ctrlMap = ipaControls;
ctrlMap[&controls::FrameDurationLimits] =
ControlInfo(static_cast<int64_t>(mode_.minFrameDuration.get<std::micro>()),
- static_cast<int64_t>(mode_.maxFrameDuration.get<std::micro>()));
+ static_cast<int64_t>(mode_.maxFrameDuration.get<std::micro>()),
+ static_cast<int64_t>(defaultMinFrameDuration.get<std::micro>()));
ctrlMap[&controls::AnalogueGain] =
ControlInfo(static_cast<float>(mode_.minAnalogueGain),
- static_cast<float>(mode_.maxAnalogueGain));
+ static_cast<float>(mode_.maxAnalogueGain),
+ static_cast<float>(defaultAnalogueGain));
ctrlMap[&controls::ExposureTime] =
- ControlInfo(static_cast<int32_t>(mode_.minShutter.get<std::micro>()),
- static_cast<int32_t>(mode_.maxShutter.get<std::micro>()));
+ ControlInfo(static_cast<int32_t>(mode_.minExposureTime.get<std::micro>()),
+ static_cast<int32_t>(mode_.maxExposureTime.get<std::micro>()),
+ static_cast<int32_t>(defaultExposureTime.get<std::micro>()));
/* Declare colour processing related controls for non-mono sensors. */
if (!monoSensor_)
@@ -299,11 +306,11 @@ void IpaBase::start(const ControlList &controls, StartResult *result)
/* SwitchMode may supply updated exposure/gain values to use. */
AgcStatus agcStatus;
- agcStatus.shutterTime = 0.0s;
+ agcStatus.exposureTime = 0.0s;
agcStatus.analogueGain = 0.0;
metadata.get("agc.status", agcStatus);
- if (agcStatus.shutterTime && agcStatus.analogueGain) {
+ if (agcStatus.exposureTime && agcStatus.analogueGain) {
ControlList ctrls(sensorCtrls_);
applyAGC(&agcStatus, ctrls);
result->controls = std::move(ctrls);
@@ -599,7 +606,7 @@ void IpaBase::setMode(const IPACameraSensorInfo &sensorInfo)
mode_.sensitivity = helper_->getModeSensitivity(mode_);
const ControlInfo &gainCtrl = sensorCtrls_.at(V4L2_CID_ANALOGUE_GAIN);
- const ControlInfo &shutterCtrl = sensorCtrls_.at(V4L2_CID_EXPOSURE);
+ const ControlInfo &exposureTimeCtrl = sensorCtrls_.at(V4L2_CID_EXPOSURE);
mode_.minAnalogueGain = helper_->gain(gainCtrl.min().get<int32_t>());
mode_.maxAnalogueGain = helper_->gain(gainCtrl.max().get<int32_t>());
@@ -610,11 +617,15 @@ void IpaBase::setMode(const IPACameraSensorInfo &sensorInfo)
*/
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();
- helper_->getBlanking(mode_.maxShutter,
- mode_.minFrameDuration, mode_.maxFrameDuration);
+ /*
+ * Exposure time is calculated based on the limits of the frame
+ * durations.
+ */
+ mode_.minExposureTime = helper_->exposure(exposureTimeCtrl.min().get<int32_t>(),
+ mode_.minLineLength);
+ mode_.maxExposureTime = Duration::max();
+ helper_->getBlanking(mode_.maxExposureTime, mode_.minFrameDuration,
+ mode_.maxFrameDuration);
}
void IpaBase::setCameraTimeoutValue()
@@ -753,6 +764,42 @@ void IpaBase::applyControls(const ControlList &controls)
af->setMode(mode->second);
}
+ /*
+ * Because some AE controls are mode-specific, handle the AE-related
+ * mode changes first.
+ */
+ const auto analogueGainMode = controls.get(controls::AnalogueGainMode);
+ const auto exposureTimeMode = controls.get(controls::ExposureTimeMode);
+
+ if (analogueGainMode || exposureTimeMode) {
+ RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>(
+ controller_.getAlgorithm("agc"));
+ if (agc) {
+ if (analogueGainMode) {
+ if (*analogueGainMode == controls::AnalogueGainModeManual)
+ agc->disableAutoGain();
+ else
+ agc->enableAutoGain();
+
+ libcameraMetadata_.set(controls::AnalogueGainMode,
+ *analogueGainMode);
+ }
+
+ if (exposureTimeMode) {
+ if (*exposureTimeMode == controls::ExposureTimeModeManual)
+ agc->disableAutoExposure();
+ else
+ agc->enableAutoExposure();
+
+ libcameraMetadata_.set(controls::ExposureTimeMode,
+ *exposureTimeMode);
+ }
+ } else {
+ LOG(IPARPI, Warning)
+ << "Could not set AnalogueGainMode or ExposureTimeMode - no AGC algorithm";
+ }
+ }
+
/* Iterate over controls */
for (auto const &ctrl : controls) {
LOG(IPARPI, Debug) << "Request ctrl: "
@@ -760,23 +807,8 @@ void IpaBase::applyControls(const ControlList &controls)
<< " = " << ctrl.second.toString();
switch (ctrl.first) {
- case controls::AE_ENABLE: {
- RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>(
- controller_.getAlgorithm("agc"));
- if (!agc) {
- LOG(IPARPI, Warning)
- << "Could not set AE_ENABLE - no AGC algorithm";
- break;
- }
-
- if (ctrl.second.get<bool>() == false)
- agc->disableAuto();
- else
- agc->enableAuto();
-
- libcameraMetadata_.set(controls::AeEnable, ctrl.second.get<bool>());
- break;
- }
+ case controls::EXPOSURE_TIME_MODE:
+ break; /* We already handled this one above */
case controls::EXPOSURE_TIME: {
RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>(
@@ -787,13 +819,23 @@ void IpaBase::applyControls(const ControlList &controls)
break;
}
+ /*
+ * Ignore manual exposure time when the auto exposure
+ * algorithm is running.
+ */
+ if (agc->autoExposureEnabled())
+ break;
+
/* The control provides units of microseconds. */
- agc->setFixedShutter(0, ctrl.second.get<int32_t>() * 1.0us);
+ agc->setFixedExposureTime(0, ctrl.second.get<int32_t>() * 1.0us);
libcameraMetadata_.set(controls::ExposureTime, ctrl.second.get<int32_t>());
break;
}
+ case controls::ANALOGUE_GAIN_MODE:
+ break; /* We already handled this one above */
+
case controls::ANALOGUE_GAIN: {
RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>(
controller_.getAlgorithm("agc"));
@@ -803,6 +845,13 @@ void IpaBase::applyControls(const ControlList &controls)
break;
}
+ /*
+ * Ignore manual analogue gain value when the auto gain
+ * algorithm is running.
+ */
+ if (agc->autoGainEnabled())
+ break;
+
agc->setFixedAnalogueGain(0, ctrl.second.get<float>());
libcameraMetadata_.set(controls::AnalogueGain,
@@ -859,6 +908,13 @@ void IpaBase::applyControls(const ControlList &controls)
break;
}
+ /*
+ * Ignore AE_EXPOSURE_MODE if the shutter or the gain
+ * are in auto mode.
+ */
+ if (agc->autoExposureEnabled() || agc->autoGainEnabled())
+ break;
+
int32_t idx = ctrl.second.get<int32_t>();
if (ExposureModeTable.count(idx)) {
agc->setExposureMode(ExposureModeTable.at(idx));
@@ -1017,6 +1073,25 @@ void IpaBase::applyControls(const ControlList &controls)
break;
}
+ case controls::COLOUR_TEMPERATURE: {
+ /* Silently ignore this control for a mono sensor. */
+ if (monoSensor_)
+ break;
+
+ auto temperatureK = ctrl.second.get<int32_t>();
+ RPiController::AwbAlgorithm *awb = dynamic_cast<RPiController::AwbAlgorithm *>(
+ controller_.getAlgorithm("awb"));
+ if (!awb) {
+ LOG(IPARPI, Warning)
+ << "Could not set COLOUR_TEMPERATURE - no AWB algorithm";
+ break;
+ }
+
+ awb->setColourTemperature(temperatureK);
+ /* This metadata will get reported back automatically. */
+ break;
+ }
+
case controls::BRIGHTNESS: {
RPiController::ContrastAlgorithm *contrast = dynamic_cast<RPiController::ContrastAlgorithm *>(
controller_.getAlgorithm("contrast"));
@@ -1281,7 +1356,7 @@ void IpaBase::fillDeviceStatus(const ControlList &sensorControls, unsigned int i
int32_t hblank = sensorControls.get(V4L2_CID_HBLANK).get<int32_t>();
deviceStatus.lineLength = helper_->hblankToLineLength(hblank);
- deviceStatus.shutterSpeed = helper_->exposure(exposureLines, deviceStatus.lineLength);
+ deviceStatus.exposureTime = helper_->exposure(exposureLines, deviceStatus.lineLength);
deviceStatus.analogueGain = helper_->gain(gainCode);
deviceStatus.frameLength = mode_.height + vblank;
@@ -1308,7 +1383,7 @@ void IpaBase::reportMetadata(unsigned int ipaContext)
DeviceStatus *deviceStatus = rpiMetadata.getLocked<DeviceStatus>("device.status");
if (deviceStatus) {
libcameraMetadata_.set(controls::ExposureTime,
- deviceStatus->shutterSpeed.get<std::micro>());
+ deviceStatus->exposureTime.get<std::micro>());
libcameraMetadata_.set(controls::AnalogueGain, deviceStatus->analogueGain);
libcameraMetadata_.set(controls::FrameDuration,
helper_->exposure(deviceStatus->frameLength, deviceStatus->lineLength).get<std::micro>());
@@ -1319,9 +1394,19 @@ void IpaBase::reportMetadata(unsigned int ipaContext)
}
AgcPrepareStatus *agcPrepareStatus = rpiMetadata.getLocked<AgcPrepareStatus>("agc.prepare_status");
- if (agcPrepareStatus) {
- libcameraMetadata_.set(controls::AeLocked, agcPrepareStatus->locked);
+ if (agcPrepareStatus)
libcameraMetadata_.set(controls::DigitalGain, agcPrepareStatus->digitalGain);
+
+ RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>(
+ controller_.getAlgorithm("agc"));
+ if (agc) {
+ if (!agc->autoExposureEnabled() && !agc->autoGainEnabled())
+ libcameraMetadata_.set(controls::AeState, controls::AeStateIdle);
+ else if (agcPrepareStatus)
+ libcameraMetadata_.set(controls::AeState,
+ agcPrepareStatus->locked
+ ? controls::AeStateConverged
+ : controls::AeStateSearching);
}
LuxStatus *luxStatus = rpiMetadata.getLocked<LuxStatus>("lux.status");
@@ -1459,15 +1544,15 @@ void IpaBase::applyFrameDurations(Duration minFrameDuration, Duration maxFrameDu
/*
* Calculate the maximum exposure time possible for the AGC to use.
- * getBlanking() will update maxShutter with the largest exposure
+ * getBlanking() will update maxExposureTime with the largest exposure
* value possible.
*/
- Duration maxShutter = Duration::max();
- helper_->getBlanking(maxShutter, minFrameDuration_, maxFrameDuration_);
+ Duration maxExposureTime = Duration::max();
+ helper_->getBlanking(maxExposureTime, minFrameDuration_, maxFrameDuration_);
RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>(
controller_.getAlgorithm("agc"));
- agc->setMaxShutter(maxShutter);
+ agc->setMaxExposureTime(maxExposureTime);
}
void IpaBase::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls)
@@ -1484,14 +1569,14 @@ void IpaBase::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls)
gainCode = std::clamp<int32_t>(gainCode, minGainCode, maxGainCode);
/* getBlanking might clip exposure time to the fps limits. */
- Duration exposure = agcStatus->shutterTime;
+ Duration exposure = agcStatus->exposureTime;
auto [vblank, hblank] = helper_->getBlanking(exposure, minFrameDuration_, maxFrameDuration_);
int32_t exposureLines = helper_->exposureLines(exposure,
helper_->hblankToLineLength(hblank));
LOG(IPARPI, Debug) << "Applying AGC Exposure: " << exposure
- << " (Shutter lines: " << exposureLines << ", AGC requested "
- << agcStatus->shutterTime << ") Gain: "
+ << " (Exposure lines: " << exposureLines << ", AGC requested "
+ << agcStatus->exposureTime << ") Gain: "
<< agcStatus->analogueGain << " (Gain Code: "
<< gainCode << ")";