[PATCH v2 6/9] ipa: rkisp1: Move loader functions into helper class
Paul Elder
paul.elder at ideasonboard.com
Fri Sep 13 12:41:49 CEST 2024
On Fri, Sep 13, 2024 at 10:55:10AM +0100, Kieran Bingham wrote:
> Quoting Stefan Klug (2024-09-13 08:57:24)
> > In preparation to the polynomial LSC data, move the current loader into
> > it's own helper class.
> >
> > Signed-off-by: Stefan Klug <stefan.klug at ideasonboard.com>
> > ---
> > src/ipa/rkisp1/algorithms/lsc.cpp | 125 ++++++++++++++++++------------
> > 1 file changed, 76 insertions(+), 49 deletions(-)
> >
> > diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp
> > index 87a04ec048f8..12867b8f7d0f 100644
> > --- a/src/ipa/rkisp1/algorithms/lsc.cpp
> > +++ b/src/ipa/rkisp1/algorithms/lsc.cpp
> > @@ -70,6 +70,70 @@ namespace ipa::rkisp1::algorithms {
> >
> > LOG_DEFINE_CATEGORY(RkISP1Lsc)
> >
> > +class LscClassicLoader
> > +{
> > +public:
> > + int parseLscData(const YamlObject &yamlSets,
> > + std::map<unsigned int, LensShadingCorrection::Components> &lscData)
> > + {
> > + const auto &sets = yamlSets.asList();
> > +
> > + for (const auto &yamlSet : sets) {
> > + uint32_t ct = yamlSet["ct"].get<uint32_t>(0);
> > +
> > + if (lscData.count(ct)) {
> > + LOG(RkISP1Lsc, Error)
> > + << "Multiple sets found for color temperature "
> > + << ct;
> > + return -EINVAL;
> > + }
> > +
> > + LensShadingCorrection::Components &set = lscData[ct];
> > +
> > + set.ct = ct;
> > + set.r = parseTable(yamlSet, "r");
> > + set.gr = parseTable(yamlSet, "gr");
> > + set.gb = parseTable(yamlSet, "gb");
> > + set.b = parseTable(yamlSet, "b");
> > +
> > + if (set.r.empty() || set.gr.empty() ||
> > + set.gb.empty() || set.b.empty()) {
> > + LOG(RkISP1Lsc, Error)
> > + << "Set for color temperature " << ct
> > + << " is missing tables";
> > + return -EINVAL;
> > + }
> > + }
> > +
> > + if (lscData.empty()) {
> > + LOG(RkISP1Lsc, Error) << "Failed to load any sets";
> > + return -EINVAL;
> > + }
> > +
> > + return 0;
> > + }
> > +
> > +private:
> > + std::vector<uint16_t> parseTable(const YamlObject &tuningData,
> > + const char *prop)
> > + {
> > + static constexpr unsigned int kLscNumSamples =
> > + RKISP1_CIF_ISP_LSC_SAMPLES_MAX * RKISP1_CIF_ISP_LSC_SAMPLES_MAX;
> > +
> > + std::vector<uint16_t> table =
> > + tuningData[prop].getList<uint16_t>().value_or(std::vector<uint16_t>{});
> > + if (table.size() != kLscNumSamples) {
> > + LOG(RkISP1Lsc, Error)
> > + << "Invalid '" << prop << "' values: expected "
> > + << kLscNumSamples
> > + << " elements, got " << table.size();
> > + return {};
>
> Aha - I think this is where the input validation happens?
>
> This enforces all the tables are identically sized and we'd never hit
> the assertion right?
>
> I think that earns the tag for the previous patch ...
>
>
>
> > + }
> > +
> > + return table;
> > + }
> > +};
> > +
> > static std::vector<double> parseSizes(const YamlObject &tuningData,
> > const char *prop)
> > {
> > @@ -100,25 +164,6 @@ static std::vector<double> parseSizes(const YamlObject &tuningData,
> > return sizes;
> > }
> >
> > -static std::vector<uint16_t> parseTable(const YamlObject &tuningData,
> > - const char *prop)
> > -{
> > - static constexpr unsigned int kLscNumSamples =
> > - RKISP1_CIF_ISP_LSC_SAMPLES_MAX * RKISP1_CIF_ISP_LSC_SAMPLES_MAX;
> > -
> > - std::vector<uint16_t> table =
> > - tuningData[prop].getList<uint16_t>().value_or(std::vector<uint16_t>{});
> > - if (table.size() != kLscNumSamples) {
> > - LOG(RkISP1Lsc, Error)
> > - << "Invalid '" << prop << "' values: expected "
> > - << kLscNumSamples
> > - << " elements, got " << table.size();
> > - return {};
> > - }
> > -
> > - return table;
> > -}
> > -
> > LensShadingCorrection::LensShadingCorrection()
> > : lastAppliedCt_(0), lastAppliedQuantizedCt_(0)
> > {
> > @@ -145,39 +190,21 @@ int LensShadingCorrection::init([[maybe_unused]] IPAContext &context,
> > return -EINVAL;
> > }
> >
> > - const auto &sets = yamlSets.asList();
> > std::map<unsigned int, Components> lscData;
> > - for (const auto &yamlSet : sets) {
> > - uint32_t ct = yamlSet["ct"].get<uint32_t>(0);
> > -
> > - if (lscData.count(ct)) {
> > - LOG(RkISP1Lsc, Error)
> > - << "Multiple sets found for color temperature "
> > - << ct;
> > - return -EINVAL;
> > - }
> > -
> > - Components &set = lscData[ct];
> > -
> > - set.ct = ct;
> > - set.r = parseTable(yamlSet, "r");
> > - set.gr = parseTable(yamlSet, "gr");
> > - set.gb = parseTable(yamlSet, "gb");
> > - set.b = parseTable(yamlSet, "b");
> > -
> > - if (set.r.empty() || set.gr.empty() ||
> > - set.gb.empty() || set.b.empty()) {
> > - LOG(RkISP1Lsc, Error)
> > - << "Set for color temperature " << ct
> > - << " is missing tables";
> > - return -EINVAL;
> > - }
> > + int res = 0;
> > + std::optional<std::string> type = tuningData["type"].get<std::string>();
> > + if (!type.has_value()) {
> > + LOG(RkISP1Lsc, Warning) << "LSC data is in classic format. "
>
> I wonder if we'd call this the 'table' format rather than classic ? But
> I don't think it matters.
>
> I could imagine some crazy use case might still want the full control of
> the table ... so it might not ... get deprecated.
>
> That makes me ponder if we should just call them 'table' and
> 'polynomial'.
+1 if it doesn't get deprecated yeah.
>
> But either way, for me this loader is a good way to abstract and move
> forwards.
Reviewed-by: Paul Elder <paul.elder at ideasonboard.com>
>
>
> Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
>
> > + << "This will be deprecated soon.";
> > + auto loader = LscClassicLoader();
> > + res = loader.parseLscData(yamlSets, lscData);
> > + } else {
> > + LOG(RkISP1Lsc, Error) << "Unsupported LSC type '" << *type << "'";
> > + res = -EINVAL;
> > }
> >
> > - if (lscData.empty()) {
> > - LOG(RkISP1Lsc, Error) << "Failed to load any sets";
> > - return -EINVAL;
> > - }
> > + if (res)
> > + return res;
> >
> > sets_.setData(std::move(lscData));
> >
> > --
> > 2.43.0
> >
More information about the libcamera-devel
mailing list