[libcamera-devel] [PATCH v5 17/23] libcamera: pipeline, ipa: raspberrypi: Use new data definition

Paul Elder paul.elder at ideasonboard.com
Sat Dec 5 11:31:00 CET 2020


Now that we can generate custom functions and data structures with mojo,
switch the raspberrypi pipeline handler and IPA to use the custom data
structures as defined in the mojom data definition file.

Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>

---
Changes in v5:
- minor fixes
- use new struct names

Changes in v4:
- rename Controls to controls
- use the renamed header (raspberrypi_ipa_interface.h)

Changes in v3:
- use ipa::rpi namespace
- rebase on the RPi namespace patch series newly merged into master

Changes in v2:
- rebased on "libcamera: pipeline: ipa: raspberrypi: Rework drop frame
  signalling"
- use newly customized RPi IPA interface
---
 include/libcamera/ipa/raspberrypi.h           |  41 ++--
 src/ipa/raspberrypi/raspberrypi.cpp           | 158 ++++++--------
 .../pipeline/raspberrypi/raspberrypi.cpp      | 193 +++++++++---------
 3 files changed, 182 insertions(+), 210 deletions(-)

diff --git a/include/libcamera/ipa/raspberrypi.h b/include/libcamera/ipa/raspberrypi.h
index df30b4a2..e145de3f 100644
--- a/include/libcamera/ipa/raspberrypi.h
+++ b/include/libcamera/ipa/raspberrypi.h
@@ -28,24 +28,29 @@ enum BufferMask {
 static constexpr unsigned int MaxLsGridSize = 32 << 10;
 
 /* List of controls handled by the Raspberry Pi IPA */
-static const ControlInfoMap Controls = {
-	{ &controls::AeEnable, ControlInfo(false, true) },
-	{ &controls::ExposureTime, ControlInfo(0, 999999) },
-	{ &controls::AnalogueGain, ControlInfo(1.0f, 32.0f) },
-	{ &controls::AeMeteringMode, ControlInfo(controls::AeMeteringModeValues) },
-	{ &controls::AeConstraintMode, ControlInfo(controls::AeConstraintModeValues) },
-	{ &controls::AeExposureMode, ControlInfo(controls::AeExposureModeValues) },
-	{ &controls::ExposureValue, ControlInfo(0.0f, 16.0f) },
-	{ &controls::AwbEnable, ControlInfo(false, true) },
-	{ &controls::ColourGains, ControlInfo(0.0f, 32.0f) },
-	{ &controls::AwbMode, ControlInfo(controls::AwbModeValues) },
-	{ &controls::Brightness, ControlInfo(-1.0f, 1.0f) },
-	{ &controls::Contrast, ControlInfo(0.0f, 32.0f) },
-	{ &controls::Saturation, ControlInfo(0.0f, 32.0f) },
-	{ &controls::Sharpness, ControlInfo(0.0f, 16.0f, 1.0f) },
-	{ &controls::ColourCorrectionMatrix, ControlInfo(-16.0f, 16.0f) },
-	{ &controls::ScalerCrop, ControlInfo(Rectangle{}, Rectangle(65535, 65535, 65535, 65535), Rectangle{}) },
-};
+static ControlInfoMap controls;
+
+inline void initializeRPiControls()
+{
+	controls = {
+		{ &controls::AeEnable, ControlInfo(false, true) },
+		{ &controls::ExposureTime, ControlInfo(0, 999999) },
+		{ &controls::AnalogueGain, ControlInfo(1.0f, 32.0f) },
+		{ &controls::AeMeteringMode, ControlInfo(controls::AeMeteringModeValues) },
+		{ &controls::AeConstraintMode, ControlInfo(controls::AeConstraintModeValues) },
+		{ &controls::AeExposureMode, ControlInfo(controls::AeExposureModeValues) },
+		{ &controls::ExposureValue, ControlInfo(0.0f, 16.0f) },
+		{ &controls::AwbEnable, ControlInfo(false, true) },
+		{ &controls::ColourGains, ControlInfo(0.0f, 32.0f) },
+		{ &controls::AwbMode, ControlInfo(controls::AwbModeValues) },
+		{ &controls::Brightness, ControlInfo(-1.0f, 1.0f) },
+		{ &controls::Contrast, ControlInfo(0.0f, 32.0f) },
+		{ &controls::Saturation, ControlInfo(0.0f, 32.0f) },
+		{ &controls::Sharpness, ControlInfo(0.0f, 16.0f, 1.0f) },
+		{ &controls::ColourCorrectionMatrix, ControlInfo(-16.0f, 16.0f) },
+		{ &controls::ScalerCrop, ControlInfo(Rectangle{}, Rectangle(65535, 65535, 65535, 65535), Rectangle{}) },
+	};
+}
 
 } /* namespace RPi */
 
diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp
index 4dc02dc8..29e4854e 100644
--- a/src/ipa/raspberrypi/raspberrypi.cpp
+++ b/src/ipa/raspberrypi/raspberrypi.cpp
@@ -19,6 +19,7 @@
 #include <libcamera/ipa/ipa_interface.h>
 #include <libcamera/ipa/ipa_module_info.h>
 #include <libcamera/ipa/raspberrypi.h>
+#include <libcamera/ipa/raspberrypi_ipa_interface.h>
 #include <libcamera/request.h>
 #include <libcamera/span.h>
 
@@ -59,7 +60,7 @@ constexpr unsigned int DefaultExposureTime = 20000;
 
 LOG_DEFINE_CATEGORY(IPARPI)
 
-class IPARPi : public IPAInterface
+class IPARPi : public ipa::rpi::IPARPiInterface
 {
 public:
 	IPARPi()
@@ -67,6 +68,7 @@ public:
 		  frameCount_(0), checkCount_(0), mistrustCount_(0),
 		  lsTable_(nullptr)
 	{
+		RPi::initializeRPiControls();
 	}
 
 	~IPARPi()
@@ -81,12 +83,14 @@ public:
 
 	void configure(const CameraSensorInfo &sensorInfo,
 		       const std::map<unsigned int, IPAStream> &streamConfig,
-		       const std::map<unsigned int, const ControlInfoMap &> &entityControls,
-		       const IPAOperationData &data,
-		       IPAOperationData *response) override;
+		       const std::map<unsigned int, ControlInfoMap> &entityControls,
+		       const ipa::rpi::ConfigInput &data,
+		       ipa::rpi::ConfigOutput *response) override;
 	void mapBuffers(const std::vector<IPABuffer> &buffers) override;
 	void unmapBuffers(const std::vector<unsigned int> &ids) override;
-	void processEvent(const IPAOperationData &event) override;
+	void signalStatReady(const uint32_t bufferId) override;
+	void signalQueueRequest(const ControlList &controls) override;
+	void signalIspPrepare(const ipa::rpi::ISPConfig &data) override;
 
 private:
 	void setMode(const CameraSensorInfo &sensorInfo);
@@ -142,6 +146,11 @@ private:
 
 	/* LS table allocation passed in from the pipeline handler. */
 	FileDescriptor lsTableHandle_;
+	/*
+	 * LS table allocation passed in from the pipeline handler,
+	 * in the context of the pipeline handler.
+	 */
+	int32_t lsTableHandlePH_;
 	void *lsTable_;
 };
 
@@ -191,15 +200,13 @@ void IPARPi::setMode(const CameraSensorInfo &sensorInfo)
 
 void IPARPi::configure(const CameraSensorInfo &sensorInfo,
 		       [[maybe_unused]] const std::map<unsigned int, IPAStream> &streamConfig,
-		       const std::map<unsigned int, const ControlInfoMap &> &entityControls,
-		       const IPAOperationData &ipaConfig,
-		       IPAOperationData *result)
+		       const std::map<unsigned int, ControlInfoMap> &entityControls,
+		       const ipa::rpi::ConfigInput &ipaConfig,
+		       ipa::rpi::ConfigOutput *result)
 {
 	if (entityControls.empty())
 		return;
 
-	result->operation = 0;
-
 	unicamCtrls_ = entityControls.at(0);
 	ispCtrls_ = entityControls.at(1);
 
@@ -223,32 +230,28 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,
 		helper_->GetDelays(exposureDelay, gainDelay);
 		sensorMetadata = helper_->SensorEmbeddedDataPresent();
 
-		result->data.push_back(gainDelay);
-		result->data.push_back(exposureDelay);
-		result->data.push_back(sensorMetadata);
-
-		result->operation |= RPi::IPA_CONFIG_STAGGERED_WRITE;
+		result->op_ |= ipa::rpi::ConfigStaggeredWrite;
+		result->sensorConfig_.gainDelay_ = gainDelay;
+		result->sensorConfig_.exposureDelay_ = exposureDelay;
+		result->sensorConfig_.sensorMetadata_ = sensorMetadata;
 	}
 
 	/* Re-assemble camera mode using the sensor info. */
 	setMode(sensorInfo);
 
