diff options
Diffstat (limited to 'users/flokli/ipu6-softisp/libcamera/0019-libcamera-Soft-IPA-use-CameraSensorHelper-for-analog.patch')
-rw-r--r-- | users/flokli/ipu6-softisp/libcamera/0019-libcamera-Soft-IPA-use-CameraSensorHelper-for-analog.patch | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/users/flokli/ipu6-softisp/libcamera/0019-libcamera-Soft-IPA-use-CameraSensorHelper-for-analog.patch b/users/flokli/ipu6-softisp/libcamera/0019-libcamera-Soft-IPA-use-CameraSensorHelper-for-analog.patch new file mode 100644 index 000000000000..5b562c603c52 --- /dev/null +++ b/users/flokli/ipu6-softisp/libcamera/0019-libcamera-Soft-IPA-use-CameraSensorHelper-for-analog.patch @@ -0,0 +1,239 @@ +From b0c07674abecb05dc0af93a4b749971f057bc3c6 Mon Sep 17 00:00:00 2001 +From: Andrei Konovalov <andrey.konovalov.ynk@gmail.com> +Date: Mon, 11 Mar 2024 15:15:22 +0100 +Subject: [PATCH 19/21] libcamera: Soft IPA: use CameraSensorHelper for + analogue gain + +Use CameraSensorHelper to convert the analogue gain code read from the +camera sensor into real analogue gain value. In the future this makes +it possible to use faster AE/AGC algorithm. For now the same AE/AGC +algorithm is used, but even then the CameraSensorHelper lets us use the +full range of analogue gain values. + +If there is no CameraSensorHelper for the camera sensor in use, a +warning log message is printed, and the AE/AGC works exactly as before +this change. + +Signed-off-by: Andrei Konovalov <andrey.konovalov.ynk@gmail.com> +Reviewed-by: Hans de Goede <hdegoede@redhat.com> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +Reviewed-by: Milan Zamazal <mzamazal@redhat.com> +--- + .../internal/software_isp/software_isp.h | 3 +- + src/ipa/simple/soft_simple.cpp | 77 ++++++++++++------- + src/libcamera/pipeline/simple/simple.cpp | 2 +- + src/libcamera/software_isp/software_isp.cpp | 8 +- + 4 files changed, 57 insertions(+), 33 deletions(-) + +diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h +index 8d25e979..2a6db7ba 100644 +--- a/include/libcamera/internal/software_isp/software_isp.h ++++ b/include/libcamera/internal/software_isp/software_isp.h +@@ -26,6 +26,7 @@ + #include <libcamera/ipa/soft_ipa_interface.h> + #include <libcamera/ipa/soft_ipa_proxy.h> + ++#include "libcamera/internal/camera_sensor.h" + #include "libcamera/internal/dma_heaps.h" + #include "libcamera/internal/pipeline_handler.h" + #include "libcamera/internal/shared_mem_object.h" +@@ -43,7 +44,7 @@ LOG_DECLARE_CATEGORY(SoftwareIsp) + class SoftwareIsp + { + public: +- SoftwareIsp(PipelineHandler *pipe, const ControlInfoMap &sensorControls); ++ SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor); + ~SoftwareIsp(); + + int loadConfiguration([[maybe_unused]] const std::string &filename) { return 0; } +diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp +index ac027568..e4d64762 100644 +--- a/src/ipa/simple/soft_simple.cpp ++++ b/src/ipa/simple/soft_simple.cpp +@@ -22,6 +22,8 @@ + #include "libcamera/internal/software_isp/debayer_params.h" + #include "libcamera/internal/software_isp/swisp_stats.h" + ++#include "libipa/camera_sensor_helper.h" ++ + #include "black_level.h" + + namespace libcamera { +@@ -67,18 +69,27 @@ private: + DebayerParams *params_; + SwIspStats *stats_; + BlackLevel blackLevel_; ++ std::unique_ptr<CameraSensorHelper> camHelper_; + + int32_t exposure_min_, exposure_max_; +- int32_t again_min_, again_max_; +- int32_t again_, exposure_; ++ int32_t exposure_; ++ double again_min_, again_max_, againMinStep_; ++ double again_; + unsigned int ignore_updates_; + }; + +-int IPASoftSimple::init([[maybe_unused]] const IPASettings &settings, ++int IPASoftSimple::init(const IPASettings &settings, + const SharedFD &fdStats, + const SharedFD &fdParams, + const ControlInfoMap &sensorInfoMap) + { ++ camHelper_ = CameraSensorHelperFactoryBase::create(settings.sensorModel); ++ if (camHelper_ == nullptr) { ++ LOG(IPASoft, Warning) ++ << "Failed to create camera sensor helper for " ++ << settings.sensorModel; ++ } ++ + fdStats_ = fdStats; + if (!fdStats_.isValid()) { + LOG(IPASoft, Error) << "Invalid Statistics handle"; +@@ -132,25 +143,35 @@ int IPASoftSimple::configure(const ControlInfoMap &sensorInfoMap) + exposure_min_ = 1; + } + +- again_min_ = gain_info.min().get<int32_t>(); +- again_max_ = gain_info.max().get<int32_t>(); +- /* +- * The camera sensor gain (g) is usually not equal to the value written +- * into the gain register (x). But the way how the AGC algorithm changes +- * the gain value to make the total exposure closer to the optimum assumes +- * that g(x) is not too far from linear function. If the minimal gain is 0, +- * the g(x) is likely to be far from the linear, like g(x) = a / (b * x + c). +- * To avoid unexpected changes to the gain by the AGC algorithm (abrupt near +- * one edge, and very small near the other) we limit the range of the gain +- * values used. +- */ +- if (!again_min_) { +- LOG(IPASoft, Warning) << "Minimum gain is zero, that can't be linear"; +- again_min_ = std::min(100, again_min_ / 2 + again_max_ / 2); ++ int32_t again_min = gain_info.min().get<int32_t>(); ++ int32_t again_max = gain_info.max().get<int32_t>(); ++ ++ if (camHelper_) { ++ again_min_ = camHelper_->gain(again_min); ++ again_max_ = camHelper_->gain(again_max); ++ againMinStep_ = (again_max_ - again_min_) / 100.0; ++ } else { ++ /* ++ * The camera sensor gain (g) is usually not equal to the value written ++ * into the gain register (x). But the way how the AGC algorithm changes ++ * the gain value to make the total exposure closer to the optimum assumes ++ * that g(x) is not too far from linear function. If the minimal gain is 0, ++ * the g(x) is likely to be far from the linear, like g(x) = a / (b * x + c). ++ * To avoid unexpected changes to the gain by the AGC algorithm (abrupt near ++ * one edge, and very small near the other) we limit the range of the gain ++ * values used. ++ */ ++ again_max_ = again_max; ++ if (!again_min) { ++ LOG(IPASoft, Warning) << "Minimum gain is zero, that can't be linear"; ++ again_min_ = std::min(100, again_min / 2 + again_max / 2); ++ } ++ againMinStep_ = 1.0; + } + + LOG(IPASoft, Info) << "Exposure " << exposure_min_ << "-" << exposure_max_ +- << ", gain " << again_min_ << "-" << again_max_; ++ << ", gain " << again_min_ << "-" << again_max_ ++ << " (" << againMinStep_ << ")"; + + return 0; + } +@@ -252,12 +273,14 @@ void IPASoftSimple::processStats(const ControlList &sensorControls) + ControlList ctrls(sensorControls); + + exposure_ = ctrls.get(V4L2_CID_EXPOSURE).get<int32_t>(); +- again_ = ctrls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>(); ++ int32_t again = ctrls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>(); ++ again_ = camHelper_ ? camHelper_->gain(again) : again; + + updateExposure(exposureMSV); + + ctrls.set(V4L2_CID_EXPOSURE, exposure_); +- ctrls.set(V4L2_CID_ANALOGUE_GAIN, again_); ++ ctrls.set(V4L2_CID_ANALOGUE_GAIN, ++ static_cast<int32_t>(camHelper_ ? camHelper_->gainCode(again_) : again_)); + + ignore_updates_ = 2; + +@@ -276,7 +299,7 @@ void IPASoftSimple::updateExposure(double exposureMSV) + static constexpr uint8_t kExpNumeratorUp = kExpDenominator + 1; + static constexpr uint8_t kExpNumeratorDown = kExpDenominator - 1; + +- int next; ++ double next; + + if (exposureMSV < kExposureOptimal - kExposureSatisfactory) { + next = exposure_ * kExpNumeratorUp / kExpDenominator; +@@ -286,18 +309,18 @@ void IPASoftSimple::updateExposure(double exposureMSV) + exposure_ = next; + if (exposure_ >= exposure_max_) { + next = again_ * kExpNumeratorUp / kExpDenominator; +- if (next - again_ < 1) +- again_ += 1; ++ if (next - again_ < againMinStep_) ++ again_ += againMinStep_; + else + again_ = next; + } + } + + if (exposureMSV > kExposureOptimal + kExposureSatisfactory) { +- if (exposure_ == exposure_max_ && again_ != again_min_) { ++ if (exposure_ == exposure_max_ && again_ > again_min_) { + next = again_ * kExpNumeratorDown / kExpDenominator; +- if (again_ - next < 1) +- again_ -= 1; ++ if (again_ - next < againMinStep_) ++ again_ -= againMinStep_; + else + again_ = next; + } else { +diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp +index c3ebb7b7..7e932a14 100644 +--- a/src/libcamera/pipeline/simple/simple.cpp ++++ b/src/libcamera/pipeline/simple/simple.cpp +@@ -525,7 +525,7 @@ int SimpleCameraData::init() + * Instantiate Soft ISP if this is enabled for the given driver and no converter is used. + */ + if (!converter_ && pipe->swIspEnabled()) { +- swIsp_ = std::make_unique<SoftwareIsp>(pipe, sensor_->controls()); ++ swIsp_ = std::make_unique<SoftwareIsp>(pipe, sensor_.get()); + if (!swIsp_->isValid()) { + LOG(SimplePipeline, Warning) + << "Failed to create software ISP, disabling software debayering"; +diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp +index 9b49be41..ea4d96e4 100644 +--- a/src/libcamera/software_isp/software_isp.cpp ++++ b/src/libcamera/software_isp/software_isp.cpp +@@ -60,9 +60,9 @@ LOG_DEFINE_CATEGORY(SoftwareIsp) + /** + * \brief Constructs SoftwareIsp object + * \param[in] pipe The pipeline handler in use +- * \param[in] sensorControls ControlInfoMap describing the controls supported by the sensor ++ * \param[in] sensor Pointer to the CameraSensor instance owned by the pipeline handler + */ +-SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const ControlInfoMap &sensorControls) ++SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor) + : debayer_(nullptr), + debayerParams_{ DebayerParams::kGain10, DebayerParams::kGain10, DebayerParams::kGain10, 0.5f, 0 }, + dmaHeap_(DmaHeap::DmaHeapFlag::Cma | DmaHeap::DmaHeapFlag::System) +@@ -97,10 +97,10 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const ControlInfoMap &sensorCont + return; + } + +- int ret = ipa_->init(IPASettings{ "No cfg file", "No sensor model" }, ++ int ret = ipa_->init(IPASettings{ "No cfg file", sensor->model() }, + debayer_->getStatsFD(), + sharedParams_.fd(), +- sensorControls); ++ sensor->controls()); + if (ret) { + LOG(SoftwareIsp, Error) << "IPA init failed"; + debayer_.reset(); +-- +2.43.2 + |