[libcamera-devel] [PATCH v7 04/12] libcamera: IPAInterface: Replace C API with the new C++-only API

Paul Elder paul.elder at ideasonboard.com
Thu Feb 11 08:18:38 CET 2021


Remove everything related to the C API, including ipa_context,
ipa_context_wrapper, and IPAInterfaceWrapper. Also remove relevant
documentation.

ipaCreate() provided by IPA implementations, and createInterface()
provided by IPAModule (wrapper around IPA implementation) both now
return a C++ object IPAInterface instead of struct ipa_context.

Although IPAInterfaceWrapper is the only component of libipa, the
skeleton and build files for libipa are retained.

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

---
No change in v7

Changes in v6:
- remove definitions and documentation for IPASettings, IPAStream,
  IPABuffer, and IPAOperationData, as the first three are moved to
  mojom, and the last is simply superseded

Squashed in v5
- change some words, remove some outdated points
- don't remove libipa, only remove IPAInterfaceWrapper
  - as a result, libipa is now empty
- update IPAInterface documentation
  - add todo on how to generate documentation for the new IPAInterface
    implementations

No change in v4

No change in v3

Changes in v2:
- add documentation for IPAModule::createInterface()

---

This is a combination of 6 commits:

---

libcamera: IPAModule: Replace ipa_context with IPAInterface

With the new IPC infrastructure, we no longer need the C interface as
provided by struct ipa_context. Make ipaCreate_() and createInterface()
return IPAInterface.

Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>
Reviewed-by: Jacopo Mondi <jacopo at jmondi.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>

---

libcamera: ipa_context_wrapper: Remove ipa_context_wrapper

Since ipa_context has been replaced with custom IPAInterfaces, it is not
longer needed. Remove it.

Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>
Reviewed-by: Jacopo Mondi <jacopo at jmondi.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>

---

libcamera: IPAInterface: remove ipa_context and functions from documentation

Remove all the documentation related to ipa_context and the C IPA API,
as well as the documentation about the functions in the IPAInterface.

Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>
Reviewed-by: Jacopo Mondi <jacopo at jmondi.org>

---

libcamera: IPAInterface: Remove all functions from IPAInterface

Now that all the functions in the IPA interface are defined in the data
definition file and a specialized IPAInterface is generated per pipeline
handler, remove all the functions from the base IPAInterface.

Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>
Reviewed-by: Jacopo Mondi <jacopo at jmondi.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>

---

libcamera: IPAInterface: make ipaCreate return IPAInterface

With the new IPC infrastructure, we no longer need the C interface as
provided by struct ipa_context. Make ipaCreate return IPAinterface.

Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo at jmondi.org>

---

ipa: remove IPAInterfaceWrapper

As every pipeline has its own proxy, IPAInterfaceWrapper is no
longer necessary. Remove it.

Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>
Acked-by: Jacopo Mondi <jacopo at jmondi.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>

Used to be "ipa: remove libipa"
---
 .../libcamera/internal/ipa_context_wrapper.h  |  53 --
 include/libcamera/internal/ipa_module.h       |   4 +-
 include/libcamera/internal/meson.build        |   1 -
 include/libcamera/ipa/ipa_interface.h         | 147 +---
 src/ipa/ipu3/ipu3.cpp                         |   2 -
 src/ipa/libipa/ipa_interface_wrapper.cpp      | 287 --------
 src/ipa/libipa/ipa_interface_wrapper.h        |  61 --
 src/ipa/libipa/meson.build                    |   2 -
 src/ipa/raspberrypi/raspberrypi.cpp           |   2 -
 src/ipa/rkisp1/rkisp1.cpp                     |   2 -
 src/ipa/vimc/vimc.cpp                         |   2 -
 src/libcamera/ipa_context_wrapper.cpp         | 298 --------
 src/libcamera/ipa_interface.cpp               | 650 +-----------------
 src/libcamera/ipa_module.cpp                  |  18 +-
 src/libcamera/meson.build                     |   1 -
 15 files changed, 48 insertions(+), 1482 deletions(-)
 delete mode 100644 include/libcamera/internal/ipa_context_wrapper.h
 delete mode 100644 src/ipa/libipa/ipa_interface_wrapper.cpp
 delete mode 100644 src/ipa/libipa/ipa_interface_wrapper.h
 delete mode 100644 src/libcamera/ipa_context_wrapper.cpp

diff --git a/include/libcamera/internal/ipa_context_wrapper.h b/include/libcamera/internal/ipa_context_wrapper.h
deleted file mode 100644
index ec27e48e..00000000
--- a/include/libcamera/internal/ipa_context_wrapper.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2019, Google Inc.
- *
- * ipa_context_wrapper.h - Image Processing Algorithm context wrapper
- */
-#ifndef __LIBCAMERA_INTERNAL_IPA_CONTEXT_WRAPPER_H__
-#define __LIBCAMERA_INTERNAL_IPA_CONTEXT_WRAPPER_H__
-
-#include <libcamera/ipa/ipa_interface.h>
-
-#include "libcamera/internal/control_serializer.h"
-
-namespace libcamera {
-
-class IPAContextWrapper final : public IPAInterface
-{
-public:
-	IPAContextWrapper(struct ipa_context *context);
-	~IPAContextWrapper();
-
-	int init(const IPASettings &settings) override;
-	int start(const IPAOperationData &data,
-		  IPAOperationData *result) override;
-	void stop() override;
-	void configure(const CameraSensorInfo &sensorInfo,
-		       const std::map<unsigned int, IPAStream> &streamConfig,
-		       const std::map<unsigned int, const ControlInfoMap &> &entityControls,
-		       const IPAOperationData &ipaConfig,
-		       IPAOperationData *result) override;
-
-	void mapBuffers(const std::vector<IPABuffer> &buffers) override;
-	void unmapBuffers(const std::vector<unsigned int> &ids) override;
-
-	virtual void processEvent(const IPAOperationData &data) override;
-
-private:
-	static void queue_frame_action(void *ctx, unsigned int frame,
-				       struct ipa_operation_data &data);
-	static const struct ipa_callback_ops callbacks_;
-
-	void doQueueFrameAction(unsigned int frame,
-				const IPAOperationData &data);
-
-	struct ipa_context *ctx_;
-	IPAInterface *intf_;
-
-	ControlSerializer serializer_;
-};
-
-} /* namespace libcamera */
-
-#endif /* __LIBCAMERA_INTERNAL_IPA_CONTEXT_WRAPPER_H__ */
diff --git a/include/libcamera/internal/ipa_module.h b/include/libcamera/internal/ipa_module.h
index c2df2476..19fc5827 100644
--- a/include/libcamera/internal/ipa_module.h
+++ b/include/libcamera/internal/ipa_module.h
@@ -33,7 +33,7 @@ public:
 
 	bool load();
 
-	struct ipa_context *createContext();
+	IPAInterface *createInterface();
 
 	bool match(PipelineHandler *pipe,
 		   uint32_t minVersion, uint32_t maxVersion) const;
@@ -52,7 +52,7 @@ private:
 	bool loaded_;
 
 	void *dlHandle_;
-	typedef struct ipa_context *(*IPAIntfFactory)();
+	typedef IPAInterface *(*IPAIntfFactory)(void);
 	IPAIntfFactory ipaCreate_;
 };
 
diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build
index e67a359f..62d3967d 100644
--- a/include/libcamera/internal/meson.build
+++ b/include/libcamera/internal/meson.build
@@ -26,7 +26,6 @@ libcamera_internal_headers = files([
     'event_notifier.h',
     'file.h',
     'formats.h',
-    'ipa_context_wrapper.h',
     'ipa_manager.h',
     'ipa_module.h',
     'ipa_proxy.h',
diff --git a/include/libcamera/ipa/ipa_interface.h b/include/libcamera/ipa/ipa_interface.h
index df12f9ce..47f81d1d 100644
--- a/include/libcamera/ipa/ipa_interface.h
+++ b/include/libcamera/ipa/ipa_interface.h
@@ -10,111 +10,6 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct ipa_context {
-	const struct ipa_context_ops *ops;
-};
-
-struct ipa_settings {
-	const char *configuration_file;
-};
-
-struct ipa_sensor_info {
-	const char *model;
-	uint8_t bits_per_pixel;
-	struct {
-		uint32_t width;
-		uint32_t height;
-	} active_area;
-	struct {
-		int32_t left;
-		int32_t top;
-		uint32_t width;
-		uint32_t height;
-	} analog_crop;
-	struct {
-		uint32_t width;
-		uint32_t height;
-	} output_size;
-	uint64_t pixel_rate;
-	uint32_t line_length;
-};
-
-struct ipa_stream {
-	unsigned int id;
-	unsigned int pixel_format;
-	unsigned int width;
-	unsigned int height;
-};
-
-struct ipa_control_info_map {
-	unsigned int id;
-	const uint8_t *data;
-	size_t size;
-};
-
-struct ipa_buffer_plane {
-	int dmabuf;
-	size_t length;
-};
-
-struct ipa_buffer {
-	unsigned int id;
-	unsigned int num_planes;
-	struct ipa_buffer_plane planes[3];
-};
-
-struct ipa_control_list {
-	const uint8_t *data;
-	unsigned int size;
-};
-
-struct ipa_operation_data {
-	unsigned int operation;
-	const uint32_t *data;
-	unsigned int num_data;
-	const struct ipa_control_list *lists;
-	unsigned int num_lists;
-};
-
-struct ipa_callback_ops {
-	void (*queue_frame_action)(void *cb_ctx, unsigned int frame,
-				   struct ipa_operation_data &data);
-};
-
-struct ipa_context_ops {
-	void (*destroy)(struct ipa_context *ctx);
-	void *(*get_interface)(struct ipa_context *ctx);
-	void (*init)(struct ipa_context *ctx,
-		     const struct ipa_settings *settings);
-	int (*start)(struct ipa_context *ctx);
-	void (*stop)(struct ipa_context *ctx);
-	void (*register_callbacks)(struct ipa_context *ctx,
-				   const struct ipa_callback_ops *callbacks,
-				   void *cb_ctx);
-	void (*configure)(struct ipa_context *ctx,
-			  const struct ipa_sensor_info *sensor_info,
-			  const struct ipa_stream *streams,
-			  unsigned int num_streams,
-			  const struct ipa_control_info_map *maps,
-			  unsigned int num_maps);
-	void (*map_buffers)(struct ipa_context *ctx,
-			    const struct ipa_buffer *buffers,
-			    size_t num_buffers);
-	void (*unmap_buffers)(struct ipa_context *ctx, const unsigned int *ids,
-			      size_t num_buffers);
-	void (*process_event)(struct ipa_context *ctx,
-			      const struct ipa_operation_data *data);
-};
-
-struct ipa_context *ipaCreate();
-
-#ifdef __cplusplus
-}
-
 #include <map>
 #include <vector>
 
@@ -125,52 +20,18 @@ struct ipa_context *ipaCreate();
 
 namespace libcamera {
 
-struct IPASettings {
-	std::string configurationFile;
-};
-
-struct IPAStream {
-	unsigned int pixelFormat;
-	Size size;
-};
-
-struct IPABuffer {
-	unsigned int id;
-	std::vector<FrameBuffer::Plane> planes;
-};
-
-struct IPAOperationData {
-	unsigned int operation;
-	std::vector<uint32_t> data;
-	std::vector<ControlList> controls;
-};
-
 struct CameraSensorInfo;
 
 class IPAInterface
 {
 public:
 	virtual ~IPAInterface() = default;
-
-	virtual int init(const IPASettings &settings) = 0;
-	virtual int start(const IPAOperationData &data,
-			  IPAOperationData *result) = 0;
-	virtual void stop() = 0;
-
-	virtual void configure(const CameraSensorInfo &sensorInfo,
-			       const std::map<unsigned int, IPAStream> &streamConfig,
-			       const std::map<unsigned int, const ControlInfoMap &> &entityControls,
-			       const IPAOperationData &ipaConfig,
-			       IPAOperationData *result) = 0;
-
-	virtual void mapBuffers(const std::vector<IPABuffer> &buffers) = 0;
-	virtual void unmapBuffers(const std::vector<unsigned int> &ids) = 0;
-
-	virtual void processEvent(const IPAOperationData &data) = 0;
-	Signal<unsigned int, const IPAOperationData &> queueFrameAction;
 };
 
 } /* namespace libcamera */
-#endif
+
+extern "C" {
+libcamera::IPAInterface *ipaCreate();
+}
 
 #endif /* __LIBCAMERA_IPA_INTERFACE_H__ */
diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp
index b11b03ef..d5bde223 100644
--- a/src/ipa/ipu3/ipu3.cpp
+++ b/src/ipa/ipu3/ipu3.cpp
@@ -19,8 +19,6 @@
 #include <libcamera/ipa/ipa_module_info.h>
 #include <libcamera/request.h>
 
-#include <libipa/ipa_interface_wrapper.h>
-
 #include "libcamera/internal/buffer.h"
 #include "libcamera/internal/log.h"
 
diff --git a/src/ipa/libipa/ipa_interface_wrapper.cpp b/src/ipa/libipa/ipa_interface_wrapper.cpp
deleted file mode 100644
index 40628489..00000000
--- a/src/ipa/libipa/ipa_interface_wrapper.cpp
+++ /dev/null
@@ -1,287 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2019, Google Inc.
- *
- * ipa_interface_wrapper.cpp - Image Processing Algorithm interface wrapper
- */
-
-#include "ipa_interface_wrapper.h"
-
-#include <map>
-#include <string.h>
-#include <unistd.h>
-#include <vector>
-
-#include <libcamera/ipa/ipa_interface.h>
-
-#include "libcamera/internal/byte_stream_buffer.h"
-#include "libcamera/internal/camera_sensor.h"
-
-/**
- * \file ipa_interface_wrapper.h
- * \brief Image Processing Algorithm interface wrapper
- */
-
-namespace libcamera {
-
-/**
- * \class IPAInterfaceWrapper
- * \brief Wrap an IPAInterface and expose it as an ipa_context
- *
- * This class implements the ipa_context API based on a provided IPAInterface.
- * It helps IPAs that implement the IPAInterface API to provide the external
- * ipa_context API.
- *
- * To use the wrapper, an IPA module simple creates a new instance of its
- * IPAInterface implementation, and passes it to the constructor of the
- * IPAInterfaceWrapper. As IPAInterfaceWrapper inherits from ipa_context, the
- * constructed wrapper can then be directly returned from the IPA module's
- * ipaCreate() function.
- *
- * \code{.cpp}
- * class MyIPA : public IPAInterface
- * {
- * 	...
- * };
- *
- * struct ipa_context *ipaCreate()
- * {
- * 	return new IPAInterfaceWrapper(std::make_unique<MyIPA>());
- * }
- * \endcode
- *
- * The wrapper takes ownership of the IPAInterface and will automatically
- * delete it when the wrapper is destroyed.
- */
-
-/**
- * \brief Construct an IPAInterfaceWrapper wrapping \a interface
- * \param[in] interface The interface to wrap
- */
-IPAInterfaceWrapper::IPAInterfaceWrapper(std::unique_ptr<IPAInterface> interface)
-	: ipa_(std::move(interface)), callbacks_(nullptr), cb_ctx_(nullptr)
-{
-	ops = &operations_;
-
-	ipa_->queueFrameAction.connect(this, &IPAInterfaceWrapper::queueFrameAction);
-}
-
-void IPAInterfaceWrapper::destroy(struct ipa_context *_ctx)
-{
-	IPAInterfaceWrapper *ctx = static_cast<IPAInterfaceWrapper *>(_ctx);
-
-	delete ctx;
-}
-
-void *IPAInterfaceWrapper::get_interface(struct ipa_context *_ctx)
-{
-	IPAInterfaceWrapper *ctx = static_cast<IPAInterfaceWrapper *>(_ctx);
-
-	return ctx->ipa_.get();
-}
-
-void IPAInterfaceWrapper::init(struct ipa_context *_ctx,
-			       const struct ipa_settings *settings)
-{
-	IPAInterfaceWrapper *ctx = static_cast<IPAInterfaceWrapper *>(_ctx);
-
-	IPASettings ipaSettings{
-		.configurationFile = settings->configuration_file
-	};
-	ctx->ipa_->init(ipaSettings);
-}
-
-int IPAInterfaceWrapper::start(struct ipa_context *_ctx)
-{
-	IPAInterfaceWrapper *ctx = static_cast<IPAInterfaceWrapper *>(_ctx);
-
-	/* \todo Translate the data and result. */
-	IPAOperationData data = {};
-	return ctx->ipa_->start(data, nullptr);
-}
-
-void IPAInterfaceWrapper::stop(struct ipa_context *_ctx)
-{
-	IPAInterfaceWrapper *ctx = static_cast<IPAInterfaceWrapper *>(_ctx);
-
-	ctx->ipa_->stop();
-}
-
-void IPAInterfaceWrapper::register_callbacks(struct ipa_context *_ctx,
-					     const struct ipa_callback_ops *callbacks,
-					     void *cb_ctx)
-{
-	IPAInterfaceWrapper *ctx = static_cast<IPAInterfaceWrapper *>(_ctx);
-
-	ctx->callbacks_ = callbacks;
-	ctx->cb_ctx_ = cb_ctx;
-}
-
-void IPAInterfaceWrapper::configure(struct ipa_context *_ctx,
-				    const struct ipa_sensor_info *sensor_info,
-				    const struct ipa_stream *streams,
-				    unsigned int num_streams,
-				    const struct ipa_control_info_map *maps,
-				    unsigned int num_maps)
-{
-	IPAInterfaceWrapper *ctx = static_cast<IPAInterfaceWrapper *>(_ctx);
-
-	ctx->serializer_.reset();
-
-	/* Translate the IPA sensor info. */
-	CameraSensorInfo sensorInfo{};
-	sensorInfo.model = sensor_info->model;
-	sensorInfo.bitsPerPixel = sensor_info->bits_per_pixel;
-	sensorInfo.activeAreaSize = { sensor_info->active_area.width,
-				      sensor_info->active_area.height };
-	sensorInfo.analogCrop = { sensor_info->analog_crop.left,
-				  sensor_info->analog_crop.top,
-				  sensor_info->analog_crop.width,
-				  sensor_info->analog_crop.height };
-	sensorInfo.outputSize = { sensor_info->output_size.width,
-				  sensor_info->output_size.height };
-	sensorInfo.pixelRate = sensor_info->pixel_rate;
-	sensorInfo.lineLength = sensor_info->line_length;
-
-	/* Translate the IPA stream configurations map. */
-	std::map<unsigned int, IPAStream> ipaStreams;
-
-	for (unsigned int i = 0; i < num_streams; ++i) {
-		const struct ipa_stream &stream = streams[i];
-
-		ipaStreams[stream.id] = {
-			stream.pixel_format,
-			Size(stream.width, stream.height),
-		};
-	}
-
-	/* Translate the IPA entity controls map. */
-	std::map<unsigned int, const ControlInfoMap &> entityControls;
-	std::map<unsigned int, ControlInfoMap> infoMaps;
-
-	for (unsigned int i = 0; i < num_maps; ++i) {
-		const struct ipa_control_info_map &ipa_map = maps[i];
-		ByteStreamBuffer byteStream(ipa_map.data, ipa_map.size);
-		unsigned int id = ipa_map.id;
-
-		infoMaps[id] = ctx->serializer_.deserialize<ControlInfoMap>(byteStream);
-		entityControls.emplace(id, infoMaps[id]);
-	}
-
-	/* \todo Translate the ipaConfig and result. */
-	IPAOperationData ipaConfig;
-	ctx->ipa_->configure(sensorInfo, ipaStreams, entityControls, ipaConfig,
-			     nullptr);
-}
-
-void IPAInterfaceWrapper::map_buffers(struct ipa_context *_ctx,
-				      const struct ipa_buffer *_buffers,
-				      size_t num_buffers)
-{
-	IPAInterfaceWrapper *ctx = static_cast<IPAInterfaceWrapper *>(_ctx);
-	std::vector<IPABuffer> buffers(num_buffers);
-
-	for (unsigned int i = 0; i < num_buffers; ++i) {
-		const struct ipa_buffer &_buffer = _buffers[i];
-		IPABuffer &buffer = buffers[i];
-		std::vector<FrameBuffer::Plane> &planes = buffer.planes;
-
-		buffer.id = _buffer.id;
-
-		planes.resize(_buffer.num_planes);
-		for (unsigned int j = 0; j < _buffer.num_planes; ++j) {
-			planes[j].fd = FileDescriptor(_buffer.planes[j].dmabuf);
-			planes[j].length = _buffer.planes[j].length;
-		}
-	}
-
-	ctx->ipa_->mapBuffers(buffers);
-}
-
-void IPAInterfaceWrapper::unmap_buffers(struct ipa_context *_ctx,
-					const unsigned int *_ids,
-					size_t num_buffers)
-{
-	IPAInterfaceWrapper *ctx = static_cast<IPAInterfaceWrapper *>(_ctx);
-	std::vector<unsigned int> ids(_ids, _ids + num_buffers);
-	ctx->ipa_->unmapBuffers(ids);
-}
-
-void IPAInterfaceWrapper::process_event(struct ipa_context *_ctx,
-					const struct ipa_operation_data *data)
-{
-	IPAInterfaceWrapper *ctx = static_cast<IPAInterfaceWrapper *>(_ctx);
-	IPAOperationData opData;
-
-	opData.operation = data->operation;
-
-	opData.data.resize(data->num_data);
-	memcpy(opData.data.data(), data->data,
-	       data->num_data * sizeof(*data->data));
-
-	opData.controls.resize(data->num_lists);
-	for (unsigned int i = 0; i < data->num_lists; ++i) {
-		const struct ipa_control_list *c_list = &data->lists[i];
-		ByteStreamBuffer byteStream(c_list->data, c_list->size);
-		opData.controls[i] = ctx->serializer_.deserialize<ControlList>(byteStream);
-	}
-
-	ctx->ipa_->processEvent(opData);
-}
-
-void IPAInterfaceWrapper::queueFrameAction(unsigned int frame,
-					   const IPAOperationData &data)
-{
-	if (!callbacks_)
-		return;
-
-	struct ipa_operation_data c_data;
-	c_data.operation = data.operation;
-	c_data.data = data.data.data();
-	c_data.num_data = data.data.size();
-
-	struct ipa_control_list control_lists[data.controls.size()];
-	c_data.lists = control_lists;
-	c_data.num_lists = data.controls.size();
-
-	std::size_t listsSize = 0;
-	for (const auto &list : data.controls)
-		listsSize += serializer_.binarySize(list);
-
-	std::vector<uint8_t> binaryData(listsSize);
-	ByteStreamBuffer byteStreamBuffer(binaryData.data(), listsSize);
-
-	unsigned int i = 0;
-	for (const auto &list : data.controls) {
-		struct ipa_control_list &c_list = control_lists[i];
-		c_list.size = serializer_.binarySize(list);
-
-		ByteStreamBuffer b = byteStreamBuffer.carveOut(c_list.size);
-		serializer_.serialize(list, b);
-
-		c_list.data = b.base();
-	}
-
-	callbacks_->queue_frame_action(cb_ctx_, frame, c_data);
-}
-
-#ifndef __DOXYGEN__
-/*
- * This construct confuses Doygen and makes it believe that all members of the
- * operations is a member of IPAInterfaceWrapper. It must thus be hidden.
- */
-const struct ipa_context_ops IPAInterfaceWrapper::operations_ = {
-	.destroy = &IPAInterfaceWrapper::destroy,
-	.get_interface = &IPAInterfaceWrapper::get_interface,
-	.init = &IPAInterfaceWrapper::init,
-	.start = &IPAInterfaceWrapper::start,
-	.stop = &IPAInterfaceWrapper::stop,
-	.register_callbacks = &IPAInterfaceWrapper::register_callbacks,
-	.configure = &IPAInterfaceWrapper::configure,
-	.map_buffers = &IPAInterfaceWrapper::map_buffers,
-	.unmap_buffers = &IPAInterfaceWrapper::unmap_buffers,
-	.process_event = &IPAInterfaceWrapper::process_event,
-};
-#endif
-
-} /* namespace libcamera */
diff --git a/src/ipa/libipa/ipa_interface_wrapper.h b/src/ipa/libipa/ipa_interface_wrapper.h
deleted file mode 100644
index a1c70159..00000000
--- a/src/ipa/libipa/ipa_interface_wrapper.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2019, Google Inc.
- *
- * ipa_interface_wrapper.h - Image Processing Algorithm interface wrapper
- */
-#ifndef __LIBCAMERA_IPA_INTERFACE_WRAPPER_H__
-#define __LIBCAMERA_IPA_INTERFACE_WRAPPER_H__
-
-#include <memory>
-
-#include <libcamera/ipa/ipa_interface.h>
-
-#include "libcamera/internal/control_serializer.h"
-
-namespace libcamera {
-
-class IPAInterfaceWrapper : public ipa_context
-{
-public:
-	IPAInterfaceWrapper(std::unique_ptr<IPAInterface> interface);
-
-private:
-	static void destroy(struct ipa_context *ctx);
-	static void *get_interface(struct ipa_context *ctx);
-	static void init(struct ipa_context *ctx,
-			 const struct ipa_settings *settings);
-	static int start(struct ipa_context *ctx);
-	static void stop(struct ipa_context *ctx);
-	static void register_callbacks(struct ipa_context *ctx,
-				       const struct ipa_callback_ops *callbacks,
-				       void *cb_ctx);
-	static void configure(struct ipa_context *ctx,
-			      const struct ipa_sensor_info *sensor_info,
-			      const struct ipa_stream *streams,
-			      unsigned int num_streams,
-			      const struct ipa_control_info_map *maps,
-			      unsigned int num_maps);
-	static void map_buffers(struct ipa_context *ctx,
-				const struct ipa_buffer *c_buffers,
-				size_t num_buffers);
-	static void unmap_buffers(struct ipa_context *ctx,
-				  const unsigned int *ids,
-				  size_t num_buffers);
-	static void process_event(struct ipa_context *ctx,
-				  const struct ipa_operation_data *data);
-
-	static const struct ipa_context_ops operations_;
-
-	void queueFrameAction(unsigned int frame, const IPAOperationData &data);
-
-	std::unique_ptr<IPAInterface> ipa_;
-	const struct ipa_callback_ops *callbacks_;
-	void *cb_ctx_;
-
-	ControlSerializer serializer_;
-};
-
-} /* namespace libcamera */
-
-#endif /* __LIBCAMERA_IPA_INTERFACE_WRAPPER_H__ */
diff --git a/src/ipa/libipa/meson.build b/src/ipa/libipa/meson.build
index 22626405..b29ef0f4 100644
--- a/src/ipa/libipa/meson.build
+++ b/src/ipa/libipa/meson.build
@@ -1,11 +1,9 @@
 # SPDX-License-Identifier: CC0-1.0
 
 libipa_headers = files([
-    'ipa_interface_wrapper.h',
 ])
 
 libipa_sources = files([
-    'ipa_interface_wrapper.cpp',
 ])
 
 libipa_includes = include_directories('..')
diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp
index ff14cfc4..1ecba1e1 100644
--- a/src/ipa/raspberrypi/raspberrypi.cpp
+++ b/src/ipa/raspberrypi/raspberrypi.cpp
@@ -23,8 +23,6 @@
 #include <libcamera/request.h>
 #include <libcamera/span.h>
 
-#include <libipa/ipa_interface_wrapper.h>
-
 #include "libcamera/internal/buffer.h"
 #include "libcamera/internal/camera_sensor.h"
 #include "libcamera/internal/log.h"
diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp
index 39783abd..f4812d8d 100644
--- a/src/ipa/rkisp1/rkisp1.cpp
+++ b/src/ipa/rkisp1/rkisp1.cpp
@@ -22,8 +22,6 @@
 #include <libcamera/ipa/rkisp1.h>
 #include <libcamera/request.h>
 
-#include <libipa/ipa_interface_wrapper.h>
-
 #include "libcamera/internal/log.h"
 
 namespace libcamera {
diff --git a/src/ipa/vimc/vimc.cpp b/src/ipa/vimc/vimc.cpp
index 074902ee..436a5559 100644
--- a/src/ipa/vimc/vimc.cpp
+++ b/src/ipa/vimc/vimc.cpp
@@ -17,8 +17,6 @@
 #include <libcamera/ipa/ipa_interface.h>
 #include <libcamera/ipa/ipa_module_info.h>
 
-#include <libipa/ipa_interface_wrapper.h>
-
 #include "libcamera/internal/file.h"
 #include "libcamera/internal/log.h"
 
diff --git a/src/libcamera/ipa_context_wrapper.cpp b/src/libcamera/ipa_context_wrapper.cpp
deleted file mode 100644
index 19c44ad8..00000000
--- a/src/libcamera/ipa_context_wrapper.cpp
+++ /dev/null
@@ -1,298 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2019, Google Inc.
- *
- * ipa_context_wrapper.cpp - Image Processing Algorithm context wrapper
- */
-
-#include "libcamera/internal/ipa_context_wrapper.h"
-
-#include <vector>
-
-#include <libcamera/controls.h>
-
-#include "libcamera/internal/byte_stream_buffer.h"
-#include "libcamera/internal/camera_sensor.h"
-#include "libcamera/internal/utils.h"
-
-/**
- * \file ipa_context_wrapper.h
- * \brief Image Processing Algorithm context wrapper
- */
-
-namespace libcamera {
-
-/**
- * \class IPAContextWrapper
- * \brief Wrap an ipa_context and expose it as an IPAInterface
- *
- * The IPAContextWrapper class wraps an ipa_context, provided by an IPA module, and
- * exposes an IPAInterface. This mechanism is used for IPAs that are not
- * isolated in a separate process to allow direct calls from pipeline handler
- * using the IPAInterface API instead of the lower-level ipa_context API.
- *
- * The IPAInterface methods are converted to the ipa_context API by translating
- * all C++ arguments into plain C structures or byte arrays that contain no
- * pointer, as required by the ipa_context API.
- */
-
-/**
- * \brief Construct an IPAContextWrapper instance that wraps the \a context
- * \param[in] context The IPA module context
- *
- * Ownership of the \a context is passed to the IPAContextWrapper. The context remains
- * valid for the whole lifetime of the wrapper and is destroyed automatically
- * with it.
- */
-IPAContextWrapper::IPAContextWrapper(struct ipa_context *context)
-	: ctx_(context), intf_(nullptr)
-{
-	if (!ctx_)
-		return;
-
-	bool forceCApi = !!utils::secure_getenv("LIBCAMERA_IPA_FORCE_C_API");
-
-	if (!forceCApi && ctx_ && ctx_->ops->get_interface) {
-		intf_ = reinterpret_cast<IPAInterface *>(ctx_->ops->get_interface(ctx_));
-		intf_->queueFrameAction.connect(this, &IPAContextWrapper::doQueueFrameAction);
-		return;
-	}
-
-	ctx_->ops->register_callbacks(ctx_, &IPAContextWrapper::callbacks_,
-				      this);
-}
-
-IPAContextWrapper::~IPAContextWrapper()
-{
-	if (!ctx_)
-		return;
-
-	ctx_->ops->destroy(ctx_);
-}
-
-int IPAContextWrapper::init(const IPASettings &settings)
-{
-	if (intf_)
-		return intf_->init(settings);
-
-	if (!ctx_)
-		return 0;
-
-	struct ipa_settings c_settings;
-	c_settings.configuration_file = settings.configurationFile.c_str();
-
-	ctx_->ops->init(ctx_, &c_settings);
-
-	return 0;
-}
-
-int IPAContextWrapper::start(const IPAOperationData &data,
-			     IPAOperationData *result)
-{
-	if (intf_)
-		return intf_->start(data, result);
-
-	if (!ctx_)
-		return 0;
-
-	return ctx_->ops->start(ctx_);
-}
-
-void IPAContextWrapper::stop()
-{
-	if (intf_)
-		return intf_->stop();
-
-	if (!ctx_)
-		return;
-
-	ctx_->ops->stop(ctx_);
-}
-
-void IPAContextWrapper::configure(const CameraSensorInfo &sensorInfo,
-				  const std::map<unsigned int, IPAStream> &streamConfig,
-				  const std::map<unsigned int, const ControlInfoMap &> &entityControls,
-				  const IPAOperationData &ipaConfig,
-				  IPAOperationData *result)
-{
-	if (intf_)
-		return intf_->configure(sensorInfo, streamConfig,
-					entityControls, ipaConfig, result);
-
-	if (!ctx_)
-		return;
-
-	serializer_.reset();
-
-	/* Translate the camera sensor info. */
-	struct ipa_sensor_info sensor_info = {};
-	sensor_info.model = sensorInfo.model.c_str();
-	sensor_info.bits_per_pixel = sensorInfo.bitsPerPixel;
-	sensor_info.active_area.width = sensorInfo.activeAreaSize.width;
-	sensor_info.active_area.height = sensorInfo.activeAreaSize.height;
-	sensor_info.analog_crop.left = sensorInfo.analogCrop.x;
-	sensor_info.analog_crop.top = sensorInfo.analogCrop.y;
-	sensor_info.analog_crop.width = sensorInfo.analogCrop.width;
-	sensor_info.analog_crop.height = sensorInfo.analogCrop.height;
-	sensor_info.output_size.width = sensorInfo.outputSize.width;
-	sensor_info.output_size.height = sensorInfo.outputSize.height;
-	sensor_info.pixel_rate = sensorInfo.pixelRate;
-	sensor_info.line_length = sensorInfo.lineLength;
-
-	/* Translate the IPA stream configurations map. */
-	struct ipa_stream c_streams[streamConfig.size()];
-
-	unsigned int i = 0;
-	for (const auto &stream : streamConfig) {
-		struct ipa_stream *c_stream = &c_streams[i];
-		unsigned int id = stream.first;
-		const IPAStream &ipaStream = stream.second;
-
-		c_stream->id = id;
-		c_stream->pixel_format = ipaStream.pixelFormat;
-		c_stream->width = ipaStream.size.width;
-		c_stream->height = ipaStream.size.height;
-
-		++i;
-	}
-
-	/* Translate the IPA entity controls map. */
-	struct ipa_control_info_map c_info_maps[entityControls.size()];
-	std::vector<std::vector<uint8_t>> data(entityControls.size());
-
-	i = 0;
-	for (const auto &info : entityControls) {
-		struct ipa_control_info_map &c_info_map = c_info_maps[i];
-		unsigned int id = info.first;
-		const ControlInfoMap &infoMap = info.second;
-
-		size_t infoMapSize = serializer_.binarySize(infoMap);
-		data[i].resize(infoMapSize);
-		ByteStreamBuffer byteStream(data[i].data(), data[i].size());
-		serializer_.serialize(infoMap, byteStream);
-
-		c_info_map.id = id;
-		c_info_map.data = byteStream.base();
-		c_info_map.size = byteStream.size();
-
-		++i;
-	}
-
-	/* \todo Translate the ipaConfig and reponse */
-	ctx_->ops->configure(ctx_, &sensor_info, c_streams, streamConfig.size(),
-			     c_info_maps, entityControls.size());
-}
-
-void IPAContextWrapper::mapBuffers(const std::vector<IPABuffer> &buffers)
-{
-	if (intf_)
-		return intf_->mapBuffers(buffers);
-
-	if (!ctx_)
-		return;
-
-	struct ipa_buffer c_buffers[buffers.size()];
-
-	for (unsigned int i = 0; i < buffers.size(); ++i) {
-		struct ipa_buffer &c_buffer = c_buffers[i];
-		const IPABuffer &buffer = buffers[i];
-		const std::vector<FrameBuffer::Plane> &planes = buffer.planes;
-
-		c_buffer.id = buffer.id;
-		c_buffer.num_planes = planes.size();
-
-		for (unsigned int j = 0; j < planes.size(); ++j) {
-			const FrameBuffer::Plane &plane = planes[j];
-			c_buffer.planes[j].dmabuf = plane.fd.fd();
-			c_buffer.planes[j].length = plane.length;
-		}
-	}
-
-	ctx_->ops->map_buffers(ctx_, c_buffers, buffers.size());
-}
-
-void IPAContextWrapper::unmapBuffers(const std::vector<unsigned int> &ids)
-{
-	if (intf_)
-		return intf_->unmapBuffers(ids);
-
-	if (!ctx_)
-		return;
-
-	ctx_->ops->unmap_buffers(ctx_, ids.data(), ids.size());
-}
-
-void IPAContextWrapper::processEvent(const IPAOperationData &data)
-{
-	if (intf_)
-		return intf_->processEvent(data);
-
-	if (!ctx_)
-		return;
-
-	struct ipa_operation_data c_data;
-	c_data.operation = data.operation;
-	c_data.data = data.data.data();
-	c_data.num_data = data.data.size();
-
-	struct ipa_control_list control_lists[data.controls.size()];
-	c_data.lists = control_lists;
-	c_data.num_lists = data.controls.size();
-
-	std::size_t listsSize = 0;
-	for (const auto &list : data.controls)
-		listsSize += serializer_.binarySize(list);
-
-	std::vector<uint8_t> binaryData(listsSize);
-	ByteStreamBuffer byteStreamBuffer(binaryData.data(), listsSize);
-
-	unsigned int i = 0;
-	for (const auto &list : data.controls) {
-		struct ipa_control_list &c_list = control_lists[i];
-		c_list.size = serializer_.binarySize(list);
-		ByteStreamBuffer b = byteStreamBuffer.carveOut(c_list.size);
-
-		serializer_.serialize(list, b);
-
-		c_list.data = b.base();
-	}
-
-	ctx_->ops->process_event(ctx_, &c_data);
-}
-
-void IPAContextWrapper::doQueueFrameAction(unsigned int frame,
-					   const IPAOperationData &data)
-{
-	IPAInterface::queueFrameAction.emit(frame, data);
-}
-
-void IPAContextWrapper::queue_frame_action(void *ctx, unsigned int frame,
-					   struct ipa_operation_data &data)
-{
-	IPAContextWrapper *_this = static_cast<IPAContextWrapper *>(ctx);
-	IPAOperationData opData;
-
-	opData.operation = data.operation;
-	for (unsigned int i = 0; i < data.num_data; ++i)
-		opData.data.push_back(data.data[i]);
-
-	for (unsigned int i = 0; i < data.num_lists; ++i) {
-		const struct ipa_control_list &c_list = data.lists[i];
-		ByteStreamBuffer b(c_list.data, c_list.size);
-		opData.controls.push_back(_this->serializer_.deserialize<ControlList>(b));
-	}
-
-	_this->doQueueFrameAction(frame, opData);
-}
-
-#ifndef __DOXYGEN__
-/*
- * This construct confuses Doxygen and makes it believe that all members of the
- * operations is a member of IPAContextWrapper. It must thus be hidden.
- */
-const struct ipa_callback_ops IPAContextWrapper::callbacks_ = {
-	.queue_frame_action = &IPAContextWrapper::queue_frame_action,
-};
-#endif
-
-} /* namespace libcamera */
diff --git a/src/libcamera/ipa_interface.cpp b/src/libcamera/ipa_interface.cpp
index 5be6f787..f0a6faae 100644
--- a/src/libcamera/ipa_interface.cpp
+++ b/src/libcamera/ipa_interface.cpp
@@ -15,371 +15,51 @@
  * an Image Processing Algorithm (IPA) module. An IPA module is developed for a
  * specific pipeline handler and each pipeline handler may be compatible with
  * multiple IPA implementations, both open and closed source. To support this,
- * libcamera communicates with IPA modules through a standard plain C interface.
+ * libcamera communicates with IPA modules through a per-pipeline C++ interface.
  *
- * IPA modules shall expose a public function named ipaCreate() with the
- * following prototype.
+ * IPA modules shall provide an ipaCreate() function exported as a public C
+ * symbol with the following prototype:
  *
  * \code{.c}
- * struct ipa_context *ipaCreate();
+ * IPAInterface *ipaCreate();
  * \endcode
  *
- * The ipaCreate() function creates an instance of an IPA context, which models
+ * The ipaCreate() function creates an instance of an IPA interface, which models
  * a context of execution for the IPA. IPA modules shall support creating one
  * context per camera, as required by their associated pipeline handler.
  *
- * The IPA module context operations are defined in the struct ipa_context_ops.
- * They model a low-level interface to configure the IPA, notify it of events,
- * and receive IPA actions through callbacks. An IPA module stores a pointer to
- * the operations corresponding to its context in the ipa_context::ops field.
- * That pointer is immutable for the lifetime of the context, and may differ
- * between different contexts created by the same IPA module.
+ * The IPA module interface operations are defined in the mojom file
+ * corresponding to the pipeline handler, in
+ * include/libcamera/ipa/{pipeline_name}.mojom.
  *
- * The IPA interface defines base data types and functions to exchange data. On
- * top of this, each pipeline handler is responsible for defining the set of
- * events and actions used to communicate with their IPA. These are collectively
- * referred to as IPA operations and define the pipeline handler-specific IPA
- * protocol. Each operation defines the data that it carries, and how that data
- * is encoded in the ipa_context_ops functions arguments.
+ * The IPA interface is specific to each pipeline handler. The pipeline handlers
+ * define a set of operations used to communicate with their IPA modules. The
+ * operations, along with the data structures they use, are collectively
+ * referred to as the IPA protocol.
+ *
+ * The IPA protocol is defined using the
+ * <a href="https://chromium.googlesource.com/chromium/src/+/master/mojo/public/tools/bindings/README.md">Mojo interface definition language</a>,
+ * in a Mojo module file stored in include/libcamera/ipa/{pipeline_name}.mojom.
+ * The Mojo module contains two Mojo interfaces: IPAInterface defines the
+ * operations exposed by the IPA and called by the pipeline handler, and
+ * IPAEventInterface defines the events generated by the IPA and received by the
+ * pipeline handler.
  *
  * \todo Add reference to how pipelines shall document their protocol.
  *
  * IPAs can be isolated in a separate process. This implies that arguments to
- * the IPA interface functions may need to be transferred over IPC. All
- * arguments use Plain Old Data types and are documented either in the form of C
- * data types, or as a textual description of byte arrays for types that can't
- * be expressed using C data types (such as arrays of mixed data types). IPA
- * modules can thus use the C API without calling into libcamera to access the
- * data passed to the IPA context operations.
+ * the IPA interface functions may need to be transferred over IPC. An IPA
+ * proxy is auto-generated based on the mojom file, which abstracts away the
+ * (de)serialization from the pipeline handler and the IPA implementation. Thus
+ * any C++ structure that is defined in the mojom file, or the C++ libcamera
+ * objects that are listed in core.mojom, can be used directly.
  *
  * Due to IPC, synchronous communication between pipeline handlers and IPAs can
- * be costly. For that reason, the interface operates asynchronously. This
- * implies that methods don't return a status, and that all methods may copy
- * their arguments.
- *
- * The IPAInterface class is a C++ representation of the ipa_context_ops, using
- * C++ data classes provided by libcamera. This is the API exposed to pipeline
- * handlers to communicate with IPA modules. IPA modules may use the
- * IPAInterface API internally if they want to benefit from the data and helper
- * classes offered by libcamera.
- *
- * When an IPA module is loaded directly into the libcamera process and uses
- * the IPAInterface API internally, short-circuiting the path to the
- * ipa_context_ops and back to IPAInterface is desirable. To support this, IPA
- * modules may implement the ipa_context_ops::get_interface function to return a
- * pointer to their internal IPAInterface.
- */
-
-/**
- * \struct ipa_context
- * \brief IPA module context of execution
- *
- * This structure models a context of execution for an IPA module. It is
- * instantiated by the IPA module ipaCreate() function. IPA modules allocate
- * context instances in an implementation-defined way, contexts shall thus be
- * destroyed using the ipa_operation::destroy function only.
- *
- * The ipa_context structure provides a pointer to the IPA context operations.
- * It shall otherwise be treated as a constant black-box cookie and passed
- * unmodified to the functions defined in struct ipa_context_ops.
- *
- * IPA modules are expected to extend struct ipa_context by inheriting from it,
- * either through structure embedding to model inheritance in plain C, or
- * through C++ class inheritance. A simple example of the latter is available
- * in the IPAContextWrapper class implementation.
- *
- * \var ipa_context::ops
- * \brief The IPA context operations
- */
-
-/**
- * \struct ipa_settings
- * \brief IPA initialization settings for the IPA context operations
- * \sa IPASettings
- *
- * \var ipa_settings::configuration_file
- * \brief The name of the IPA configuration file (may be null or point to an
- * empty string)
- */
-
-/**
- * \struct ipa_sensor_info
- * \brief Camera sensor information for the IPA context operations
- * \sa libcamera::CameraSensorInfo
- *
- * \var ipa_sensor_info::model
- * \brief The camera sensor model name
- * \todo Remove this field as soon as no IPA depends on it anymore
- *
- * \var ipa_sensor_info::bits_per_pixel
- * \brief The camera sensor image format bit depth
- * \sa libcamera::CameraSensorInfo::bitsPerPixel
- *
- * \var ipa_sensor_info::active_area.width
- * \brief The camera sensor pixel array active area width
- * \sa libcamera::CameraSensorInfo::activeAreaSize
- *
- * \var ipa_sensor_info::active_area.height
- * \brief The camera sensor pixel array active area height
- * \sa libcamera::CameraSensorInfo::activeAreaSize
- *
- * \var ipa_sensor_info::active_area
- * \brief The camera sensor pixel array active size
- * \sa libcamera::CameraSensorInfo::activeAreaSize
- *
- * \var ipa_sensor_info::analog_crop.left
- * \brief The left coordinate of the analog crop rectangle, relative to the
- * pixel array active area
- * \sa libcamera::CameraSensorInfo::analogCrop
- *
- * \var ipa_sensor_info::analog_crop.top
- * \brief The top coordinate of the analog crop rectangle, relative to the pixel
- * array active area
- * \sa libcamera::CameraSensorInfo::analogCrop
- *
- * \var ipa_sensor_info::analog_crop.width
- * \brief The horizontal size of the analog crop rectangle
- * \sa libcamera::CameraSensorInfo::analogCrop
- *
- * \var ipa_sensor_info::analog_crop.height
- * \brief The vertical size of the analog crop rectangle
- * \sa libcamera::CameraSensorInfo::analogCrop
- *
- * \var ipa_sensor_info::analog_crop
- * \brief The analog crop rectangle
- * \sa libcamera::CameraSensorInfo::analogCrop
- *
- * \var ipa_sensor_info::output_size.width
- * \brief The horizontal size of the output image
- * \sa libcamera::CameraSensorInfo::outputSize
- *
- * \var ipa_sensor_info::output_size.height
- * \brief The vertical size of the output image
- * \sa libcamera::CameraSensorInfo::outputSize
- *
- * \var ipa_sensor_info::output_size
- * \brief The size of the output image
- * \sa libcamera::CameraSensorInfo::outputSize
- *
- * \var ipa_sensor_info::pixel_rate
- * \brief The number of pixel produced in a second
- * \sa libcamera::CameraSensorInfo::pixelRate
- *
- * \var ipa_sensor_info::line_length
- * \brief The full line length, including blanking, in pixel units
- * \sa libcamera::CameraSensorInfo::lineLength
- */
-
-/**
- * \struct ipa_stream
- * \brief Stream information for the IPA context operations
- *
- * \var ipa_stream::id
- * \brief Identifier for the stream, defined by the IPA protocol
- *
- * \var ipa_stream::pixel_format
- * \brief The stream pixel format, as defined by the PixelFormat class
- *
- * \var ipa_stream::width
- * \brief The stream width in pixels
- *
- * \var ipa_stream::height
- * \brief The stream height in pixels
- */
-
-/**
- * \struct ipa_control_info_map
- * \brief ControlInfoMap description for the IPA context operations
- *
- * \var ipa_control_info_map::id
- * \brief Identifier for the ControlInfoMap, defined by the IPA protocol
- *
- * \var ipa_control_info_map::data
- * \brief Pointer to a control packet for the ControlInfoMap
- * \sa ipa_controls.h
- *
- * \var ipa_control_info_map::size
- * \brief The size of the control packet in bytes
- */
-
-/**
- * \struct ipa_buffer_plane
- * \brief A plane for an ipa_buffer
- *
- * \var ipa_buffer_plane::dmabuf
- * \brief The dmabuf file descriptor for the plane (-1 for unused planes)
- *
- * \var ipa_buffer_plane::length
- * \brief The plane length in bytes (0 for unused planes)
- */
-
-/**
- * \struct ipa_buffer
- * \brief Buffer information for the IPA context operations
- *
- * \var ipa_buffer::id
- * \brief The buffer unique ID (see \ref libcamera::IPABuffer::id)
- *
- * \var ipa_buffer::num_planes
- * \brief The number of used planes in the ipa_buffer::planes array
- *
- * \var ipa_buffer::planes
- * \brief The buffer planes (up to 3)
- */
-
-/**
- * \struct ipa_control_list
- * \brief ControlList description for the IPA context operations
- *
- * \var ipa_control_list::data
- * \brief Pointer to a control packet for the ControlList
- * \sa ipa_controls.h
- *
- * \var ipa_control_list::size
- * \brief The size of the control packet in bytes
- */
-
-/**
- * \struct ipa_operation_data
- * \brief IPA operation data for the IPA context operations
- * \sa libcamera::IPAOperationData
- *
- * \var ipa_operation_data::operation
- * \brief IPA protocol operation
- *
- * \var ipa_operation_data::data
- * \brief Pointer to the operation data array
- *
- * \var ipa_operation_data::num_data
- * \brief Number of entries in the ipa_operation_data::data array
- *
- * \var ipa_operation_data::lists
- * \brief Pointer to an array of ipa_control_list
- *
- * \var ipa_operation_data::num_lists
- * \brief Number of entries in the ipa_control_list array
- */
-
-/**
- * \struct ipa_callback_ops
- * \brief IPA context operations as a set of function pointers
- */
-
-/**
- * \var ipa_callback_ops::queue_frame_action
- * \brief Queue an action associated with a frame to the pipeline handler
- * \param[in] cb_ctx The callback context registered with
- * ipa_context_ops::register_callbacks
- * \param[in] frame The frame number
- *
- * \sa libcamera::IPAInterface::queueFrameAction
- */
-
-/**
- * \struct ipa_context_ops
- * \brief IPA context operations as a set of function pointers
- *
- * To allow for isolation of IPA modules in separate processes, the functions
- * defined in the ipa_context_ops structure return only data related to the
- * libcamera side of the operations. In particular, error related to the
- * libcamera side of the IPC may be returned. Data returned by the IPA,
- * including status information, shall be provided through callbacks from the
- * IPA to libcamera.
- */
-
-/**
- * \var ipa_context_ops::destroy
- * \brief Destroy the IPA context created by the module's ipaCreate() function
- * \param[in] ctx The IPA context
- */
-
-/**
- * \var ipa_context_ops::get_interface
- * \brief Retrieve the IPAInterface implemented by the ipa_context (optional)
- * \param[in] ctx The IPA context
- *
- * IPA modules may implement this function to expose their internal
- * IPAInterface, if any. When implemented, libcamera may at its sole discretion
- * call it and then bypass the ipa_context_ops API by calling the IPAInterface
- * methods directly. IPA modules shall still implement and support the full
- * ipa_context_ops API.
- */
-
-/**
- * \var ipa_context_ops::init
- * \brief Initialise the IPA context
- * \param[in] ctx The IPA context
- * \param[in] settings The IPA initialization settings
- *
- * \sa libcamera::IPAInterface::init()
- */
-
-/**
- * \var ipa_context_ops::start
- * \brief Start the IPA context
- *
- * \sa libcamera::IPAInterface::start()
- */
-
-/**
- * \var ipa_context_ops::stop
- * \brief Stop the IPA context
- *
- * \sa libcamera::IPAInterface::stop()
- */
-
-/**
- * \var ipa_context_ops::register_callbacks
- * \brief Register callback operation from the IPA to the pipeline handler
- * \param[in] ctx The IPA context
- * \param[in] callback The IPA callback operations
- * \param[in] cb_ctx The callback context, passed to all callback operations
- */
-
-/**
- * \var ipa_context_ops::configure
- * \brief Configure the IPA stream and sensor settings
- * \param[in] ctx The IPA context
- * \param[in] sensor_info Camera sensor information
- * \param[in] streams Configuration of all active streams
- * \param[in] num_streams The number of entries in the \a streams array
- * \param[in] maps Controls provided by the pipeline entities
- * \param[in] num_maps The number of entries in the \a maps array
- *
- * \sa libcamera::IPAInterface::configure()
- */
-
-/**
- * \var ipa_context_ops::map_buffers
- * \brief Map buffers shared between the pipeline handler and the IPA
- * \param[in] ctx The IPA context
- * \param[in] buffers The buffers to map
- * \param[in] num_buffers The number of entries in the \a buffers array
- *
- * The dmabuf file descriptors provided in \a buffers are borrowed from the
- * caller and are only guaranteed to be valid during the map_buffers() call.
- * Should the callee need to store a copy of the file descriptors, it shall
- * duplicate them first with ::%dup().
- *
- * \sa libcamera::IPAInterface::mapBuffers()
- */
-
-/**
- * \var ipa_context_ops::unmap_buffers
- * \brief Unmap buffers shared by the pipeline to the IPA
- * \param[in] ctx The IPA context
- * \param[in] ids The IDs of the buffers to unmap
- * \param[in] num_buffers The number of entries in the \a ids array
- *
- * \sa libcamera::IPAInterface::unmapBuffers()
- */
-
-/**
- * \var ipa_context_ops::process_event
- * \brief Process an event from the pipeline handler
- * \param[in] ctx The IPA context
- *
- * \sa libcamera::IPAInterface::processEvent()
+ * be costly. For that reason, functions that cannot afford the high cost
+ * should be marked as [async] in the mojom file, and they will operate
+ * asynchronously. This implies that these methods don't return a status, and
+ * that all methods may copy their arguments. Synchronous functions are still
+ * allowed, but should be used with caution.
  */
 
 /**
@@ -387,276 +67,14 @@
  * \brief Entry point to the IPA modules
  *
  * This function is the entry point to the IPA modules. It is implemented by
- * every IPA module, and called by libcamera to create a new IPA context.
+ * every IPA module, and called by libcamera to create a new IPA interface
+ * instance.
  *
- * \return A newly created IPA context
+ * \return A newly created IPA interface instance
  */
 
 namespace libcamera {
 
-/**
- * \struct IPASettings
- * \brief IPA interface initialization settings
- *
- * The IPASettings structure stores data passed to the IPAInterface::init()
- * function. The data contains settings that don't depend on a particular camera
- * or pipeline configuration and are valid for the whole life time of the IPA
- * interface.
- */
-
-/**
- * \var IPASettings::configurationFile
- * \brief The name of the IPA configuration file
- *
- * This field may be an empty string if the IPA doesn't require a configuration
- * file.
- */
-
-/**
- * \struct IPAStream
- * \brief Stream configuration for the IPA interface
- *
- * The IPAStream structure stores stream configuration parameters needed by the
- * IPAInterface::configure() method. It mirrors the StreamConfiguration class
- * that is not suitable for this purpose due to not being serializable.
- */
-
-/**
- * \var IPAStream::pixelFormat
- * \brief The stream pixel format
- */
-
-/**
- * \var IPAStream::size
- * \brief The stream size in pixels
- */
-
-/**
- * \struct IPABuffer
- * \brief Buffer information for the IPA interface
- *
- * The IPABuffer structure associates buffer memory with a unique ID. It is
- * used to map buffers to the IPA with IPAInterface::mapBuffers(), after which
- * buffers will be identified by their ID in the IPA interface.
- */
-
-/**
- * \var IPABuffer::id
- * \brief The buffer unique ID
- *
- * Buffers mapped to the IPA are identified by numerical unique IDs. The IDs
- * are chosen by the pipeline handler to fulfil the following constraints:
- *
- * - IDs shall be positive integers different than zero
- * - IDs shall be unique among all mapped buffers
- *
- * When buffers are unmapped with IPAInterface::unmapBuffers() their IDs are
- * freed and may be reused for new buffer mappings.
- */
-
-/**
- * \var IPABuffer::planes
- * \brief The buffer planes description
- *
- * Stores the dmabuf handle and length for each plane of the buffer.
- */
-
-/**
- * \struct IPAOperationData
- * \brief Parameters for IPA operations
- *
- * The IPAOperationData structure carries parameters for the IPA operations
- * performed through the IPAInterface::processEvent() method and the
- * IPAInterface::queueFrameAction signal.
- */
-
-/**
- * \var IPAOperationData::operation
- * \brief IPA protocol operation
- *
- * The operation field describes which operation the receiver shall perform. It
- * defines, through the IPA protocol, how the other fields of the structure are
- * interpreted. The protocol freely assigns numerical values to operations.
- */
-
-/**
- * \var IPAOperationData::data
- * \brief Operation integer data
- *
- * The interpretation and position of different values in the array are defined
- * by the IPA protocol.
- */
-
-/**
- * \var IPAOperationData::controls
- * \brief Operation controls data
- *
- * The interpretation and position of different values in the array are defined
- * by the IPA protocol.
- */
-
-/**
- * \class IPAInterface
- * \brief C++ Interface for IPA implementation
- *
- * This pure virtual class defines a C++ API corresponding to the ipa_context,
- * ipa_context_ops and ipa_callback_ops API. It is used by pipeline handlers to
- * interact with IPA modules, and may be used internally in IPA modules if
- * desired to benefit from the data and helper classes provided by libcamera.
- *
- * Functions defined in the ipa_context_ops structure are mapped to IPAInterface
- * methods, while functions defined in the ipa_callback_ops are mapped to
- * IPAInterface signals. As with the C API, the IPA C++ interface uses
- * serializable data types only. It reuses structures defined by the C API, or
- * defines corresponding classes using C++ containers when required.
- *
- * Due to process isolation all arguments to the IPAInterface methods and
- * signals may need to be transferred over IPC. The class thus uses serializable
- * data types only. The IPA C++ interface defines custom data structures that
- * mirror core libcamera structures when the latter are not suitable, such as
- * IPAStream to carry StreamConfiguration data.
- *
- * As for the functions defined in struct ipa_context_ops, the methods defined
- * by this class shall not return data from the IPA.
- *
- * The pipeline handler shall use the IPAManager to locate a compatible
- * IPAInterface. The interface may then be used to interact with the IPA module.
- */
-
-/**
- * \fn IPAInterface::init()
- * \brief Initialise the IPAInterface
- * \param[in] settings The IPA initialization settings
- *
- * This function initializes the IPA interface. It shall be called before any
- * other function of the IPAInterface. The \a settings carry initialization
- * parameters that are valid for the whole life time of the IPA interface.
- */
-
-/**
- * \fn IPAInterface::start()
- * \brief Start the IPA
- * \param[in] data Protocol-specific data for the start operation
- * \param[out] result Result of the start operation
- *
- * This method informs the IPA module that the camera is about to be started.
- * The IPA module shall prepare any resources it needs to operate.
- *
- * The \a data and \a result parameters carry custom data passed by the
- * pipeline handler to the IPA and back. The pipeline handler may set the \a
- * result parameter to null if the IPA protocol doesn't need to pass a result
- * back through the start() function.
- *
- * \return 0 on success or a negative error code otherwise
- */
-
-/**
- * \fn IPAInterface::stop()
- * \brief Stop the IPA
- *
- * This method informs the IPA module that the camera is stopped. The IPA module
- * shall release resources prepared in start().
- */
-
-/**
- * \fn IPAInterface::configure()
- * \brief Configure the IPA stream and sensor settings
- * \param[in] sensorInfo Camera sensor information
- * \param[in] streamConfig Configuration of all active streams
- * \param[in] entityControls Controls provided by the pipeline entities
- * \param[in] ipaConfig Pipeline-handler-specific configuration data
- * \param[out] result Pipeline-handler-specific configuration result
- *
- * This method shall be called when the camera is started to inform the IPA of
- * the camera's streams and the sensor settings. The meaning of the numerical
- * keys in the \a streamConfig and \a entityControls maps is defined by the IPA
- * protocol.
- *
- * The \a sensorInfo conveys information about the camera sensor settings that
- * the pipeline handler has selected for the configuration. The IPA may use
- * that information to tune its algorithms.
- *
- * The \a ipaConfig and \a result parameters carry custom data passed by the
- * pipeline handler to the IPA and back. The pipeline handler may set the \a
- * result parameter to null if the IPA protocol doesn't need to pass a result
- * back through the configure() function.
- */
-
-/**
- * \fn IPAInterface::mapBuffers()
- * \brief Map buffers shared between the pipeline handler and the IPA
- * \param[in] buffers List of buffers to map
- *
- * This method informs the IPA module of memory buffers set up by the pipeline
- * handler that the IPA needs to access. It provides dmabuf file handles for
- * each buffer, and associates the buffers with unique numerical IDs.
- *
- * IPAs shall map the dmabuf file handles to their address space and keep a
- * cache of the mappings, indexed by the buffer numerical IDs. The IDs are used
- * in all other IPA interface methods to refer to buffers, including the
- * unmapBuffers() method.
- *
- * All buffers that the pipeline handler wishes to share with an IPA shall be
- * mapped with this method. Buffers may be mapped all at once with a single
- * call, or mapped and unmapped dynamically at runtime, depending on the IPA
- * protocol. Regardless of the protocol, all buffers mapped at a given time
- * shall have unique numerical IDs.
- *
- * The numerical IDs have no meaning defined by the IPA interface, and IPA
- * protocols shall not give them any specific meaning either. They should be
- * treated as opaque handles by IPAs, with the only exception that ID zero is
- * invalid.
- *
- * \sa unmapBuffers()
- *
- * \todo Provide a generic implementation of mapBuffers and unmapBuffers for
- * IPAs
- */
-
-/**
- * \fn IPAInterface::unmapBuffers()
- * \brief Unmap buffers shared by the pipeline to the IPA
- * \param[in] ids List of buffer IDs to unmap
- *
- * This method removes mappings set up with mapBuffers(). Buffers may be
- * unmapped all at once with a single call, or selectively at runtime, depending
- * on the IPA protocol. Numerical IDs of unmapped buffers may be reused when
- * mapping new buffers.
- *
- * \sa mapBuffers()
- */
-
-/**
- * \fn IPAInterface::processEvent()
- * \brief Process an event from the pipeline handler
- * \param[in] data IPA operation data
- *
- * This operation is used by pipeline handlers to inform the IPA module of
- * events that occurred during the on-going capture operation.
- *
- * The event notified by the pipeline handler with this method is handled by the
- * IPA, which interprets the operation parameters according to the separately
- * documented IPA protocol.
- */
-
-/**
- * \var IPAInterface::queueFrameAction
- * \brief Queue an action associated with a frame to the pipeline handler
- * \param[in] frame The frame number for the action
- * \param[in] data IPA operation data
- *
- * This signal is emitted when the IPA wishes to queue a FrameAction on the
- * pipeline. The pipeline is still responsible for the scheduling of the action
- * on its timeline.
- *
- * This signal is emitted by the IPA to queue an action to be executed by the
- * pipeline handler on a frame. The type of action is identified by the
- * \a data.operation field, as defined by the IPA protocol, and the rest of the
- * \a data is interpreted accordingly. The pipeline handler shall queue the
- * action and execute it as appropriate.
- *
- * The signal is only emitted when the IPA is running, that is after start() and
- * before stop() have been called.
- */
+/* \todo Figure out how to generate IPAInterface documentation. */
 
 } /* namespace libcamera */
diff --git a/src/libcamera/ipa_module.cpp b/src/libcamera/ipa_module.cpp
index de512a7f..f53e529b 100644
--- a/src/libcamera/ipa_module.cpp
+++ b/src/libcamera/ipa_module.cpp
@@ -391,13 +391,13 @@ const std::string &IPAModule::path() const
 /**
  * \brief Load the IPA implementation factory from the shared object
  *
- * The IPA module shared object implements an ipa_context object to be used
+ * The IPA module shared object implements an IPAInterface object to be used
  * by pipeline handlers. This method loads the factory function from the
- * shared object. Later, createContext() can be called to instantiate the
- * ipa_context.
+ * shared object. Later, createInterface() can be called to instantiate the
+ * IPAInterface.
  *
  * This method only needs to be called successfully once, after which
- * createContext() can be called as many times as ipa_context instances are
+ * createInterface() can be called as many times as IPAInterface instances are
  * needed.
  *
  * Calling this function on an invalid module (as returned by isValid()) is
@@ -439,20 +439,18 @@ bool IPAModule::load()
 }
 
 /**
- * \brief Instantiate an IPA context
+ * \brief Instantiate an IPA interface
  *
  * After loading the IPA module with load(), this method creates an instance of
- * the IPA module context. Ownership of the context is passed to the caller, and
- * the context shall be destroyed by calling the \ref ipa_context_ops::destroy
- * "ipa_context::ops::destroy()" function.
+ * the IPA module interface.
  *
  * Calling this function on a module that has not yet been loaded, or an
  * invalid module (as returned by load() and isValid(), respectively) is
  * an error.
  *
- * \return The IPA context on success, or nullptr on error
+ * \return The IPA interface on success, or nullptr on error
  */
-struct ipa_context *IPAModule::createContext()
+IPAInterface *IPAModule::createInterface()
 {
 	if (!valid_ || !loaded_)
 		return nullptr;
diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
index 0875fede..f86dca90 100644
--- a/src/libcamera/meson.build
+++ b/src/libcamera/meson.build
@@ -24,7 +24,6 @@ libcamera_sources = files([
     'formats.cpp',
     'framebuffer_allocator.cpp',
     'geometry.cpp',
-    'ipa_context_wrapper.cpp',
     'ipa_controls.cpp',
     'ipa_data_serializer.cpp',
     'ipa_interface.cpp',
-- 
2.27.0



More information about the libcamera-devel mailing list