summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUmang Jain <umang.jain@ideasonboard.com>2021-05-21 10:04:40 +0530
committerUmang Jain <umang.jain@ideasonboard.com>2021-06-28 14:12:06 +0530
commit1124e47bb94d796e17ed01a97f7bf08df81f107f (patch)
tree091e783267b1ee20838ec443b94f26e36071bf5f
parentdaf1cf0c737bdee9e42a9aaf64af997609a90951 (diff)
ipu3: Import the Intel IPA skeleton from libcamera
Import the raw Intel IPU3 IPA from libcamera master at revision b2cc8a2f57333f. Also, copy the build enviroment and adapt the meson.build to build the shared library. The ipu3.cpp is now ready for integration with the Intel IPA library. Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>
-rw-r--r--ipu3.cpp241
-rw-r--r--meson.build83
2 files changed, 324 insertions, 0 deletions
diff --git a/ipu3.cpp b/ipu3.cpp
new file mode 100644
index 0000000..827a980
--- /dev/null
+++ b/ipu3.cpp
@@ -0,0 +1,241 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+/*
+ * Copyright (C) 2020, Google Inc.
+ *
+ * ipu3.cpp - IPU3 Image Processing Algorithms
+ */
+
+#include <stdint.h>
+#include <sys/mman.h>
+
+#include <linux/intel-ipu3.h>
+#include <linux/v4l2-controls.h>
+
+#include <libcamera/buffer.h>
+#include <libcamera/control_ids.h>
+#include <libcamera/ipa/ipa_interface.h>
+#include <libcamera/ipa/ipa_module_info.h>
+#include <libcamera/ipa/ipu3_ipa_interface.h>
+#include <libcamera/request.h>
+
+#include <libcamera/base/log.h>
+
+#include "libcamera-helpers/mapped_buffer.h"
+
+namespace libcamera {
+
+LOG_DEFINE_CATEGORY(IPAIPU3)
+
+namespace ipa::ipu3 {
+
+class IPAIPU3 : public IPAIPU3Interface
+{
+public:
+ int init([[maybe_unused]] const IPASettings &settings) override
+ {
+ return 0;
+ }
+ int start() override;
+ void stop() override {}
+
+ int configure(const IPAConfigInfo &configInfo) override;
+
+ void mapBuffers(const std::vector<IPABuffer> &buffers) override;
+ void unmapBuffers(const std::vector<unsigned int> &ids) override;
+ void processEvent(const IPU3Event &event) override;
+
+private:
+ void processControls(unsigned int frame, const ControlList &controls);
+ void fillParams(unsigned int frame, ipu3_uapi_params *params);
+ void parseStatistics(unsigned int frame,
+ int64_t frameTimestamp,
+ const ipu3_uapi_stats_3a *stats);
+
+ void setControls(unsigned int frame);
+
+ std::map<unsigned int, MappedFrameBuffer> buffers_;
+
+ ControlInfoMap ctrls_;
+
+ IPACameraSensorInfo sensorInfo_;
+
+ /* Camera sensor controls. */
+ uint32_t exposure_;
+ uint32_t minExposure_;
+ uint32_t maxExposure_;
+ uint32_t gain_;
+ uint32_t minGain_;
+ uint32_t maxGain_;
+};
+
+int IPAIPU3::start()
+{
+ setControls(0);
+
+ return 0;
+}
+
+int IPAIPU3::configure(const IPAConfigInfo &configInfo)
+{
+ if (configInfo.entityControls.empty()) {
+ LOG(IPAIPU3, Error) << "No controls provided";
+ return -ENODATA;
+ }
+
+ sensorInfo_ = configInfo.sensorInfo;
+
+ ctrls_ = configInfo.entityControls.at(0);
+
+ const auto itExp = ctrls_.find(V4L2_CID_EXPOSURE);
+ if (itExp == ctrls_.end()) {
+ LOG(IPAIPU3, Error) << "Can't find exposure control";
+ return -EINVAL;
+ }
+
+ const auto itGain = ctrls_.find(V4L2_CID_ANALOGUE_GAIN);
+ if (itGain == ctrls_.end()) {
+ LOG(IPAIPU3, Error) << "Can't find gain control";
+ return -EINVAL;
+ }
+
+ minExposure_ = std::max(itExp->second.min().get<int32_t>(), 1);
+ maxExposure_ = itExp->second.max().get<int32_t>();
+ exposure_ = maxExposure_;
+
+ minGain_ = std::max(itGain->second.min().get<int32_t>(), 1);
+ maxGain_ = itGain->second.max().get<int32_t>();
+ gain_ = maxGain_;
+
+ return 0;
+}
+
+void IPAIPU3::mapBuffers(const std::vector<IPABuffer> &buffers)
+{
+ for (const IPABuffer &buffer : buffers) {
+ const FrameBuffer fb(buffer.planes);
+ buffers_.emplace(buffer.id,
+ MappedFrameBuffer(&fb, PROT_READ | PROT_WRITE));
+ }
+}
+
+void IPAIPU3::unmapBuffers(const std::vector<unsigned int> &ids)
+{
+ for (unsigned int id : ids) {
+ auto it = buffers_.find(id);
+ if (it == buffers_.end())
+ continue;
+
+ buffers_.erase(it);
+ }
+}
+
+void IPAIPU3::processEvent(const IPU3Event &event)
+{
+ switch (event.op) {
+ case EventProcessControls: {
+ processControls(event.frame, event.controls);
+ break;
+ }
+ case EventStatReady: {
+ auto it = buffers_.find(event.bufferId);
+ if (it == buffers_.end()) {
+ LOG(IPAIPU3, Error) << "Could not find stats buffer!";
+ return;
+ }
+
+ Span<uint8_t> mem = it->second.maps()[0];
+ const ipu3_uapi_stats_3a *stats =
+ reinterpret_cast<ipu3_uapi_stats_3a *>(mem.data());
+
+ parseStatistics(event.frame, event.frameTimestamp, stats);
+ break;
+ }
+ case EventFillParams: {
+ auto it = buffers_.find(event.bufferId);
+ if (it == buffers_.end()) {
+ LOG(IPAIPU3, Error) << "Could not find param buffer!";
+ return;
+ }
+
+ Span<uint8_t> mem = it->second.maps()[0];
+ ipu3_uapi_params *params =
+ reinterpret_cast<ipu3_uapi_params *>(mem.data());
+
+ fillParams(event.frame, params);
+ break;
+ }
+ default:
+ LOG(IPAIPU3, Error) << "Unknown event " << event.op;
+ break;
+ }
+}
+
+void IPAIPU3::processControls([[maybe_unused]] unsigned int frame,
+ [[maybe_unused]] const ControlList &controls)
+{
+ /* \todo Start processing for 'frame' based on 'controls'. */
+}
+
+void IPAIPU3::fillParams(unsigned int frame, ipu3_uapi_params *params)
+{
+ /* Prepare parameters buffer. */
+ memset(params, 0, sizeof(*params));
+
+ /* \todo Fill in parameters buffer. */
+
+ IPU3Action op;
+ op.op = ActionParamFilled;
+
+ queueFrameAction.emit(frame, op);
+}
+
+void IPAIPU3::parseStatistics(unsigned int frame,
+ [[maybe_unused]] int64_t frameTimestamp,
+ [[maybe_unused]] const ipu3_uapi_stats_3a *stats)
+{
+ ControlList ctrls(controls::controls);
+
+ /* \todo React to statistics and update internal state machine. */
+ /* \todo Add meta-data information to ctrls. */
+
+ IPU3Action op;
+ op.op = ActionMetadataReady;
+ op.controls = ctrls;
+
+ queueFrameAction.emit(frame, op);
+}
+
+void IPAIPU3::setControls(unsigned int frame)
+{
+ IPU3Action op;
+ op.op = ActionSetSensorControls;
+
+ ControlList ctrls(ctrls_);
+ ctrls.set(V4L2_CID_EXPOSURE, static_cast<int32_t>(exposure_));
+ ctrls.set(V4L2_CID_ANALOGUE_GAIN, static_cast<int32_t>(gain_));
+ op.controls = ctrls;
+
+ queueFrameAction.emit(frame, op);
+}
+
+} /* namespace ipa::ipu3 */
+
+/*
+ * External IPA module interface
+ */
+
+extern "C" {
+const struct IPAModuleInfo ipaModuleInfo = {
+ IPA_MODULE_API_VERSION,
+ 1,
+ "PipelineHandlerIPU3",
+ "ipu3",
+};
+
+IPAInterface *ipaCreate()
+{
+ return new ipa::ipu3::IPAIPU3();
+}
+}
+
+} /* namespace libcamera */
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..80fb18d
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,83 @@
+# SPDX-License-Identifier: CC0-1.0
+project('ipu3-ipa', 'c', 'cpp',
+ meson_version : '>= 0.55',
+ version : '0.0.0',
+ default_options : [
+ 'werror=true',
+ 'warning_level=2',
+ 'cpp_std=c++17',
+ ],
+ license : 'Apache-2.0')
+
+ipa_name = 'intel-ipu3-ipa'
+
+ipa_install_dir = get_option('libdir') / 'libcamera'
+
+cc = meson.get_compiler('c')
+libcamera_dep = dependency('libcamera')
+libcamera_base = dependency('libcamera-base')
+libatomic = cc.find_library('atomic', required : false)
+
+config_h = configuration_data()
+
+if cc.has_header_symbol('stdlib.h', 'secure_getenv', prefix : '#define _GNU_SOURCE')
+ config_h.set('HAVE_SECURE_GETENV', 1)
+endif
+
+configure_file(output : 'config.h', configuration : config_h)
+common_arguments = [
+ '-DLIBCAMERA_BASE_PRIVATE',
+ '-Wshadow',
+ '-include', 'config.h',
+]
+
+ipa_includes = [
+ include_directories('include'),
+]
+
+c_arguments = []
+cpp_arguments = []
+
+if cc.get_id() == 'clang'
+ if cc.version().version_compare('<5')
+ error('clang version is too old, ipa-ipu3 requires 5.0 or newer')
+ endif
+
+ # Use libc++ by default if available instead of libstdc++ when compiling
+ # with clang.
+ if cc.find_library('libc++', required: false).found()
+ cpp_arguments += [
+ '-stdlib=libc++',
+ ]
+ endif
+
+ cpp_arguments += [
+ '-Wextra-semi',
+ ]
+endif
+
+c_arguments += common_arguments
+cpp_arguments += common_arguments
+
+add_project_arguments(c_arguments, language : 'c')
+add_project_arguments(cpp_arguments, language : 'cpp')
+
+ipu3_ipa_files = files([
+ 'ipu3.cpp',
+])
+
+ipu3_ipa_deps = [
+ libatomic,
+ libcamera_base,
+ libcamera_dep,
+]
+
+subdir('src')
+
+mod = shared_module(ipa_name,
+ [ipu3_ipa_files, libcamera_helpers],
+ name_prefix : '',
+ include_directories : ipa_includes,
+ dependencies : ipu3_ipa_deps,
+ install : true,
+ install_dir : ipa_install_dir)