summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKieran Bingham <kieran.bingham@ideasonboard.com>2021-05-11 00:06:06 +0530
committerUmang Jain <umang.jain@ideasonboard.com>2021-06-28 17:54:08 +0530
commita792bc5079566a586d7d951c5ca873b3e43823d5 (patch)
treeeabb658eac3aeac4e3866c68607d05a7a00f243f
parent062a6159113d55c6c49a72e8491751f3fad54334 (diff)
ipu3: Integrate AIQ/AIC
Utilise the AIQ and AIC libraries to handle image control within the IPU3. Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>
-rw-r--r--ipu3.cpp139
1 files 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<std::string, std::string> 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<int32_t>();
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;