-	/*
-	 * The ipaConfig.data always gives us the user transform first. Note that
-	 * this will always make the LS table pointer (if present) element 1.
-	 */
-	mode_.transform = static_cast<libcamera::Transform>(ipaConfig.data[0]);
+	mode_.transform = static_cast<libcamera::Transform>(ipaConfig.transform_);
 
 	/* Store the lens shading table pointer and handle if available. */
-	if (ipaConfig.operation & RPi::IPA_CONFIG_LS_TABLE) {
+	if (ipaConfig.op_ & ipa::rpi::ConfigLsTable) {
 		/* Remove any previous table, if there was one. */
 		if (lsTable_) {
 			munmap(lsTable_, RPi::MaxLsGridSize);
 			lsTable_ = nullptr;
 		}
 
-		/* Map the LS table buffer into user space (now element 1). */
-		lsTableHandle_ = FileDescriptor(ipaConfig.data[1]);
+		/* Map the LS table buffer into user space. */
+		lsTableHandle_ = FileDescriptor(ipaConfig.lsTableHandle_);
+		lsTableHandlePH_ = ipaConfig.lsTableHandleStatic_;
 		if (lsTableHandle_.isValid()) {
 			lsTable_ = mmap(nullptr, RPi::MaxLsGridSize, PROT_READ | PROT_WRITE,
 					MAP_SHARED, lsTableHandle_.fd(), 0);
@@ -270,18 +273,15 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,
 	 */
 	frameCount_ = 0;
 	checkCount_ = 0;
-	unsigned int dropFrame = 0;
+	result->op_ |= ipa::rpi::ConfigDropFrames;
 	if (controllerInit_) {
-		dropFrame = helper_->HideFramesModeSwitch();
+		result->dropFrameCount_ = helper_->HideFramesModeSwitch();
 		mistrustCount_ = helper_->MistrustFramesModeSwitch();
 	} else {
-		dropFrame = helper_->HideFramesStartup();
+		result->dropFrameCount_ = helper_->HideFramesStartup();
 		mistrustCount_ = helper_->MistrustFramesStartup();
 	}
 
-	result->data.push_back(dropFrame);
-	result->operation |= RPi::IPA_CONFIG_DROP_FRAMES;
-
 	/* These zero values mean not program anything (unless overwritten). */
 	struct AgcStatus agcStatus;
 	agcStatus.shutter_time = 0.0;
@@ -306,9 +306,9 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,
 	if (agcStatus.shutter_time != 0.0 && agcStatus.analogue_gain != 0.0) {
 		ControlList ctrls(unicamCtrls_);
 		applyAGC(&agcStatus, ctrls);
-		result->controls.push_back(ctrls);
 
-		result->operation |= RPi::IPA_CONFIG_SENSOR;
+		result->op_ |= ipa::rpi::ConfigSensor;
+		result->controls_ = std::move(ctrls);
 	}
 
 	lastMode_ = mode_;
@@ -333,56 +333,38 @@ void IPARPi::unmapBuffers(const std::vector<unsigned int> &ids)
 	}
 }
 
-void IPARPi::processEvent(const IPAOperationData &event)
+void IPARPi::signalStatReady(const uint32_t bufferId)
 {
-	switch (event.operation) {
-	case RPi::IPA_EVENT_SIGNAL_STAT_READY: {
-		unsigned int bufferId = event.data[0];
-
-		if (++checkCount_ != frameCount_) /* assert here? */
-			LOG(IPARPI, Error) << "WARNING: Prepare/Process mismatch!!!";
-		if (frameCount_ > mistrustCount_)
-			processStats(bufferId);
-
-		reportMetadata();
-
-		IPAOperationData op;
-		op.operation = RPi::IPA_ACTION_STATS_METADATA_COMPLETE;
-		op.data = { bufferId & RPi::BufferMask::ID };
-		op.controls = { libcameraMetadata_ };
-		queueFrameAction.emit(0, op);
-		break;
-	}
+	if (++checkCount_ != frameCount_) /* assert here? */
+		LOG(IPARPI, Error) << "WARNING: Prepare/Process mismatch!!!";
+	if (frameCount_ > mistrustCount_)
+		processStats(bufferId);
 
-	case RPi::IPA_EVENT_SIGNAL_ISP_PREPARE: {
-		unsigned int embeddedbufferId = event.data[0];
-		unsigned int bayerbufferId = event.data[1];
+	reportMetadata();
 
-		/*
-		 * At start-up, or after a mode-switch, we may want to
-		 * avoid running the control algos for a few frames in case
-		 * they are "unreliable".
-		 */
-		prepareISP(embeddedbufferId);
-		frameCount_++;
-
-		/* Ready to push the input buffer into the ISP. */
-		IPAOperationData op;
-		op.operation = RPi::IPA_ACTION_RUN_ISP;
-		op.data = { bayerbufferId & RPi::BufferMask::ID };
-		queueFrameAction.emit(0, op);
-		break;
-	}
+	statsMetadataComplete.emit(bufferId & RPi::BufferMask::ID, libcameraMetadata_);
+}
 
-	case RPi::IPA_EVENT_QUEUE_REQUEST: {
-		queueRequest(event.controls[0]);
-		break;
-	}
+void IPARPi::signalQueueRequest(const ControlList &controls)
+{
+	queueRequest(controls);
+}
 
-	default:
-		LOG(IPARPI, Error) << "Unknown event " << event.operation;
-		break;
-	}
+void IPARPi::signalIspPrepare(const ipa::rpi::ISPConfig &data)
+{
+	unsigned int embeddedbufferId = data.embeddedbufferId_;
+	unsigned int bayerbufferId = data.bayerbufferId_;
+
+	/*
+	 * At start-up, or after a mode-switch, we may want to
+	 * avoid running the control algos for a few frames in case
+	 * they are "unreliable".
+	 */
+	prepareISP(embeddedbufferId);
+	frameCount_++;
+
+	/* Ready to push the input buffer into the ISP. */
+	runIsp.emit(bayerbufferId & RPi::BufferMask::ID);
 }
 
 void IPARPi::reportMetadata()
@@ -693,10 +675,7 @@ void IPARPi::queueRequest(const ControlList &controls)
 
 void IPARPi::returnEmbeddedBuffer(unsigned int bufferId)
 {
-	IPAOperationData op;
-	op.operation = RPi::IPA_ACTION_EMBEDDED_COMPLETE;
-	op.data = { bufferId & RPi::BufferMask::ID };
-	queueFrameAction.emit(0, op);
+	embeddedComplete.emit(bufferId & RPi::BufferMask::ID);
 }
 
 void IPARPi::prepareISP(unsigned int bufferId)
@@ -757,12 +736,8 @@ void IPARPi::prepareISP(unsigned int bufferId)
 		if (dpcStatus)
 			applyDPC(dpcStatus, ctrls);
 
-		if (!ctrls.empty()) {
-			IPAOperationData op;
-			op.operation = RPi::IPA_ACTION_V4L2_SET_ISP;
-			op.controls.push_back(ctrls);
-			queueFrameAction.emit(0, op);
-		}
+		if (!ctrls.empty())
+			setIsp.emit(ctrls);
 	}
 }
 
