From patchwork Sat Dec 5 10:30:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 10574 X-Patchwork-Delegate: paul.elder@ideasonboard.com Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 56E51BDB20 for ; Sat, 5 Dec 2020 10:31:43 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 24630635FE; Sat, 5 Dec 2020 11:31:43 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="cqYj4k4R"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4BD91635F2 for ; Sat, 5 Dec 2020 11:31:41 +0100 (CET) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 546712A4; Sat, 5 Dec 2020 11:31:38 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1607164301; bh=+qhtveCJo7tYqPRF3N4sKW3prAjAAnSw9Ccl6jB6210=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cqYj4k4RNeUbBFeoD/ACDXYMVJ35BQeNbwAVluuEZthFT3On/nq4Q/htRBzye6HJw aMZeHN9pnncjGglkXlt5h/ij5q3cHncPqGJzKxsWOnqjZbeUQ3t2b+suZc617Z9XMA SPexQzMqbmbu5GqtXMfzxLmepi2UIH5SdIO+17YI= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Sat, 5 Dec 2020 19:30:54 +0900 Message-Id: <20201205103106.242080-12-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201205103106.242080-1-paul.elder@ideasonboard.com> References: <20201205103106.242080-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 11/23] libcamera: IPAInterface: Replace C API with the new C++-only API X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" 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 --- 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 Reviewed-by: Niklas Söderlund Reviewed-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- 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 Reviewed-by: Niklas Söderlund Reviewed-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- 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 Reviewed-by: Niklas Söderlund Reviewed-by: Jacopo Mondi --- 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 Reviewed-by: Niklas Söderlund Reviewed-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- 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 Reviewed-by: Jacopo Mondi --- ipa: remove IPAInterfaceWrapper As every pipeline has its own proxy, IPAInterfaceWrapper is no longer necessary. Remove it. Signed-off-by: Paul Elder Reviewed-by: Niklas Söderlund Acked-by: Jacopo Mondi Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham Used to be "ipa: remove libipa" --- .../libcamera/internal/ipa_context_wrapper.h | 52 -- include/libcamera/internal/ipa_module.h | 4 +- include/libcamera/internal/meson.build | 1 - include/libcamera/ipa/ipa_interface.h | 126 +---- src/ipa/libipa/ipa_interface_wrapper.cpp | 285 ---------- 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 | 297 ---------- src/libcamera/ipa_interface.cpp | 534 ++---------------- src/libcamera/ipa_module.cpp | 18 +- src/libcamera/meson.build | 1 - 14 files changed, 56 insertions(+), 1331 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 8f767e84..00000000 --- a/include/libcamera/internal/ipa_context_wrapper.h +++ /dev/null @@ -1,52 +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 - -#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() override; - void stop() override; - void configure(const CameraSensorInfo &sensorInfo, - const std::map &streamConfig, - const std::map &entityControls, - const IPAOperationData &ipaConfig, - IPAOperationData *result) override; - - void mapBuffers(const std::vector &buffers) override; - void unmapBuffers(const std::vector &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 7cde023f..2c172ab3 100644 --- a/include/libcamera/internal/meson.build +++ b/include/libcamera/internal/meson.build @@ -23,7 +23,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 322b7079..f6c40dc6 100644 --- a/include/libcamera/ipa/ipa_interface.h +++ b/include/libcamera/ipa/ipa_interface.h @@ -10,111 +10,6 @@ #include #include -#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 #include @@ -151,25 +46,12 @@ class IPAInterface { public: virtual ~IPAInterface() = default; - - virtual int init(const IPASettings &settings) = 0; - virtual int start() = 0; - virtual void stop() = 0; - - virtual void configure(const CameraSensorInfo &sensorInfo, - const std::map &streamConfig, - const std::map &entityControls, - const IPAOperationData &ipaConfig, - IPAOperationData *result) = 0; - - virtual void mapBuffers(const std::vector &buffers) = 0; - virtual void unmapBuffers(const std::vector &ids) = 0; - - virtual void processEvent(const IPAOperationData &data) = 0; - Signal queueFrameAction; }; } /* namespace libcamera */ -#endif + +extern "C" { +libcamera::IPAInterface *ipaCreate(); +} #endif /* __LIBCAMERA_IPA_INTERFACE_H__ */ diff --git a/src/ipa/libipa/ipa_interface_wrapper.cpp b/src/ipa/libipa/ipa_interface_wrapper.cpp deleted file mode 100644 index cee532e3..00000000 --- a/src/ipa/libipa/ipa_interface_wrapper.cpp +++ /dev/null @@ -1,285 +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 -#include -#include -#include - -#include - -#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()); - * } - * \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 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(_ctx); - - delete ctx; -} - -void *IPAInterfaceWrapper::get_interface(struct ipa_context *_ctx) -{ - IPAInterfaceWrapper *ctx = static_cast(_ctx); - - return ctx->ipa_.get(); -} - -void IPAInterfaceWrapper::init(struct ipa_context *_ctx, - const struct ipa_settings *settings) -{ - IPAInterfaceWrapper *ctx = static_cast(_ctx); - - IPASettings ipaSettings{ - .configurationFile = settings->configuration_file - }; - ctx->ipa_->init(ipaSettings); -} - -int IPAInterfaceWrapper::start(struct ipa_context *_ctx) -{ - IPAInterfaceWrapper *ctx = static_cast(_ctx); - - return ctx->ipa_->start(); -} - -void IPAInterfaceWrapper::stop(struct ipa_context *_ctx) -{ - IPAInterfaceWrapper *ctx = static_cast(_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(_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(_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 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 entityControls; - std::map 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(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(_ctx); - std::vector 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 &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(_ctx); - std::vector 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(_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(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 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 - -#include - -#include "libcamera/internal/control_serializer.h" - -namespace libcamera { - -class IPAInterfaceWrapper : public ipa_context -{ -public: - IPAInterfaceWrapper(std::unique_ptr 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 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 29d48b1b..4dc02dc8 100644 --- a/src/ipa/raspberrypi/raspberrypi.cpp +++ b/src/ipa/raspberrypi/raspberrypi.cpp @@ -22,8 +22,6 @@ #include #include -#include - #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 07d7f1b2..10301a19 100644 --- a/src/ipa/rkisp1/rkisp1.cpp +++ b/src/ipa/rkisp1/rkisp1.cpp @@ -22,8 +22,6 @@ #include #include -#include - #include "libcamera/internal/log.h" namespace libcamera { diff --git a/src/ipa/vimc/vimc.cpp b/src/ipa/vimc/vimc.cpp index cf841135..483aeadd 100644 --- a/src/ipa/vimc/vimc.cpp +++ b/src/ipa/vimc/vimc.cpp @@ -17,8 +17,6 @@ #include #include -#include - #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 231300ce..00000000 --- a/src/libcamera/ipa_context_wrapper.cpp +++ /dev/null @@ -1,297 +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 - -#include - -#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(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() -{ - if (intf_) - return intf_->start(); - - 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 &streamConfig, - const std::map &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> 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 &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 &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 &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 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(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(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 23fc56d7..edbfd979 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 + * Mojo interface definition language, + * 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,9 +67,10 @@ * \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 { @@ -499,16 +180,10 @@ namespace libcamera { * \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. + * This pure virtual class defines a skeletal C++ API for IPA modules. + * Specializations of this class must be defined in a mojom file in + * include/libcamera/ipa/ (see the IPA Writers Guide for details + * on how to do so). * * Due to process isolation all arguments to the IPAInterface methods and * signals may need to be transferred over IPC. The class thus uses serializable @@ -516,140 +191,15 @@ namespace libcamera { * 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. + * Custom data structures may also be defined in the mojom file, in which case + * the (de)serialization will automatically be generated. If any other libcamera + * structures are to be used as parameters, then a de/serializer for them must + * be implemented in IPADataSerializer. * * 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 - * - * 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. - * - * \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 f7f3627c..1472a41a 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -23,7 +23,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',