@@ -357,6 +357,39 @@ RPiCameraConfiguration::RPiCameraConfiguration(const RPiCameraData *data)
{
}
+static const std::vector<ColorSpace> validColorSpaces = {
+ ColorSpace::Sycc,
+ ColorSpace::Smpte170m,
+ ColorSpace::Rec709
+};
+
+static std::optional<ColorSpace> fixColorSpace(const std::optional<ColorSpace> &colorSpace,
+ CameraConfiguration::Status &status)
+{
+ if (!colorSpace)
+ return std::nullopt;
+
+ /*
+ * We prefer to restore any YCbCr encoding and range information that may have been
+ * removed from RGB streams. This ensures the colour spaces will be converted correctly
+ * into the colour spaces that the drivers handle, namely V4L2_COLORSPACE_JPEG,
+ * V4L2_COLORSPACE_SMPTE170M and V4L2_COLORSPACE_REC709.
+ *
+ * Luckily, the primaries and transfer function are enough for us to deduce exactly which
+ * ColorSpace was originally intended.
+ */
+ for (const auto &cs : validColorSpaces) {
+ if (colorSpace->primaries == cs.primaries &&
+ colorSpace->transferFunction == cs.transferFunction)
+ return cs;
+ }
+
+ /* If nothing was matched, ask for sYCC. */
+ LOG(RPI, Debug) << "No match for colour space " << colorSpace->toString();
+ status = CameraConfiguration::Adjusted;
+ return ColorSpace::Sycc;
+}
+
CameraConfiguration::Status RPiCameraConfiguration::validate()
{
Status status = Valid;
@@ -533,7 +566,26 @@ CameraConfiguration::Status RPiCameraConfiguration::validate()
V4L2DeviceFormat format;
format.fourcc = dev->toV4L2PixelFormat(cfg.pixelFormat);
format.size = cfg.size;
- format.colorSpace = cfg.colorSpace;
+ /*
+ * Make sure the colour space is the one we want converted for our drivers, with
+ * the YCbCr information restored. status will be set to Adjusted if we didn't
+ * like the input colour space.
+ */
+ format.colorSpace = fixColorSpace(cfg.colorSpace, status);
+
+ /*
+ * When it comes back, RGB streams will have had the YCbCr information
+ * overwritten again, so let's figure out what we really expect to be
+ * returned.
+ */
+ auto checkColorSpace = format.colorSpace;
+ if (checkColorSpace) {
+ const PixelFormatInfo &info = PixelFormatInfo::info(cfg.pixelFormat);
+ if (info.colourEncoding == PixelFormatInfo::ColourEncodingRGB) {
+ checkColorSpace->ycbcrEncoding = ColorSpace::YcbcrEncoding::None;
+ checkColorSpace->range = ColorSpace::Range::Full;
+ }
+ }
LOG(RPI, Debug)
<< "Try color space " << ColorSpace::toString(cfg.colorSpace);
@@ -542,7 +594,7 @@ CameraConfiguration::Status RPiCameraConfiguration::validate()
if (ret)
return Invalid;
- if (cfg.colorSpace != format.colorSpace) {
+ if (checkColorSpace != format.colorSpace) {
status = Adjusted;
LOG(RPI, Debug)
<< "Color space changed from "
In this patch we fix up colour spaces by adding the YCbCr information that is now not present for streams with an RGB output format. We need this information so that colour spaces are translated into the V4L2 ones that the Raspberry Pi hardware drivers will interpret correctly. Related to this, the YCbCr information is once again removed before the actual colour space is returned to us, so we have to be more careful about how we check that we got what we expected. Signed-off-by: David Plowman <david.plowman@raspberrypi.com> --- .../pipeline/raspberrypi/raspberrypi.cpp | 56 ++++++++++++++++++- 1 file changed, 54 insertions(+), 2 deletions(-)