summaryrefslogtreecommitdiff
path: root/src/ipa
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipa')
-rw-r--r--src/ipa/rkisp1/rkisp1.cpp3
-rw-r--r--src/ipa/simple/algorithms/agc.cpp11
-rw-r--r--src/ipa/simple/algorithms/awb.cpp21
-rw-r--r--src/ipa/simple/algorithms/awb.h6
-rw-r--r--src/ipa/simple/algorithms/blc.cpp21
-rw-r--r--src/ipa/simple/algorithms/blc.h2
-rw-r--r--src/ipa/simple/algorithms/lut.cpp15
-rw-r--r--src/ipa/simple/algorithms/lut.h5
-rw-r--r--src/ipa/simple/ipa_context.h13
-rw-r--r--src/ipa/simple/soft_simple.cpp24
10 files changed, 95 insertions, 26 deletions
diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp
index cb487ae5..70ce0cba 100644
--- a/src/ipa/rkisp1/rkisp1.cpp
+++ b/src/ipa/rkisp1/rkisp1.cpp
@@ -211,8 +211,7 @@ int IPARkISP1::init(const IPASettings &settings, unsigned int hwRevision,
int IPARkISP1::start()
{
- setControls(0);
-
+ /* \todo Properly handle startup controls. */
return 0;
}
diff --git a/src/ipa/simple/algorithms/agc.cpp b/src/ipa/simple/algorithms/agc.cpp
index 72aade14..c46bb0eb 100644
--- a/src/ipa/simple/algorithms/agc.cpp
+++ b/src/ipa/simple/algorithms/agc.cpp
@@ -11,6 +11,8 @@
#include <libcamera/base/log.h>
+#include "control_ids.h"
+
namespace libcamera {
LOG_DEFINE_CATEGORY(IPASoftExposure)
@@ -97,10 +99,15 @@ void Agc::updateExposure(IPAContext &context, IPAFrameContext &frameContext, dou
void Agc::process(IPAContext &context,
[[maybe_unused]] const uint32_t frame,
- [[maybe_unused]] IPAFrameContext &frameContext,
+ IPAFrameContext &frameContext,
const SwIspStats *stats,
- [[maybe_unused]] ControlList &metadata)
+ ControlList &metadata)
{
+ utils::Duration exposureTime =
+ context.configuration.agc.lineDuration * frameContext.sensor.exposure;
+ metadata.set(controls::ExposureTime, exposureTime.get<std::micro>());
+ metadata.set(controls::AnalogueGain, frameContext.sensor.gain);
+
/*
* Calculate Mean Sample Value (MSV) according to formula from:
* https://www.araa.asn.au/acra/acra2007/papers/paper84final.pdf
diff --git a/src/ipa/simple/algorithms/awb.cpp b/src/ipa/simple/algorithms/awb.cpp
index ec77c6e5..55719059 100644
--- a/src/ipa/simple/algorithms/awb.cpp
+++ b/src/ipa/simple/algorithms/awb.cpp
@@ -17,6 +17,8 @@
#include "libipa/colours.h"
#include "simple/ipa_context.h"
+#include "control_ids.h"
+
namespace libcamera {
LOG_DEFINE_CATEGORY(IPASoftAwb)
@@ -32,15 +34,32 @@ int Awb::configure(IPAContext &context,
return 0;
}
+void Awb::prepare(IPAContext &context,
+ [[maybe_unused]] const uint32_t frame,
+ IPAFrameContext &frameContext,
+ [[maybe_unused]] DebayerParams *params)
+{
+ auto &gains = context.activeState.awb.gains;
+ frameContext.gains.red = gains.r();
+ frameContext.gains.blue = gains.b();
+}
+
void Awb::process(IPAContext &context,
[[maybe_unused]] const uint32_t frame,
- [[maybe_unused]] IPAFrameContext &frameContext,
+ IPAFrameContext &frameContext,
const SwIspStats *stats,
ControlList &metadata)
{
const SwIspStats::Histogram &histogram = stats->yHistogram;
const uint8_t blackLevel = context.activeState.blc.level;
+ const float maxGain = 1024.0;
+ const float mdGains[] = {
+ static_cast<float>(frameContext.gains.red / maxGain),
+ static_cast<float>(frameContext.gains.blue / maxGain)
+ };
+ metadata.set(controls::ColourGains, mdGains);
+
/*
* Black level must be subtracted to get the correct AWB ratios, they
* would be off if they were computed from the whole brightness range
diff --git a/src/ipa/simple/algorithms/awb.h b/src/ipa/simple/algorithms/awb.h
index db1496cd..ad993f39 100644
--- a/src/ipa/simple/algorithms/awb.h
+++ b/src/ipa/simple/algorithms/awb.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
- * Copyright (C) 2024, Red Hat Inc.
+ * Copyright (C) 2024-2025 Red Hat Inc.
*
* Auto white balance
*/
@@ -20,6 +20,10 @@ public:
~Awb() = default;
int configure(IPAContext &context, const IPAConfigInfo &configInfo) override;
+ void prepare(IPAContext &context,
+ const uint32_t frame,
+ IPAFrameContext &frameContext,
+ DebayerParams *params) override;
void process(IPAContext &context,
const uint32_t frame,
IPAFrameContext &frameContext,
diff --git a/src/ipa/simple/algorithms/blc.cpp b/src/ipa/simple/algorithms/blc.cpp
index 1d7d370b..8c1e9ed0 100644
--- a/src/ipa/simple/algorithms/blc.cpp
+++ b/src/ipa/simple/algorithms/blc.cpp
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
- * Copyright (C) 2024, Red Hat Inc.
+ * Copyright (C) 2024-2025, Red Hat Inc.
*
* Black level handling
*/
@@ -11,6 +11,8 @@
#include <libcamera/base/log.h>
+#include "control_ids.h"
+
namespace libcamera {
namespace ipa::soft::algorithms {
@@ -49,13 +51,20 @@ void BlackLevel::process(IPAContext &context,
[[maybe_unused]] const uint32_t frame,
IPAFrameContext &frameContext,
const SwIspStats *stats,
- [[maybe_unused]] ControlList &metadata)
+ ControlList &metadata)
{
+ /* Assign each of the R G G B channels as the same black level. */
+ const int32_t blackLevel = context.activeState.blc.level * 256;
+ const int32_t blackLevels[] = {
+ blackLevel, blackLevel, blackLevel, blackLevel
+ };
+ metadata.set(controls::SensorBlackLevels, blackLevels);
+
if (context.configuration.black.level.has_value())
return;
- if (frameContext.sensor.exposure == exposure_ &&
- frameContext.sensor.gain == gain_) {
+ if (frameContext.sensor.exposure == context.activeState.blc.lastExposure &&
+ frameContext.sensor.gain == context.activeState.blc.lastGain) {
return;
}
@@ -79,8 +88,8 @@ void BlackLevel::process(IPAContext &context,
seen += histogram[i];
if (seen >= pixelThreshold) {
context.activeState.blc.level = i * histogramRatio;
- exposure_ = frameContext.sensor.exposure;
- gain_ = frameContext.sensor.gain;
+ context.activeState.blc.lastExposure = frameContext.sensor.exposure;
+ context.activeState.blc.lastGain = frameContext.sensor.gain;
LOG(IPASoftBL, Debug)
<< "Auto-set black level: "
<< i << "/" << SwIspStats::kYHistogramSize
diff --git a/src/ipa/simple/algorithms/blc.h b/src/ipa/simple/algorithms/blc.h
index 52d59cab..db9e6d63 100644
--- a/src/ipa/simple/algorithms/blc.h
+++ b/src/ipa/simple/algorithms/blc.h
@@ -30,8 +30,6 @@ public:
ControlList &metadata) override;
private:
- int32_t exposure_;
- double gain_;
std::optional<uint8_t> definedLevel_;
};
diff --git a/src/ipa/simple/algorithms/lut.cpp b/src/ipa/simple/algorithms/lut.cpp
index a06cdeba..e8638f27 100644
--- a/src/ipa/simple/algorithms/lut.cpp
+++ b/src/ipa/simple/algorithms/lut.cpp
@@ -87,9 +87,11 @@ int16_t Lut::ccmValue(unsigned int i, float ccm) const
void Lut::prepare(IPAContext &context,
[[maybe_unused]] const uint32_t frame,
- [[maybe_unused]] IPAFrameContext &frameContext,
+ IPAFrameContext &frameContext,
DebayerParams *params)
{
+ frameContext.contrast = context.activeState.knobs.contrast;
+
/*
* Update the gamma table if needed. This means if black level changes
* and since the black level gets updated only if a lower value is
@@ -139,6 +141,17 @@ void Lut::prepare(IPAContext &context,
}
}
+void Lut::process([[maybe_unused]] IPAContext &context,
+ [[maybe_unused]] const uint32_t frame,
+ [[maybe_unused]] IPAFrameContext &frameContext,
+ [[maybe_unused]] const SwIspStats *stats,
+ ControlList &metadata)
+{
+ const auto &contrast = frameContext.contrast;
+ if (contrast)
+ metadata.set(controls::Contrast, contrast.value());
+}
+
REGISTER_IPA_ALGORITHM(Lut, "Lut")
} /* namespace ipa::soft::algorithms */
diff --git a/src/ipa/simple/algorithms/lut.h b/src/ipa/simple/algorithms/lut.h
index 77324800..ba8b9021 100644
--- a/src/ipa/simple/algorithms/lut.h
+++ b/src/ipa/simple/algorithms/lut.h
@@ -30,6 +30,11 @@ public:
const uint32_t frame,
IPAFrameContext &frameContext,
DebayerParams *params) override;
+ void process(IPAContext &context,
+ const uint32_t frame,
+ IPAFrameContext &frameContext,
+ const SwIspStats *stats,
+ ControlList &metadata) override;
private:
void updateGammaTable(IPAContext &context);
diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h
index 17bcd4ca..6b1a0655 100644
--- a/src/ipa/simple/ipa_context.h
+++ b/src/ipa/simple/ipa_context.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
- * Copyright (C) 2024 Red Hat, Inc.
+ * Copyright (C) 2024-2025 Red Hat, Inc.
*
* Simple pipeline IPA Context
*/
@@ -18,6 +18,8 @@
#include <libipa/fc_queue.h>
+#include "core_ipa_interface.h"
+
namespace libcamera {
namespace ipa::soft {
@@ -27,6 +29,7 @@ struct IPASessionConfiguration {
struct {
int32_t exposureMin, exposureMax;
double againMin, againMax, againMinStep;
+ utils::Duration lineDuration;
} agc;
struct {
std::optional<uint8_t> level;
@@ -36,6 +39,8 @@ struct IPASessionConfiguration {
struct IPAActiveState {
struct {
uint8_t level;
+ int32_t lastExposure;
+ double lastGain;
} blc;
struct {
@@ -70,6 +75,11 @@ struct IPAFrameContext : public FrameContext {
int32_t exposure;
double gain;
} sensor;
+ struct {
+ double red;
+ double blue;
+ } gains;
+ std::optional<double> contrast;
};
struct IPAContext {
@@ -78,6 +88,7 @@ struct IPAContext {
{
}
+ IPACameraSensorInfo sensorInfo;
IPASessionConfiguration configuration;
IPAActiveState activeState;
FCQueue<IPAFrameContext> frameContexts;
diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp
index a87c6cdd..c94c4cd5 100644
--- a/src/ipa/simple/soft_simple.cpp
+++ b/src/ipa/simple/soft_simple.cpp
@@ -5,6 +5,7 @@
* Simple Software Image Processing Algorithm module
*/
+#include <chrono>
#include <stdint.h>
#include <sys/mman.h>
@@ -32,6 +33,8 @@
namespace libcamera {
LOG_DEFINE_CATEGORY(IPASoft)
+using namespace std::literals::chrono_literals;
+
namespace ipa::soft {
/* Maximum number of frame contexts to be held */
@@ -50,7 +53,8 @@ public:
int init(const IPASettings &settings,
const SharedFD &fdStats,
const SharedFD &fdParams,
- const ControlInfoMap &sensorInfoMap,
+ const IPACameraSensorInfo &sensorInfo,
+ const ControlInfoMap &sensorControls,
ControlInfoMap *ipaControls,
bool *ccmEnabled) override;
int configure(const IPAConfigInfo &configInfo) override;
@@ -89,7 +93,8 @@ IPASoftSimple::~IPASoftSimple()
int IPASoftSimple::init(const IPASettings &settings,
const SharedFD &fdStats,
const SharedFD &fdParams,
- const ControlInfoMap &sensorInfoMap,
+ const IPACameraSensorInfo &sensorInfo,
+ const ControlInfoMap &sensorControls,
ControlInfoMap *ipaControls,
bool *ccmEnabled)
{
@@ -100,6 +105,8 @@ int IPASoftSimple::init(const IPASettings &settings,
<< settings.sensorModel;
}
+ context_.sensorInfo = sensorInfo;
+
/* Load the tuning data file */
File file(settings.configurationFile);
if (!file.open(File::OpenModeFlag::ReadOnly)) {
@@ -173,12 +180,12 @@ int IPASoftSimple::init(const IPASettings &settings,
* Don't save the min and max control values yet, as e.g. the limits
* for V4L2_CID_EXPOSURE depend on the configured sensor resolution.
*/
- if (sensorInfoMap.find(V4L2_CID_EXPOSURE) == sensorInfoMap.end()) {
+ if (sensorControls.find(V4L2_CID_EXPOSURE) == sensorControls.end()) {
LOG(IPASoft, Error) << "Don't have exposure control";
return -EINVAL;
}
- if (sensorInfoMap.find(V4L2_CID_ANALOGUE_GAIN) == sensorInfoMap.end()) {
+ if (sensorControls.find(V4L2_CID_ANALOGUE_GAIN) == sensorControls.end()) {
LOG(IPASoft, Error) << "Don't have gain control";
return -EINVAL;
}
@@ -198,6 +205,8 @@ int IPASoftSimple::configure(const IPAConfigInfo &configInfo)
context_.activeState = {};
context_.frameContexts.clear();
+ context_.configuration.agc.lineDuration =
+ context_.sensorInfo.minLineLength * 1.0s / context_.sensorInfo.pixelRate;
context_.configuration.agc.exposureMin = exposureInfo.min().get<int32_t>();
context_.configuration.agc.exposureMax = exposureInfo.max().get<int32_t>();
if (!context_.configuration.agc.exposureMin) {
@@ -299,15 +308,10 @@ void IPASoftSimple::processStats(const uint32_t frame,
int32_t again = sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>();
frameContext.sensor.gain = camHelper_ ? camHelper_->gain(again) : again;
- /*
- * Software ISP currently does not produce any metadata. Use an empty
- * ControlList for now.
- *
- * \todo Implement proper metadata handling
- */
ControlList metadata(controls::controls);
for (auto const &algo : algorithms())
algo->process(context_, frame, frameContext, stats_, metadata);
+ metadataReady.emit(frame, metadata);
/* Sanity check */
if (!sensorControls.contains(V4L2_CID_EXPOSURE) ||