From a792bc5079566a586d7d951c5ca873b3e43823d5 Mon Sep 17 00:00:00 2001 From: Kieran Bingham Date: Tue, 11 May 2021 00:06:06 +0530 Subject: ipu3: Integrate AIQ/AIC Utilise the AIQ and AIC libraries to handle image control within the IPU3. Signed-off-by: Kieran Bingham Signed-off-by: Umang Jain --- ipu3.cpp | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 130 insertions(+), 9 deletions(-) diff --git a/ipu3.cpp b/ipu3.cpp index 827a980..e943201 100644 --- a/ipu3.cpp +++ b/ipu3.cpp @@ -22,6 +22,11 @@ #include "libcamera-helpers/mapped_buffer.h" +/* IA AIQ Wrapper API */ +#include "aic/aic.h" +#include "aiq/aiq.h" +#include "binary_data.h" + namespace libcamera { LOG_DEFINE_CATEGORY(IPAIPU3) @@ -31,10 +36,8 @@ namespace ipa::ipu3 { class IPAIPU3 : public IPAIPU3Interface { public: - int init([[maybe_unused]] const IPASettings &settings) override - { - return 0; - } + int init(const IPASettings &settings) override; + int start() override; void stop() override {} @@ -45,7 +48,7 @@ public: void processEvent(const IPU3Event &event) override; private: - void processControls(unsigned int frame, const ControlList &controls); + void processControls(unsigned int frame, const ControlList &metadata); void fillParams(unsigned int frame, ipu3_uapi_params *params); void parseStatistics(unsigned int frame, int64_t frameTimestamp, @@ -66,8 +69,70 @@ private: uint32_t gain_; uint32_t minGain_; uint32_t maxGain_; + + /* Intel Library Instances. */ + aiq::AIQ aiq_; + aic::AIC aic_; + + /* Temporary storage until we have a FrameContext object / struct */ + aiq::AiqInputParameters aiqInputParams_; + aiq::AiqResults results_; + + BinaryData aiqb_; + BinaryData nvm_; + BinaryData aiqd_; }; +int IPAIPU3::init(const IPASettings &settings) +{ + int ret; + + /* + * Temporary mapping of the sensor name to the AIQB data file. + * + * \todo: This mapping table should be handled more generically + * or through the configuration interfaces perhaps. + */ + std::map aiqb_paths = { + { "ov13858", "/usr/share/libcamera/ipa/ipu3/00ov13858.aiqb" }, + { "ov5670", "/usr/share/libcamera/ipa/ipu3/01ov5670.aiqb" }, + { "imx258", "/etc/camera/ipu3/00imx258.aiqb" }, + }; + + LOG(IPAIPU3, Info) << "Initialising IPA IPU3 for " + << settings.sensorModel; + + auto it = aiqb_paths.find(settings.sensorModel); + if (it == aiqb_paths.end()) { + LOG(IPAIPU3, Error) << "Failed to identify tuning data"; + return -EINVAL; + } + + LOG(IPAIPU3, Info) << "Using tuning file: " << it->second; + ret = aiqb_.load(it->second.c_str()); + if (ret) { + LOG(IPAIPU3, Error) << "Failed to load AIQB"; + return -ENODATA; + } + + /* + * Todo: nvm_ and aiqd_ are left as empty nullptrs. + * These need to be identified and loaded as required. + */ + + ret = aiq_.init(aiqb_, nvm_, aiqd_); + if (ret) + return ret; + + ret = aic_.init(aiqb_); + if (ret) + return ret; + + aiqInputParams_.init(); + + return 0; +} + int IPAIPU3::start() { setControls(0); @@ -106,6 +171,29 @@ int IPAIPU3::configure(const IPAConfigInfo &configInfo) maxGain_ = itGain->second.max().get(); gain_ = maxGain_; + int ret; + + ret = aiq_.configure(); + if (ret) { + LOG(IPAIPU3, Error) << "Failed to configure the AIQ"; + return ret; + } + + ret = aiqInputParams_.configure(configInfo); + if (ret) { + LOG(IPAIPU3, Error) << "Failed to configure AiqInputParams"; + return ret; + } + + ret = aic_.configure(configInfo); + if (ret) { + LOG(IPAIPU3, Error) << "Failed to configure the AIC"; + return ret; + } + + /* Set AE/AWB defaults, this typically might not belong here */ + aiqInputParams_.setAeAwbAfDefaults(); + return 0; } @@ -181,7 +269,28 @@ void IPAIPU3::fillParams(unsigned int frame, ipu3_uapi_params *params) /* Prepare parameters buffer. */ memset(params, 0, sizeof(*params)); - /* \todo Fill in parameters buffer. */ + /* + * Call into the AIQ object, and set up the library with any requested + * controls or settings from the incoming request. + * + * (statistics are fed into the library as a separate event + * when available) + * + * - Run algorithms + * + * - Fill params buffer with the results of the algorithms. + */ + + /* Run algorithms into/using this context structure */ + if (frame % 10 == 0) + aiq_.run2a(frame, aiqInputParams_, results_); + + aic_.updateRuntimeParams(results_); + aic_.run(params); + + exposure_ = results_.ae()->exposures[0].sensor_exposure->coarse_integration_time; + gain_ = results_.ae()->exposures[0].sensor_exposure->analog_gain_code_global; + setControls(frame); IPU3Action op; op.op = ActionParamFilled; @@ -190,13 +299,25 @@ void IPAIPU3::fillParams(unsigned int frame, ipu3_uapi_params *params) } void IPAIPU3::parseStatistics(unsigned int frame, - [[maybe_unused]] int64_t frameTimestamp, - [[maybe_unused]] const ipu3_uapi_stats_3a *stats) + int64_t frameTimestamp, + 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. */ + + /* *stats comes from the IPU3 hardware. We need to give this data into + * the AIQ library. + */ + + ASSERT (frameTimestamp > 0); + aiq_.setStatistics(frame, frameTimestamp, results_, stats); + + /* Set frame durations from exposure results */ + ia_aiq_exposure_sensor_parameters *sensorExposure = results_.ae()->exposures->sensor_exposure; + int64_t frameDuration = (sensorExposure->line_length_pixels * sensorExposure->frame_length_lines) / + (sensorInfo_.pixelRate / 1e6); + ctrls.set(controls::FrameDuration, frameDuration); IPU3Action op; op.op = ActionMetadataReady; -- cgit v1.2.1