summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ipa/raspberrypi/raspberrypi.cpp42
-rw-r--r--src/libcamera/pipeline/raspberrypi/raspberrypi.cpp5
2 files changed, 43 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_);
diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
index 82ae0482..6fbdba04 100644
--- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
+++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
@@ -1433,6 +1433,11 @@ void RPiCameraData::unicamBufferDequeue(FrameBuffer *buffer)
* DelayedControl and queue them along with the frame buffer.
*/
ControlList ctrl = delayedCtrls_->get(buffer->metadata().sequence);
+ /*
+ * Add the frame timestamp to the ControlList for the IPA to use
+ * as it does not receive the FrameBuffer object.
+ */
+ ctrl.set(controls::SensorTimestamp, buffer->metadata().timestamp);
bayerQueue_.push({ buffer, std::move(ctrl) });
} else {
embeddedQueue_.push(buffer);