@@ -473,10 +473,11 @@ void IPAIPU3::computeParams(const uint32_t frame, const uint32_t bufferId)
*/
params->use = {};
- IPAFrameContext &frameContext = context_.frameContexts.getOrInitContext(frame);
+ IPAFrameContext *frameContext = context_.frameContexts.getOrInitContext(frame);
+ ASSERT(frameContext);
for (const auto &algo : algorithms())
- algo->prepare(context_, frame, frameContext, params);
+ algo->prepare(context_, frame, *frameContext, params);
paramsComputed.emit(frame);
}
@@ -506,15 +507,16 @@ void IPAIPU3::processStats(const uint32_t frame,
const ipu3_uapi_stats_3a *stats =
reinterpret_cast<ipu3_uapi_stats_3a *>(mem.data());
- IPAFrameContext &frameContext = context_.frameContexts.getOrInitContext(frame);
+ IPAFrameContext *frameContext = context_.frameContexts.getOrInitContext(frame);
+ ASSERT(frameContext);
- std::tie(frameContext.sensor.exposure, frameContext.sensor.gain) =
+ std::tie(frameContext->sensor.exposure, frameContext->sensor.gain) =
agc::extractControls(sensorControls, context_.camHelper.get());
ControlList metadata(controls::controls);
for (const auto &algo : algorithms())
- algo->process(context_, frame, frameContext, stats, metadata);
+ algo->process(context_, frame, *frameContext, stats, metadata);
setControls(frame);
@@ -558,11 +560,12 @@ void IPAIPU3::initializeFrameContext(IPAFrameContext &frameContext,
*/
void IPAIPU3::setControls(unsigned int frame)
{
- IPAFrameContext &frameContext = context_.frameContexts.getOrInitContext(frame);
+ IPAFrameContext *frameContext = context_.frameContexts.getOrInitContext(frame);
+ ASSERT(frameContext);
ControlList ctrls(context_.sensorControls);
agc::prepareControls(ctrls, context_.camHelper.get(),
- frameContext.agc.exposure, frameContext.agc.gain);
+ frameContext->agc.exposure, frameContext->agc.gain);
ControlList lensCtrls(lensCtrls_);
lensCtrls.set(V4L2_CID_FOCUS_ABSOLUTE,
@@ -54,7 +54,7 @@ public:
initialized_ = false;
}
- FC &getOrInitContext(unsigned int frame, const ControlList &controls = {})
+ FC *getOrInitContext(unsigned int frame, const ControlList &controls = {})
{
FC &fc = contexts_[frame % contexts_.size()];
FrameContext &frameContext = fc;
@@ -64,23 +64,10 @@ public:
frameContext.frame_ = frame;
initCallback_(fc, controls);
initialized_ = true;
- return fc;
+ return &fc;
}
- /*
- * If the IPA algorithms try to access a frame context slot which
- * has been already overwritten by a newer context, it means the
- * frame context queue has overflowed and the desired context
- * has been forever lost. The pipeline handler shall avoid
- * queueing more requests to the IPA than the frame context
- * queue size.
- */
- if (frame < frameContext.frame_)
- LOG(FCQueue, Fatal) << "Frame context for " << frame
- << " has been overwritten by "
- << frameContext.frame_;
-
- if (frame == frameContext.frame_) {
+ if (frame <= frameContext.frame_) {
if (!controls.empty()) {
/* Too late to apply the controls. Store them for later. */
LOG(FCQueue, Warning)
@@ -89,8 +76,17 @@ public:
controlsToApply_.merge(controls,
ControlList::MergePolicy::OverwriteExisting);
}
+
+ if (frame < frameContext.frame_) {
+ LOG(FCQueue, Warning)
+ << "Frame context for " << frame
+ << " is already overwritten by "
+ << frameContext.frame_;
+ return nullptr;
+ }
+
LOG(FCQueue, Debug) << "Got " << frame;
- return fc;
+ return &fc;
}
const ControlList *controls2 = &controls;
@@ -107,7 +103,7 @@ public:
initCallback_(fc, *controls2);
controlsToApply_.clear();
- return fc;
+ return &fc;
}
private:
@@ -243,11 +243,13 @@ void IPAMaliC55::initializeFrameContext(IPAFrameContext &frameContext,
void IPAMaliC55::fillParams(unsigned int request,
[[maybe_unused]] uint32_t bufferId)
{
- IPAFrameContext &frameContext = context_.frameContexts.getOrInitContext(request);
+ IPAFrameContext *frameContext = context_.frameContexts.getOrInitContext(request);
MaliC55Params params(buffers_.at(bufferId).planes()[0]);
+ ASSERT(frameContext);
+
for (const auto &algo : algorithms())
- algo->prepare(context_, request, frameContext, ¶ms);
+ algo->prepare(context_, request, *frameContext, ¶ms);
paramsComputed.emit(request, params.bytesused());
}
@@ -255,13 +257,15 @@ void IPAMaliC55::fillParams(unsigned int request,
void IPAMaliC55::processStats(unsigned int request, unsigned int bufferId,
const ControlList &sensorControls)
{
- IPAFrameContext &frameContext = context_.frameContexts.getOrInitContext(request);
+ IPAFrameContext *frameContext = context_.frameContexts.getOrInitContext(request);
const mali_c55_stats_buffer *stats = nullptr;
+ ASSERT(frameContext);
+
stats = reinterpret_cast<mali_c55_stats_buffer *>(
buffers_.at(bufferId).planes()[0].data());
- std::tie(frameContext.sensor.exposure, frameContext.sensor.gain) =
+ std::tie(frameContext->sensor.exposure, frameContext->sensor.gain) =
agc::extractControls(sensorControls, context_.camHelper.get());
ControlList metadata(controls::controls);
@@ -269,10 +273,10 @@ void IPAMaliC55::processStats(unsigned int request, unsigned int bufferId,
for (const auto &a : algorithms()) {
Algorithm *algo = static_cast<Algorithm *>(a.get());
- algo->process(context_, request, frameContext, stats, metadata);
+ algo->process(context_, request, *frameContext, stats, metadata);
}
- setControls(frameContext);
+ setControls(*frameContext);
statsProcessed.emit(request, metadata);
}
@@ -216,15 +216,16 @@ int IPARkISP1::init(const IPASettings &settings, unsigned int hwRevision,
void IPARkISP1::start(const ControlList &controls, const uint32_t paramBufferId,
StartResult *result)
{
- IPAFrameContext &frameContext = context_.frameContexts.getOrInitContext(0, controls);
+ IPAFrameContext *frameContext = context_.frameContexts.getOrInitContext(0, controls);
+ ASSERT(frameContext);
if (paramBufferId != 0)
- result->paramBufferBytesUsed = computeParamsInternal(frameContext,
+ result->paramBufferBytesUsed = computeParamsInternal(*frameContext,
paramBufferId);
else
result->paramBufferBytesUsed = 0;
- result->controls = getSensorControls(frameContext);
+ result->controls = getSensorControls(*frameContext);
result->code = 0;
}
@@ -336,21 +337,23 @@ uint32_t IPARkISP1::computeParamsInternal(IPAFrameContext &frameContext, const u
void IPARkISP1::computeParams(const uint32_t frame, const uint32_t bufferId)
{
- IPAFrameContext &frameContext = context_.frameContexts.getOrInitContext(frame);
+ IPAFrameContext *frameContext = context_.frameContexts.getOrInitContext(frame);
+ ASSERT(frameContext);
if (bufferId != 0) {
- uint32_t size = computeParamsInternal(frameContext, bufferId);
+ uint32_t size = computeParamsInternal(*frameContext, bufferId);
paramsComputed.emit(frame, bufferId, size);
}
- ControlList ctrls = getSensorControls(frameContext);
+ ControlList ctrls = getSensorControls(*frameContext);
setSensorControls.emit(frame, ctrls);
}
void IPARkISP1::processStats(const uint32_t frame, const uint32_t bufferId,
const ControlList &sensorControls)
{
- IPAFrameContext &frameContext = context_.frameContexts.getOrInitContext(frame);
+ IPAFrameContext *frameContext = context_.frameContexts.getOrInitContext(frame);
+ ASSERT(frameContext);
/*
* In raw capture mode, the ISP is bypassed and no statistics buffer is
@@ -361,7 +364,7 @@ void IPARkISP1::processStats(const uint32_t frame, const uint32_t bufferId,
stats = reinterpret_cast<rkisp1_stat_buffer *>(
mappedBuffers_.at(bufferId).planes()[0].data());
- std::tie(frameContext.sensor.exposure, frameContext.sensor.gain) =
+ std::tie(frameContext->sensor.exposure, frameContext->sensor.gain) =
agc::extractControls(sensorControls, context_.camHelper.get());
ControlList metadata(controls::controls);
@@ -370,7 +373,7 @@ void IPARkISP1::processStats(const uint32_t frame, const uint32_t bufferId,
Algorithm *algo = static_cast<Algorithm *>(a.get());
if (algo->disabled_)
continue;
- algo->process(context_, frame, frameContext, stats, metadata);
+ algo->process(context_, frame, *frameContext, stats, metadata);
}
context_.debugMetadata.moveEntries(metadata);
@@ -237,9 +237,11 @@ void IPASoftIsp::computeParams(const uint32_t frame)
{
context_.activeState.combinedMatrix = Matrix<float, 3, 3>::identity();
- IPAFrameContext &frameContext = context_.frameContexts.getOrInitContext(frame);
+ IPAFrameContext *frameContext = context_.frameContexts.getOrInitContext(frame);
+ ASSERT(frameContext);
+
for (const auto &algo : algorithms())
- algo->prepare(context_, frame, frameContext, params_);
+ algo->prepare(context_, frame, *frameContext, params_);
params_->combinedMatrix = context_.activeState.combinedMatrix;
paramsComputed.emit(frame);
@@ -249,19 +251,20 @@ void IPASoftIsp::processStats(const uint32_t frame,
[[maybe_unused]] const uint32_t bufferId,
const ControlList &sensorControls)
{
- IPAFrameContext &frameContext = context_.frameContexts.getOrInitContext(frame);
+ IPAFrameContext *frameContext = context_.frameContexts.getOrInitContext(frame);
+ ASSERT(frameContext);
- std::tie(frameContext.sensor.exposure, frameContext.sensor.gain) =
+ std::tie(frameContext->sensor.exposure, frameContext->sensor.gain) =
agc::extractControls(sensorControls, context_.camHelper.get());
ControlList metadata(controls::controls);
for (const auto &algo : algorithms())
- algo->process(context_, frame, frameContext, stats_, metadata);
+ algo->process(context_, frame, *frameContext, stats_, metadata);
metadataReady.emit(frame, metadata);
ControlList ctrls(context_.sensorControls);
agc::prepareControls(ctrls, context_.camHelper.get(),
- frameContext.agc.exposure, frameContext.agc.gain);
+ frameContext->agc.exposure, frameContext->agc.gain);
setSensorControls.emit(ctrls);
}
If a requested frame context in the FCQueue was overwritten, libcamera crashes with a fatal log message. This condition occurs in rare cases with very high system load or in multi camera setups where the main camera thread is blocked by e.g. starting a seond camera for a considerable amount of time. Still we sould not crash in these cases. To be able to handle the situation in upcoming patches, modify getOrInitContext() to return a pointer instead of a reference and return a nullptr instead of the fatal log. Add an ASSERT() to all callers so that we still crash in these cases. More fine grained handling needs to be implemented later. Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com> --- src/ipa/ipu3/ipu3.cpp | 17 ++++++++++------- src/ipa/libipa/fc_queue.h | 32 ++++++++++++++------------------ src/ipa/mali-c55/mali-c55.cpp | 16 ++++++++++------ src/ipa/rkisp1/rkisp1.cpp | 21 ++++++++++++--------- src/ipa/softisp/softisp.cpp | 15 +++++++++------ 5 files changed, 55 insertions(+), 46 deletions(-)