@@ -819,10 +794,7 @@ void IPARPi::processStats(unsigned int bufferId)
 		ControlList ctrls(unicamCtrls_);
 		applyAGC(&agcStatus, ctrls);
 
-		IPAOperationData op;
-		op.operation = RPi::IPA_ACTION_V4L2_SET_STAGGERED;
-		op.controls.push_back(ctrls);
-		queueFrameAction.emit(0, op);
+		setStaggered.emit(ctrls);
 	}
 }
 
@@ -1052,7 +1024,7 @@ void IPARPi::applyLS(const struct AlscStatus *lsStatus, ControlList &ctrls)
 		.grid_width = w,
 		.grid_stride = w,
 		.grid_height = h,
-		.dmabuf = lsTableHandle_.fd(),
+		.dmabuf = lsTableHandlePH_,
 		.ref_transform = 0,
 		.corner_sampled = 1,
 		.gain_format = GAIN_FORMAT_U4P10
@@ -1129,9 +1101,9 @@ const struct IPAModuleInfo ipaModuleInfo = {
 	"raspberrypi",
 };
 
-struct ipa_context *ipaCreate()
+IPAInterface *ipaCreate()
 {
-	return new IPAInterfaceWrapper(std::make_unique<IPARPi>());
+	return new IPARPi();
 }
 
 } /* extern "C" */
diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
index 6fcdf557..f11c4112 100644
--- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
+++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
@@ -17,6 +17,8 @@
 #include <libcamera/file_descriptor.h>
 #include <libcamera/formats.h>
 #include <libcamera/ipa/raspberrypi.h>
+#include <libcamera/ipa/raspberrypi_ipa_interface.h>
+#include <libcamera/ipa/raspberrypi_ipa_proxy.h>
 #include <libcamera/logging.h>
 #include <libcamera/property_ids.h>
 #include <libcamera/request.h>
@@ -145,7 +147,11 @@ public:
 	int loadIPA();
 	int configureIPA(const CameraConfiguration *config);
 
-	void queueFrameAction(unsigned int frame, const IPAOperationData &action);
+	void statsMetadataComplete(uint32_t bufferId, const ControlList &controls);
+	void runIsp(uint32_t bufferId);
+	void embeddedComplete(uint32_t bufferId);
+	void setIsp(const ControlList &controls);
+	void setStaggered(const ControlList &controls);
 
 	/* bufferComplete signal handlers. */
 	void unicamBufferDequeue(FrameBuffer *buffer);
@@ -157,6 +163,8 @@ public:
 	void handleExternalBuffer(FrameBuffer *buffer, RPi::Stream *stream);
 	void handleState();
 
+	std::unique_ptr<ipa::rpi::IPAProxyRPi> ipa_;
+
 	CameraSensor *sensor_;
 	/* Array of Unicam and ISP device streams and associated buffers/streams. */
 	RPi::Device<Unicam, 2> unicam_;
@@ -453,6 +461,7 @@ CameraConfiguration::Status RPiCameraConfiguration::validate()
 PipelineHandlerRPi::PipelineHandlerRPi(CameraManager *manager)
 	: PipelineHandler(manager), unicam_(nullptr), isp_(nullptr)
 {
+	RPi::initializeRPiControls();
 }
 
 CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,
@@ -941,7 +950,7 @@ bool PipelineHandlerRPi::match(DeviceEnumerator *enumerator)
 	}
 
 	/* Register the controls that the Raspberry Pi IPA can handle. */
-	data->controlInfo_ = RPi::Controls;
+	data->controlInfo_ = RPi::controls;
 	/* Initialize the camera properties. */
 	data->properties_ = data->sensor_->properties();
 
