pipeline: ipa: raspberrypi: Use IPA cookies

Pass an IPA cookie from the pipeline handler to the IPA and eventually back to
the pipeline handler through the setDelayedControls signal. This cookie is used
to index the RPiController::Metadata object to be used for the frame.

The IPA cookie is then returned from DelayedControls when the frame with the
applied controls has been returned from the sensor, and eventually passed back
to the IPA from the signalIspPrepare signal.

Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
Reviewed-by: David Plowman <david.plowman@raspberrypi.com>
Tested-by: David Plowman <david.plowman@raspberrypi.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
Naushir Patuck 2022-11-15 09:07:54 +00:00 committed by Laurent Pinchart
parent 44cffefd60
commit 546154b134
3 changed files with 37 additions and 27 deletions

View file

@ -29,6 +29,8 @@ struct ISPConfig {
uint32 bayerBufferId; uint32 bayerBufferId;
bool embeddedBufferPresent; bool embeddedBufferPresent;
libcamera.ControlList controls; libcamera.ControlList controls;
uint32 ipaContext;
uint32 delayContext;
}; };
struct IPAConfig { struct IPAConfig {
@ -119,7 +121,7 @@ interface IPARPiInterface {
*/ */
unmapBuffers(array<uint32> ids); unmapBuffers(array<uint32> ids);
[async] signalStatReady(uint32 bufferId); [async] signalStatReady(uint32 bufferId, uint32 ipaContext);
[async] signalQueueRequest(libcamera.ControlList controls); [async] signalQueueRequest(libcamera.ControlList controls);
[async] signalIspPrepare(ISPConfig data); [async] signalIspPrepare(ISPConfig data);
}; };
@ -129,5 +131,5 @@ interface IPARPiEventInterface {
runIsp(uint32 bufferId); runIsp(uint32 bufferId);
embeddedComplete(uint32 bufferId); embeddedComplete(uint32 bufferId);
setIspControls(libcamera.ControlList controls); setIspControls(libcamera.ControlList controls);
setDelayedControls(libcamera.ControlList controls); setDelayedControls(libcamera.ControlList controls, uint32 delayContext);
}; };

View file

