From 1124e47bb94d796e17ed01a97f7bf08df81f107f Mon Sep 17 00:00:00 2001 From: Umang Jain Date: Fri, 21 May 2021 10:04:40 +0530 Subject: 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 --- ipu3.cpp | 241 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ meson.build | 83 +++++++++++++++++++++ 2 files changed, 324 insertions(+) create mode 100644 ipu3.cpp create mode 100644 meson.build 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 +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#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 &buffers) override; + void unmapBuffers(const std::vector &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 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(), 1); + maxExposure_ = itExp->second.max().get(); + exposure_ = maxExposure_; + + minGain_ = std::max(itGain->second.min().get(), 1); + maxGain_ = itGain->second.max().get(); + gain_ = maxGain_; + + return 0; +} + +void IPAIPU3::mapBuffers(const std::vector &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 &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 mem = it->second.maps()[0]; + const ipu3_uapi_stats_3a *stats = + reinterpret_cast(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 mem = it->second.maps()[0]; + ipu3_uapi_params *params = + reinterpret_cast(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(exposure_)); + ctrls.set(V4L2_CID_ANALOGUE_GAIN, static_cast(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) -- cgit v1.2.1