ipa: raspberrypi: Better heuristics for calculating Unicam timeout
The existing mechanism of setting a timeout value simply uses the maximum possible frame length advertised by the sensor mode. This can be problematic when, for example, the IMX477 sensor can use a frame length of over 600 seconds. However, for typical usage the frame length will never go over several 100s of milliseconds, making the timeout very impractical. Store a list of the last 10 frame length values requested by the AGC. On startup, and at the end of every frame, take the maximum frame length value from this list and return that to the pipeline handler through the setCameraTimeoutValue() signal. This allows the timeout value to better track the actual sensor usage. Signed-off-by: Naushir Patuck <naush@raspberrypi.com> Reviewed-by: David Plowman <david.plowman@raspberrypi.com> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
parent
b6d84ed456
commit
9648e85994
1 changed files with 42 additions and 3 deletions
|
@ -8,6 +8,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <deque>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -64,6 +65,9 @@ using utils::Duration;
|
||||||
/* Number of metadata objects available in the context list. */
|
/* Number of metadata objects available in the context list. */
|
||||||
constexpr unsigned int numMetadataContexts = 16;
|
constexpr unsigned int numMetadataContexts = 16;
|
||||||
|
|
||||||
|
/* Number of frame length times to hold in the queue. */
|
||||||
|
constexpr unsigned int FrameLengthsQueueSize = 10;
|
||||||
|
|
||||||
/* Configure the sensor with these values initially. */
|
/* Configure the sensor with these values initially. */
|
||||||
constexpr double defaultAnalogueGain = 1.0;
|
constexpr double defaultAnalogueGain = 1.0;
|
||||||
constexpr Duration defaultExposureTime = 20.0ms;
|
constexpr Duration defaultExposureTime = 20.0ms;
|
||||||
|
@ -121,7 +125,8 @@ class IPARPi : public IPARPiInterface
|
||||||
public:
|
public:
|
||||||
IPARPi()
|
IPARPi()
|
||||||
: controller_(), frameCount_(0), checkCount_(0), mistrustCount_(0),
|
: controller_(), frameCount_(0), checkCount_(0), mistrustCount_(0),
|
||||||
lastRunTimestamp_(0), lsTable_(nullptr), firstStart_(true)
|
lastRunTimestamp_(0), lsTable_(nullptr), firstStart_(true),
|
||||||
|
lastTimeout_(0s)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,6 +160,7 @@ private:
|
||||||
void fillDeviceStatus(const ControlList &sensorControls, unsigned int ipaContext);
|
void fillDeviceStatus(const ControlList &sensorControls, unsigned int ipaContext);
|
||||||
RPiController::StatisticsPtr fillStatistics(bcm2835_isp_stats *stats) const;
|
RPiController::StatisticsPtr fillStatistics(bcm2835_isp_stats *stats) const;
|
||||||
void processStats(unsigned int bufferId, unsigned int ipaContext);
|
void processStats(unsigned int bufferId, unsigned int ipaContext);
|
||||||
|
void setCameraTimeoutValue();
|
||||||
void applyFrameDurations(Duration minFrameDuration, Duration maxFrameDuration);
|
void applyFrameDurations(Duration minFrameDuration, Duration maxFrameDuration);
|
||||||
void applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls);
|
void applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls);
|
||||||
void applyAWB(const struct AwbStatus *awbStatus, ControlList &ctrls);
|
void applyAWB(const struct AwbStatus *awbStatus, ControlList &ctrls);
|
||||||
|
@ -220,6 +226,10 @@ private:
|
||||||
|
|
||||||
/* Maximum gain code for the sensor. */
|
/* Maximum gain code for the sensor. */
|
||||||
uint32_t maxSensorGainCode_;
|
uint32_t maxSensorGainCode_;
|
||||||
|
|
||||||
|
/* Track the frame length times over FrameLengthsQueueSize frames. */
|
||||||
|
std::deque<Duration> frameLengths_;
|
||||||
|
Duration lastTimeout_;
|
||||||
};
|
};
|
||||||
|
|
||||||
int IPARPi::init(const IPASettings &settings, bool lensPresent, IPAInitResult *result)
|
int IPARPi::init(const IPASettings &settings, bool lensPresent, IPAInitResult *result)
|
||||||
|
@ -284,6 +294,11 @@ void IPARPi::start(const ControlList &controls, StartConfig *startConfig)
|
||||||
|
|
||||||
controller_.switchMode(mode_, &metadata);
|
controller_.switchMode(mode_, &metadata);
|
||||||
|
|
||||||
|
/* Reset the frame lengths queue state. */
|
||||||
|
lastTimeout_ = 0s;
|
||||||
|
frameLengths_.clear();
|
||||||
|
frameLengths_.resize(FrameLengthsQueueSize, 0s);
|
||||||
|
|
||||||
/* SwitchMode may supply updated exposure/gain values to use. */
|
/* SwitchMode may supply updated exposure/gain values to use. */
|
||||||
AgcStatus agcStatus;
|
AgcStatus agcStatus;
|
||||||
agcStatus.shutterTime = 0.0s;
|
agcStatus.shutterTime = 0.0s;
|
||||||
|
@ -294,6 +309,7 @@ void IPARPi::start(const ControlList &controls, StartConfig *startConfig)
|
||||||
ControlList ctrls(sensorCtrls_);
|
ControlList ctrls(sensorCtrls_);
|
||||||
applyAGC(&agcStatus, ctrls);
|
applyAGC(&agcStatus, ctrls);
|
||||||
startConfig->controls = std::move(ctrls);
|
startConfig->controls = std::move(ctrls);
|
||||||
|
setCameraTimeoutValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -340,8 +356,6 @@ void IPARPi::start(const ControlList &controls, StartConfig *startConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
startConfig->dropFrameCount = dropFrameCount_;
|
startConfig->dropFrameCount = dropFrameCount_;
|
||||||
const Duration maxSensorFrameDuration = mode_.maxFrameLength * mode_.maxLineLength;
|
|
||||||
setCameraTimeout.emit(maxSensorFrameDuration.get<std::milli>());
|
|
||||||
|
|
||||||
firstStart_ = false;
|
firstStart_ = false;
|
||||||
lastRunTimestamp_ = 0;
|
lastRunTimestamp_ = 0;
|
||||||
|
@ -1434,6 +1448,22 @@ void IPARPi::processStats(unsigned int bufferId, unsigned int ipaContext)
|
||||||
applyAGC(&agcStatus, ctrls);
|
applyAGC(&agcStatus, ctrls);
|
||||||
|
|
||||||
setDelayedControls.emit(ctrls, ipaContext);
|
setDelayedControls.emit(ctrls, ipaContext);
|
||||||
|
setCameraTimeoutValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPARPi::setCameraTimeoutValue()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Take the maximum value of the exposure queue as the camera timeout
|
||||||
|
* value to pass back to the pipeline handler. Only signal if it has changed
|
||||||
|
* from the last set value.
|
||||||
|
*/
|
||||||
|
auto max = std::max_element(frameLengths_.begin(), frameLengths_.end());
|
||||||
|
|
||||||
|
if (*max != lastTimeout_) {
|
||||||
|
setCameraTimeout.emit(max->get<std::milli>());
|
||||||
|
lastTimeout_ = *max;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1522,6 +1552,15 @@ void IPARPi::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls)
|
||||||
*/
|
*/
|
||||||
if (mode_.minLineLength != mode_.maxLineLength)
|
if (mode_.minLineLength != mode_.maxLineLength)
|
||||||
ctrls.set(V4L2_CID_HBLANK, static_cast<int32_t>(hblank));
|
ctrls.set(V4L2_CID_HBLANK, static_cast<int32_t>(hblank));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Store the frame length times in a circular queue, up-to FrameLengthsQueueSize
|
||||||
|
* elements. This will be used to advertise a camera timeout value to the
|
||||||
|
* pipeline handler.
|
||||||
|
*/
|
||||||
|
frameLengths_.pop_front();
|
||||||
|
frameLengths_.push_back(helper_->exposure(vblank + mode_.height,
|
||||||
|
helper_->hblankToLineLength(hblank)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPARPi::applyDG(const struct AgcStatus *dgStatus, ControlList &ctrls)
|
void IPARPi::applyDG(const struct AgcStatus *dgStatus, ControlList &ctrls)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue