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.cpp86
1 files changed, 72 insertions, 14 deletions
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);
}