@@ -65,7 +65,7 @@ struct IPASessionConfiguration {
double minAnalogueGain;
double maxAnalogueGain;
- int32_t defVBlank;
+ unsigned int vBlank;
utils::Duration lineDuration;
Size size;
} sensor;
@@ -250,7 +250,7 @@ int IPARkISP1::configure(const IPAConfigInfo &ipaConfig,
const IPACameraSensorInfo &info = ipaConfig.sensorInfo;
const ControlInfo vBlank = sensorControls_.find(V4L2_CID_VBLANK)->second;
- context_.configuration.sensor.defVBlank = vBlank.def().get<int32_t>();
+ context_.configuration.sensor.vBlank = vBlank.def().get<int32_t>();
context_.configuration.sensor.size = info.outputSize;
context_.configuration.sensor.lineDuration = info.minLineLength * 1.0s / info.pixelRate;
@@ -261,8 +261,6 @@ int IPARkISP1::configure(const IPAConfigInfo &ipaConfig,
* When the AGC computes the new exposure values for a frame, it needs
* to know the limits for exposure time and analogue gain. As it depends
* on the sensor, update it with the controls.
- *
- * \todo take VBLANK into account for maximum exposure time
*/
context_.configuration.sensor.minExposureTime =
minExposure * context_.configuration.sensor.lineDuration;
@@ -457,6 +455,33 @@ void IPARkISP1::setControls(unsigned int frame)
uint32_t gain = context_.camHelper->gainCode(frameContext.agc.gain);
uint32_t vblank = frameContext.agc.vblank;
+ /*
+ * Update the exposure limits if vblank has changed. Even if the controls
+ * will actually be applied to the sensor with some frames of latency
+ * by DelayedControls, all the algorithms calculations from now on should
+ * use the new limits.
+ *
+ * \todo Sensors usually have a margin that limits the max exposure to
+ * be shorter by the full frame length:
+ *
+ * (max_exposure_lines = height + vblank - margin)
+ *
+ * As the margin is a sensor-specific parameter either:
+ * - Ignore the margin and rely on the driver clamping the exposure
+ * value correctly
+ * - Defer to the sensor helpers by creating an exposure() function that
+ * subtract the margin from the frame length
+ *
+ * For the time being ignore the margins and rely on the driver doing
+ * the adjustment.
+ */
+ if (vblank != context_.configuration.sensor.vBlank) {
+ context_.configuration.sensor.vBlank = vblank;
+ context_.configuration.sensor.maxExposureTime =
+ (vblank + context_.configuration.sensor.size.height) *
+ context_.configuration.sensor.lineDuration;
+ }
+
LOG(IPARkISP1, Debug)
<< "Set controls for frame " << frame << ": exposure " << exposure
<< ", gain " << frameContext.agc.gain << ", vblank " << vblank;
The AGC algorithm implementation of the RkISP1 IPA is implemented deriving the generic AgcMeanLuminance class, which limits the achievable exposure time using a maxExposureTime parameter provided by the IPA module. The RkISP1 IPA fetches the maxExposureTime value from the IPAContext sensor.maxExposureTime value, which is initialized at IPA init() and configure() time, but never updated later on, effectively limiting the achievable exposure time to the frame duration programmed at startup time. Whenever the frame duration is changed, the maximum exposure time should change accordingly, but in the current implementation this doesn't happen. Fix this by updating the sensor.maxExposureTime value when a new set of controls is sent to the pipeline handler. Store the current VBLANK value in the IPAContext by replacing 'defVBlank' which is never used and use it to detect changes in the blanking value. Whenever the blanking changes, update the maximum exposure limit accordingly. As reported in a comment in the code, even if the new sensor controls will be programmed in the sensor with a delay of a few frames on the pipeline handler side, the limits for the algorithms should be updated immediately. Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> --- src/ipa/rkisp1/ipa_context.h | 2 +- src/ipa/rkisp1/rkisp1.cpp | 31 ++++++++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 4 deletions(-)