summaryrefslogtreecommitdiff
path: root/src/ipa/ipu3/ipu3.cpp
diff options
context:
space:
mode:
authorJean-Michel Hautbois <jeanmichel.hautbois@ideasonboard.com>2021-03-16 21:27:27 +0100
committerKieran Bingham <kieran.bingham@ideasonboard.com>2021-04-22 10:12:53 +0100
commitb2ddc9b11815976ec0bdf741fded993b8bc9ef4d (patch)
treef21468f97357e817bf04e9dfed5c90a7654c9fc5 /src/ipa/ipu3/ipu3.cpp
parent3ebb692f323eaace79ae4932bd119df2de361650 (diff)
ipa: ipu3: Add support for IPU3 AWB algorithm
The IPA will locally modify the parameters before they are passed down to the ImgU. Use a local parameter object to give a reference to those algorithms. Inherit from the Algorithm class to implement basic AWB functions. The configure() call will set exposure and gain to their minimum value, so while AGC is not there, the frames will be dark. Once AWB is done, a color temperature is estimated and a default CCM matrix will be used (yet to be tuned). Implement a basic "grey-world" AWB algorithm just for demonstration purpose. The BDS output size is passed by the pipeline handler to the IPA. The best grid is then calculated to maximize the number of pixels taken into account in each cells. As commented in the source code, it can be improved, as it has (at least) one limitation: if a cell is big (say 128 pixels wide) and indicated as saturated, it won't be taken into account at all. Maybe is it possible to have a smaller one, at the cost of a few pixels to lose, in which case we can center the grid using the x_start and y_start parameters. Signed-off-by: Jean-Michel Hautbois <jeanmichel.hautbois@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Tested-by: Jacopo Mondi <jacopo@jmondi.org> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Diffstat (limited to 'src/ipa/ipu3/ipu3.cpp')
-rw-r--r--src/ipa/ipu3/ipu3.cpp86
1 files changed, 78 insertions, 8 deletions
diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp
index 38477cad..a4d327ab 100644
--- a/src/ipa/ipu3/ipu3.cpp
+++ b/src/ipa/ipu3/ipu3.cpp
@@ -21,6 +21,11 @@
#include "libcamera/internal/buffer.h"
#include "libcamera/internal/log.h"
+#include "ipu3_awb.h"
+
+static constexpr uint32_t kMaxCellWidthPerSet = 160;
+static constexpr uint32_t kMaxCellHeightPerSet = 56;
+
namespace libcamera {
LOG_DEFINE_CATEGORY(IPAIPU3)
@@ -51,6 +56,7 @@ private:
const ipu3_uapi_stats_3a *stats);
void setControls(unsigned int frame);
+ void calculateBdsGrid(const Size &bdsOutputSize);
std::map<unsigned int, MappedFrameBuffer> buffers_;
@@ -63,6 +69,14 @@ private:
uint32_t gain_;
uint32_t minGain_;
uint32_t maxGain_;
+
+ /* Interface to the AWB algorithm */
+ std::unique_ptr<IPU3Awb> awbAlgo_;
+
+ /* Local parameter storage */
+ struct ipu3_uapi_params params_;
+
+ struct ipu3_uapi_grid_config bdsGrid_;
};
int IPAIPU3::start()
@@ -72,8 +86,58 @@ int IPAIPU3::start()
return 0;
}
+/**
+ * This method calculates a grid for the AWB algorithm in the IPU3 firmware.
+ * Its input is the BDS output size calculated in the ImgU.
+ * It is limited for now to the simplest method: find the lesser error
+ * with the width/height and respective log2 width/height of the cells.
+ *
+ * \todo The frame is divided into cells which can be 8x8 => 128x128.
+ * As a smaller cell improves the algorithm precision, adapting the
+ * x_start and y_start parameters of the grid would provoke a loss of
+ * some pixels but would also result in more accurate algorithms.
+ */
+void IPAIPU3::calculateBdsGrid(const Size &bdsOutputSize)
+{
+ uint32_t minError = std::numeric_limits<uint32_t>::max();
+ Size best;
+ Size bestLog2;
+ bdsGrid_ = {};
+
+ for (uint32_t widthShift = 3; widthShift <= 7; ++widthShift) {
+ uint32_t width = std::min(kMaxCellWidthPerSet,
+ bdsOutputSize.width >> widthShift);
+ width = width << widthShift;
+ for (uint32_t heightShift = 3; heightShift <= 7; ++heightShift) {
+ int32_t height = std::min(kMaxCellHeightPerSet,
+ bdsOutputSize.height >> heightShift);
+ height = height << heightShift;
+ uint32_t error = std::abs(static_cast<int>(width - bdsOutputSize.width))
+ + std::abs(static_cast<int>(height - bdsOutputSize.height));
+
+ if (error > minError)
+ continue;
+
+ minError = error;
+ best.width = width;
+ best.height = height;
+ bestLog2.width = widthShift;
+ bestLog2.height = heightShift;
+ }
+ }
+
+ bdsGrid_.width = best.width >> bestLog2.width;
+ bdsGrid_.block_width_log2 = bestLog2.width;
+ bdsGrid_.height = best.height >> bestLog2.height;
+ bdsGrid_.block_height_log2 = bestLog2.height;
+
+ LOG(IPAIPU3, Debug) << "Best grid found is: ("
+ << (int)bdsGrid_.width << " << " << (int)bdsGrid_.block_width_log2 << ") x ("
+ << (int)bdsGrid_.height << " << " << (int)bdsGrid_.block_height_log2 << ")";
+}
+
void IPAIPU3::configure(const std::map<uint32_t, ControlInfoMap> &entityControls,
- [[maybe_unused]] const Size &bdsOutputSize)
+ const Size &bdsOutputSize)
{
if (entityControls.empty())
return;
@@ -94,11 +158,18 @@ void IPAIPU3::configure(const std::map<uint32_t, ControlInfoMap> &entityControls
minExposure_ = std::max(itExp->second.min().get<int32_t>(), 1);
maxExposure_ = itExp->second.max().get<int32_t>();
- exposure_ = maxExposure_;
+ exposure_ = minExposure_;
minGain_ = std::max(itGain->second.min().get<int32_t>(), 1);
maxGain_ = itGain->second.max().get<int32_t>();
- gain_ = maxGain_;
+ gain_ = minGain_;
+
+ params_ = {};
+
+ calculateBdsGrid(bdsOutputSize);
+
+ awbAlgo_ = std::make_unique<IPU3Awb>();
+ awbAlgo_->initialise(params_, bdsOutputSize, bdsGrid_);
}
void IPAIPU3::mapBuffers(const std::vector<IPABuffer> &buffers)
@@ -170,10 +241,10 @@ void IPAIPU3::processControls([[maybe_unused]] unsigned int frame,
void IPAIPU3::fillParams(unsigned int frame, ipu3_uapi_params *params)
{
- /* Prepare parameters buffer. */
- memset(params, 0, sizeof(*params));
+ /* Pass a default gamma of 1.0 (default linear correction) */
+ awbAlgo_->updateWbParameters(params_, 1.0);
- /* \todo Fill in parameters buffer. */
+ *params = params_;
IPU3Action op;
op.op = ActionParamFilled;
@@ -186,8 +257,7 @@ void IPAIPU3::parseStatistics(unsigned int frame,
{
ControlList ctrls(controls::controls);
- /* \todo React to statistics and update internal state machine. */
- /* \todo Add meta-data information to ctrls. */
+ awbAlgo_->calculateWBGains(stats);
IPU3Action op;
op.op = ActionMetadataReady;