diff options
author | David Plowman <david.plowman@raspberrypi.com> | 2023-09-15 16:58:41 +0100 |
---|---|---|
committer | Jacopo Mondi <jacopo.mondi@ideasonboard.com> | 2023-09-16 17:33:44 +0200 |
commit | b2cb498a1ac32ed7a659645e529f29e51e566d3f (patch) | |
tree | 71e30d635f281262326156b485209bdbf7d1c456 /src/ipa/rpi/controller/rpi/agc_channel.h | |
parent | cd940f7fd3a0636c79bfcb2ebb462e17f92cb987 (diff) |
ipa: rpi: agc: Reorganise code for multi-channel AGC
This commit does the basic reorganisation of the code in order to
implement multi-channel AGC. The main changes are:
* The previous Agc class (in agc.cpp) has become the AgcChannel class
in (agc_channel.cpp).
* A new Agc class is introduced which is a wrapper round a number of
AgcChannels.
* The basic plumbing from ipa_base.cpp to Agc is updated to include a
channel number. All the existing controls are hardwired to talk
directly to channel 0.
There are a couple of limitations which we expect to apply to
multi-channel AGC. We're not allowing different frame durations to be
applied to the channels, nor are we allowing separate metering
modes. To be fair, supporting these things is not impossible, but
there are reasons why it may be tricky so they remain "TBD" for now.
This patch only includes the basic reorganisation and plumbing. It
does not yet update the important methods (switchMode, prepare and
process) to implement multi-channel AGC properly. This will appear in
a subsequent commit. For now, these functions are hard-coded just to
use channel 0, thereby preserving the existing behaviour.
Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
Reviewed-by: Naushir Patuck <naush@raspberrypi.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Diffstat (limited to 'src/ipa/rpi/controller/rpi/agc_channel.h')
-rw-r--r-- | src/ipa/rpi/controller/rpi/agc_channel.h | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/src/ipa/rpi/controller/rpi/agc_channel.h b/src/ipa/rpi/controller/rpi/agc_channel.h new file mode 100644 index 00000000..aca79ef2 --- /dev/null +++ b/src/ipa/rpi/controller/rpi/agc_channel.h @@ -0,0 +1,137 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2023, Raspberry Pi Ltd + * + * agc_channel.h - AGC/AEC control algorithm + */ +#pragma once + +#include <map> +#include <string> +#include <vector> + +#include <libcamera/base/utils.h> + +#include "../agc_status.h" +#include "../awb_status.h" +#include "../controller.h" +#include "../pwl.h" + +/* This is our implementation of AGC. */ + +namespace RPiController { + +struct AgcMeteringMode { + std::vector<double> weights; + int read(const libcamera::YamlObject ¶ms); +}; + +struct AgcExposureMode { + std::vector<libcamera::utils::Duration> shutter; + std::vector<double> 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<AgcConstraint> AgcConstraintMode; + +struct AgcConfig { + int read(const libcamera::YamlObject ¶ms); + std::map<std::string, AgcMeteringMode> meteringModes; + std::map<std::string, AgcExposureMode> exposureModes; + std::map<std::string, AgcConstraintMode> constraintModes; + 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; +}; + +class AgcChannel +{ +public: + AgcChannel(); + int read(const libcamera::YamlObject ¶ms, + const Controller::HardwareConfig &hardwareConfig); + unsigned int getConvergenceFrames() const; + std::vector<double> 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, Metadata *imageMetadata); + +private: + bool updateLockStatus(DeviceStatus const &deviceStatus); + AgcConfig config_; + void housekeepConfig(); + void fetchCurrentExposure(Metadata *imageMetadata); + void fetchAwbStatus(Metadata *imageMetadata); + void computeGain(StatisticsPtr &statistics, Metadata *imageMetadata, + double &gain, double &targetY); + void computeTargetExposure(double gain); + void filterExposure(); + bool applyDigitalGain(double gain, double targetY); + 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 */ |