[libcamera-devel,v5,6/7] pipeline: ipa: raspberrypi: Use IPA cookies
diff mbox series

Message ID 20221031114522.14215-7-naush@raspberrypi.com
State Superseded
Headers show
Series
  • Raspberry Pi AGC digital gain fixes
Related show

Commit Message

Naushir Patuck Oct. 31, 2022, 11:45 a.m. UTC
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>
---
 include/libcamera/ipa/raspberrypi.mojom       |  6 ++-
 src/ipa/raspberrypi/raspberrypi.cpp           | 42 ++++++++++---------
 .../pipeline/raspberrypi/raspberrypi.cpp      | 16 ++++---
 3 files changed, 37 insertions(+), 27 deletions(-)

Comments

Kieran Bingham Nov. 8, 2022, 5:40 p.m. UTC | #1
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@raspberrypi.com>
> Reviewed-by: David Plowman <david.plowman@raspberrypi.com>
> Tested-by: David Plowman <david.plowman@raspberrypi.com>

Reviewed-by: Kieran Bingham <kieran.bingham@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
>

Patch
diff mbox series

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);