[{"id":19801,"web_url":"https://patchwork.libcamera.org/comment/19801/","msgid":"<20210923062656.GN4382@pyrite.rasen.tech>","date":"2021-09-23T06:26:56","subject":"Re: [libcamera-devel] [PATCH 2/3] libcamera: Support passing\n\tColorSpaces to V4L2 drivers","submitter":{"id":17,"url":"https://patchwork.libcamera.org/api/people/17/","name":"Paul Elder","email":"paul.elder@ideasonboard.com"},"content":"Hi David,\n\nOn Thu, Aug 05, 2021 at 03:21:53PM +0100, David Plowman wrote:\n> The ColorSpace class is added to the StreamConfiguration, and is now\n> passed to V4L2 devices where it is handled appropriately. Note how\n> this means that the colour space is configured per-stream (though\n> platforms may restrict this).\n> \n> Signed-off-by: David Plowman <david.plowman@raspberrypi.com>\n> ---\n>  include/libcamera/internal/v4l2_videodevice.h |   2 +\n>  include/libcamera/stream.h                    |   3 +\n>  src/libcamera/v4l2_videodevice.cpp            | 117 ++++++++++++++++++\n>  3 files changed, 122 insertions(+)\n> \n> diff --git a/include/libcamera/internal/v4l2_videodevice.h b/include/libcamera/internal/v4l2_videodevice.h\n> index e767ec84..c05899cf 100644\n> --- a/include/libcamera/internal/v4l2_videodevice.h\n> +++ b/include/libcamera/internal/v4l2_videodevice.h\n> @@ -20,6 +20,7 @@\n>  #include <libcamera/base/log.h>\n>  #include <libcamera/base/signal.h>\n>  \n> +#include <libcamera/color_space.h>\n>  #include <libcamera/framebuffer.h>\n>  #include <libcamera/geometry.h>\n>  #include <libcamera/pixel_format.h>\n> @@ -163,6 +164,7 @@ public:\n>  \n>  \tV4L2PixelFormat fourcc;\n>  \tSize size;\n> +\tColorSpace colorSpace;\n>  \n>  \tstd::array<Plane, 3> planes;\n>  \tunsigned int planesCount = 0;\n> diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h\n> index 0c55e716..131f7733 100644\n> --- a/include/libcamera/stream.h\n> +++ b/include/libcamera/stream.h\n> @@ -12,6 +12,7 @@\n>  #include <string>\n>  #include <vector>\n>  \n> +#include <libcamera/color_space.h>\n>  #include <libcamera/framebuffer.h>\n>  #include <libcamera/geometry.h>\n>  #include <libcamera/pixel_format.h>\n> @@ -47,6 +48,8 @@ struct StreamConfiguration {\n>  \n>  \tunsigned int bufferCount;\n>  \n> +\tColorSpace colorSpace;\n> +\n>  \tStream *stream() const { return stream_; }\n>  \tvoid setStream(Stream *stream) { stream_ = stream; }\n>  \tconst StreamFormats &formats() const { return formats_; }\n> diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp\n> index da2af6a1..7f30412c 100644\n> --- a/src/libcamera/v4l2_videodevice.cpp\n> +++ b/src/libcamera/v4l2_videodevice.cpp\n> @@ -366,6 +366,11 @@ bool V4L2BufferCache::Entry::operator==(const FrameBuffer &buffer) const\n>   * \\brief The image size in pixels\n>   */\n>  \n> +/**\n> + * \\var V4L2DeviceFormat::colorSpace\n> + * \\brief The color space of the pixels\n> + */\n> +\n>  /**\n>   * \\var V4L2DeviceFormat::fourcc\n>   * \\brief The fourcc code describing the pixel encoding scheme\n> @@ -731,6 +736,114 @@ int V4L2VideoDevice::getFormat(V4L2DeviceFormat *format)\n>  \t\treturn getFormatSingleplane(format);\n>  }\n>  \n> +static const std::vector<std::pair<ColorSpace, v4l2_colorspace>> colorSpaceToV4l2 = {\n\nWhat's wrong with a map? iirc ColorSpace has operator==() so\nshouldn't find() below *just work*?\n\n> +\t{ ColorSpace::RAW, V4L2_COLORSPACE_RAW },\n> +\t{ ColorSpace::JFIF, V4L2_COLORSPACE_JPEG },\n> +\t{ ColorSpace::SMPTE170M, V4L2_COLORSPACE_SMPTE170M },\n> +\t{ ColorSpace::REC709, V4L2_COLORSPACE_REC709 },\n> +\t{ ColorSpace::REC2020, V4L2_COLORSPACE_BT2020 },\n> +};\n> +\n> +static const std::map<ColorSpace::Encoding, v4l2_ycbcr_encoding> encodingToV4l2 = {\n> +\t{ ColorSpace::Encoding::REC601, V4L2_YCBCR_ENC_601 },\n> +\t{ ColorSpace::Encoding::REC709, V4L2_YCBCR_ENC_709 },\n> +\t{ ColorSpace::Encoding::REC2020, V4L2_YCBCR_ENC_BT2020 },\n> +};\n> +\n> +static const std::map<ColorSpace::TransferFunction, v4l2_xfer_func> transferFunctionToV4l2 = {\n> +\t{ ColorSpace::TransferFunction::IDENTITY, V4L2_XFER_FUNC_NONE },\n> +\t{ ColorSpace::TransferFunction::SRGB, V4L2_XFER_FUNC_SRGB },\n> +\t{ ColorSpace::TransferFunction::REC709, V4L2_XFER_FUNC_709 },\n> +};\n> +\n> +static const std::map<ColorSpace::Range, v4l2_quantization> rangeToV4l2 = {\n> +\t{ ColorSpace::Range::FULL, V4L2_QUANTIZATION_FULL_RANGE },\n> +\t{ ColorSpace::Range::LIMITED, V4L2_QUANTIZATION_LIM_RANGE },\n> +};\n\nAlso I would move the reverse-maps that you have below here, so that\nit's easier to see them together if changes need to be made on them.\n(Does C++ have a double-sided map...?)\n\n> +\n> +template<typename T>\n> +static void setColorSpace(const ColorSpace &colorSpace, T &v4l2PixFormat)\n> +{\n> +\tif (!colorSpace.isFullyDefined())\n> +\t\tLOG(V4L2, Warning) << \"Setting non-fully defined colour space\"\n> +\t\t\t\t   << colorSpace.toString();\n> +\n> +\tv4l2PixFormat.colorspace = V4L2_COLORSPACE_DEFAULT;\n> +\tv4l2PixFormat.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;\n> +\tv4l2PixFormat.xfer_func = V4L2_XFER_FUNC_DEFAULT;\n> +\tv4l2PixFormat.quantization = V4L2_QUANTIZATION_DEFAULT;\n> +\n> +\tauto itColor = std::find_if(colorSpaceToV4l2.begin(), colorSpaceToV4l2.end(),\n> +\t\t\t\t     [&colorSpace](const std::pair<ColorSpace, v4l2_colorspace> &item) { return colorSpace == item.first; });\n> +\tif (itColor != colorSpaceToV4l2.end())\n> +\t\tv4l2PixFormat.colorspace = itColor->second;\n> +\n> +\tauto itEncoding = encodingToV4l2.find(colorSpace.encoding);\n> +\tif (itEncoding != encodingToV4l2.end())\n> +\t\tv4l2PixFormat.ycbcr_enc = itEncoding->second;\n> +\n> +\tauto itTransfer = transferFunctionToV4l2.find(colorSpace.transferFunction);\n> +\tif (itTransfer != transferFunctionToV4l2.end())\n> +\t\tv4l2PixFormat.xfer_func = itTransfer->second;\n> +\n> +\tauto itRange = rangeToV4l2.find(colorSpace.range);\n> +\tif (itRange != rangeToV4l2.end())\n> +\t\tv4l2PixFormat.quantization = itRange->second;\n> +}\n> +\n> +static const std::map<uint32_t, ColorSpace> v4l2ToColorSpace = {\n> +\t{ V4L2_COLORSPACE_RAW, ColorSpace::RAW },\n> +\t{ V4L2_COLORSPACE_JPEG, ColorSpace::JFIF },\n> +\t{ V4L2_COLORSPACE_SRGB, ColorSpace::JFIF },\n> +\t{ V4L2_COLORSPACE_SMPTE170M, ColorSpace::SMPTE170M },\n> +\t{ V4L2_COLORSPACE_REC709, ColorSpace::REC709 },\n> +\t{ V4L2_COLORSPACE_BT2020, ColorSpace::REC2020 },\n> +};\n> +\n> +static const std::map<uint32_t, ColorSpace::Encoding> v4l2ToEncoding = {\n> +\t{ V4L2_YCBCR_ENC_601, ColorSpace::Encoding::REC601 },\n> +\t{ V4L2_YCBCR_ENC_709, ColorSpace::Encoding::REC709 },\n> +\t{ V4L2_YCBCR_ENC_BT2020, ColorSpace::Encoding::REC2020 },\n> +};\n> +\n> +static const std::map<uint32_t, ColorSpace::TransferFunction> v4l2ToTransferFunction = {\n> +\t{ V4L2_XFER_FUNC_NONE, ColorSpace::TransferFunction::IDENTITY },\n> +\t{ V4L2_XFER_FUNC_SRGB, ColorSpace::TransferFunction::SRGB },\n> +\t{ V4L2_XFER_FUNC_709, ColorSpace::TransferFunction::REC709 },\n> +};\n> +\n> +static const std::map<uint32_t, ColorSpace::Range> v4l2ToRange = {\n> +\t{ V4L2_QUANTIZATION_FULL_RANGE, ColorSpace::Range::FULL },\n> +\t{ V4L2_QUANTIZATION_LIM_RANGE, ColorSpace::Range::LIMITED },\n> +};\n> +\n> +template<typename T>\n> +static ColorSpace getColorSpace(const T &v4l2PixFormat)\n> +{\n> +\tColorSpace colorSpace;\n> +\n> +\tauto itColor = v4l2ToColorSpace.find(v4l2PixFormat.colorspace);\n> +\tif (itColor != v4l2ToColorSpace.end())\n> +\t\tcolorSpace = itColor->second;\n> +\n> +\tauto itEncoding = v4l2ToEncoding.find(v4l2PixFormat.ycbcr_enc);\n> +\tif (itEncoding != v4l2ToEncoding.end())\n> +\t\tcolorSpace.encoding = itEncoding->second;\n> +\n> +\tauto itTransfer = v4l2ToTransferFunction.find(v4l2PixFormat.xfer_func);\n> +\tif (itTransfer != v4l2ToTransferFunction.end())\n> +\t\tcolorSpace.transferFunction = itTransfer->second;\n> +\n> +\tauto itRange = v4l2ToRange.find(v4l2PixFormat.quantization);\n> +\tif (itRange != v4l2ToRange.end())\n> +\t\tcolorSpace.range = itRange->second;\n> +\n> +\tif (!colorSpace.isFullyDefined())\n> +\t\tLOG(V4L2, Warning) << \"Returning non-fully defined colour space\"\n> +\t\t\t\t   << colorSpace.toString();\n> +\treturn colorSpace;\n> +}\n> +\n>  /**\n>   * \\brief Try an image format on the V4L2 video device\n>   * \\param[inout] format The image format to test applicability to the video device\n> @@ -840,6 +953,7 @@ int V4L2VideoDevice::getFormatMultiplane(V4L2DeviceFormat *format)\n>  \tformat->size.width = pix->width;\n>  \tformat->size.height = pix->height;\n>  \tformat->fourcc = V4L2PixelFormat(pix->pixelformat);\n> +\tformat->colorSpace = getColorSpace(*pix);\n>  \tformat->planesCount = pix->num_planes;\n>  \n>  \tfor (unsigned int i = 0; i < format->planesCount; ++i) {\n> @@ -862,6 +976,7 @@ int V4L2VideoDevice::trySetFormatMultiplane(V4L2DeviceFormat *format, bool set)\n>  \tpix->pixelformat = format->fourcc;\n>  \tpix->num_planes = format->planesCount;\n>  \tpix->field = V4L2_FIELD_NONE;\n> +\tsetColorSpace(format->colorSpace, *pix);\n\nI suppose if no color space is set in the StreamConfiguration then it'll\njust configure default.\n\nOtherwise, looks good to me.\n\n\nPaul\n\n>  \n>  \tASSERT(pix->num_planes <= std::size(pix->plane_fmt));\n>  \n> @@ -910,6 +1025,7 @@ int V4L2VideoDevice::getFormatSingleplane(V4L2DeviceFormat *format)\n>  \tformat->size.width = pix->width;\n>  \tformat->size.height = pix->height;\n>  \tformat->fourcc = V4L2PixelFormat(pix->pixelformat);\n> +\tformat->colorSpace = getColorSpace(*pix);\n>  \tformat->planesCount = 1;\n>  \tformat->planes[0].bpl = pix->bytesperline;\n>  \tformat->planes[0].size = pix->sizeimage;\n> @@ -929,6 +1045,7 @@ int V4L2VideoDevice::trySetFormatSingleplane(V4L2DeviceFormat *format, bool set)\n>  \tpix->pixelformat = format->fourcc;\n>  \tpix->bytesperline = format->planes[0].bpl;\n>  \tpix->field = V4L2_FIELD_NONE;\n> +\tsetColorSpace(format->colorSpace, *pix);\n>  \tret = ioctl(set ? VIDIOC_S_FMT : VIDIOC_TRY_FMT, &v4l2Format);\n>  \tif (ret) {\n>  \t\tLOG(V4L2, Error)\n> -- \n> 2.20.1\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 A5BDABDC71\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 23 Sep 2021 06:27:05 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id EA48B6918F;\n\tThu, 23 Sep 2021 08:27:04 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id B632060245\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 23 Sep 2021 08:27:03 +0200 (CEST)","from pyrite.rasen.tech (unknown\n\t[IPv6:2400:4051:61:600:2c71:1b79:d06d:5032])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 4D23545E;\n\tThu, 23 Sep 2021 08:27:02 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"wgbSFFKi\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1632378423;\n\tbh=Hw0pskD+q7e3ksLJGEanAVveBvmGxtlJ9GwYeAHDdbU=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=wgbSFFKiYwhcbtdBTnnGNrz9S+H+Ca8yoVYUWyRltDh8zn0I81p279k0T2SxvelTs\n\t5x7DNbPdCwpyQ0knUDRySPUCfdL1qZLsSGnHWsTZHvbaJPVIKAxS5zg8YLpaR6hGYi\n\tuoEZ4/kvhzh5YVUjdqV6ghvcIPdbKDVG37IVwtZg=","Date":"Thu, 23 Sep 2021 15:26:56 +0900","From":"paul.elder@ideasonboard.com","To":"David Plowman <david.plowman@raspberrypi.com>","Message-ID":"<20210923062656.GN4382@pyrite.rasen.tech>","References":"<20210805142154.20324-1-david.plowman@raspberrypi.com>\n\t<20210805142154.20324-3-david.plowman@raspberrypi.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=us-ascii","Content-Disposition":"inline","In-Reply-To":"<20210805142154.20324-3-david.plowman@raspberrypi.com>","Subject":"Re: [libcamera-devel] [PATCH 2/3] libcamera: Support passing\n\tColorSpaces to V4L2 drivers","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>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":19816,"web_url":"https://patchwork.libcamera.org/comment/19816/","msgid":"<56e155fdedb4b7656eb7751b4f5ce66f8cad7044.camel@ndufresne.ca>","date":"2021-09-23T13:03:14","subject":"Re: [libcamera-devel] [PATCH 2/3] libcamera: Support passing\n\tColorSpaces to V4L2 drivers","submitter":{"id":30,"url":"https://patchwork.libcamera.org/api/people/30/","name":"Nicolas Dufresne","email":"nicolas@ndufresne.ca"},"content":"Le jeudi 05 août 2021 à 15:21 +0100, David Plowman a écrit :\n> The ColorSpace class is added to the StreamConfiguration, and is now\n> passed to V4L2 devices where it is handled appropriately. Note how\n> this means that the colour space is configured per-stream (though\n> platforms may restrict this).\n\nV4L2 being fail safe, it will update the chosen colorspace to a supported one.\nHow do you report back this change, I don't see any code related to that ?\n\np.s. to complete the GStreamer integration, we need to advertise the final\ncolorspace rather then the initially preferred one.\n\n> \n> Signed-off-by: David Plowman <david.plowman@raspberrypi.com>\n> ---\n>  include/libcamera/internal/v4l2_videodevice.h |   2 +\n>  include/libcamera/stream.h                    |   3 +\n>  src/libcamera/v4l2_videodevice.cpp            | 117 ++++++++++++++++++\n>  3 files changed, 122 insertions(+)\n> \n> diff --git a/include/libcamera/internal/v4l2_videodevice.h b/include/libcamera/internal/v4l2_videodevice.h\n> index e767ec84..c05899cf 100644\n> --- a/include/libcamera/internal/v4l2_videodevice.h\n> +++ b/include/libcamera/internal/v4l2_videodevice.h\n> @@ -20,6 +20,7 @@\n>  #include <libcamera/base/log.h>\n>  #include <libcamera/base/signal.h>\n>  \n> +#include <libcamera/color_space.h>\n>  #include <libcamera/framebuffer.h>\n>  #include <libcamera/geometry.h>\n>  #include <libcamera/pixel_format.h>\n> @@ -163,6 +164,7 @@ public:\n>  \n>  \tV4L2PixelFormat fourcc;\n>  \tSize size;\n> +\tColorSpace colorSpace;\n>  \n>  \tstd::array<Plane, 3> planes;\n>  \tunsigned int planesCount = 0;\n> diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h\n> index 0c55e716..131f7733 100644\n> --- a/include/libcamera/stream.h\n> +++ b/include/libcamera/stream.h\n> @@ -12,6 +12,7 @@\n>  #include <string>\n>  #include <vector>\n>  \n> +#include <libcamera/color_space.h>\n>  #include <libcamera/framebuffer.h>\n>  #include <libcamera/geometry.h>\n>  #include <libcamera/pixel_format.h>\n> @@ -47,6 +48,8 @@ struct StreamConfiguration {\n>  \n>  \tunsigned int bufferCount;\n>  \n> +\tColorSpace colorSpace;\n> +\n>  \tStream *stream() const { return stream_; }\n>  \tvoid setStream(Stream *stream) { stream_ = stream; }\n>  \tconst StreamFormats &formats() const { return formats_; }\n> diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp\n> index da2af6a1..7f30412c 100644\n> --- a/src/libcamera/v4l2_videodevice.cpp\n> +++ b/src/libcamera/v4l2_videodevice.cpp\n> @@ -366,6 +366,11 @@ bool V4L2BufferCache::Entry::operator==(const FrameBuffer &buffer) const\n>   * \\brief The image size in pixels\n>   */\n>  \n> +/**\n> + * \\var V4L2DeviceFormat::colorSpace\n> + * \\brief The color space of the pixels\n> + */\n> +\n>  /**\n>   * \\var V4L2DeviceFormat::fourcc\n>   * \\brief The fourcc code describing the pixel encoding scheme\n> @@ -731,6 +736,114 @@ int V4L2VideoDevice::getFormat(V4L2DeviceFormat *format)\n>  \t\treturn getFormatSingleplane(format);\n>  }\n>  \n> +static const std::vector<std::pair<ColorSpace, v4l2_colorspace>> colorSpaceToV4l2 = {\n> +\t{ ColorSpace::RAW, V4L2_COLORSPACE_RAW },\n> +\t{ ColorSpace::JFIF, V4L2_COLORSPACE_JPEG },\n> +\t{ ColorSpace::SMPTE170M, V4L2_COLORSPACE_SMPTE170M },\n> +\t{ ColorSpace::REC709, V4L2_COLORSPACE_REC709 },\n> +\t{ ColorSpace::REC2020, V4L2_COLORSPACE_BT2020 },\n> +};\n> +\n> +static const std::map<ColorSpace::Encoding, v4l2_ycbcr_encoding> encodingToV4l2 = {\n> +\t{ ColorSpace::Encoding::REC601, V4L2_YCBCR_ENC_601 },\n> +\t{ ColorSpace::Encoding::REC709, V4L2_YCBCR_ENC_709 },\n> +\t{ ColorSpace::Encoding::REC2020, V4L2_YCBCR_ENC_BT2020 },\n> +};\n> +\n> +static const std::map<ColorSpace::TransferFunction, v4l2_xfer_func> transferFunctionToV4l2 = {\n> +\t{ ColorSpace::TransferFunction::IDENTITY, V4L2_XFER_FUNC_NONE },\n> +\t{ ColorSpace::TransferFunction::SRGB, V4L2_XFER_FUNC_SRGB },\n> +\t{ ColorSpace::TransferFunction::REC709, V4L2_XFER_FUNC_709 },\n> +};\n> +\n> +static const std::map<ColorSpace::Range, v4l2_quantization> rangeToV4l2 = {\n> +\t{ ColorSpace::Range::FULL, V4L2_QUANTIZATION_FULL_RANGE },\n> +\t{ ColorSpace::Range::LIMITED, V4L2_QUANTIZATION_LIM_RANGE },\n> +};\n> +\n> +template<typename T>\n> +static void setColorSpace(const ColorSpace &colorSpace, T &v4l2PixFormat)\n> +{\n> +\tif (!colorSpace.isFullyDefined())\n> +\t\tLOG(V4L2, Warning) << \"Setting non-fully defined colour space\"\n> +\t\t\t\t   << colorSpace.toString();\n> +\n> +\tv4l2PixFormat.colorspace = V4L2_COLORSPACE_DEFAULT;\n> +\tv4l2PixFormat.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;\n> +\tv4l2PixFormat.xfer_func = V4L2_XFER_FUNC_DEFAULT;\n> +\tv4l2PixFormat.quantization = V4L2_QUANTIZATION_DEFAULT;\n> +\n> +\tauto itColor = std::find_if(colorSpaceToV4l2.begin(), colorSpaceToV4l2.end(),\n> +\t\t\t\t     [&colorSpace](const std::pair<ColorSpace, v4l2_colorspace> &item) { return colorSpace == item.first; });\n> +\tif (itColor != colorSpaceToV4l2.end())\n> +\t\tv4l2PixFormat.colorspace = itColor->second;\n> +\n> +\tauto itEncoding = encodingToV4l2.find(colorSpace.encoding);\n> +\tif (itEncoding != encodingToV4l2.end())\n> +\t\tv4l2PixFormat.ycbcr_enc = itEncoding->second;\n> +\n> +\tauto itTransfer = transferFunctionToV4l2.find(colorSpace.transferFunction);\n> +\tif (itTransfer != transferFunctionToV4l2.end())\n> +\t\tv4l2PixFormat.xfer_func = itTransfer->second;\n> +\n> +\tauto itRange = rangeToV4l2.find(colorSpace.range);\n> +\tif (itRange != rangeToV4l2.end())\n> +\t\tv4l2PixFormat.quantization = itRange->second;\n> +}\n> +\n> +static const std::map<uint32_t, ColorSpace> v4l2ToColorSpace = {\n> +\t{ V4L2_COLORSPACE_RAW, ColorSpace::RAW },\n> +\t{ V4L2_COLORSPACE_JPEG, ColorSpace::JFIF },\n> +\t{ V4L2_COLORSPACE_SRGB, ColorSpace::JFIF },\n> +\t{ V4L2_COLORSPACE_SMPTE170M, ColorSpace::SMPTE170M },\n> +\t{ V4L2_COLORSPACE_REC709, ColorSpace::REC709 },\n> +\t{ V4L2_COLORSPACE_BT2020, ColorSpace::REC2020 },\n> +};\n> +\n> +static const std::map<uint32_t, ColorSpace::Encoding> v4l2ToEncoding = {\n> +\t{ V4L2_YCBCR_ENC_601, ColorSpace::Encoding::REC601 },\n> +\t{ V4L2_YCBCR_ENC_709, ColorSpace::Encoding::REC709 },\n> +\t{ V4L2_YCBCR_ENC_BT2020, ColorSpace::Encoding::REC2020 },\n> +};\n> +\n> +static const std::map<uint32_t, ColorSpace::TransferFunction> v4l2ToTransferFunction = {\n> +\t{ V4L2_XFER_FUNC_NONE, ColorSpace::TransferFunction::IDENTITY },\n> +\t{ V4L2_XFER_FUNC_SRGB, ColorSpace::TransferFunction::SRGB },\n> +\t{ V4L2_XFER_FUNC_709, ColorSpace::TransferFunction::REC709 },\n> +};\n> +\n> +static const std::map<uint32_t, ColorSpace::Range> v4l2ToRange = {\n> +\t{ V4L2_QUANTIZATION_FULL_RANGE, ColorSpace::Range::FULL },\n> +\t{ V4L2_QUANTIZATION_LIM_RANGE, ColorSpace::Range::LIMITED },\n> +};\n> +\n> +template<typename T>\n> +static ColorSpace getColorSpace(const T &v4l2PixFormat)\n> +{\n> +\tColorSpace colorSpace;\n> +\n> +\tauto itColor = v4l2ToColorSpace.find(v4l2PixFormat.colorspace);\n> +\tif (itColor != v4l2ToColorSpace.end())\n> +\t\tcolorSpace = itColor->second;\n> +\n> +\tauto itEncoding = v4l2ToEncoding.find(v4l2PixFormat.ycbcr_enc);\n> +\tif (itEncoding != v4l2ToEncoding.end())\n> +\t\tcolorSpace.encoding = itEncoding->second;\n> +\n> +\tauto itTransfer = v4l2ToTransferFunction.find(v4l2PixFormat.xfer_func);\n> +\tif (itTransfer != v4l2ToTransferFunction.end())\n> +\t\tcolorSpace.transferFunction = itTransfer->second;\n> +\n> +\tauto itRange = v4l2ToRange.find(v4l2PixFormat.quantization);\n> +\tif (itRange != v4l2ToRange.end())\n> +\t\tcolorSpace.range = itRange->second;\n> +\n> +\tif (!colorSpace.isFullyDefined())\n> +\t\tLOG(V4L2, Warning) << \"Returning non-fully defined colour space\"\n> +\t\t\t\t   << colorSpace.toString();\n> +\treturn colorSpace;\n> +}\n> +\n>  /**\n>   * \\brief Try an image format on the V4L2 video device\n>   * \\param[inout] format The image format to test applicability to the video device\n> @@ -840,6 +953,7 @@ int V4L2VideoDevice::getFormatMultiplane(V4L2DeviceFormat *format)\n>  \tformat->size.width = pix->width;\n>  \tformat->size.height = pix->height;\n>  \tformat->fourcc = V4L2PixelFormat(pix->pixelformat);\n> +\tformat->colorSpace = getColorSpace(*pix);\n>  \tformat->planesCount = pix->num_planes;\n>  \n>  \tfor (unsigned int i = 0; i < format->planesCount; ++i) {\n> @@ -862,6 +976,7 @@ int V4L2VideoDevice::trySetFormatMultiplane(V4L2DeviceFormat *format, bool set)\n>  \tpix->pixelformat = format->fourcc;\n>  \tpix->num_planes = format->planesCount;\n>  \tpix->field = V4L2_FIELD_NONE;\n> +\tsetColorSpace(format->colorSpace, *pix);\n>  \n>  \tASSERT(pix->num_planes <= std::size(pix->plane_fmt));\n>  \n> @@ -910,6 +1025,7 @@ int V4L2VideoDevice::getFormatSingleplane(V4L2DeviceFormat *format)\n>  \tformat->size.width = pix->width;\n>  \tformat->size.height = pix->height;\n>  \tformat->fourcc = V4L2PixelFormat(pix->pixelformat);\n> +\tformat->colorSpace = getColorSpace(*pix);\n>  \tformat->planesCount = 1;\n>  \tformat->planes[0].bpl = pix->bytesperline;\n>  \tformat->planes[0].size = pix->sizeimage;\n> @@ -929,6 +1045,7 @@ int V4L2VideoDevice::trySetFormatSingleplane(V4L2DeviceFormat *format, bool set)\n>  \tpix->pixelformat = format->fourcc;\n>  \tpix->bytesperline = format->planes[0].bpl;\n>  \tpix->field = V4L2_FIELD_NONE;\n> +\tsetColorSpace(format->colorSpace, *pix);\n>  \tret = ioctl(set ? VIDIOC_S_FMT : VIDIOC_TRY_FMT, &v4l2Format);\n>  \tif (ret) {\n>  \t\tLOG(V4L2, Error)","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 50B5ABDC71\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 23 Sep 2021 13:03:19 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id A5D586918C;\n\tThu, 23 Sep 2021 15:03:18 +0200 (CEST)","from mail-qv1-xf33.google.com (mail-qv1-xf33.google.com\n\t[IPv6:2607:f8b0:4864:20::f33])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 27A6469189\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 23 Sep 2021 15:03:17 +0200 (CEST)","by mail-qv1-xf33.google.com with SMTP id a13so4026576qvo.9\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 23 Sep 2021 06:03:17 -0700 (PDT)","from nicolas-tpx395.localdomain (173-246-12-168.qc.cable.ebox.net.\n\t[173.246.12.168]) by smtp.gmail.com with ESMTPSA id\n\t9sm4212712qkc.52.2021.09.23.06.03.14\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tThu, 23 Sep 2021 06:03:15 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key;\n\tunprotected) header.d=ndufresne-ca.20210112.gappssmtp.com\n\theader.i=@ndufresne-ca.20210112.gappssmtp.com\n\theader.b=\"QvpS8DhX\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=ndufresne-ca.20210112.gappssmtp.com; s=20210112;\n\th=message-id:subject:from:to:date:in-reply-to:references:user-agent\n\t:mime-version:content-transfer-encoding;\n\tbh=rOg0ETOkE5rTEInouap4YZmQj06vVJpX9wc6IAQW+co=;\n\tb=QvpS8DhXoM9A+BBjZLru4KiN4LBHP0UaH5QchVxcbMAQyze+mDWFHaEuVCKVzUC3Ck\n\tCJ+3S1ZHXieeq4TDIcF7pAllmOlzypxB9QL4kWB+hta+VylNranIFnu5DySjftz7HAhV\n\td0AgRh6YEg0GQi9OwkcV45W0Q1z3pXuF7zV/bycv458Oo66ouUGoa/+cpBXi3DOX7+RV\n\te/CQtrafc52LyaVbKGGAjnqIfdAJtroQPdYqA0ZJoShFh6G2rbjwT75nuj0o75V3od51\n\tCLoR+mkT/d7RtPv9p1rVczPTCPhwwyaPC5ed5VgGkEl4dT1Y8r/Ex9maw00XPhMLG8DA\n\tomfw==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112;\n\th=x-gm-message-state:message-id:subject:from:to:date:in-reply-to\n\t:references:user-agent:mime-version:content-transfer-encoding;\n\tbh=rOg0ETOkE5rTEInouap4YZmQj06vVJpX9wc6IAQW+co=;\n\tb=HTsxcQ8LfSYcgIcaYPTOOYMkBAf5yyCWKM38RuCWS9nzJgSZlohSWljVDIlWc2zjB7\n\t+yWLlnV8e3v73AfgAtYbrbLkFemzz/6eJFPqbbM5MoyWRtr2dCz2rDuReqGtINT+ZQoc\n\tCE1TiC8wMynnXh77wwkfBXB3vA88zfG01WL31dh0lob5g+QK1Qghk61F7jPt4Zf3AOKr\n\tD0ewdboXcbsfSZP8dq3qJngwsmGsBX+evOOreikY7LaH9g+gSqhXlug5TPdNM7XjDITL\n\tOLtEYrOmPftert97LjwgttqQ3tpnjCd6iSjK9ZAafzUJc75tZrlEFPsJTrutziM1AIa4\n\tHnfg==","X-Gm-Message-State":"AOAM531Gg4CxRyW1JW2M3eA6w2GcrL7ZcdOFvWpAeP6lQzZEM2Ei3pXl\n\tYU0FsHMu9Gx2s2QuKwp9BbA8Xw==","X-Google-Smtp-Source":"ABdhPJzCP7QdcNIQAyxr1GUH0qrO8xZxS4iaIKZu2U5jDTzRGTBN8v0k5l8o4uLWJzB5vJ6LZHtgSA==","X-Received":"by 2002:a05:6214:13ee:: with SMTP id\n\tch14mr4009041qvb.43.1632402195718; \n\tThu, 23 Sep 2021 06:03:15 -0700 (PDT)","Message-ID":"<56e155fdedb4b7656eb7751b4f5ce66f8cad7044.camel@ndufresne.ca>","From":"Nicolas Dufresne <nicolas@ndufresne.ca>","To":"David Plowman <david.plowman@raspberrypi.com>, \n\tlibcamera-devel@lists.libcamera.org","Date":"Thu, 23 Sep 2021 09:03:14 -0400","In-Reply-To":"<20210805142154.20324-3-david.plowman@raspberrypi.com>","References":"<20210805142154.20324-1-david.plowman@raspberrypi.com>\n\t<20210805142154.20324-3-david.plowman@raspberrypi.com>","Content-Type":"text/plain; charset=\"UTF-8\"","User-Agent":"Evolution 3.40.4 (3.40.4-1.fc34) ","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","Subject":"Re: [libcamera-devel] [PATCH 2/3] libcamera: Support passing\n\tColorSpaces to V4L2 drivers","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>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":19840,"web_url":"https://patchwork.libcamera.org/comment/19840/","msgid":"<CAHW6GYLZPAYN9xg2etdNKVGUH84b+jmvy24HH31OJfRw4XUYyA@mail.gmail.com>","date":"2021-09-24T11:55:03","subject":"Re: [libcamera-devel] [PATCH 2/3] libcamera: Support passing\n\tColorSpaces to V4L2 drivers","submitter":{"id":42,"url":"https://patchwork.libcamera.org/api/people/42/","name":"David Plowman","email":"david.plowman@raspberrypi.com"},"content":"Hi\n\nThanks for the feedback, that wasn't something I realised! Thanks also\nto everyone else for their comments higher up this thread - I'll roll\nall that into a new version over the next few days and re-post.\n\nBest regards\nDavid\n\nOn Thu, 23 Sept 2021 at 14:03, Nicolas Dufresne <nicolas@ndufresne.ca> wrote:\n>\n> Le jeudi 05 août 2021 à 15:21 +0100, David Plowman a écrit :\n> > The ColorSpace class is added to the StreamConfiguration, and is now\n> > passed to V4L2 devices where it is handled appropriately. Note how\n> > this means that the colour space is configured per-stream (though\n> > platforms may restrict this).\n>\n> V4L2 being fail safe, it will update the chosen colorspace to a supported one.\n> How do you report back this change, I don't see any code related to that ?\n>\n> p.s. to complete the GStreamer integration, we need to advertise the final\n> colorspace rather then the initially preferred one.\n>\n> >\n> > Signed-off-by: David Plowman <david.plowman@raspberrypi.com>\n> > ---\n> >  include/libcamera/internal/v4l2_videodevice.h |   2 +\n> >  include/libcamera/stream.h                    |   3 +\n> >  src/libcamera/v4l2_videodevice.cpp            | 117 ++++++++++++++++++\n> >  3 files changed, 122 insertions(+)\n> >\n> > diff --git a/include/libcamera/internal/v4l2_videodevice.h b/include/libcamera/internal/v4l2_videodevice.h\n> > index e767ec84..c05899cf 100644\n> > --- a/include/libcamera/internal/v4l2_videodevice.h\n> > +++ b/include/libcamera/internal/v4l2_videodevice.h\n> > @@ -20,6 +20,7 @@\n> >  #include <libcamera/base/log.h>\n> >  #include <libcamera/base/signal.h>\n> >\n> > +#include <libcamera/color_space.h>\n> >  #include <libcamera/framebuffer.h>\n> >  #include <libcamera/geometry.h>\n> >  #include <libcamera/pixel_format.h>\n> > @@ -163,6 +164,7 @@ public:\n> >\n> >       V4L2PixelFormat fourcc;\n> >       Size size;\n> > +     ColorSpace colorSpace;\n> >\n> >       std::array<Plane, 3> planes;\n> >       unsigned int planesCount = 0;\n> > diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h\n> > index 0c55e716..131f7733 100644\n> > --- a/include/libcamera/stream.h\n> > +++ b/include/libcamera/stream.h\n> > @@ -12,6 +12,7 @@\n> >  #include <string>\n> >  #include <vector>\n> >\n> > +#include <libcamera/color_space.h>\n> >  #include <libcamera/framebuffer.h>\n> >  #include <libcamera/geometry.h>\n> >  #include <libcamera/pixel_format.h>\n> > @@ -47,6 +48,8 @@ struct StreamConfiguration {\n> >\n> >       unsigned int bufferCount;\n> >\n> > +     ColorSpace colorSpace;\n> > +\n> >       Stream *stream() const { return stream_; }\n> >       void setStream(Stream *stream) { stream_ = stream; }\n> >       const StreamFormats &formats() const { return formats_; }\n> > diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp\n> > index da2af6a1..7f30412c 100644\n> > --- a/src/libcamera/v4l2_videodevice.cpp\n> > +++ b/src/libcamera/v4l2_videodevice.cpp\n> > @@ -366,6 +366,11 @@ bool V4L2BufferCache::Entry::operator==(const FrameBuffer &buffer) const\n> >   * \\brief The image size in pixels\n> >   */\n> >\n> > +/**\n> > + * \\var V4L2DeviceFormat::colorSpace\n> > + * \\brief The color space of the pixels\n> > + */\n> > +\n> >  /**\n> >   * \\var V4L2DeviceFormat::fourcc\n> >   * \\brief The fourcc code describing the pixel encoding scheme\n> > @@ -731,6 +736,114 @@ int V4L2VideoDevice::getFormat(V4L2DeviceFormat *format)\n> >               return getFormatSingleplane(format);\n> >  }\n> >\n> > +static const std::vector<std::pair<ColorSpace, v4l2_colorspace>> colorSpaceToV4l2 = {\n> > +     { ColorSpace::RAW, V4L2_COLORSPACE_RAW },\n> > +     { ColorSpace::JFIF, V4L2_COLORSPACE_JPEG },\n> > +     { ColorSpace::SMPTE170M, V4L2_COLORSPACE_SMPTE170M },\n> > +     { ColorSpace::REC709, V4L2_COLORSPACE_REC709 },\n> > +     { ColorSpace::REC2020, V4L2_COLORSPACE_BT2020 },\n> > +};\n> > +\n> > +static const std::map<ColorSpace::Encoding, v4l2_ycbcr_encoding> encodingToV4l2 = {\n> > +     { ColorSpace::Encoding::REC601, V4L2_YCBCR_ENC_601 },\n> > +     { ColorSpace::Encoding::REC709, V4L2_YCBCR_ENC_709 },\n> > +     { ColorSpace::Encoding::REC2020, V4L2_YCBCR_ENC_BT2020 },\n> > +};\n> > +\n> > +static const std::map<ColorSpace::TransferFunction, v4l2_xfer_func> transferFunctionToV4l2 = {\n> > +     { ColorSpace::TransferFunction::IDENTITY, V4L2_XFER_FUNC_NONE },\n> > +     { ColorSpace::TransferFunction::SRGB, V4L2_XFER_FUNC_SRGB },\n> > +     { ColorSpace::TransferFunction::REC709, V4L2_XFER_FUNC_709 },\n> > +};\n> > +\n> > +static const std::map<ColorSpace::Range, v4l2_quantization> rangeToV4l2 = {\n> > +     { ColorSpace::Range::FULL, V4L2_QUANTIZATION_FULL_RANGE },\n> > +     { ColorSpace::Range::LIMITED, V4L2_QUANTIZATION_LIM_RANGE },\n> > +};\n> > +\n> > +template<typename T>\n> > +static void setColorSpace(const ColorSpace &colorSpace, T &v4l2PixFormat)\n> > +{\n> > +     if (!colorSpace.isFullyDefined())\n> > +             LOG(V4L2, Warning) << \"Setting non-fully defined colour space\"\n> > +                                << colorSpace.toString();\n> > +\n> > +     v4l2PixFormat.colorspace = V4L2_COLORSPACE_DEFAULT;\n> > +     v4l2PixFormat.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;\n> > +     v4l2PixFormat.xfer_func = V4L2_XFER_FUNC_DEFAULT;\n> > +     v4l2PixFormat.quantization = V4L2_QUANTIZATION_DEFAULT;\n> > +\n> > +     auto itColor = std::find_if(colorSpaceToV4l2.begin(), colorSpaceToV4l2.end(),\n> > +                                  [&colorSpace](const std::pair<ColorSpace, v4l2_colorspace> &item) { return colorSpace == item.first; });\n> > +     if (itColor != colorSpaceToV4l2.end())\n> > +             v4l2PixFormat.colorspace = itColor->second;\n> > +\n> > +     auto itEncoding = encodingToV4l2.find(colorSpace.encoding);\n> > +     if (itEncoding != encodingToV4l2.end())\n> > +             v4l2PixFormat.ycbcr_enc = itEncoding->second;\n> > +\n> > +     auto itTransfer = transferFunctionToV4l2.find(colorSpace.transferFunction);\n> > +     if (itTransfer != transferFunctionToV4l2.end())\n> > +             v4l2PixFormat.xfer_func = itTransfer->second;\n> > +\n> > +     auto itRange = rangeToV4l2.find(colorSpace.range);\n> > +     if (itRange != rangeToV4l2.end())\n> > +             v4l2PixFormat.quantization = itRange->second;\n> > +}\n> > +\n> > +static const std::map<uint32_t, ColorSpace> v4l2ToColorSpace = {\n> > +     { V4L2_COLORSPACE_RAW, ColorSpace::RAW },\n> > +     { V4L2_COLORSPACE_JPEG, ColorSpace::JFIF },\n> > +     { V4L2_COLORSPACE_SRGB, ColorSpace::JFIF },\n> > +     { V4L2_COLORSPACE_SMPTE170M, ColorSpace::SMPTE170M },\n> > +     { V4L2_COLORSPACE_REC709, ColorSpace::REC709 },\n> > +     { V4L2_COLORSPACE_BT2020, ColorSpace::REC2020 },\n> > +};\n> > +\n> > +static const std::map<uint32_t, ColorSpace::Encoding> v4l2ToEncoding = {\n> > +     { V4L2_YCBCR_ENC_601, ColorSpace::Encoding::REC601 },\n> > +     { V4L2_YCBCR_ENC_709, ColorSpace::Encoding::REC709 },\n> > +     { V4L2_YCBCR_ENC_BT2020, ColorSpace::Encoding::REC2020 },\n> > +};\n> > +\n> > +static const std::map<uint32_t, ColorSpace::TransferFunction> v4l2ToTransferFunction = {\n> > +     { V4L2_XFER_FUNC_NONE, ColorSpace::TransferFunction::IDENTITY },\n> > +     { V4L2_XFER_FUNC_SRGB, ColorSpace::TransferFunction::SRGB },\n> > +     { V4L2_XFER_FUNC_709, ColorSpace::TransferFunction::REC709 },\n> > +};\n> > +\n> > +static const std::map<uint32_t, ColorSpace::Range> v4l2ToRange = {\n> > +     { V4L2_QUANTIZATION_FULL_RANGE, ColorSpace::Range::FULL },\n> > +     { V4L2_QUANTIZATION_LIM_RANGE, ColorSpace::Range::LIMITED },\n> > +};\n> > +\n> > +template<typename T>\n> > +static ColorSpace getColorSpace(const T &v4l2PixFormat)\n> > +{\n> > +     ColorSpace colorSpace;\n> > +\n> > +     auto itColor = v4l2ToColorSpace.find(v4l2PixFormat.colorspace);\n> > +     if (itColor != v4l2ToColorSpace.end())\n> > +             colorSpace = itColor->second;\n> > +\n> > +     auto itEncoding = v4l2ToEncoding.find(v4l2PixFormat.ycbcr_enc);\n> > +     if (itEncoding != v4l2ToEncoding.end())\n> > +             colorSpace.encoding = itEncoding->second;\n> > +\n> > +     auto itTransfer = v4l2ToTransferFunction.find(v4l2PixFormat.xfer_func);\n> > +     if (itTransfer != v4l2ToTransferFunction.end())\n> > +             colorSpace.transferFunction = itTransfer->second;\n> > +\n> > +     auto itRange = v4l2ToRange.find(v4l2PixFormat.quantization);\n> > +     if (itRange != v4l2ToRange.end())\n> > +             colorSpace.range = itRange->second;\n> > +\n> > +     if (!colorSpace.isFullyDefined())\n> > +             LOG(V4L2, Warning) << \"Returning non-fully defined colour space\"\n> > +                                << colorSpace.toString();\n> > +     return colorSpace;\n> > +}\n> > +\n> >  /**\n> >   * \\brief Try an image format on the V4L2 video device\n> >   * \\param[inout] format The image format to test applicability to the video device\n> > @@ -840,6 +953,7 @@ int V4L2VideoDevice::getFormatMultiplane(V4L2DeviceFormat *format)\n> >       format->size.width = pix->width;\n> >       format->size.height = pix->height;\n> >       format->fourcc = V4L2PixelFormat(pix->pixelformat);\n> > +     format->colorSpace = getColorSpace(*pix);\n> >       format->planesCount = pix->num_planes;\n> >\n> >       for (unsigned int i = 0; i < format->planesCount; ++i) {\n> > @@ -862,6 +976,7 @@ int V4L2VideoDevice::trySetFormatMultiplane(V4L2DeviceFormat *format, bool set)\n> >       pix->pixelformat = format->fourcc;\n> >       pix->num_planes = format->planesCount;\n> >       pix->field = V4L2_FIELD_NONE;\n> > +     setColorSpace(format->colorSpace, *pix);\n> >\n> >       ASSERT(pix->num_planes <= std::size(pix->plane_fmt));\n> >\n> > @@ -910,6 +1025,7 @@ int V4L2VideoDevice::getFormatSingleplane(V4L2DeviceFormat *format)\n> >       format->size.width = pix->width;\n> >       format->size.height = pix->height;\n> >       format->fourcc = V4L2PixelFormat(pix->pixelformat);\n> > +     format->colorSpace = getColorSpace(*pix);\n> >       format->planesCount = 1;\n> >       format->planes[0].bpl = pix->bytesperline;\n> >       format->planes[0].size = pix->sizeimage;\n> > @@ -929,6 +1045,7 @@ int V4L2VideoDevice::trySetFormatSingleplane(V4L2DeviceFormat *format, bool set)\n> >       pix->pixelformat = format->fourcc;\n> >       pix->bytesperline = format->planes[0].bpl;\n> >       pix->field = V4L2_FIELD_NONE;\n> > +     setColorSpace(format->colorSpace, *pix);\n> >       ret = ioctl(set ? VIDIOC_S_FMT : VIDIOC_TRY_FMT, &v4l2Format);\n> >       if (ret) {\n> >               LOG(V4L2, Error)\n>\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 60535BF01C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 24 Sep 2021 11:55:16 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 9DEEF6918A;\n\tFri, 24 Sep 2021 13:55:15 +0200 (CEST)","from mail-wr1-x42f.google.com (mail-wr1-x42f.google.com\n\t[IPv6:2a00:1450:4864:20::42f])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 7CCD9687DD\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 24 Sep 2021 13:55:14 +0200 (CEST)","by mail-wr1-x42f.google.com with SMTP id w17so26595642wrv.10\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 24 Sep 2021 04:55:14 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key;\n\tunprotected) header.d=raspberrypi.com header.i=@raspberrypi.com\n\theader.b=\"KrSuKkbR\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google;\n\th=mime-version:references:in-reply-to:from:date:message-id:subject:to\n\t:cc:content-transfer-encoding;\n\tbh=ai0A1V2BdK4ouLK4FjtsTmgEaVQvBKKdogKWBUqU2OE=;\n\tb=KrSuKkbRd2maDRPLBIE8NX0mYELmvweBusZBXoOhvIt2NJvqXH2iX1SGqAqUOK/jJp\n\tk20ZAvksKDbM2C2w+1nXJ4P91fSS2bUg9w3eeDLcMOtqHA+dA/eulXFHSjXzwO6MGVBj\n\t5tZ64N4VFANdaGYXogseqGHC8QFZUslc7WEwnuIdBvlSPntmh7DADKdlDdGknaEp2/wK\n\t3WV7MmETdEbGGQtE8rDbjKLR/U/NNeHoTY7FDntz617jZ25KeBeBr5WyFBDA5vu9uRYV\n\tU9phg+D7zR18IEqkj76RPLvbzadIGTHDN74UTFd+/3Gwz74ldLFu0IfnkScEcbvyWPZ8\n\tpTdg==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112;\n\th=x-gm-message-state:mime-version:references:in-reply-to:from:date\n\t:message-id:subject:to:cc:content-transfer-encoding;\n\tbh=ai0A1V2BdK4ouLK4FjtsTmgEaVQvBKKdogKWBUqU2OE=;\n\tb=P5eQJJVuM38jyfBhP+4a3jvb0BDEwMWYj/q1Eg82Nqg65YqhpbB9nFcGnSNm6VWo/a\n\tbS3qT6rwPXOsjVAbjBgZ7s66UfphcUUbzm9no0wxeKBpoVEwHRsdjC6kTAMzlfpWT8fJ\n\ta6970Jy/SCFwKGIGN0+1Kr8cjAx0G19nb5zD/IMyGHvmky80A0l/hbjXvjfJMk+U/V68\n\tHdhFochI/6Y6jYUpDVKfWakn6e5pyQqVM9kxTEvXx/M8LQmFzrk7SQV/dVYaklsWBRXd\n\teK0/SbNItf5RIvkbyNWrBt6A4Js645J3vM4uENjvsdw8c7zNH7cT7cBl1bKyGcCbjDrk\n\tL6iw==","X-Gm-Message-State":"AOAM530MqWUl08QQLPQBBn+rJD7zWQ47G4QuK+WNsO+6//KzEpMDi9ax\n\txgsQukgQ/PBmASt/0zM/x7qnGHpHsEZqTkxmP6PQSWMmjRt4jw==","X-Google-Smtp-Source":"ABdhPJwHoEslOhCwgHTCoRlUADOA5TP4Vx2rxhq4lss6CeCql0ZoD3rp9qtSzux3HWGrDmS8wYiNAP89+btB4tOIE2c=","X-Received":"by 2002:adf:9bdb:: with SMTP id\n\te27mr10804133wrc.162.1632484514053; \n\tFri, 24 Sep 2021 04:55:14 -0700 (PDT)","MIME-Version":"1.0","References":"<20210805142154.20324-1-david.plowman@raspberrypi.com>\n\t<20210805142154.20324-3-david.plowman@raspberrypi.com>\n\t<56e155fdedb4b7656eb7751b4f5ce66f8cad7044.camel@ndufresne.ca>","In-Reply-To":"<56e155fdedb4b7656eb7751b4f5ce66f8cad7044.camel@ndufresne.ca>","From":"David Plowman <david.plowman@raspberrypi.com>","Date":"Fri, 24 Sep 2021 12:55:03 +0100","Message-ID":"<CAHW6GYLZPAYN9xg2etdNKVGUH84b+jmvy24HH31OJfRw4XUYyA@mail.gmail.com>","To":"Nicolas Dufresne <nicolas@ndufresne.ca>","Content-Type":"text/plain; charset=\"UTF-8\"","Content-Transfer-Encoding":"quoted-printable","Subject":"Re: [libcamera-devel] [PATCH 2/3] libcamera: Support passing\n\tColorSpaces to V4L2 drivers","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>","Cc":"libcamera devel <libcamera-devel@lists.libcamera.org>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]