[libcamera-devel] [PATCH v6 6/7] libcamera: Add validateColorSpaces to CameraConfiguration class

David Plowman david.plowman at raspberrypi.com
Thu Nov 25 13:58:44 CET 2021


Hi Jacopo

Thanks for reviewing this.

On Wed, 24 Nov 2021 at 23:55, Jacopo Mondi <jacopo at jmondi.org> wrote:
>
> Hi David,
>
> On Thu, Nov 18, 2021 at 03:19:32PM +0000, David Plowman wrote:
> > This method forces raw streams to have the "raw" color space, and also
> > optionally makes all output streams to share the same color space as
> > some platforms may require this.
>
> I feel like it's a bit early, we don't have much platforms supporting
> colorspaces and it might be the requirements are different ?

I added this function because - a very long time ago now! - there had
been a worry about different pipeline handlers writing their own bits
of code, so I wanted to create something that people could share. But
I agree that the jury is still out on how useful this is.

>
> >
> > Signed-off-by: David Plowman <david.plowman at raspberrypi.com>
> > ---
> >  include/libcamera/camera.h |  2 ++
> >  src/libcamera/camera.cpp   | 51 ++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 53 insertions(+)
> >
> > diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h
> > index 601ee46e..fdab4410 100644
> > --- a/include/libcamera/camera.h
> > +++ b/include/libcamera/camera.h
> > @@ -69,6 +69,8 @@ public:
> >  protected:
> >       CameraConfiguration();
> >
> > +     Status validateColorSpaces(bool sharedColorSpace);
> > +
> >       std::vector<StreamConfiguration> config_;
> >  };
> >
> > diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp
> > index 400a7cf0..c1541685 100644
> > --- a/src/libcamera/camera.cpp
> > +++ b/src/libcamera/camera.cpp
> > @@ -20,6 +20,7 @@
> >
> >  #include "libcamera/internal/camera.h"
> >  #include "libcamera/internal/camera_controls.h"
> > +#include "libcamera/internal/formats.h"
> >  #include "libcamera/internal/pipeline_handler.h"
> >
> >  /**
> > @@ -314,6 +315,56 @@ std::size_t CameraConfiguration::size() const
> >       return config_.size();
> >  }
> >
> > +static bool isRaw(const PixelFormat &pixFmt)
> > +{
> > +     const PixelFormatInfo &info = PixelFormatInfo::info(pixFmt);
> > +     return info.isValid() &&
> > +            info.colourEncoding == PixelFormatInfo::ColourEncodingRAW;
> > +}
>
> I've seen this pattern so many times I'm surprised we don't have an
> helper
>
> > +
> > +CameraConfiguration::Status CameraConfiguration::validateColorSpaces(bool sharedColorSpace)
>
> Shouldn't this be documented ?

Of course, I must have forgotten.

>
> > +{
> > +     Status status = Valid;
> > +
> > +     /* Find the largest non-raw stream (if any). */
> > +     int index = -1;
> > +     for (unsigned int i = 0; i < config_.size(); i++) {
>
> for (auto &[i, cfg] utils::enumerate(config_)) is nicer

Ooh, it gets ever more like Python! I didn't know you could do that...

>
> > +             const StreamConfiguration &cfg = config_[i];
> > +             if (!isRaw(cfg.pixelFormat) && (index < 0 || cfg.size > config_[i].size))
> > +                     index = i;
> > +     }
>
> If you make sure the selected index has a colorspace the rest of the
> function can be simplified
>
>         StreamConfiguration largerYUV;
>         for (auto const &cfg : configs_) {
>                 if (isRaw(cfg.pixelformat))
>                         continue;
>
>                 if (cfg.size > largerYUV.size && cfg.colorSpace)
>                         largerYUV = cfg;
>         }
>
>         if (!largerYUV.colorSpace)
>                 ...
>
> And you could catch the case where there are no colorspaces at all
> earlier (what happens in that case ?)
>
>
> > +
> > +     /*
> > +      * Here we force raw streams to the correct color space. We handle
> > +      * the case where all output streams are to share a color space,
> > +      * which will match the color space of the largest (non-raw) stream.
> > +      */
> > +     for (auto &cfg : config_) {
> > +             std::optional<ColorSpace> initialColorSpace = cfg.colorSpace;
> > +
> > +             if (isRaw(cfg.pixelFormat))
> > +                     cfg.colorSpace = ColorSpace::Raw;
>
>                 if (isRaw(cfg.pixelFormat)) {
>                         if (cfg.colorSpace == ColorSpace::Raw)
>                                 continue;
>
>                         cfg.colorSpace = ColorSpace::Raw;
>                         status = Adjusted;
>                         continue;
>                 }
>
> > +             else if (sharedColorSpace) {
>
> the rest of the function can then be
>
>                 if (!sharedColorSpace)
>                         continue;
>
>                 if (cfg->colorSpace == largerYUV.colorSpace)
>                         continue;
>
>                 cfg.colorspace = largerYUV.colorspace
>                 status = Adjusted;
>         }
>
>         return status;
>
> Again not tested, I might have missed something indeed
>
> I would also call the "sharedColorSpace" flag "forceColorSpace" ?

With "forceColorSpace" I'm left wondering what I am "forcing"... at
least "sharedColorSpace" implies that some colour spaces are somehow
being shared. Perhaps we could have "shareOutputColorSpaces" if that's
not too long? That's 100% clear, I think!

>
> > +                     /*
> > +                      * When all outputs share a color space, use the biggest
> > +                      * output if that was set. If that was blank, but this
> > +                      * stream's is not, then use this stream's color space for
> > +                      * largest stream.
> > +                      * (index must be != -1 if there are any non-raw streams.)
> > +                      */
> > +                     if (config_[index].colorSpace)
>
> Can index be -1 here ?
>

I'll have another look at all this and see if I can make it all a bit
"more obvious".

Thanks!
David

> > +                             cfg.colorSpace = config_[index].colorSpace;
> > +                     else if (cfg.colorSpace)
>
> Thanks
>    j
>
> > +                             config_[index].colorSpace = cfg.colorSpace;
> > +             }
> > +
> > +             if (cfg.colorSpace != initialColorSpace)
> > +                     status = Adjusted;
> > +     }
> > +
> > +     return status;
> > +}
> > +
> >  /**
> >   * \var CameraConfiguration::transform
> >   * \brief User-specified transform to be applied to the image
> > --
> > 2.20.1
> >


More information about the libcamera-devel mailing list