[libcamera-devel] [PATCH v5 6/7] pipeline: ipa: raspberrypi: Use IPA cookies

Kieran Bingham kieran.bingham at ideasonboard.com
Tue Nov 8 18:40:34 CET 2022


Quoting Naushir Patuck via libcamera-devel (2022-10-31 11:45:21)
> 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 at raspberrypi.com>
> Reviewed-by: David Plowman <david.plowman at raspberrypi.com>
> Tested-by: David Plowman <david.plowman at raspberrypi.com>

Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>

> ---
>  include/libcamera/ipa/raspberrypi.mojom       |  6 ++-
>  src/ipa/raspberrypi/raspberrypi.cpp           | 42 ++++++++++---------
>  .../pipeline/raspberrypi/raspberrypi.cpp      | 16 ++++---
>  3 files changed, 37 insertions(+), 27 deletions(-)
> 
> diff --git a/include/libcamera/ipa/raspberrypi.mojom b/include/libcamera/ipa/raspberrypi.mojom
> index 40f78d9e3b3f..325d2d855bc0 100644
> --- a/include/libcamera/ipa/raspberrypi.mojom
> +++ b/include/libcamera/ipa/raspberrypi.mojom
> @@ -37,6 +37,8 @@ struct ISPConfig {
>         uint32 bayerBufferId;
>         bool embeddedBufferPresent;
>         libcamera.ControlList controls;
> +       uint32 ipaContext;
> +       uint32 delayContext;
>  };
>  
>  struct IPAConfig {
> @@ -127,7 +129,7 @@ interface IPARPiInterface {
>          */
>         unmapBuffers(array<uint32> ids);
>  
> -       [async] signalStatReady(uint32 bufferId);
> +       [async] signalStatReady(uint32 bufferId, uint32 ipaContext);
>         [async] signalQueueRequest(libcamera.ControlList controls);
>         [async] signalIspPrepare(ISPConfig data);
>  };
> @@ -137,5 +139,5 @@ interface IPARPiEventInterface {
>         runIsp(uint32 bufferId);
>         embeddedComplete(uint32 bufferId);
>         setIspControls(libcamera.ControlList controls);
> -       setDelayedControls(libcamera.ControlList controls);
> +       setDelayedControls(libcamera.ControlList controls, uint32 delayContext);
>  };
> diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp
> index 799a4fe70000..194171a8bc96 100644
> --- a/src/ipa/raspberrypi/raspberrypi.cpp
> +++ b/src/ipa/raspberrypi/raspberrypi.cpp
> @@ -126,7 +126,7 @@ public:
>                       ControlList *controls, IPAConfigResult *result) override;
>         void mapBuffers(const std::vector<IPABuffer> &buffers) 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 signalIspPrepare(const ISPConfig &data) override;
>  
> @@ -137,9 +137,9 @@ private:
>         void queueRequest(const ControlList &controls);
>         void returnEmbeddedBuffer(unsigned int bufferId);
>         void prepareISP(const ISPConfig &data);
> -       void reportMetadata();
> -       void fillDeviceStatus(const ControlList &sensorControls);
> -       void processStats(unsigned int bufferId);
> +       void reportMetadata(unsigned int ipaContext);
> +       void fillDeviceStatus(const ControlList &sensorControls, unsigned int ipaContext);
> +       void processStats(unsigned int bufferId, unsigned int ipaContext);
>         void applyFrameDurations(Duration minFrameDuration, Duration maxFrameDuration);
>         void applyAGC(const struct AgcStatus *agcStatus, 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? */
>                 LOG(IPARPI, Error) << "WARNING: Prepare/Process mismatch!!!";
>         if (processPending_ && frameCount_ > mistrustCount_)
> -               processStats(bufferId);
> +               processStats(bufferId, context);
>  
> -       reportMetadata();
> +       reportMetadata(context);
>  
>         statsMetadataComplete.emit(bufferId & MaskID, libcameraMetadata_);
>  }
> @@ -540,9 +542,9 @@ void IPARPi::signalIspPrepare(const ISPConfig &data)
>         runIsp.emit(data.bayerBufferId & MaskID);
>  }
>  
> -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);
>  
>         /*
> @@ -1009,12 +1011,12 @@ void IPARPi::returnEmbeddedBuffer(unsigned int bufferId)
>  void IPARPi::prepareISP(const ISPConfig &data)
>  {
>         int64_t frameTimestamp = data.controls.get(controls::SensorTimestamp).value_or(0);
> -       RPiController::Metadata lastMetadata;
> -       RPiController::Metadata &rpiMetadata = rpiMetadata_[0];
> +       unsigned int ipaContext = data.ipaContext % rpiMetadata_.size();
> +       RPiController::Metadata &rpiMetadata = rpiMetadata_[ipaContext];
>         Span<uint8_t> embeddedBuffer;
>  
> -       lastMetadata = std::move(rpiMetadata);
> -       fillDeviceStatus(data.controls);
> +       rpiMetadata.clear();
> +       fillDeviceStatus(data.controls, ipaContext);
>  
>         if (data.embeddedBufferPresent) {
>                 /*
> @@ -1046,7 +1048,9 @@ void IPARPi::prepareISP(const ISPConfig &data)
>                  * current frame, or any other bits of metadata that were added
>                  * in helper_->Prepare().
>                  */
> -               rpiMetadata.merge(lastMetadata);
> +               RPiController::Metadata &lastMetadata =
> +                       rpiMetadata_[ipaContext ? ipaContext : rpiMetadata_.size()];
> +               rpiMetadata.mergeCopy(lastMetadata);
>                 processPending_ = false;
>                 return;
>         }
> @@ -1105,7 +1109,7 @@ void IPARPi::prepareISP(const ISPConfig &data)
>                 setIspControls.emit(ctrls);
>  }
>  
> -void IPARPi::fillDeviceStatus(const ControlList &sensorControls)
> +void IPARPi::fillDeviceStatus(const ControlList &sensorControls, unsigned int ipaContext)
>  {
>         DeviceStatus deviceStatus = {};
>  
> @@ -1121,12 +1125,12 @@ void IPARPi::fillDeviceStatus(const ControlList &sensorControls)
>  
>         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);
>         if (it == buffers_.end()) {
> @@ -1145,7 +1149,7 @@ void IPARPi::processStats(unsigned int bufferId)
>                 ControlList ctrls(sensorCtrls_);
>                 applyAGC(&agcStatus, ctrls);
>  
> -               setDelayedControls.emit(ctrls);
> +               setDelayedControls.emit(ctrls, ipaContext);
>         }
>  }
>  
> diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
> index 29626c0ef14e..cae1f7b9aea3 100644
> --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
> +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
> @@ -206,7 +206,7 @@ public:
>         void runIsp(uint32_t bufferId);
>         void embeddedComplete(uint32_t bufferId);
>         void setIspControls(const ControlList &controls);
> -       void setDelayedControls(const ControlList &controls);
> +       void setDelayedControls(const ControlList &controls, uint32_t delayContext);
>         void setSensorControls(ControlList &controls);
>         void unicamTimeout();
>  
> @@ -262,6 +262,7 @@ public:
>         struct BayerFrame {
>                 FrameBuffer *buffer;
>                 ControlList controls;
> +               unsigned int delayContext;
>         };
>  
>         std::queue<BayerFrame> bayerQueue_;
> @@ -1792,9 +1793,9 @@ void RPiCameraData::setIspControls(const ControlList &controls)
>         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";
>         handleState();
>  }
> @@ -1867,13 +1868,13 @@ void RPiCameraData::unicamBufferDequeue(FrameBuffer *buffer)
>                  * Lookup the sensor controls used for this frame sequence from
>                  * 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
>                  * as it does not receive the FrameBuffer object.
>                  */
>                 ctrl.set(controls::SensorTimestamp, buffer->metadata().timestamp);
> -               bayerQueue_.push({ buffer, std::move(ctrl) });
> +               bayerQueue_.push({ buffer, std::move(ctrl), delayContext });
>         } else {
>                 embeddedQueue_.push(buffer);
>         }
> @@ -1923,7 +1924,8 @@ void RPiCameraData::ispOutputDequeue(FrameBuffer *buffer)
>          * application until after the IPA signals so.
>          */
>         if (stream == &isp_[Isp::Stats]) {
> -               ipa_->signalStatReady(ipa::RPi::MaskStats | static_cast<unsigned int>(index));
> +               ipa_->signalStatReady(ipa::RPi::MaskStats | static_cast<unsigned int>(index),
> +                                     requestQueue_.front()->sequence());
>         } else {
>                 /* Any other ISP output can be handed back to the application now. */
>                 handleStreamBuffer(buffer, stream);
> @@ -2168,6 +2170,8 @@ void RPiCameraData::tryRunPipeline()
>         ipa::RPi::ISPConfig ispPrepare;
>         ispPrepare.bayerBufferId = ipa::RPi::MaskBayerData | bayerId;
>         ispPrepare.controls = std::move(bayerFrame.controls);
> +       ispPrepare.ipaContext = request->sequence();
> +       ispPrepare.delayContext = bayerFrame.delayContext;
>  
>         if (embeddedBuffer) {
>                 unsigned int embeddedId = unicam_[Unicam::Embedded].getBufferId(embeddedBuffer);
> -- 
> 2.25.1
>


More information about the libcamera-devel mailing list