new file mode 100644
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024, Red Hat Inc.
+ *
+ * Black level handling
+ */
+
+#include "blc.h"
+
+#include <numeric>
+
+#include <libcamera/base/log.h>
+
+namespace libcamera {
+
+namespace ipa::soft::algorithms {
+
+LOG_DEFINE_CATEGORY(IPASoftBL)
+
+BlackLevel::BlackLevel()
+{
+}
+
+int BlackLevel::init(IPAContext &context,
+ [[maybe_unused]] const YamlObject &tuningData)
+{
+ context.activeState.black.level = 255;
+ return 0;
+}
+
+void BlackLevel::process(IPAContext &context,
+ [[maybe_unused]] const uint32_t frame,
+ [[maybe_unused]] IPAFrameContext &frameContext,
+ const SwIspStats *stats,
+ [[maybe_unused]] ControlList &metadata)
+{
+ const SwIspStats::Histogram &histogram = stats->yHistogram;
+
+ /*
+ * The constant is selected to be "good enough", not overly conservative or
+ * aggressive. There is no magic about the given value.
+ */
+ constexpr float ignoredPercentage_ = 0.02;
+ const unsigned int total =
+ std::accumulate(begin(histogram), end(histogram), 0);
+ const unsigned int pixelThreshold = ignoredPercentage_ * total;
+ const unsigned int histogramRatio = 256 / SwIspStats::kYHistogramSize;
+ const unsigned int currentBlackIdx =
+ context.activeState.black.level / histogramRatio;
+
+ for (unsigned int i = 0, seen = 0;
+ i < currentBlackIdx && i < SwIspStats::kYHistogramSize;
+ i++) {
+ seen += histogram[i];
+ if (seen >= pixelThreshold) {
+ context.activeState.black.level = i * histogramRatio;
+ LOG(IPASoftBL, Debug)
+ << "Auto-set black level: "
+ << i << "/" << SwIspStats::kYHistogramSize
+ << " (" << 100 * (seen - histogram[i]) / total << "% below, "
+ << 100 * seen / total << "% at or below)";
+ break;
+ }
+ };
+}
+
+REGISTER_IPA_ALGORITHM(BlackLevel, "BlackLevel")
+
+} /* namespace ipa::soft::algorithms */
+
+} /* namespace libcamera */
new file mode 100644
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024, Red Hat Inc.
+ *
+ * Black level handling
+ */
+
+#pragma once
+
+#include <libcamera/controls.h>
+
+#include "libcamera/internal/software_isp/swisp_stats.h"
+
+#include "algorithm.h"
+#include "ipa_context.h"
+
+namespace libcamera {
+
+namespace ipa::soft::algorithms {
+
+class BlackLevel : public Algorithm
+{
+public:
+ BlackLevel();
+ ~BlackLevel() = default;
+
+ int init(IPAContext &context, const YamlObject &tuningData)
+ override;
+ void process(IPAContext &context, const uint32_t frame,
+ IPAFrameContext &frameContext,
+ const SwIspStats *stats,
+ ControlList &metadata) override;
+};
+
+} /* namespace ipa::soft::algorithms */
+
+} /* namespace libcamera */
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: CC0-1.0
soft_simple_ipa_algorithms = files([
+ 'blc.cpp',
])
deleted file mode 100644
@@ -1,93 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2024, Red Hat Inc.
- *
- * black level handling
- */
-
-#include "black_level.h"
-
-#include <numeric>
-
-#include <libcamera/base/log.h>
-
-namespace libcamera {
-
-LOG_DEFINE_CATEGORY(IPASoftBL)
-
-namespace ipa::soft {
-
-/**
- * \class BlackLevel
- * \brief Object providing black point level for software ISP
- *
- * Black level can be provided in hardware tuning files or, if no tuning file is
- * available for the given hardware, guessed automatically, with less accuracy.
- * As tuning files are not yet implemented for software ISP, BlackLevel
- * currently provides only guessed black levels.
- *
- * This class serves for tracking black level as a property of the underlying
- * hardware, not as means of enhancing a particular scene or image.
- *
- * The class is supposed to be instantiated for the given camera stream.
- * The black level can be retrieved using BlackLevel::get() method. It is
- * initially 0 and may change when updated using BlackLevel::update() method.
- */
-
-BlackLevel::BlackLevel()
- : blackLevel_(255), blackLevelSet_(false)
-{
-}
-
-/**
- * \brief Return the current black level
- *
- * \return The black level, in the range from 0 (minimum) to 255 (maximum).
- * If the black level couldn't be determined yet, return 0.
- */
-uint8_t BlackLevel::get() const
-{
- return blackLevelSet_ ? blackLevel_ : 0;
-}
-
-/**
- * \brief Update black level from the provided histogram
- * \param[in] yHistogram The histogram to be used for updating black level
- *
- * The black level is property of the given hardware, not image. It is updated
- * only if it has not been yet set or if it is lower than the lowest value seen
- * so far.
- */
-void BlackLevel::update(SwIspStats::Histogram &yHistogram)
-{
- /*
- * The constant is selected to be "good enough", not overly conservative or
- * aggressive. There is no magic about the given value.
- */
- constexpr float ignoredPercentage_ = 0.02;
- const unsigned int total =
- std::accumulate(begin(yHistogram), end(yHistogram), 0);
- const unsigned int pixelThreshold = ignoredPercentage_ * total;
- const unsigned int histogramRatio = 256 / SwIspStats::kYHistogramSize;
- const unsigned int currentBlackIdx = blackLevel_ / histogramRatio;
-
- for (unsigned int i = 0, seen = 0;
- i < currentBlackIdx && i < SwIspStats::kYHistogramSize;
- i++) {
- seen += yHistogram[i];
- if (seen >= pixelThreshold) {
- blackLevel_ = i * histogramRatio;
- blackLevelSet_ = true;
- LOG(IPASoftBL, Debug)
- << "Auto-set black level: "
- << i << "/" << SwIspStats::kYHistogramSize
- << " (" << 100 * (seen - yHistogram[i]) / total << "% below, "
- << 100 * seen / total << "% at or below)";
- break;
- }
- };
-}
-
-} /* namespace ipa::soft */
-
-} /* namespace libcamera */
deleted file mode 100644
@@ -1,33 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2024, Red Hat Inc.
- *
- * black level handling
- */
-
-#pragma once
-
-#include <array>
-#include <stdint.h>
-
-#include "libcamera/internal/software_isp/swisp_stats.h"
-
-namespace libcamera {
-
-namespace ipa::soft {
-
-class BlackLevel
-{
-public:
- BlackLevel();
- uint8_t get() const;
- void update(SwIspStats::Histogram &yHistogram);
-
-private:
- uint8_t blackLevel_;
- bool blackLevelSet_;
-};
-
-} /* namespace ipa::soft */
-
-} /* namespace libcamera */
@@ -3,4 +3,5 @@
---
version: 1
algorithms:
+ - BlackLevel:
...
@@ -50,4 +50,12 @@ namespace libcamera::ipa::soft {
* \brief The current state of IPA algorithms
*/
+/**
+ * \var IPAActiveState::black
+ * \brief Context for the Black Level algorithm
+ *
+ * \var IPAActiveState::black.level
+ * \brief Current determined black level
+ */
+
} /* namespace libcamera::ipa::soft */
@@ -7,6 +7,8 @@
#pragma once
+#include <stdint.h>
+
#include <libipa/fc_queue.h>
namespace libcamera {
@@ -17,6 +19,9 @@ struct IPASessionConfiguration {
};
struct IPAActiveState {
+ struct {
+ uint8_t level;
+ } black;
};
struct IPAFrameContext : public FrameContext {
@@ -8,7 +8,6 @@ ipa_name = 'ipa_soft_simple'
soft_simple_sources = files([
'ipa_context.cpp',
'soft_simple.cpp',
- 'black_level.cpp',
])
soft_simple_sources += soft_simple_ipa_algorithms
@@ -29,7 +29,6 @@
#include "libipa/camera_sensor_helper.h"
-#include "black_level.h"
#include "module.h"
namespace libcamera {
@@ -61,7 +60,7 @@ class IPASoftSimple : public ipa::soft::IPASoftInterface, public Module
{
public:
IPASoftSimple()
- : params_(nullptr), stats_(nullptr), blackLevel_(BlackLevel()),
+ : params_(nullptr), stats_(nullptr),
context_({ {}, {}, { kMaxFrameContexts } }),
ignoreUpdates_(0)
{
@@ -93,7 +92,6 @@ private:
SwIspStats *stats_;
std::unique_ptr<CameraSensorHelper> camHelper_;
ControlInfoMap sensorInfoMap_;
- BlackLevel blackLevel_;
static constexpr unsigned int kGammaLookupSize = 1024;
std::array<uint8_t, kGammaLookupSize> gammaTable_;
@@ -303,9 +301,7 @@ void IPASoftSimple::processStats(const uint32_t frame,
algo->process(context_, frame, frameContext, stats_, metadata);
SwIspStats::Histogram histogram = stats_->yHistogram;
- if (ignoreUpdates_ > 0)
- blackLevel_.update(histogram);
- const uint8_t blackLevel = blackLevel_.get();
+ const uint8_t blackLevel = context_.activeState.black.level;
/*
* Black level must be subtracted to get the correct AWB ratios, they