From e297673e7686160bed5773ea54866f570f939feb Mon Sep 17 00:00:00 2001 From: Umang Jain Date: Tue, 30 Aug 2022 13:17:20 +0530 Subject: libcamera: v4l2_device: Adjust colorspace based on pixel format V4L2 has no "none" YCbCr encoding, and thus reports an encoding for all formats, including RGB and raw formats. This causes the libcamera ColorSpace to report incorrect encodings for non-YUV formats. Fix it by overriding the encoding reported by the kernel to YCbCrEncoding::None for non-YUV pixel formats and media bus formats. Similarly, override the quantization range of non-YUV formats to full range, as limited range isn't used for RGB and raw formats. Signed-off-by: Umang Jain Reviewed-by: Laurent Pinchart Reviewed-by: Paul Elder --- src/libcamera/v4l2_device.cpp | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) (limited to 'src/libcamera/v4l2_device.cpp') diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index b22a981f..301620f8 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -24,6 +24,7 @@ #include #include +#include "libcamera/internal/formats.h" #include "libcamera/internal/sysfs.h" /** @@ -805,6 +806,7 @@ static const std::map rangeToV4l2 = { /** * \brief Convert the color space fields in a V4L2 format to a ColorSpace * \param[in] v4l2Format A V4L2 format containing color space information + * \param[in] colourEncoding Type of colour encoding * * The colorspace, ycbcr_enc, xfer_func and quantization fields within a * V4L2 format structure are converted to a corresponding ColorSpace. @@ -816,7 +818,8 @@ static const std::map rangeToV4l2 = { * \retval std::nullopt One or more V4L2 color space fields were not recognised */ template -std::optional V4L2Device::toColorSpace(const T &v4l2Format) +std::optional V4L2Device::toColorSpace(const T &v4l2Format, + PixelFormatInfo::ColourEncoding colourEncoding) { auto itColor = v4l2ToColorSpace.find(v4l2Format.colorspace); if (itColor == v4l2ToColorSpace.end()) @@ -839,6 +842,14 @@ std::optional V4L2Device::toColorSpace(const T &v4l2Format) return std::nullopt; colorSpace.ycbcrEncoding = itYcbcrEncoding->second; + + /* + * V4L2 has no "none" encoding, override the value returned by + * the kernel for non-YUV formats as YCbCr encoding isn't + * applicable in that case. + */ + if (colourEncoding != PixelFormatInfo::ColourEncodingYUV) + colorSpace.ycbcrEncoding = ColorSpace::YcbcrEncoding::None; } if (v4l2Format.quantization != V4L2_QUANTIZATION_DEFAULT) { @@ -847,14 +858,24 @@ std::optional V4L2Device::toColorSpace(const T &v4l2Format) return std::nullopt; colorSpace.range = itRange->second; + + /* + * "Limited" quantization range is only meant for YUV formats. + * Override the range to "Full" for all other formats. + */ + if (colourEncoding != PixelFormatInfo::ColourEncodingYUV) + colorSpace.range = ColorSpace::Range::Full; } return colorSpace; } -template std::optional V4L2Device::toColorSpace(const struct v4l2_pix_format &); -template std::optional V4L2Device::toColorSpace(const struct v4l2_pix_format_mplane &); -template std::optional V4L2Device::toColorSpace(const struct v4l2_mbus_framefmt &); +template std::optional V4L2Device::toColorSpace(const struct v4l2_pix_format &, + PixelFormatInfo::ColourEncoding); +template std::optional V4L2Device::toColorSpace(const struct v4l2_pix_format_mplane &, + PixelFormatInfo::ColourEncoding); +template std::optional V4L2Device::toColorSpace(const struct v4l2_mbus_framefmt &, + PixelFormatInfo::ColourEncoding); /** * \brief Fill in the color space fields of a V4L2 format from a ColorSpace -- cgit v1.2.1