summaryrefslogtreecommitdiff
path: root/src/ipa
diff options
context:
space:
mode:
authorNaushir Patuck <naush@raspberrypi.com>2021-05-10 10:58:15 +0100
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2021-05-11 03:14:42 +0300
commit99feb66df02988831c9e8535649b99fad9a78069 (patch)
treed5a9447a641cb8dc986f14dfeb549e91a4e941a5 /src/ipa
parenta80db5a72391e8dba60c2dcf20397eb73b379574 (diff)
ipa: raspberrypi: Rate-limit the controller algorithms
The controller algorithms currently run on every frame provided to the IPA by the pipeline handler. This may be undesirable for very fast fps operating modes where it could significantly increase the computation cycles (per unit time) without providing any significant changes to the IQ parameters. The added latencies could also cause dropped frames. Pass the FrameBuffer timestamp to the IPA through the controls. This timestamp will be used to rate-limit the controller algorithms to run with a minimum inter-frame time given by a compile time constant, currently set to 16.66ms. On startup, we don't rate-limit the algorithms until after the number of frames required for convergence. Signed-off-by: Naushir Patuck <naush@raspberrypi.com> Reviewed-by: David Plowman <david.plowman@raspberrypi.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'src/ipa')
-rw-r--r--src/ipa/raspberrypi/raspberrypi.cpp42
1 files changed, 38 insertions, 4 deletions
diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp
index 07409621..52d91db2 100644
--- a/src/ipa/raspberrypi/raspberrypi.cpp
+++ b/src/ipa/raspberrypi/raspberrypi.cpp
@@ -61,6 +61,14 @@ constexpr unsigned int DefaultExposureTime = 20000;
constexpr double defaultMinFrameDuration = 1e6 / 30.0;
constexpr double defaultMaxFrameDuration = 1e6 / 0.01;
+/*
+ * Determine the minimum allowable inter-frame duration (in us) to run the
+ * controller algorithms. If the pipeline handler provider frames at a rate
+ * higher than this, we rate-limit the controller Prepare() and Process() calls
+ * to lower than or equal to this rate.
+ */
+constexpr double controllerMinFrameDuration = 1e6 / 60.0;
+
LOG_DEFINE_CATEGORY(IPARPI)
class IPARPi : public ipa::RPi::IPARPiInterface
@@ -68,7 +76,7 @@ class IPARPi : public ipa::RPi::IPARPiInterface
public:
IPARPi()
: controller_(), frameCount_(0), checkCount_(0), mistrustCount_(0),
- lsTable_(nullptr), firstStart_(true)
+ lastRunTimestamp_(0), lsTable_(nullptr), firstStart_(true)
{
}
@@ -146,6 +154,12 @@ private:
/* Number of frames that need to be dropped on startup. */
unsigned int dropFrameCount_;
+ /* Frame timestamp for the last run of the controller. */
+ uint64_t lastRunTimestamp_;
+
+ /* Do we run a Controller::process() for this frame? */
+ bool processPending_;
+
/* LS table allocation passed in from the pipeline handler. */
FileDescriptor lsTableHandle_;
void *lsTable_;
@@ -262,6 +276,7 @@ void IPARPi::start(const ControlList &controls, ipa::RPi::StartConfig *startConf
startConfig->dropFrameCount = dropFrameCount_;
firstStart_ = false;
+ lastRunTimestamp_ = 0;
}
void IPARPi::setMode(const CameraSensorInfo &sensorInfo)
@@ -406,7 +421,7 @@ void IPARPi::signalStatReady(uint32_t bufferId)
{
if (++checkCount_ != frameCount_) /* assert here? */
LOG(IPARPI, Error) << "WARNING: Prepare/Process mismatch!!!";
- if (frameCount_ > mistrustCount_)
+ if (processPending_ && frameCount_ > mistrustCount_)
processStats(bufferId);
reportMetadata();
@@ -894,10 +909,11 @@ void IPARPi::returnEmbeddedBuffer(unsigned int bufferId)
void IPARPi::prepareISP(const ipa::RPi::ISPConfig &data)
{
+ int64_t frameTimestamp = data.controls.get(controls::SensorTimestamp);
+ RPiController::Metadata lastMetadata;
Span<uint8_t> embeddedBuffer;
- rpiMetadata_.Clear();
-
+ lastMetadata = std::move(rpiMetadata_);
fillDeviceStatus(data.controls);
if (data.embeddedBufferPresent) {
@@ -920,6 +936,24 @@ void IPARPi::prepareISP(const ipa::RPi::ISPConfig &data)
if (data.embeddedBufferPresent)
returnEmbeddedBuffer(data.embeddedBufferId);
+ /* Allow a 10% margin on the comparison below. */
+ constexpr double eps = controllerMinFrameDuration * 1e3 * 0.1;
+ if (lastRunTimestamp_ && frameCount_ > dropFrameCount_ &&
+ frameTimestamp - lastRunTimestamp_ + eps < controllerMinFrameDuration * 1e3) {
+ /*
+ * Ensure we merge the previous frame's metadata with the current
+ * frame. This will not overwrite exposure/gain values for the
+ * current frame, or any other bits of metadata that were added
+ * in helper_->Prepare().
+ */
+ rpiMetadata_.Merge(lastMetadata);
+ processPending_ = false;
+ return;
+ }
+
+ lastRunTimestamp_ = frameTimestamp;
+ processPending_ = true;
+
ControlList ctrls(ispCtrls_);
controller_.Prepare(&rpiMetadata_);