@ -126,7 +126,7 @@ public:
ControlList *controls, IPAConfigResult *result) override; ControlList *controls, IPAConfigResult *result) override;
void mapBuffers(const std::vector<IPABuffer> &buffers) override; void mapBuffers(const std::vector<IPABuffer> &buffers) override;
void unmapBuffers(const std::vector<unsigned int> &ids) override; void unmapBuffers(const std::vector<unsigned int> &ids) override;
void signalStatReady(const uint32_t bufferId) override; void signalStatReady(const uint32_t bufferId, uint32_t ipaContext) override;
void signalQueueRequest(const ControlList &controls) override; void signalQueueRequest(const ControlList &controls) override;
void signalIspPrepare(const ISPConfig &data) override; void signalIspPrepare(const ISPConfig &data) override;
@ -137,9 +137,9 @@ private:
void queueRequest(const ControlList &controls); void queueRequest(const ControlList &controls);
void returnEmbeddedBuffer(unsigned int bufferId); void returnEmbeddedBuffer(unsigned int bufferId);
void prepareISP(const ISPConfig &data); void prepareISP(const ISPConfig &data);
void reportMetadata(); void reportMetadata(unsigned int ipaContext);
void fillDeviceStatus(const ControlList &sensorControls); void fillDeviceStatus(const ControlList &sensorControls, unsigned int ipaContext);
void processStats(unsigned int bufferId); void processStats(unsigned int bufferId, unsigned int ipaContext);
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);
@ -509,14 +509,16 @@ void IPARPi::unmapBuffers(const std::vector<unsigned int> &ids)
} }
} }
void IPARPi::signalStatReady(uint32_t bufferId) void IPARPi::signalStatReady(uint32_t bufferId, uint32_t ipaContext)
{ {
unsigned int context = ipaContext % rpiMetadata_.size();
if (++checkCount_ != frameCount_) /* assert here? */ if (++checkCount_ != frameCount_) /* assert here? */
LOG(IPARPI, Error) << "WARNING: Prepare/Process mismatch!!!"; LOG(IPARPI, Error) << "WARNING: Prepare/Process mismatch!!!";
if (processPending_ && frameCount_ > mistrustCount_) if (processPending_ && frameCount_ > mistrustCount_)
processStats(bufferId); processStats(bufferId, context);
reportMetadata(); reportMetadata(context);
statsMetadataComplete.emit(bufferId, libcameraMetadata_); statsMetadataComplete.emit(bufferId, libcameraMetadata_);
} }
@ -540,9 +542,9 @@ void IPARPi::signalIspPrepare(const ISPConfig &data)
runIsp.emit(data.bayerBufferId); runIsp.emit(data.bayerBufferId);
} }
void IPARPi::reportMetadata() void IPARPi::reportMetadata(unsigned int ipaContext)
{ {
RPiController::Metadata &rpiMetadata = rpiMetadata_[0]; RPiController::Metadata &rpiMetadata = rpiMetadata_[ipaContext];
std::unique_lock<RPiController::Metadata> lock(rpiMetadata); std::unique_lock<RPiController::Metadata> lock(rpiMetadata);
/* /*
@ -1011,12 +1013,12 @@ void IPARPi::returnEmbeddedBuffer(unsigned int bufferId)
void IPARPi::prepareISP(const ISPConfig &data) void IPARPi::prepareISP(const ISPConfig &data)
{ {
int64_t frameTimestamp = data.controls.get(controls::SensorTimestamp).value_or(0); int64_t frameTimestamp = data.controls.get(controls::SensorTimestamp).value_or(0);
RPiController::Metadata lastMetadata; unsigned int ipaContext = data.ipaContext % rpiMetadata_.size();
RPiController::Metadata &rpiMetadata = rpiMetadata_[0]; RPiController::Metadata &rpiMetadata = rpiMetadata_[ipaContext];
Span<uint8_t> embeddedBuffer; Span<uint8_t> embeddedBuffer;
lastMetadata = std::move(rpiMetadata); rpiMetadata.clear();
fillDeviceStatus(data.controls); fillDeviceStatus(data.controls, ipaContext);
if (data.embeddedBufferPresent) { if (data.embeddedBufferPresent) {
/* /*
@ -1048,7 +1050,9 @@ void IPARPi::prepareISP(const ISPConfig &data)
* current frame, or any other bits of metadata that were added * current frame, or any other bits of metadata that were added
* in helper_->Prepare(). * in helper_->Prepare().
*/ */
rpiMetadata.merge(lastMetadata); RPiController::Metadata &lastMetadata =
rpiMetadata_[ipaContext ? ipaContext : rpiMetadata_.size()];
rpiMetadata.mergeCopy(lastMetadata);
processPending_ = false; processPending_ = false;
return; return;
} }
@ -1107,7 +1111,7 @@ void IPARPi::prepareISP(const ISPConfig &data)
setIspControls.emit(ctrls); setIspControls.emit(ctrls);
} }
void IPARPi::fillDeviceStatus(const ControlList &sensorControls) void IPARPi::fillDeviceStatus(const ControlList &sensorControls, unsigned int ipaContext)
{ {
DeviceStatus deviceStatus = {}; DeviceStatus deviceStatus = {};
@ -1123,12 +1127,12 @@ void IPARPi::fillDeviceStatus(const ControlList &sensorControls)
LOG(IPARPI, Debug) << "Metadata - " << deviceStatus; LOG(IPARPI, Debug) << "Metadata - " << deviceStatus;
rpiMetadata_[0].set("device.status", deviceStatus); rpiMetadata_[ipaContext].set("device.status", deviceStatus);
} }
void IPARPi::processStats(unsigned int bufferId) void IPARPi::processStats(unsigned int bufferId, unsigned int ipaContext)
{ {
RPiController::Metadata &rpiMetadata = rpiMetadata_[0]; RPiController::Metadata &rpiMetadata = rpiMetadata_[ipaContext];
auto it = buffers_.find(bufferId); auto it = buffers_.find(bufferId);
if (it == buffers_.end()) { if (it == buffers_.end()) {
@ -1147,7 +1151,7 @@ void IPARPi::processStats(unsigned int bufferId)
ControlList ctrls(sensorCtrls_); ControlList ctrls(sensorCtrls_);
applyAGC(&agcStatus, ctrls); applyAGC(&agcStatus, ctrls);
setDelayedControls.emit(ctrls); setDelayedControls.emit(ctrls, ipaContext);
} }
} }

