/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2023, Raspberry Pi Ltd * * agc_channel.h - AGC/AEC control algorithm */ #pragma once #include #include #include #include #include "../agc_status.h" #include "../awb_status.h" #include "../controller.h" #include "../pwl.h" /* This is our implementation of AGC. */ namespace RPiController { using AgcChannelTotalExposures = std::vector; struct AgcMeteringMode { std::vector weights; int read(const libcamera::YamlObject ¶ms); }; struct AgcExposureMode { std::vector shutter; std::vector gain; int read(const libcamera::YamlObject ¶ms); }; struct AgcConstraint { enum class Bound { LOWER = 0, UPPER = 1 }; Bound bound; double qLo; double qHi; Pwl yTarget; int read(const libcamera::YamlObject ¶ms); }; typedef std::vector AgcConstraintMode; struct AgcChannelConstraint { enum class Bound { LOWER = 0, UPPER = 1 }; Bound bound; unsigned int channel; double factor; int read(const libcamera::YamlObject ¶ms); }; struct AgcConfig { int read(const libcamera::YamlObject ¶ms); std::map meteringModes; std::map exposureModes; std::map constraintModes; std::vector channelConstraints; Pwl yTarget; double speed; uint16_t startupFrames; unsigned int convergenceFrames; double maxChange; double minChange; double fastReduceThreshold; double speedUpThreshold; std::string defaultMeteringMode; std::string defaultExposureMode; std::string defaultConstraintMode; double baseEv; libcamera::utils::Duration defaultExposureTime; double defaultAnalogueGain; double stableRegion; bool desaturate; }; class AgcChannel { public: AgcChannel(); int read(const libcamera::YamlObject ¶ms, const Controller::HardwareConfig &hardwareConfig); unsigned int getConvergenceFrames() const; std::vector const &getWeights() const; void setEv(double ev); void setFlickerPeriod(libcamera::utils::Duration flickerPeriod); void setMaxShutter(libcamera::utils::Duration maxShutter); void setFixedShutter(libcamera::utils::Duration fixedShutter); void setFixedAnalogueGain(double fixedAnalogueGain); void setMeteringMode(std::string const &meteringModeName); void setExposureMode(std::string const &exposureModeName); void setConstraintMode(std::string const &contraintModeName); void enableAuto(); void disableAuto(); void switchMode(CameraMode const &cameraMode, Metadata *metadata); void prepare(Metadata *imageMetadata); void process(StatisticsPtr &stats, DeviceStatus const &deviceStatus, Metadata *imageMetadata, const AgcChannelTotalExposures &channelTotalExposures); private: bool updateLockStatus(DeviceStatus const &deviceStatus); AgcConfig config_; void housekeepConfig(); void fetchCurrentExposure(DeviceStatus const &deviceStatus); void fetchAwbStatus(Metadata *imageMetadata); void computeGain(StatisticsPtr &statistics, Metadata *imageMetadata, double &gain, double &targetY); void computeTargetExposure(double gain); void filterExposure(); bool applyChannelConstraints(const AgcChannelTotalExposures &channelTotalExposures); bool applyDigitalGain(double gain, double targetY, bool channelBound); void divideUpExposure(); void writeAndFinish(Metadata *imageMetadata, bool desaturate); libcamera::utils::Duration limitShutter(libcamera::utils::Duration shutter); double limitGain(double gain) const; AgcMeteringMode *meteringMode_; AgcExposureMode *exposureMode_; AgcConstraintMode *constraintMode_; CameraMode mode_; uint64_t frameCount_; AwbStatus awb_; struct ExposureValues { ExposureValues(); libcamera::utils::Duration shutter; double analogueGain; libcamera::utils::Duration totalExposure; libcamera::utils::Duration totalExposureNoDG; /* without digital gain */ }; ExposureValues current_; /* values for the current frame */ ExposureValues target_; /* calculate the values we want here */ ExposureValues filtered_; /* these values are filtered towards target */ AgcStatus status_; int lockCount_; DeviceStatus lastDeviceStatus_; libcamera::utils::Duration lastTargetExposure_; /* Below here the "settings" that applications can change. */ std::string meteringModeName_; std::string exposureModeName_; std::string constraintModeName_; double ev_; libcamera::utils::Duration flickerPeriod_; libcamera::utils::Duration maxShutter_; libcamera::utils::Duration fixedShutter_; double fixedAnalogueGain_; }; } /* namespace RPiController */