[{"id":24874,"web_url":"https://patchwork.libcamera.org/comment/24874/","msgid":"<20220831220921.GD27075@pyrite.rasen.tech>","date":"2022-08-31T22:09:21","subject":"Re: [libcamera-devel] [PATCH v4 2/7] libcamera: v4l2_device: Adjust\n\tcolorspace based on pixel format","submitter":{"id":97,"url":"https://patchwork.libcamera.org/api/people/97/","name":"Nicolas Dufresne via libcamera-devel","email":"libcamera-devel@lists.libcamera.org"},"content":"On Tue, Aug 30, 2022 at 01:17:20PM +0530, Umang Jain via libcamera-devel wrote:\n> V4L2 has no \"none\" YCbCr encoding, and thus reports an encoding for all\n> formats, including RGB and raw formats. This causes the libcamera\n> ColorSpace to report incorrect encodings for non-YUV formats. Fix it by\n> overriding the encoding reported by the kernel to YCbCrEncoding::None\n> for non-YUV pixel formats and media bus formats.\n> \n> Similarly, override the quantization range of non-YUV formats to full\n> range, as limited range isn't used for RGB and raw formats.\n> \n> Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>\n> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\nReviewed-by: Paul Elder <paul.elder@ideasonboard.com>\n\n> ---\n>  include/libcamera/internal/v4l2_device.h |  5 +++-\n>  src/libcamera/v4l2_device.cpp            | 29 +++++++++++++++++++----\n>  src/libcamera/v4l2_subdevice.cpp         | 30 ++++++++++++++++++++++--\n>  src/libcamera/v4l2_videodevice.cpp       | 12 ++++++----\n>  4 files changed, 65 insertions(+), 11 deletions(-)\n> \n> diff --git a/include/libcamera/internal/v4l2_device.h b/include/libcamera/internal/v4l2_device.h\n> index a52a5f2c..75304be1 100644\n> --- a/include/libcamera/internal/v4l2_device.h\n> +++ b/include/libcamera/internal/v4l2_device.h\n> @@ -22,6 +22,8 @@\n>  #include <libcamera/color_space.h>\n>  #include <libcamera/controls.h>\n>  \n> +#include \"libcamera/internal/formats.h\"\n> +\n>  namespace libcamera {\n>  \n>  class EventNotifier;\n> @@ -59,7 +61,8 @@ protected:\n>  \tint fd() const { return fd_.get(); }\n>  \n>  \ttemplate<typename T>\n> -\tstatic std::optional<ColorSpace> toColorSpace(const T &v4l2Format);\n> +\tstatic std::optional<ColorSpace> toColorSpace(const T &v4l2Format,\n> +\t\t\t\t\t\t      PixelFormatInfo::ColourEncoding colourEncoding);\n>  \n>  \ttemplate<typename T>\n>  \tstatic int fromColorSpace(const std::optional<ColorSpace> &colorSpace, T &v4l2Format);\n> diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp\n> index b22a981f..301620f8 100644\n> --- a/src/libcamera/v4l2_device.cpp\n> +++ b/src/libcamera/v4l2_device.cpp\n> @@ -24,6 +24,7 @@\n>  #include <libcamera/base/log.h>\n>  #include <libcamera/base/utils.h>\n>  \n> +#include \"libcamera/internal/formats.h\"\n>  #include \"libcamera/internal/sysfs.h\"\n>  \n>  /**\n> @@ -805,6 +806,7 @@ static const std::map<ColorSpace::Range, v4l2_quantization> rangeToV4l2 = {\n>  /**\n>   * \\brief Convert the color space fields in a V4L2 format to a ColorSpace\n>   * \\param[in] v4l2Format A V4L2 format containing color space information\n> + * \\param[in] colourEncoding Type of colour encoding\n>   *\n>   * The colorspace, ycbcr_enc, xfer_func and quantization fields within a\n>   * V4L2 format structure are converted to a corresponding ColorSpace.\n> @@ -816,7 +818,8 @@ static const std::map<ColorSpace::Range, v4l2_quantization> rangeToV4l2 = {\n>   * \\retval std::nullopt One or more V4L2 color space fields were not recognised\n>   */\n>  template<typename T>\n> -std::optional<ColorSpace> V4L2Device::toColorSpace(const T &v4l2Format)\n> +std::optional<ColorSpace> V4L2Device::toColorSpace(const T &v4l2Format,\n> +\t\t\t\t\t\t   PixelFormatInfo::ColourEncoding colourEncoding)\n>  {\n>  \tauto itColor = v4l2ToColorSpace.find(v4l2Format.colorspace);\n>  \tif (itColor == v4l2ToColorSpace.end())\n> @@ -839,6 +842,14 @@ std::optional<ColorSpace> V4L2Device::toColorSpace(const T &v4l2Format)\n>  \t\t\treturn std::nullopt;\n>  \n>  \t\tcolorSpace.ycbcrEncoding = itYcbcrEncoding->second;\n> +\n> +\t\t/*\n> +\t\t * V4L2 has no \"none\" encoding, override the value returned by\n> +\t\t * the kernel for non-YUV formats as YCbCr encoding isn't\n> +\t\t * applicable in that case.\n> +\t\t */\n> +\t\tif (colourEncoding != PixelFormatInfo::ColourEncodingYUV)\n> +\t\t\tcolorSpace.ycbcrEncoding = ColorSpace::YcbcrEncoding::None;\n>  \t}\n>  \n>  \tif (v4l2Format.quantization != V4L2_QUANTIZATION_DEFAULT) {\n> @@ -847,14 +858,24 @@ std::optional<ColorSpace> V4L2Device::toColorSpace(const T &v4l2Format)\n>  \t\t\treturn std::nullopt;\n>  \n>  \t\tcolorSpace.range = itRange->second;\n> +\n> +\t\t/*\n> +\t\t * \"Limited\" quantization range is only meant for YUV formats.\n> +\t\t * Override the range to \"Full\" for all other formats.\n> +\t\t */\n> +\t\tif (colourEncoding != PixelFormatInfo::ColourEncodingYUV)\n> +\t\t\tcolorSpace.range = ColorSpace::Range::Full;\n>  \t}\n>  \n>  \treturn colorSpace;\n>  }\n>  \n> -template std::optional<ColorSpace> V4L2Device::toColorSpace(const struct v4l2_pix_format &);\n> -template std::optional<ColorSpace> V4L2Device::toColorSpace(const struct v4l2_pix_format_mplane &);\n> -template std::optional<ColorSpace> V4L2Device::toColorSpace(const struct v4l2_mbus_framefmt &);\n> +template std::optional<ColorSpace> V4L2Device::toColorSpace(const struct v4l2_pix_format &,\n> +\t\t\t\t\t\t\t    PixelFormatInfo::ColourEncoding);\n> +template std::optional<ColorSpace> V4L2Device::toColorSpace(const struct v4l2_pix_format_mplane &,\n> +\t\t\t\t\t\t\t    PixelFormatInfo::ColourEncoding);\n> +template std::optional<ColorSpace> V4L2Device::toColorSpace(const struct v4l2_mbus_framefmt &,\n> +\t\t\t\t\t\t\t    PixelFormatInfo::ColourEncoding);\n>  \n>  /**\n>   * \\brief Fill in the color space fields of a V4L2 format from a ColorSpace\n> diff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp\n> index 07a0bb07..95bfde34 100644\n> --- a/src/libcamera/v4l2_subdevice.cpp\n> +++ b/src/libcamera/v4l2_subdevice.cpp\n> @@ -503,7 +503,20 @@ int V4L2Subdevice::getFormat(unsigned int pad, V4L2SubdeviceFormat *format,\n>  \tformat->size.width = subdevFmt.format.width;\n>  \tformat->size.height = subdevFmt.format.height;\n>  \tformat->mbus_code = subdevFmt.format.code;\n> -\tformat->colorSpace = toColorSpace(subdevFmt.format);\n> +\n> +\tPixelFormatInfo::ColourEncoding colourEncoding;\n> +\tauto iter = formatInfoMap.find(subdevFmt.format.code);\n> +\tif (iter != formatInfoMap.end()) {\n> +\t\tcolourEncoding = iter->second.colourEncoding;\n> +\t} else {\n> +\t\tLOG(V4L2, Warning)\n> +\t\t\t<< \"Unknown subdev format \"\n> +\t\t\t<< utils::hex(subdevFmt.format.code, 4)\n> +\t\t\t<< \", defaulting to RGB encoding\";\n> +\n> +\t\tcolourEncoding = PixelFormatInfo::ColourEncodingRGB;\n> +\t}\n> +\tformat->colorSpace = toColorSpace(subdevFmt.format, colourEncoding);\n>  \n>  \treturn 0;\n>  }\n> @@ -549,7 +562,20 @@ int V4L2Subdevice::setFormat(unsigned int pad, V4L2SubdeviceFormat *format,\n>  \tformat->size.width = subdevFmt.format.width;\n>  \tformat->size.height = subdevFmt.format.height;\n>  \tformat->mbus_code = subdevFmt.format.code;\n> -\tformat->colorSpace = toColorSpace(subdevFmt.format);\n> +\n> +\tPixelFormatInfo::ColourEncoding colourEncoding;\n> +\tauto iter = formatInfoMap.find(subdevFmt.format.code);\n> +\tif (iter != formatInfoMap.end()) {\n> +\t\tcolourEncoding = iter->second.colourEncoding;\n> +\t} else {\n> +\t\tLOG(V4L2, Warning)\n> +\t\t\t<< \"Unknown subdev format \"\n> +\t\t\t<< utils::hex(subdevFmt.format.code, 4)\n> +\t\t\t<< \", defaulting to RGB encoding\";\n> +\n> +\t\tcolourEncoding = PixelFormatInfo::ColourEncodingRGB;\n> +\t}\n> +\tformat->colorSpace = toColorSpace(subdevFmt.format, colourEncoding);\n>  \n>  \treturn 0;\n>  }\n> diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp\n> index 5a2d0e5b..0e3f5436 100644\n> --- a/src/libcamera/v4l2_videodevice.cpp\n> +++ b/src/libcamera/v4l2_videodevice.cpp\n> @@ -931,7 +931,8 @@ int V4L2VideoDevice::getFormatMultiplane(V4L2DeviceFormat *format)\n>  \tformat->size.height = pix->height;\n>  \tformat->fourcc = V4L2PixelFormat(pix->pixelformat);\n>  \tformat->planesCount = pix->num_planes;\n> -\tformat->colorSpace = toColorSpace(*pix);\n> +\tformat->colorSpace =\n> +\t\ttoColorSpace(*pix, PixelFormatInfo::info(format->fourcc).colourEncoding);\n>  \n>  \tfor (unsigned int i = 0; i < format->planesCount; ++i) {\n>  \t\tformat->planes[i].bpl = pix->plane_fmt[i].bytesperline;\n> @@ -987,7 +988,8 @@ int V4L2VideoDevice::trySetFormatMultiplane(V4L2DeviceFormat *format, bool set)\n>  \t\tformat->planes[i].bpl = pix->plane_fmt[i].bytesperline;\n>  \t\tformat->planes[i].size = pix->plane_fmt[i].sizeimage;\n>  \t}\n> -\tformat->colorSpace = toColorSpace(*pix);\n> +\tformat->colorSpace =\n> +\t\ttoColorSpace(*pix, PixelFormatInfo::info(format->fourcc).colourEncoding);\n>  \n>  \treturn 0;\n>  }\n> @@ -1011,7 +1013,8 @@ int V4L2VideoDevice::getFormatSingleplane(V4L2DeviceFormat *format)\n>  \tformat->planesCount = 1;\n>  \tformat->planes[0].bpl = pix->bytesperline;\n>  \tformat->planes[0].size = pix->sizeimage;\n> -\tformat->colorSpace = toColorSpace(*pix);\n> +\tformat->colorSpace =\n> +\t\ttoColorSpace(*pix, PixelFormatInfo::info(format->fourcc).colourEncoding);\n>  \n>  \treturn 0;\n>  }\n> @@ -1053,7 +1056,8 @@ int V4L2VideoDevice::trySetFormatSingleplane(V4L2DeviceFormat *format, bool set)\n>  \tformat->planesCount = 1;\n>  \tformat->planes[0].bpl = pix->bytesperline;\n>  \tformat->planes[0].size = pix->sizeimage;\n> -\tformat->colorSpace = toColorSpace(*pix);\n> +\tformat->colorSpace =\n> +\t\ttoColorSpace(*pix, PixelFormatInfo::info(format->fourcc).colourEncoding);\n>  \n>  \treturn 0;\n>  }\n> -- \n> 2.37.2\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 5F235C3272\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 31 Aug 2022 22:09:31 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 95CF561FC7;\n\tThu,  1 Sep 2022 00:09:30 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 3BDB861F9C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  1 Sep 2022 00:09:28 +0200 (CEST)","from pyrite.rasen.tech (unknown [50.228.9.220])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id CE194481;\n\tThu,  1 Sep 2022 00:09:26 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1661983770;\n\tbh=L8nYOPr/ukdvLCDJyYptY0hgoF2Kjfxwdu0b8dzTu0s=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=4HskPqoAS6Z4emHmLh3TLAFMPQvTEKuUNNIIl1Gi+xWQQAemW3h2SXbLUnqtTmx1v\n\tsxieuJxx+q6TqJOjckLGdpDKUNZT83WuSpdkO+Y0DfxUg8lFcYq1TcfZYklQukwH+B\n\tXO4DyX10xJ10u+Y4YRnx0eqJ0sPnIEWrtYfubLLQ1ciFGVdPEfREMNnftk64woqmSL\n\tBhB2pGg5yDHLGp0JVxoghzuEtUqdoo846/HJM4IPrMmH7/BXjG2bMYSB3q174TCbLt\n\tdKVV4PeAWTnWNXHveZbfGQF11OCfJC83uixjLRkkrEgkzstaOxWTk4dzMdSJIiYiUR\n\tr742HGMMDTqtg==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1661983767;\n\tbh=L8nYOPr/ukdvLCDJyYptY0hgoF2Kjfxwdu0b8dzTu0s=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=KOeF3Wl55XTYoM9IxJZ88Vha+41X7e4V6rUDi5ziVHjeE5DBOV5HBPr7YbVgSm/TU\n\t9j5uXL/aau+65eA+JKsMUFAaxjXAAOiLOrJOQCBEELf0P4D+12IeJMEhAofvQSpDB6\n\tL6RDp74M09i9j38m6+GdK+0MjYuD7k3i8uZUo22g="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"KOeF3Wl5\"; dkim-atps=neutral","Date":"Wed, 31 Aug 2022 18:09:21 -0400","To":"Umang Jain <umang.jain@ideasonboard.com>","Message-ID":"<20220831220921.GD27075@pyrite.rasen.tech>","References":"<20220830074725.1059643-1-umang.jain@ideasonboard.com>\n\t<20220830074725.1059643-3-umang.jain@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=us-ascii","Content-Disposition":"inline","In-Reply-To":"<20220830074725.1059643-3-umang.jain@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v4 2/7] libcamera: v4l2_device: Adjust\n\tcolorspace based on pixel format","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Paul Elder via libcamera-devel <libcamera-devel@lists.libcamera.org>","Reply-To":"paul.elder@ideasonboard.com","Cc":"rishikeshdonadkar@gmail.com, libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]