@@ -1127,11 +1136,16 @@ void RPiCameraData::frameStarted(uint32_t sequence)
 
 int RPiCameraData::loadIPA()
 {
-	ipa_ = IPAManager::createIPA(pipe_, 1, 1);
+	ipa_ = IPAManager::createIPA<ipa::rpi::IPAProxyRPi>(pipe_, 1, 1);
+
 	if (!ipa_)
 		return -ENOENT;
 
-	ipa_->queueFrameAction.connect(this, &RPiCameraData::queueFrameAction);
+	ipa_->statsMetadataComplete.connect(this, &RPiCameraData::statsMetadataComplete);
+	ipa_->runIsp.connect(this, &RPiCameraData::runIsp);
+	ipa_->embeddedComplete.connect(this, &RPiCameraData::embeddedComplete);
+	ipa_->setIsp.connect(this, &RPiCameraData::setIsp);
+	ipa_->setStaggered.connect(this, &RPiCameraData::setStaggered);
 
 	IPASettings settings{
 		.configurationFile = ipa_->configurationFile(sensor_->model() + ".json")
@@ -1147,8 +1161,8 @@ int RPiCameraData::configureIPA(const CameraConfiguration *config)
 		static_cast<const RPiCameraConfiguration *>(config);
 
 	std::map<unsigned int, IPAStream> streamConfig;
-	std::map<unsigned int, const ControlInfoMap &> entityControls;
-	IPAOperationData ipaConfig = {};
+	std::map<unsigned int, ControlInfoMap> entityControls;
+	ipa::rpi::ConfigInput ipaConfig;
 
 	/* Get the device format to pass to the IPA. */
 	V4L2DeviceFormat sensorFormat;
@@ -1168,7 +1182,7 @@ int RPiCameraData::configureIPA(const CameraConfiguration *config)
 	entityControls.emplace(1, isp_[Isp::Input].dev()->controls());
 
 	/* Always send the user transform to the IPA. */
-	ipaConfig.data = { static_cast<unsigned int>(config->transform) };
+	ipaConfig.transform_ = static_cast<unsigned int>(config->transform);
 
 	/* Allocate the lens shading table via dmaHeap and pass to the IPA. */
 	if (!lsTable_.isValid()) {
@@ -1177,8 +1191,9 @@ int RPiCameraData::configureIPA(const CameraConfiguration *config)
 			return -ENOMEM;
 
 		/* Allow the IPA to mmap the LS table via the file descriptor. */
-		ipaConfig.operation = RPi::IPA_CONFIG_LS_TABLE;
-		ipaConfig.data.push_back(static_cast<unsigned int>(lsTable_.fd()));
+		ipaConfig.op_ |= ipa::rpi::ConfigLsTable;
+		ipaConfig.lsTableHandle_ = lsTable_;
+		ipaConfig.lsTableHandleStatic_ = lsTable_.fd();
 	}
 
 	/* We store the CameraSensorInfo for digital zoom calculations. */
@@ -1189,34 +1204,35 @@ int RPiCameraData::configureIPA(const CameraConfiguration *config)
 	}
 
 	/* Ready the IPA - it must know about the sensor resolution. */
-	IPAOperationData result;
+	ipa::rpi::ConfigOutput result;
 
 	ipa_->configure(sensorInfo_, streamConfig, entityControls, ipaConfig,
 			&result);
 
-	unsigned int resultIdx = 0;
-	if (result.operation & RPi::IPA_CONFIG_STAGGERED_WRITE) {
+	if (result.op_ & ipa::rpi::ConfigStaggeredWrite) {
 		/*
 		 * Setup our staggered control writer with the sensor default
 		 * gain and exposure delays.
 		 */
 		if (!staggeredCtrl_) {
 			staggeredCtrl_.init(unicam_[Unicam::Image].dev(),
-					    { { V4L2_CID_ANALOGUE_GAIN, result.data[resultIdx++] },
-					      { V4L2_CID_EXPOSURE, result.data[resultIdx++] } });
-			sensorMetadata_ = result.data[resultIdx++];
+					    { { V4L2_CID_ANALOGUE_GAIN,
+						result.sensorConfig_.gainDelay_ },
+					      { V4L2_CID_EXPOSURE,
+						result.sensorConfig_.exposureDelay_ } });
+			sensorMetadata_ = result.sensorConfig_.sensorMetadata_;
 		}
 	}
 
-	if (result.operation & RPi::IPA_CONFIG_SENSOR) {
-		const ControlList &ctrls = result.controls[0];
+	if (result.op_ & ipa::rpi::ConfigSensor) {
+		const ControlList &ctrls = result.controls_;
 		if (!staggeredCtrl_.set(ctrls))
 			LOG(RPI, Error) << "V4L2 staggered set failed";
 	}
 
-	if (result.operation & RPi::IPA_CONFIG_DROP_FRAMES) {
+	if (result.op_ & ipa::rpi::ConfigDropFrames) {
 		/* Configure the number of dropped frames required on startup. */
-		dropFrameCount_ = result.data[resultIdx++];
+		dropFrameCount_ = result.dropFrameCount_;
 	}
 
 	/*
@@ -1235,90 +1251,75 @@ int RPiCameraData::configureIPA(const CameraConfiguration *config)
 	return 0;
 }
 
-void RPiCameraData::queueFrameAction([[maybe_unused]] unsigned int frame,
-				     const IPAOperationData &action)
+void RPiCameraData::statsMetadataComplete(uint32_t bufferId, const ControlList &controls)
 {
-	/*
-	 * The following actions can be handled when the pipeline handler is in
-	 * a stopped state.
-	 */
-	switch (action.operation) {
-	case RPi::IPA_ACTION_V4L2_SET_STAGGERED: {
-		const ControlList &controls = action.controls[0];
-		if (!staggeredCtrl_.set(controls))
-			LOG(RPI, Error) << "V4L2 staggered set failed";
-		goto done;
-	}
+	if (state_ == State::Stopped)
+		handleState();
 
-	case RPi::IPA_ACTION_V4L2_SET_ISP: {
-		ControlList controls = action.controls[0];
-		isp_[Isp::Input].dev()->setControls(&controls);
-		goto done;
-	}
-	}
+	FrameBuffer *buffer = isp_[Isp::Stats].getBuffers().at(bufferId);
 
-	if (state_ == State::Stopped)
-		goto done;
+	handleStreamBuffer(buffer, &isp_[Isp::Stats]);
+
+	/* Fill the Request metadata buffer with what the IPA has provided */
+	Request *request = requestQueue_.front();
+	request->metadata() = std::move(controls);
 
 	/*
-	 * The following actions must not be handled when the pipeline handler
-	 * is in a stopped state.
+	 * Also update the ScalerCrop in the metadata with what we actually
+	 * used. But we must first rescale that from ISP (camera mode) pixels
+	 * back into sensor native pixels.
+	 *
+	 * Sending this information on every frame may be helpful.
 	 */
-	switch (action.operation) {
-	case RPi::IPA_ACTION_STATS_METADATA_COMPLETE: {
-		unsigned int bufferId = action.data[0];
-		FrameBuffer *buffer = isp_[Isp::Stats].getBuffers().at(bufferId);
+	if (updateScalerCrop_) {
+		updateScalerCrop_ = false;
+		scalerCrop_ = ispCrop_.scaledBy(sensorInfo_.analogCrop.size(),
+						sensorInfo_.outputSize);
+		scalerCrop_.translateBy(sensorInfo_.analogCrop.topLeft());
+	}
+	request->metadata().set(controls::ScalerCrop, scalerCrop_);
 
-		handleStreamBuffer(buffer, &isp_[Isp::Stats]);
+	state_ = State::IpaComplete;
 
-		/* Fill the Request metadata buffer with what the IPA has provided */
-		Request *request = requestQueue_.front();
-		request->metadata() = std::move(action.controls[0]);
+	handleState();
+}
 
-		/*
-		 * Also update the ScalerCrop in the metadata with what we actually
-		 * used. But we must first rescale that from ISP (camera mode) pixels
-		 * back into sensor native pixels.
-		 *
-		 * Sending this information on every frame may be helpful.
-		 */
-		if (updateScalerCrop_) {
-			updateScalerCrop_ = false;
-			scalerCrop_ = ispCrop_.scaledBy(sensorInfo_.analogCrop.size(),
-							sensorInfo_.outputSize);
-			scalerCrop_.translateBy(sensorInfo_.analogCrop.topLeft());
-		}
-		request->metadata().set(controls::ScalerCrop, scalerCrop_);
+void RPiCameraData::runIsp(uint32_t bufferId)
+{
+	if (state_ == State::Stopped)
+		handleState();
 
-		state_ = State::IpaComplete;
-		break;
-	}
+	FrameBuffer *buffer = unicam_[Unicam::Image].getBuffers().at(bufferId);
 
-	case RPi::IPA_ACTION_EMBEDDED_COMPLETE: {
-		unsigned int bufferId = action.data[0];
-		FrameBuffer *buffer = unicam_[Unicam::Embedded].getBuffers().at(bufferId);
-		handleStreamBuffer(buffer, &unicam_[Unicam::Embedded]);
-		break;
-	}
+	LOG(RPI, Debug) << "Input re-queue to ISP, buffer id " << bufferId
+			<< ", timestamp: " << buffer->metadata().timestamp;
 
-	case RPi::IPA_ACTION_RUN_ISP: {
-		unsigned int bufferId = action.data[0];
-		FrameBuffer *buffer = unicam_[Unicam::Image].getBuffers().at(bufferId);
+	isp_[Isp::Input].queueBuffer(buffer);
+	ispOutputCount_ = 0;
+	handleState();
+}
 
-		LOG(RPI, Debug) << "Input re-queue to ISP, buffer id " << bufferId
-				<< ", timestamp: " << buffer->metadata().timestamp;
+void RPiCameraData::embeddedComplete(uint32_t bufferId)
+{
+	if (state_ == State::Stopped)
+		handleState();
 
-		isp_[Isp::Input].queueBuffer(buffer);
-		ispOutputCount_ = 0;
-		break;
-	}
+	FrameBuffer *buffer = unicam_[Unicam::Embedded].getBuffers().at(bufferId);
+	handleStreamBuffer(buffer, &unicam_[Unicam::Embedded]);
+	handleState();
+}
 
-	default:
-		LOG(RPI, Error) << "Unknown action " << action.operation;
-		break;
-	}
+void RPiCameraData::setIsp(const ControlList &controls)
+{
+	ControlList ctrls = controls;
+	isp_[Isp::Input].dev()->setControls(&ctrls);
+	handleState();
+}
 
-done:
+void RPiCameraData::setStaggered(const ControlList &controls)
+{
+	if (!staggeredCtrl_.set(controls))
+		LOG(RPI, Error) << "V4L2 staggered set failed";
 	handleState();
 }
 
@@ -1420,10 +1421,7 @@ void RPiCameraData::ispOutputDequeue(FrameBuffer *buffer)
 	 * application until after the IPA signals so.
 	 */
 	if (stream == &isp_[Isp::Stats]) {
-		IPAOperationData op;
-		op.operation = RPi::IPA_EVENT_SIGNAL_STAT_READY;
-		op.data = { RPi::BufferMask::STATS | static_cast<unsigned int>(index) };
-		ipa_->processEvent(op);
+		ipa_->signalStatReady(RPi::BufferMask::STATS | static_cast<unsigned int>(index));
 	} else {
 		/* Any other ISP output can be handed back to the application now. */
 		handleStreamBuffer(buffer, stream);
@@ -1595,7 +1593,6 @@ void RPiCameraData::checkRequestCompleted()
 void RPiCameraData::tryRunPipeline()
 {
 	FrameBuffer *bayerBuffer, *embeddedBuffer;
-	IPAOperationData op;
 
 	/* If any of our request or buffer queues are empty, we cannot proceed. */
 	if (state_ != State::Idle || requestQueue_.empty() ||
@@ -1642,9 +1639,7 @@ void RPiCameraData::tryRunPipeline()
 	 * queue the ISP output buffer listed in the request to start the HW
 	 * pipeline.
 	 */
-	op.operation = RPi::IPA_EVENT_QUEUE_REQUEST;
-	op.controls = { request->controls() };
-	ipa_->processEvent(op);
+	ipa_->signalQueueRequest(request->controls());
 
 	/* Set our state to say the pipeline is active. */
 	state_ = State::Busy;
@@ -1656,10 +1651,10 @@ void RPiCameraData::tryRunPipeline()
 			<< " Bayer buffer id: " << bayerId
 			<< " Embedded buffer id: " << embeddedId;
 
-	op.operation = RPi::IPA_EVENT_SIGNAL_ISP_PREPARE;
-	op.data = { RPi::BufferMask::EMBEDDED_DATA | embeddedId,
-		    RPi::BufferMask::BAYER_DATA | bayerId };
-	ipa_->processEvent(op);
+	ipa::rpi::ISPConfig ispPrepare;
+	ispPrepare.embeddedbufferId_ = RPi::BufferMask::EMBEDDED_DATA | embeddedId;
+	ispPrepare.bayerbufferId_ = RPi::BufferMask::BAYER_DATA | bayerId;
+	ipa_->signalIspPrepare(ispPrepare);
 }
 
 bool RPiCameraData::findMatchingBuffers(FrameBuffer *&bayerBuffer, FrameBuffer *&embeddedBuffer)
-- 
2.27.0



More information about the libcamera-devel mailing list