@@ -129,8 +129,9 @@ int Agc::configure(IPAContext &context,
void Agc::queueRequest([[maybe_unused]] typename Module::Context &context,
[[maybe_unused]] const uint32_t frame,
[[maybe_unused]] typename Module::FrameContext &frameContext,
- [[maybe_unused]] const ControlList &controls)
+ const ControlList &controls)
{
+ parseControls(controls);
}
Histogram Agc::parseStatistics(const ipu3_uapi_stats_3a *stats,
@@ -137,6 +137,10 @@ static constexpr double kDefaultRelativeLuminanceTarget = 0.16;
AgcMeanLuminance::AgcMeanLuminance()
: frameCount_(0), filteredExposure_(0s), relativeLuminanceTarget_(0)
{
+ controls_[&controls::AeFlickerMode] = ControlInfo({ { ControlValue(controls::FlickerOff),
+ ControlValue(controls::FlickerManual) } },
+ ControlValue(controls::FlickerOff));
+ controls_[&controls::AeFlickerPeriod] = ControlInfo(100, 1000000);
}
AgcMeanLuminance::~AgcMeanLuminance() = default;
@@ -480,6 +484,39 @@ double AgcMeanLuminance::constraintClampGain(uint32_t constraintModeIndex,
return gain;
}
+/**
+ * \brief Parse the controls passed to an algorithm for the ones we need
+ * \param[in] controls the ControlList passed to an algorithm by the IPA
+ *
+ * This function must be called by a derived class in its queueRequest()
+ * function so that we can extract the controls needed by this base class.
+ */
+void AgcMeanLuminance::parseControls(const ControlList &controls)
+{
+ const auto &flickerMode = controls.get(controls::AeFlickerMode);
+ if (flickerMode) {
+ switch (*flickerMode) {
+ case controls::AeFlickerModeEnum::FlickerOff:
+ case controls::AeFlickerModeEnum::FlickerManual:
+ flickerMode_ = static_cast<controls::AeFlickerModeEnum>(*flickerMode);
+ break;
+ default:
+ LOG(AgcMeanLuminance, Error)
+ << "Flicker mode " << *flickerMode << " is not supported";
+ break;
+ }
+ }
+
+ const auto &flickerPeriod = controls.get(controls::AeFlickerPeriod);
+ if (flickerPeriod) {
+ /*
+ * If at some future point we support automatic flicker
+ * mitigation then this will need revision.
+ */
+ flickerPeriod_ = *flickerPeriod * 1.0us;
+ }
+}
+
/**
* \brief Apply a filter on the exposure value to limit the speed of changes
* \param[in] exposureValue The target exposure from the AGC algorithm
@@ -561,7 +598,15 @@ AgcMeanLuminance::calculateNewEv(uint32_t constraintModeIndex,
newExposureValue = filterExposure(newExposureValue);
frameCount_++;
- return exposureModeHelper->splitExposure(newExposureValue, std::nullopt);
+
+ std::optional<utils::Duration> flickerPeriod;
+
+ if (flickerMode_ == controls::AeFlickerModeEnum::FlickerManual)
+ flickerPeriod = flickerPeriod_;
+ else
+ flickerPeriod = std::nullopt;
+
+ return exposureModeHelper->splitExposure(newExposureValue, flickerPeriod);
}
/**
@@ -14,6 +14,7 @@
#include <libcamera/base/utils.h>
+#include <libcamera/control_ids.h>
#include <libcamera/controls.h>
#include "libcamera/internal/yaml_parser.h"
@@ -71,6 +72,8 @@ public:
frameCount_ = 0;
}
+ void parseControls(const ControlList &controls);
+
private:
virtual double estimateLuminance(const double gain) const = 0;
@@ -87,6 +90,8 @@ private:
uint64_t frameCount_;
utils::Duration filteredExposure_;
double relativeLuminanceTarget_;
+ utils::Duration flickerPeriod_;
+ controls::AeFlickerModeEnum flickerMode_;
std::map<int32_t, std::vector<AgcConstraint>> constraintModes_;
std::map<int32_t, std::shared_ptr<ExposureModeHelper>> exposureModeHelpers_;
@@ -238,6 +238,8 @@ void Agc::queueRequest(IPAContext &context, const uint32_t frame,
<< "Digital gain set to " << agc.manual.ispGain
<< " on request sequence " << frame;
}
+
+ parseControls(controls);
}
size_t Agc::fillGainParamBlock(IPAContext &context, IPAFrameContext &frameContext,
@@ -315,6 +315,8 @@ void Agc::queueRequest(IPAContext &context,
agc.maxFrameDuration = maxFrameDuration;
}
frameContext.agc.maxFrameDuration = agc.maxFrameDuration;
+
+ parseControls(controls);
}
/**