View file

@ -206,7 +206,7 @@ public:
void runIsp(uint32_t bufferId); void runIsp(uint32_t bufferId);
void embeddedComplete(uint32_t bufferId); void embeddedComplete(uint32_t bufferId);
void setIspControls(const ControlList &controls); void setIspControls(const ControlList &controls);
void setDelayedControls(const ControlList &controls); void setDelayedControls(const ControlList &controls, uint32_t delayContext);
void setSensorControls(ControlList &controls); void setSensorControls(ControlList &controls);
void unicamTimeout(); void unicamTimeout();
@ -262,6 +262,7 @@ public:
struct BayerFrame { struct BayerFrame {
FrameBuffer *buffer; FrameBuffer *buffer;
ControlList controls; ControlList controls;
unsigned int delayContext;
}; };
std::queue<BayerFrame> bayerQueue_; std::queue<BayerFrame> bayerQueue_;
@ -1800,9 +1801,9 @@ void RPiCameraData::setIspControls(const ControlList &controls)
handleState(); handleState();
} }
void RPiCameraData::setDelayedControls(const ControlList &controls) void RPiCameraData::setDelayedControls(const ControlList &controls, uint32_t delayContext)
{ {
if (!delayedCtrls_->push(controls, 0)) if (!delayedCtrls_->push(controls, delayContext))
LOG(RPI, Error) << "V4L2 DelayedControl set failed"; LOG(RPI, Error) << "V4L2 DelayedControl set failed";
handleState(); handleState();
} }
@ -1875,13 +1876,13 @@ void RPiCameraData::unicamBufferDequeue(FrameBuffer *buffer)
* Lookup the sensor controls used for this frame sequence from * Lookup the sensor controls used for this frame sequence from
* DelayedControl and queue them along with the frame buffer. * DelayedControl and queue them along with the frame buffer.
*/ */
auto [ctrl, cookie] = delayedCtrls_->get(buffer->metadata().sequence); auto [ctrl, delayContext] = delayedCtrls_->get(buffer->metadata().sequence);
/* /*
* Add the frame timestamp to the ControlList for the IPA to use * Add the frame timestamp to the ControlList for the IPA to use
* as it does not receive the FrameBuffer object. * as it does not receive the FrameBuffer object.
*/ */
ctrl.set(controls::SensorTimestamp, buffer->metadata().timestamp); ctrl.set(controls::SensorTimestamp, buffer->metadata().timestamp);
bayerQueue_.push({ buffer, std::move(ctrl) }); bayerQueue_.push({ buffer, std::move(ctrl), delayContext });
} else { } else {
embeddedQueue_.push(buffer); embeddedQueue_.push(buffer);
} }
@ -1931,7 +1932,8 @@ void RPiCameraData::ispOutputDequeue(FrameBuffer *buffer)
* application until after the IPA signals so. * application until after the IPA signals so.
*/ */
if (stream == &isp_[Isp::Stats]) { if (stream == &isp_[Isp::Stats]) {
ipa_->signalStatReady(RPi::MaskStats | static_cast<unsigned int>(index)); ipa_->signalStatReady(RPi::MaskStats | static_cast<unsigned int>(index),
requestQueue_.front()->sequence());
} else { } else {
/* Any other ISP output can be handed back to the application now. */ /* Any other ISP output can be handed back to the application now. */
handleStreamBuffer(buffer, stream); handleStreamBuffer(buffer, stream);
@ -2176,6 +2178,8 @@ void RPiCameraData::tryRunPipeline()
ipa::RPi::ISPConfig ispPrepare; ipa::RPi::ISPConfig ispPrepare;
ispPrepare.bayerBufferId = RPi::MaskBayerData | bayerId; ispPrepare.bayerBufferId = RPi::MaskBayerData | bayerId;
ispPrepare.controls = std::move(bayerFrame.controls); ispPrepare.controls = std::move(bayerFrame.controls);
ispPrepare.ipaContext = request->sequence();
ispPrepare.delayContext = bayerFrame.delayContext;
if (embeddedBuffer) { if (embeddedBuffer) {
unsigned int embeddedId = unicam_[Unicam::Embedded].getBufferId(embeddedBuffer); unsigned int embeddedId = unicam_[Unicam::Embedded].getBufferId(embeddedBuffer);