From patchwork Tue Aug 30 07:47:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 17250 X-Patchwork-Delegate: umang.jain@ideasonboard.com Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 74ACAC3272 for ; Tue, 30 Aug 2022 07:47:40 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1EC5561FC4; Tue, 30 Aug 2022 09:47:40 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1661845660; bh=INGsPJd+3GNhyEOLvA96weUF0WEcY7n9usQizmZPaD4=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=loMbuae9MmDC08DdwuzN7dvRzDJ0bXErtjXjmk1LTVwltwP1+qM4uRIlfkhD6mpQD EaKHDzEsTB5PrGeqQzdO0Rop/ZFD4QUw3lVaP2IUx/PVAQetNYjYC5G6nKlcaEWnS1 CYfEjIyasMkUoRrb+KKzlU+tMwgtLaQhNrm6+jkg7BoiSSesKU4xNAjlvD/97C88XK E9sBYLXVgOFeW+y/4TgQOxq1CXxkso7Gm00NGQmCGN6ICUeGj0OK0A7bKFfjizkkDE YDwWSmzJAelWGPfYe2xasap/nq2KcVxLExUNc41Y1cC4HqSFvxNRKwiHH3dX/JgANv +19t6PH/y0hEA== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7B34A61FB9 for ; Tue, 30 Aug 2022 09:47:38 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="f3/w+UZm"; dkim-atps=neutral Received: from umang.jainideasonboard.com (unknown [IPv6:2401:4900:1f3f:1548:78ac:4a3:edc3:c28a]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 6E36F481; Tue, 30 Aug 2022 09:47:36 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1661845658; bh=INGsPJd+3GNhyEOLvA96weUF0WEcY7n9usQizmZPaD4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=f3/w+UZme/7Rqx5nc4ZUKK/eaLytBeOTJArPNX2Iy1uyZLZ8AmqzSI5cvk//ehq/G Uh9wv5OfBGKNtJgGrowvs3kBipMMsn7lyG0IgG+6AzHiSwwKR4HRWWUG2B5QkyBXz7 RMyI7oCe1iLbesscNEC2j5nzus8tpa3KWsQ3a6EE= To: libcamera-devel@lists.libcamera.org Date: Tue, 30 Aug 2022 13:17:19 +0530 Message-Id: <20220830074725.1059643-2-umang.jain@ideasonboard.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20220830074725.1059643-1-umang.jain@ideasonboard.com> References: <20220830074725.1059643-1-umang.jain@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 1/7] libcamera: v4l2_subdevice: Add color encoding for media bus formats X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Umang Jain via libcamera-devel From: Umang Jain Reply-To: Umang Jain Cc: rishikeshdonadkar@gmail.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Store the colour encoding corresponding to a media bus format in the V4L2SubdeviceFormatInfo structure. This will be used to implement color space adjustments. Signed-off-by: Umang Jain Reviewed-by: Laurent Pinchart Reviewed-by: Paul Elder --- src/libcamera/v4l2_subdevice.cpp | 154 ++++++++++++++++--------------- 1 file changed, 79 insertions(+), 75 deletions(-) diff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp index d8fd92e3..07a0bb07 100644 --- a/src/libcamera/v4l2_subdevice.cpp +++ b/src/libcamera/v4l2_subdevice.cpp @@ -23,6 +23,7 @@ #include #include +#include "libcamera/internal/formats.h" #include "libcamera/internal/media_device.h" #include "libcamera/internal/media_object.h" @@ -42,10 +43,12 @@ namespace { * \brief Information about media bus formats * \param bitsPerPixel Bits per pixel * \param name Name of MBUS format + * \param colourEncoding Type of colour encoding */ struct V4L2SubdeviceFormatInfo { unsigned int bitsPerPixel; const char *name; + PixelFormatInfo::ColourEncoding colourEncoding; }; /* @@ -54,81 +57,82 @@ struct V4L2SubdeviceFormatInfo { * bus codes */ const std::map formatInfoMap = { - { MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE, { 16, "RGB444_2X8_PADHI_BE" } }, - { MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE, { 16, "RGB444_2X8_PADHI_LE" } }, - { MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE, { 16, "RGB555_2X8_PADHI_BE" } }, - { MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE, { 16, "RGB555_2X8_PADHI_LE" } }, - { MEDIA_BUS_FMT_RGB565_1X16, { 16, "RGB565_1X16" } }, - { MEDIA_BUS_FMT_BGR565_2X8_BE, { 16, "BGR565_2X8_BE" } }, - { MEDIA_BUS_FMT_BGR565_2X8_LE, { 16, "BGR565_2X8_LE" } }, - { MEDIA_BUS_FMT_RGB565_2X8_BE, { 16, "RGB565_2X8_BE" } }, - { MEDIA_BUS_FMT_RGB565_2X8_LE, { 16, "RGB565_2X8_LE" } }, - { MEDIA_BUS_FMT_RGB666_1X18, { 18, "RGB666_1X18" } }, - { MEDIA_BUS_FMT_RGB888_1X24, { 24, "RGB888_1X24" } }, - { MEDIA_BUS_FMT_RGB888_2X12_BE, { 24, "RGB888_2X12_BE" } }, - { MEDIA_BUS_FMT_RGB888_2X12_LE, { 24, "RGB888_2X12_LE" } }, - { MEDIA_BUS_FMT_ARGB8888_1X32, { 32, "ARGB8888_1X32" } }, - { MEDIA_BUS_FMT_Y8_1X8, { 8, "Y8_1X8" } }, - { MEDIA_BUS_FMT_UV8_1X8, { 8, "UV8_1X8" } }, - { MEDIA_BUS_FMT_UYVY8_1_5X8, { 12, "UYVY8_1_5X8" } }, - { MEDIA_BUS_FMT_VYUY8_1_5X8, { 12, "VYUY8_1_5X8" } }, - { MEDIA_BUS_FMT_YUYV8_1_5X8, { 12, "YUYV8_1_5X8" } }, - { MEDIA_BUS_FMT_YVYU8_1_5X8, { 12, "YVYU8_1_5X8" } }, - { MEDIA_BUS_FMT_UYVY8_2X8, { 16, "UYVY8_2X8" } }, - { MEDIA_BUS_FMT_VYUY8_2X8, { 16, "VYUY8_2X8" } }, - { MEDIA_BUS_FMT_YUYV8_2X8, { 16, "YUYV8_2X8" } }, - { MEDIA_BUS_FMT_YVYU8_2X8, { 16, "YVYU8_2X8" } }, - { MEDIA_BUS_FMT_Y10_1X10, { 10, "Y10_1X10" } }, - { MEDIA_BUS_FMT_UYVY10_2X10, { 20, "UYVY10_2X10" } }, - { MEDIA_BUS_FMT_VYUY10_2X10, { 20, "VYUY10_2X10" } }, - { MEDIA_BUS_FMT_YUYV10_2X10, { 20, "YUYV10_2X10" } }, - { MEDIA_BUS_FMT_YVYU10_2X10, { 20, "YVYU10_2X10" } }, - { MEDIA_BUS_FMT_Y12_1X12, { 12, "Y12_1X12" } }, - { MEDIA_BUS_FMT_UYVY8_1X16, { 16, "UYVY8_1X16" } }, - { MEDIA_BUS_FMT_VYUY8_1X16, { 16, "VYUY8_1X16" } }, - { MEDIA_BUS_FMT_YUYV8_1X16, { 16, "YUYV8_1X16" } }, - { MEDIA_BUS_FMT_YVYU8_1X16, { 16, "YVYU8_1X16" } }, - { MEDIA_BUS_FMT_YDYUYDYV8_1X16, { 16, "YDYUYDYV8_1X16" } }, - { MEDIA_BUS_FMT_UYVY10_1X20, { 20, "UYVY10_1X20" } }, - { MEDIA_BUS_FMT_VYUY10_1X20, { 20, "VYUY10_1X20" } }, - { MEDIA_BUS_FMT_YUYV10_1X20, { 20, "YUYV10_1X20" } }, - { MEDIA_BUS_FMT_YVYU10_1X20, { 20, "YVYU10_1X20" } }, - { MEDIA_BUS_FMT_YUV8_1X24, { 24, "YUV8_1X24" } }, - { MEDIA_BUS_FMT_YUV10_1X30, { 30, "YUV10_1X30" } }, - { MEDIA_BUS_FMT_AYUV8_1X32, { 32, "AYUV8_1X32" } }, - { MEDIA_BUS_FMT_UYVY12_2X12, { 24, "UYVY12_2X12" } }, - { MEDIA_BUS_FMT_VYUY12_2X12, { 24, "VYUY12_2X12" } }, - { MEDIA_BUS_FMT_YUYV12_2X12, { 24, "YUYV12_2X12" } }, - { MEDIA_BUS_FMT_YVYU12_2X12, { 24, "YVYU12_2X12" } }, - { MEDIA_BUS_FMT_UYVY12_1X24, { 24, "UYVY12_1X24" } }, - { MEDIA_BUS_FMT_VYUY12_1X24, { 24, "VYUY12_1X24" } }, - { MEDIA_BUS_FMT_YUYV12_1X24, { 24, "YUYV12_1X24" } }, - { MEDIA_BUS_FMT_YVYU12_1X24, { 24, "YVYU12_1X24" } }, - { MEDIA_BUS_FMT_SBGGR8_1X8, { 8, "SBGGR8_1X8" } }, - { MEDIA_BUS_FMT_SGBRG8_1X8, { 8, "SGBRG8_1X8" } }, - { MEDIA_BUS_FMT_SGRBG8_1X8, { 8, "SGRBG8_1X8" } }, - { MEDIA_BUS_FMT_SRGGB8_1X8, { 8, "SRGGB8_1X8" } }, - { MEDIA_BUS_FMT_SBGGR10_ALAW8_1X8, { 8, "SBGGR10_ALAW8_1X8" } }, - { MEDIA_BUS_FMT_SGBRG10_ALAW8_1X8, { 8, "SGBRG10_ALAW8_1X8" } }, - { MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8, { 8, "SGRBG10_ALAW8_1X8" } }, - { MEDIA_BUS_FMT_SRGGB10_ALAW8_1X8, { 8, "SRGGB10_ALAW8_1X8" } }, - { MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8, { 8, "SBGGR10_DPCM8_1X8" } }, - { MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8, { 8, "SGBRG10_DPCM8_1X8" } }, - { MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, { 8, "SGRBG10_DPCM8_1X8" } }, - { MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8, { 8, "SRGGB10_DPCM8_1X8" } }, - { MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE, { 16, "SBGGR10_2X8_PADHI_BE" } }, - { MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, { 16, "SBGGR10_2X8_PADHI_LE" } }, - { MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE, { 16, "SBGGR10_2X8_PADLO_BE" } }, - { MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE, { 16, "SBGGR10_2X8_PADLO_LE" } }, - { MEDIA_BUS_FMT_SBGGR10_1X10, { 10, "SBGGR10_1X10" } }, - { MEDIA_BUS_FMT_SGBRG10_1X10, { 10, "SGBRG10_1X10" } }, - { MEDIA_BUS_FMT_SGRBG10_1X10, { 10, "SGRBG10_1X10" } }, - { MEDIA_BUS_FMT_SRGGB10_1X10, { 10, "SRGGB10_1X10" } }, - { MEDIA_BUS_FMT_SBGGR12_1X12, { 12, "SBGGR12_1X12" } }, - { MEDIA_BUS_FMT_SGBRG12_1X12, { 12, "SGBRG12_1X12" } }, - { MEDIA_BUS_FMT_SGRBG12_1X12, { 12, "SGRBG12_1X12" } }, - { MEDIA_BUS_FMT_SRGGB12_1X12, { 12, "SRGGB12_1X12" } }, - { MEDIA_BUS_FMT_AHSV8888_1X32, { 32, "AHSV8888_1X32" } }, + { MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE, { 16, "RGB444_2X8_PADHI_BE", PixelFormatInfo::ColourEncodingRGB } }, + { MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE, { 16, "RGB444_2X8_PADHI_LE", PixelFormatInfo::ColourEncodingRGB } }, + { MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE, { 16, "RGB555_2X8_PADHI_BE", PixelFormatInfo::ColourEncodingRGB } }, + { MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE, { 16, "RGB555_2X8_PADHI_LE", PixelFormatInfo::ColourEncodingRGB } }, + { MEDIA_BUS_FMT_RGB565_1X16, { 16, "RGB565_1X16", PixelFormatInfo::ColourEncodingRGB } }, + { MEDIA_BUS_FMT_BGR565_2X8_BE, { 16, "BGR565_2X8_BE", PixelFormatInfo::ColourEncodingRGB } }, + { MEDIA_BUS_FMT_BGR565_2X8_LE, { 16, "BGR565_2X8_LE", PixelFormatInfo::ColourEncodingRGB } }, + { MEDIA_BUS_FMT_RGB565_2X8_BE, { 16, "RGB565_2X8_BE", PixelFormatInfo::ColourEncodingRGB } }, + { MEDIA_BUS_FMT_RGB565_2X8_LE, { 16, "RGB565_2X8_LE", PixelFormatInfo::ColourEncodingRGB } }, + { MEDIA_BUS_FMT_RGB666_1X18, { 18, "RGB666_1X18", PixelFormatInfo::ColourEncodingRGB } }, + { MEDIA_BUS_FMT_RGB888_1X24, { 24, "RGB888_1X24", PixelFormatInfo::ColourEncodingRGB } }, + { MEDIA_BUS_FMT_RGB888_2X12_BE, { 24, "RGB888_2X12_BE", PixelFormatInfo::ColourEncodingRGB } }, + { MEDIA_BUS_FMT_RGB888_2X12_LE, { 24, "RGB888_2X12_LE", PixelFormatInfo::ColourEncodingRGB } }, + { MEDIA_BUS_FMT_ARGB8888_1X32, { 32, "ARGB8888_1X32", PixelFormatInfo::ColourEncodingRGB } }, + { MEDIA_BUS_FMT_Y8_1X8, { 8, "Y8_1X8", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_UV8_1X8, { 8, "UV8_1X8", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_UYVY8_1_5X8, { 12, "UYVY8_1_5X8", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_VYUY8_1_5X8, { 12, "VYUY8_1_5X8", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_YUYV8_1_5X8, { 12, "YUYV8_1_5X8", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_YVYU8_1_5X8, { 12, "YVYU8_1_5X8", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_UYVY8_2X8, { 16, "UYVY8_2X8", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_VYUY8_2X8, { 16, "VYUY8_2X8", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_YUYV8_2X8, { 16, "YUYV8_2X8", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_YVYU8_2X8, { 16, "YVYU8_2X8", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_Y10_1X10, { 10, "Y10_1X10", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_UYVY10_2X10, { 20, "UYVY10_2X10", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_VYUY10_2X10, { 20, "VYUY10_2X10", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_YUYV10_2X10, { 20, "YUYV10_2X10", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_YVYU10_2X10, { 20, "YVYU10_2X10", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_Y12_1X12, { 12, "Y12_1X12", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_UYVY8_1X16, { 16, "UYVY8_1X16", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_VYUY8_1X16, { 16, "VYUY8_1X16", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_YUYV8_1X16, { 16, "YUYV8_1X16", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_YVYU8_1X16, { 16, "YVYU8_1X16", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_YDYUYDYV8_1X16, { 16, "YDYUYDYV8_1X16", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_UYVY10_1X20, { 20, "UYVY10_1X20", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_VYUY10_1X20, { 20, "VYUY10_1X20", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_YUYV10_1X20, { 20, "YUYV10_1X20", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_YVYU10_1X20, { 20, "YVYU10_1X20", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_YUV8_1X24, { 24, "YUV8_1X24", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_YUV10_1X30, { 30, "YUV10_1X30", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_AYUV8_1X32, { 32, "AYUV8_1X32", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_UYVY12_2X12, { 24, "UYVY12_2X12", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_VYUY12_2X12, { 24, "VYUY12_2X12", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_YUYV12_2X12, { 24, "YUYV12_2X12", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_YVYU12_2X12, { 24, "YVYU12_2X12", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_UYVY12_1X24, { 24, "UYVY12_1X24", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_VYUY12_1X24, { 24, "VYUY12_1X24", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_YUYV12_1X24, { 24, "YUYV12_1X24", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_YVYU12_1X24, { 24, "YVYU12_1X24", PixelFormatInfo::ColourEncodingYUV } }, + { MEDIA_BUS_FMT_SBGGR8_1X8, { 8, "SBGGR8_1X8", PixelFormatInfo::ColourEncodingRAW } }, + { MEDIA_BUS_FMT_SGBRG8_1X8, { 8, "SGBRG8_1X8", PixelFormatInfo::ColourEncodingRAW } }, + { MEDIA_BUS_FMT_SGRBG8_1X8, { 8, "SGRBG8_1X8", PixelFormatInfo::ColourEncodingRAW } }, + { MEDIA_BUS_FMT_SRGGB8_1X8, { 8, "SRGGB8_1X8", PixelFormatInfo::ColourEncodingRAW } }, + { MEDIA_BUS_FMT_SBGGR10_ALAW8_1X8, { 8, "SBGGR10_ALAW8_1X8", PixelFormatInfo::ColourEncodingRAW } }, + { MEDIA_BUS_FMT_SGBRG10_ALAW8_1X8, { 8, "SGBRG10_ALAW8_1X8", PixelFormatInfo::ColourEncodingRAW } }, + { MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8, { 8, "SGRBG10_ALAW8_1X8", PixelFormatInfo::ColourEncodingRAW } }, + { MEDIA_BUS_FMT_SRGGB10_ALAW8_1X8, { 8, "SRGGB10_ALAW8_1X8", PixelFormatInfo::ColourEncodingRAW } }, + { MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8, { 8, "SBGGR10_DPCM8_1X8", PixelFormatInfo::ColourEncodingRAW } }, + { MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8, { 8, "SGBRG10_DPCM8_1X8", PixelFormatInfo::ColourEncodingRAW } }, + { MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, { 8, "SGRBG10_DPCM8_1X8", PixelFormatInfo::ColourEncodingRAW } }, + { MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8, { 8, "SRGGB10_DPCM8_1X8", PixelFormatInfo::ColourEncodingRAW } }, + { MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE, { 16, "SBGGR10_2X8_PADHI_BE", PixelFormatInfo::ColourEncodingRAW } }, + { MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, { 16, "SBGGR10_2X8_PADHI_LE", PixelFormatInfo::ColourEncodingRAW } }, + { MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE, { 16, "SBGGR10_2X8_PADLO_BE", PixelFormatInfo::ColourEncodingRAW } }, + { MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE, { 16, "SBGGR10_2X8_PADLO_LE", PixelFormatInfo::ColourEncodingRAW } }, + { MEDIA_BUS_FMT_SBGGR10_1X10, { 10, "SBGGR10_1X10", PixelFormatInfo::ColourEncodingRAW } }, + { MEDIA_BUS_FMT_SGBRG10_1X10, { 10, "SGBRG10_1X10", PixelFormatInfo::ColourEncodingRAW } }, + { MEDIA_BUS_FMT_SGRBG10_1X10, { 10, "SGRBG10_1X10", PixelFormatInfo::ColourEncodingRAW } }, + { MEDIA_BUS_FMT_SRGGB10_1X10, { 10, "SRGGB10_1X10", PixelFormatInfo::ColourEncodingRAW } }, + { MEDIA_BUS_FMT_SBGGR12_1X12, { 12, "SBGGR12_1X12", PixelFormatInfo::ColourEncodingRAW } }, + { MEDIA_BUS_FMT_SGBRG12_1X12, { 12, "SGBRG12_1X12", PixelFormatInfo::ColourEncodingRAW } }, + { MEDIA_BUS_FMT_SGRBG12_1X12, { 12, "SGRBG12_1X12", PixelFormatInfo::ColourEncodingRAW } }, + { MEDIA_BUS_FMT_SRGGB12_1X12, { 12, "SRGGB12_1X12", PixelFormatInfo::ColourEncodingRAW } }, + /* \todo Clarify colour encoding for HSV formats */ + { MEDIA_BUS_FMT_AHSV8888_1X32, { 32, "AHSV8888_1X32", PixelFormatInfo::ColourEncodingRGB } }, }; } /* namespace */ From patchwork Tue Aug 30 07:47:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 17251 X-Patchwork-Delegate: umang.jain@ideasonboard.com Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 0EE7FC3272 for ; Tue, 30 Aug 2022 07:47:42 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id CAD1B61FC7; Tue, 30 Aug 2022 09:47:41 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1661845661; bh=YqjMQP/yqXTzS70rx2uwu27GT7lMJ5U35FUq+fek4Gc=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=G8lyKVgVXHbvoCFOS1MRYFIZLkbYMCDdJsvSrS//QsTdbkFrPA7RehDvN3fiFKjUq paVnSjd77RKzTJ7XoMtZJA7xwquX9uBRPvWE1KSNZW0TszrNwtZLcGERlIfUZYQ5mm FmnJGFs9NXtPOlBYWkD7DIr9o4gLW/vHCFB0Bycys5rDWa6fM3Fbdka6KPt2WWxLo6 ii3tU77Z1KhcuqxU1WyxN7xS4yI/I31FnvKaU2r5ue6N1XTqEiHNSggQpY689KHREd u1rjCYKk1TNAU5VOTLZgxw6w9mP0Etc4rp5FLJKHmt5PimMm5mMj3USbblx3YLKU4u BP8HVH1nHTFDg== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 43B5561FB9 for ; Tue, 30 Aug 2022 09:47:41 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="vvBYdWQe"; dkim-atps=neutral Received: from umang.jainideasonboard.com (unknown [IPv6:2401:4900:1f3f:1548:78ac:4a3:edc3:c28a]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 66C41481; Tue, 30 Aug 2022 09:47:39 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1661845661; bh=YqjMQP/yqXTzS70rx2uwu27GT7lMJ5U35FUq+fek4Gc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=vvBYdWQel3o1M4mVVJLg30SfHCfLw8J9+BvaGpw2+1FI7V6S6MjR5UxZBfii0Q+r2 RHT9zoeU/XQ8ymSUv1L12q6rVmJWGReddyMyXMHyTejVCFcXD27Ut6Z4VZHpxzPWoa hZs70G3qiNssuhrGxSg2t+NdSbCqVy9HNfUGZDSM= To: libcamera-devel@lists.libcamera.org Date: Tue, 30 Aug 2022 13:17:20 +0530 Message-Id: <20220830074725.1059643-3-umang.jain@ideasonboard.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20220830074725.1059643-1-umang.jain@ideasonboard.com> References: <20220830074725.1059643-1-umang.jain@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 2/7] libcamera: v4l2_device: Adjust colorspace based on pixel format X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Umang Jain via libcamera-devel From: Umang Jain Reply-To: Umang Jain Cc: rishikeshdonadkar@gmail.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" 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 --- include/libcamera/internal/v4l2_device.h | 5 +++- src/libcamera/v4l2_device.cpp | 29 +++++++++++++++++++---- src/libcamera/v4l2_subdevice.cpp | 30 ++++++++++++++++++++++-- src/libcamera/v4l2_videodevice.cpp | 12 ++++++---- 4 files changed, 65 insertions(+), 11 deletions(-) diff --git a/include/libcamera/internal/v4l2_device.h b/include/libcamera/internal/v4l2_device.h index a52a5f2c..75304be1 100644 --- a/include/libcamera/internal/v4l2_device.h +++ b/include/libcamera/internal/v4l2_device.h @@ -22,6 +22,8 @@ #include #include +#include "libcamera/internal/formats.h" + namespace libcamera { class EventNotifier; @@ -59,7 +61,8 @@ protected: int fd() const { return fd_.get(); } template - static std::optional toColorSpace(const T &v4l2Format); + static std::optional toColorSpace(const T &v4l2Format, + PixelFormatInfo::ColourEncoding colourEncoding); template static int fromColorSpace(const std::optional &colorSpace, T &v4l2Format); 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 diff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp index 07a0bb07..95bfde34 100644 --- a/src/libcamera/v4l2_subdevice.cpp +++ b/src/libcamera/v4l2_subdevice.cpp @@ -503,7 +503,20 @@ int V4L2Subdevice::getFormat(unsigned int pad, V4L2SubdeviceFormat *format, format->size.width = subdevFmt.format.width; format->size.height = subdevFmt.format.height; format->mbus_code = subdevFmt.format.code; - format->colorSpace = toColorSpace(subdevFmt.format); + + PixelFormatInfo::ColourEncoding colourEncoding; + auto iter = formatInfoMap.find(subdevFmt.format.code); + if (iter != formatInfoMap.end()) { + colourEncoding = iter->second.colourEncoding; + } else { + LOG(V4L2, Warning) + << "Unknown subdev format " + << utils::hex(subdevFmt.format.code, 4) + << ", defaulting to RGB encoding"; + + colourEncoding = PixelFormatInfo::ColourEncodingRGB; + } + format->colorSpace = toColorSpace(subdevFmt.format, colourEncoding); return 0; } @@ -549,7 +562,20 @@ int V4L2Subdevice::setFormat(unsigned int pad, V4L2SubdeviceFormat *format, format->size.width = subdevFmt.format.width; format->size.height = subdevFmt.format.height; format->mbus_code = subdevFmt.format.code; - format->colorSpace = toColorSpace(subdevFmt.format); + + PixelFormatInfo::ColourEncoding colourEncoding; + auto iter = formatInfoMap.find(subdevFmt.format.code); + if (iter != formatInfoMap.end()) { + colourEncoding = iter->second.colourEncoding; + } else { + LOG(V4L2, Warning) + << "Unknown subdev format " + << utils::hex(subdevFmt.format.code, 4) + << ", defaulting to RGB encoding"; + + colourEncoding = PixelFormatInfo::ColourEncodingRGB; + } + format->colorSpace = toColorSpace(subdevFmt.format, colourEncoding); return 0; } diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp index 5a2d0e5b..0e3f5436 100644 --- a/src/libcamera/v4l2_videodevice.cpp +++ b/src/libcamera/v4l2_videodevice.cpp @@ -931,7 +931,8 @@ int V4L2VideoDevice::getFormatMultiplane(V4L2DeviceFormat *format) format->size.height = pix->height; format->fourcc = V4L2PixelFormat(pix->pixelformat); format->planesCount = pix->num_planes; - format->colorSpace = toColorSpace(*pix); + format->colorSpace = + toColorSpace(*pix, PixelFormatInfo::info(format->fourcc).colourEncoding); for (unsigned int i = 0; i < format->planesCount; ++i) { format->planes[i].bpl = pix->plane_fmt[i].bytesperline; @@ -987,7 +988,8 @@ int V4L2VideoDevice::trySetFormatMultiplane(V4L2DeviceFormat *format, bool set) format->planes[i].bpl = pix->plane_fmt[i].bytesperline; format->planes[i].size = pix->plane_fmt[i].sizeimage; } - format->colorSpace = toColorSpace(*pix); + format->colorSpace = + toColorSpace(*pix, PixelFormatInfo::info(format->fourcc).colourEncoding); return 0; } @@ -1011,7 +1013,8 @@ int V4L2VideoDevice::getFormatSingleplane(V4L2DeviceFormat *format) format->planesCount = 1; format->planes[0].bpl = pix->bytesperline; format->planes[0].size = pix->sizeimage; - format->colorSpace = toColorSpace(*pix); + format->colorSpace = + toColorSpace(*pix, PixelFormatInfo::info(format->fourcc).colourEncoding); return 0; } @@ -1053,7 +1056,8 @@ int V4L2VideoDevice::trySetFormatSingleplane(V4L2DeviceFormat *format, bool set) format->planesCount = 1; format->planes[0].bpl = pix->bytesperline; format->planes[0].size = pix->sizeimage; - format->colorSpace = toColorSpace(*pix); + format->colorSpace = + toColorSpace(*pix, PixelFormatInfo::info(format->fourcc).colourEncoding); return 0; } From patchwork Tue Aug 30 07:47:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 17252 X-Patchwork-Delegate: umang.jain@ideasonboard.com Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 8CD65C3272 for ; Tue, 30 Aug 2022 07:47:45 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4098161FCA; Tue, 30 Aug 2022 09:47:45 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1661845665; bh=F57f8OYYK+J58sw9ygr9piCiPoT7m3c6N7oT+BqHHrs=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=GSHMdpmWAIC+M3Gc6rdgrCZ9Q1TntqzJ8EidYeOkvbdYBQp97vmgq+jqPbl8n0/nX iHhBezr8xQU2FRKI7ig4/UquDdZ0YBBAc/SamQsfaWAeM+xq3vLFccow+PNxW0h2FA wpL4YmikRnt7ZOk1+AgTM+g8HDs3k9efnTayDBbJOztYLkpW0S/C1u3rC1RrEgCQUZ L/qVaFzS0WCGxHKuDguiXBHN8PU2gwxPY7qzXoSkWk05xEXJ5FOGfGPd+y+7/G0g3e 88x+wkQEKHLoQ3iOKE16z3q5tqEHoth0APkDXA4vN8vzp4qz+dKbjqsQIPEb/XEIFj vI14DnTRxnoDg== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id CEC2361FB9 for ; Tue, 30 Aug 2022 09:47:43 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="mVzQHsa6"; dkim-atps=neutral Received: from umang.jainideasonboard.com (unknown [IPv6:2401:4900:1f3f:1548:78ac:4a3:edc3:c28a]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 15DA0481; Tue, 30 Aug 2022 09:47:41 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1661845663; bh=F57f8OYYK+J58sw9ygr9piCiPoT7m3c6N7oT+BqHHrs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mVzQHsa6/+dOzMVtK5fgNs5SScIyZXrKgFtxNr8sQAkM6UYoucs2JAIG1C5V8OTho HSKjs8NKFie84ouBVmY2RDYHNCCBH/bkSjfTvP9TQZdgsHoiOQjURCsEpWdz6H8XaJ /rC3jk2AChEhGgMUvGK0G+xgLNqjpGoLqmqgzrUU= To: libcamera-devel@lists.libcamera.org Date: Tue, 30 Aug 2022 13:17:21 +0530 Message-Id: <20220830074725.1059643-4-umang.jain@ideasonboard.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20220830074725.1059643-1-umang.jain@ideasonboard.com> References: <20220830074725.1059643-1-umang.jain@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 3/7] libcamera: v4l2_videodevice: Improve toColorSpace() readability X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Umang Jain via libcamera-devel From: Umang Jain Reply-To: Umang Jain Cc: rishikeshdonadkar@gmail.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Wrap V4L2Device::toColorspace() inside a private static member function in V4L2VideoDevice class. It improves readability in setting the colorspace for V4L2DeviceFormat. No functional changes intended. Signed-off-by: Umang Jain Reviewed-by: Laurent Pinchart Reviewed-by: Paul Elder --- include/libcamera/internal/v4l2_videodevice.h | 3 +++ src/libcamera/v4l2_videodevice.cpp | 19 +++++++++++-------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/include/libcamera/internal/v4l2_videodevice.h b/include/libcamera/internal/v4l2_videodevice.h index ed98a284..d157a447 100644 --- a/include/libcamera/internal/v4l2_videodevice.h +++ b/include/libcamera/internal/v4l2_videodevice.h @@ -268,6 +268,9 @@ private: void watchdogExpired(); + template + static std::optional toColorSpace(const T &v4l2Format); + V4L2Capability caps_; V4L2DeviceFormat format_; const PixelFormatInfo *formatInfo_; diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp index 0e3f5436..955e1508 100644 --- a/src/libcamera/v4l2_videodevice.cpp +++ b/src/libcamera/v4l2_videodevice.cpp @@ -914,6 +914,13 @@ int V4L2VideoDevice::trySetFormatMeta(V4L2DeviceFormat *format, bool set) return 0; } +template +std::optional V4L2VideoDevice::toColorSpace(const T &v4l2Format) +{ + V4L2PixelFormat fourcc{ v4l2Format.pixelformat }; + return V4L2Device::toColorSpace(v4l2Format, PixelFormatInfo::info(fourcc).colourEncoding); +} + int V4L2VideoDevice::getFormatMultiplane(V4L2DeviceFormat *format) { struct v4l2_format v4l2Format = {}; @@ -931,8 +938,7 @@ int V4L2VideoDevice::getFormatMultiplane(V4L2DeviceFormat *format) format->size.height = pix->height; format->fourcc = V4L2PixelFormat(pix->pixelformat); format->planesCount = pix->num_planes; - format->colorSpace = - toColorSpace(*pix, PixelFormatInfo::info(format->fourcc).colourEncoding); + format->colorSpace = toColorSpace(*pix); for (unsigned int i = 0; i < format->planesCount; ++i) { format->planes[i].bpl = pix->plane_fmt[i].bytesperline; @@ -988,8 +994,7 @@ int V4L2VideoDevice::trySetFormatMultiplane(V4L2DeviceFormat *format, bool set) format->planes[i].bpl = pix->plane_fmt[i].bytesperline; format->planes[i].size = pix->plane_fmt[i].sizeimage; } - format->colorSpace = - toColorSpace(*pix, PixelFormatInfo::info(format->fourcc).colourEncoding); + format->colorSpace = toColorSpace(*pix); return 0; } @@ -1013,8 +1018,7 @@ int V4L2VideoDevice::getFormatSingleplane(V4L2DeviceFormat *format) format->planesCount = 1; format->planes[0].bpl = pix->bytesperline; format->planes[0].size = pix->sizeimage; - format->colorSpace = - toColorSpace(*pix, PixelFormatInfo::info(format->fourcc).colourEncoding); + format->colorSpace = toColorSpace(*pix); return 0; } @@ -1056,8 +1060,7 @@ int V4L2VideoDevice::trySetFormatSingleplane(V4L2DeviceFormat *format, bool set) format->planesCount = 1; format->planes[0].bpl = pix->bytesperline; format->planes[0].size = pix->sizeimage; - format->colorSpace = - toColorSpace(*pix, PixelFormatInfo::info(format->fourcc).colourEncoding); + format->colorSpace = toColorSpace(*pix); return 0; } From patchwork Tue Aug 30 07:47:22 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 17253 X-Patchwork-Delegate: umang.jain@ideasonboard.com Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 1F2DAC3272 for ; Tue, 30 Aug 2022 07:47:47 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D2A9161FCD; Tue, 30 Aug 2022 09:47:46 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1661845666; bh=BJE/sijghjgSBi4m+tWWT8qpCRnDSH7pzLiDtsHQR6Y=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=dArSC1cf4UuQ+icETa04fQjsPRxDeIyVzJam1BW0fWBnJLQbvP5Usq49EhBw6lEpE ymGplKrfsxlqcA45JxSs++7fLtADHSzHllW4x+4RKUDs7hjrcU1MP1RdVeRTYN9ZQD jEIG+geIsODLiFzuDW3vWD5yWI8HO0eKem9n7YfRynVku/oQAmd1d9d2U7eAx3E06d JauEVezuinnum7lrZ8xD9429vdcs6wn7yh5o7lXspQ3hLkXuACXsx2Nn2Nb533hKAp 4TV2zGeUyp458gPXvmDin0I1i0fGduLZOuJjUQkXeJI444EptA9FvnmPf5jjoL+3GF xYMRHIGQzfbyQ== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 1F5C761FB9 for ; Tue, 30 Aug 2022 09:47:46 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="pwZVOdAg"; dkim-atps=neutral Received: from umang.jainideasonboard.com (unknown [IPv6:2401:4900:1f3f:1548:78ac:4a3:edc3:c28a]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 99D5D481; Tue, 30 Aug 2022 09:47:44 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1661845665; bh=BJE/sijghjgSBi4m+tWWT8qpCRnDSH7pzLiDtsHQR6Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=pwZVOdAgUymiDZzX/cwsq647IKrnpxH+ruYNw2GYCnnsS6iNUuLJYfFdv25bvGE8f PiawHbfOYYq7tWKN1pVpMtVIbwuu94GaCKmjVvhw/ThNeETFsJTAJss2g8Ln+CrCsL NVTSJz0eQwd+K0bHPTLIwQkfGpIDwzUZ9ItBaRfw= To: libcamera-devel@lists.libcamera.org Date: Tue, 30 Aug 2022 13:17:22 +0530 Message-Id: <20220830074725.1059643-5-umang.jain@ideasonboard.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20220830074725.1059643-1-umang.jain@ideasonboard.com> References: <20220830074725.1059643-1-umang.jain@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 4/7] libcamera: colorspace: Rectify the ColorSpace::Srgb preset X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Umang Jain via libcamera-devel From: Umang Jain Reply-To: Umang Jain Cc: rishikeshdonadkar@gmail.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Rectify the ColorSpace::Srgb to denote that it does not use any Y'Cbcr encoding and uses full range. The kernel on the other hand, recommends to use Rec601 as the encoding for V4L2_COLORSPACE_SRGB. It is not very explicit but it can be inferred that the kernel assumes V4L2_COLORSPACE_SRGB is a YUV-encoded one. However, when the data is in RGB, no encoding is required (and this is denoted by YcbcrEncoding::None in libcamera). Hence, to be clear on the libcamera colorspace API, rectify the ColorSpace::Srgb preset to use YcbcrEncoding::None and full range. Signed-off-by: Umang Jain Reviewed-by: Laurent Pinchart Reviewed-by: Paul Elder --- src/libcamera/color_space.cpp | 18 ++++++++++-------- src/libcamera/v4l2_device.cpp | 7 +++++-- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/libcamera/color_space.cpp b/src/libcamera/color_space.cpp index 944d0e98..ec34620a 100644 --- a/src/libcamera/color_space.cpp +++ b/src/libcamera/color_space.cpp @@ -49,8 +49,13 @@ namespace libcamera { * - Rec.2020 * * Note that there is no guarantee of a 1:1 mapping between color space names - * and definitions in libcamera and V4L2. A notable difference is that the sYCC - * libcamera color space is called JPEG in V4L2 due to historical reasons. + * and definitions in libcamera and V4L2. Two notable differences are + * + * - The sRGB libcamera color space is defined for RGB formats only with no + * Y'CbCr encoding and a full quantization range, while the V4L2 SRGB color + * space has a Y'CbCr encoding and a limited quantization range. + * - The sYCC libcamera color space is called JPEG in V4L2 due to historical + * reasons. * * \todo Define the color space fully in the libcamera API to avoid referencing * V4L2 @@ -138,16 +143,13 @@ const ColorSpace ColorSpace::Raw = { }; /** - * \brief A constant representing the sRGB color space - * - * This is identical to the sYCC color space except that the Y'CbCr - * range is limited rather than full. + * \brief A constant representing the sRGB color space (RGB formats only) */ const ColorSpace ColorSpace::Srgb = { Primaries::Rec709, TransferFunction::Srgb, - YcbcrEncoding::Rec601, - Range::Limited + YcbcrEncoding::None, + Range::Full }; /** diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 301620f8..1d899657 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -746,7 +746,11 @@ void V4L2Device::eventAvailable() static const std::map v4l2ToColorSpace = { { V4L2_COLORSPACE_RAW, ColorSpace::Raw }, - { V4L2_COLORSPACE_SRGB, ColorSpace::Srgb }, + { V4L2_COLORSPACE_SRGB, { + ColorSpace::Primaries::Rec709, + ColorSpace::TransferFunction::Srgb, + ColorSpace::YcbcrEncoding::Rec601, + ColorSpace::Range::Limited } }, { V4L2_COLORSPACE_JPEG, ColorSpace::Sycc }, { V4L2_COLORSPACE_SMPTE170M, ColorSpace::Smpte170m }, { V4L2_COLORSPACE_REC709, ColorSpace::Rec709 }, @@ -772,7 +776,6 @@ static const std::map v4l2ToRange = { static const std::vector> colorSpaceToV4l2 = { { ColorSpace::Raw, V4L2_COLORSPACE_RAW }, - { ColorSpace::Srgb, V4L2_COLORSPACE_SRGB }, { ColorSpace::Sycc, V4L2_COLORSPACE_JPEG }, { ColorSpace::Smpte170m, V4L2_COLORSPACE_SMPTE170M }, { ColorSpace::Rec709, V4L2_COLORSPACE_REC709 }, From patchwork Tue Aug 30 07:47:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 17254 X-Patchwork-Delegate: umang.jain@ideasonboard.com Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id B4E77C3272 for ; Tue, 30 Aug 2022 07:47:50 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7666F61FC1; Tue, 30 Aug 2022 09:47:50 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1661845670; bh=psmaUBKUBww47lbfze0f1NvxjgvL30karPZR5FG9adM=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=RlnV7NcqpTDgPX/N13wM5k/eb5LGeXKQgF334lqsO+roa2C5a1FUz3gczbcG+0F0N sRCt6gvAr/zOsV4UhY+xjLbHJu8DM07pAR1OSvp8DcLkaX8VfML9fWwJLFmkHc3V7K M10iVThTu6PL19Fcp1iKd9Fl4aYkqqskzu1qWtJYQ84huxovKmBYxeAg4LX3H9OdN6 xHSWjP42/6K6UNiC5bcdpQJT5hgZPVl+vUJzqzahI5bS71AmPpvU0D0G4jIzNdGuEo kEcQP1ug7Nm13F0CkeZJMGmXylhMxTcllS3tsBwYlRt8ya4ga3YdGtECZP0EkAegRP CIx39c9R+ClrQ== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 87ED761FB9 for ; Tue, 30 Aug 2022 09:47:48 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="dFpnJSv4"; dkim-atps=neutral Received: from umang.jainideasonboard.com (unknown [IPv6:2401:4900:1f3f:1548:78ac:4a3:edc3:c28a]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 18CD4481; Tue, 30 Aug 2022 09:47:46 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1661845668; bh=psmaUBKUBww47lbfze0f1NvxjgvL30karPZR5FG9adM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=dFpnJSv4E4/dS2e2OAqgnQmNEHXzJ9XpRknFD06TAoCgRf8JEJGmpAxq+PQPMt+JF FOs+BKzyTjILM9jKiBK9J5YIz2PmPnRI53YakM03hCY72p2h4FOkQkI6T1c4Ao5K+6 g7qqjXJEpCvAaYrlsPCNiLmAzWBnEODNQ9uCVMn0= To: libcamera-devel@lists.libcamera.org Date: Tue, 30 Aug 2022 13:17:23 +0530 Message-Id: <20220830074725.1059643-6-umang.jain@ideasonboard.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20220830074725.1059643-1-umang.jain@ideasonboard.com> References: <20220830074725.1059643-1-umang.jain@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 5/7] libcamera: color_space: Move color space adjustment to ColorSpace class X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Umang Jain via libcamera-devel From: Umang Jain Reply-To: Umang Jain Cc: rishikeshdonadkar@gmail.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The CameraConfiguration::validateColorSpaces() function performs color space validation on a camera configuration, by validating the color space of each stream individually, and optionally ensuring that all streams share the same color space. The individual validation is very basic, limited to ensuring that raw formats use a raw color space. Color spaces are more constrained than that: - The Y'CbCr encoding and quantization range for RGB formats must be YcbcrEncoding::None and Range::Full respectively. - The Y'CbCr encoding for YUV formats must not be YcbcrEncoding::None. Instead of open-coding these constraints in the validateColorSpaces() function, create a new ColorSpace::adjust() function to centralize color space validation and adjustment, and use it in validateColorSpaces(). Signed-off-by: Umang Jain Signed-off-by: Laurent Pinchart Reviewed-by: Umang Jain Reviewed-by: Paul Elder --- include/libcamera/color_space.h | 4 ++ src/libcamera/camera.cpp | 43 ++++++-------- src/libcamera/color_space.cpp | 101 ++++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+), 26 deletions(-) diff --git a/include/libcamera/color_space.h b/include/libcamera/color_space.h index f493f72d..6d6c2829 100644 --- a/include/libcamera/color_space.h +++ b/include/libcamera/color_space.h @@ -12,6 +12,8 @@ namespace libcamera { +class PixelFormat; + class ColorSpace { public: @@ -61,6 +63,8 @@ public: static std::string toString(const std::optional &colorSpace); static std::optional fromString(const std::string &str); + + bool adjust(PixelFormat format); }; bool operator==(const ColorSpace &lhs, const ColorSpace &rhs); diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp index a5c3aabe..9fe29ca9 100644 --- a/src/libcamera/camera.cpp +++ b/src/libcamera/camera.cpp @@ -317,17 +317,6 @@ std::size_t CameraConfiguration::size() const return config_.size(); } -namespace { - -bool isRaw(const PixelFormat &pixFmt) -{ - const PixelFormatInfo &info = PixelFormatInfo::info(pixFmt); - return info.isValid() && - info.colourEncoding == PixelFormatInfo::ColourEncodingRAW; -} - -} /* namespace */ - /** * \enum CameraConfiguration::ColorSpaceFlag * \brief Specify the behaviour of validateColorSpaces @@ -368,29 +357,31 @@ CameraConfiguration::Status CameraConfiguration::validateColorSpaces(ColorSpaceF Status status = Valid; /* - * Set all raw streams to the Raw color space, and make a note of the largest - * non-raw stream with a defined color space (if there is one). + * Set all raw streams to the Raw color space, and make a note of the + * largest non-raw stream with a defined color space (if there is one). */ - int index = -1; + std::optional colorSpace; + for (auto [i, cfg] : utils::enumerate(config_)) { - if (isRaw(cfg.pixelFormat)) { - if (cfg.colorSpace != ColorSpace::Raw) { - cfg.colorSpace = ColorSpace::Raw; - status = Adjusted; - } - } else if (cfg.colorSpace && (index == -1 || cfg.size > config_[i].size)) { - index = i; - } + if (!cfg.colorSpace) + continue; + + if (cfg.colorSpace->adjust(cfg.pixelFormat)) + status = Adjusted; + + if (cfg.colorSpace != ColorSpace::Raw && + (!colorSpace || cfg.size > config_[i].size)) + colorSpace = cfg.colorSpace; } - if (index < 0 || !(flags & ColorSpaceFlag::StreamsShareColorSpace)) + if (!colorSpace || !(flags & ColorSpaceFlag::StreamsShareColorSpace)) return status; /* Make all output color spaces the same, if requested. */ for (auto &cfg : config_) { - if (!isRaw(cfg.pixelFormat) && - cfg.colorSpace != config_[index].colorSpace) { - cfg.colorSpace = config_[index].colorSpace; + if (cfg.colorSpace != ColorSpace::Raw && + cfg.colorSpace != colorSpace) { + cfg.colorSpace = colorSpace; status = Adjusted; } } diff --git a/src/libcamera/color_space.cpp b/src/libcamera/color_space.cpp index ec34620a..7356bf7d 100644 --- a/src/libcamera/color_space.cpp +++ b/src/libcamera/color_space.cpp @@ -16,6 +16,8 @@ #include +#include "libcamera/internal/formats.h" + /** * \file color_space.h * \brief Class and enums to represent color spaces @@ -398,6 +400,105 @@ std::optional ColorSpace::fromString(const std::string &str) return colorSpace; } +/** + * \brief Adjust the color space to match a pixel format + * \param[in] format The pixel format + * + * Not all combinations of pixel formats and color spaces make sense. For + * instance, nobody uses a limited quantization range with raw Bayer formats, + * and the YcbcrEncoding::None encoding isn't valid for YUV formats. This + * function adjusts the ColorSpace to make it compatible with the given \a + * format, by applying the following rules: + * + * - The color space for RAW formats must be Raw. + * - The Y'CbCr encoding and quantization range for RGB formats must be + * YcbcrEncoding::None and Range::Full respectively. + * - The Y'CbCr encoding for YUV formats must not be YcbcrEncoding::None. The + * best encoding is in that case guessed based on the primaries and transfer + * function. + * + * \return True if the color space has been adjusted, or false if it was + * already compatible with the format and hasn't been changed + */ +bool ColorSpace::adjust(PixelFormat format) +{ + const PixelFormatInfo &info = PixelFormatInfo::info(format); + bool adjusted = false; + + switch (info.colourEncoding) { + case PixelFormatInfo::ColourEncodingRAW: + /* Raw formats must use the raw color space. */ + if (*this != ColorSpace::Raw) { + *this = ColorSpace::Raw; + adjusted = true; + } + break; + + case PixelFormatInfo::ColourEncodingRGB: + /* + * RGB formats can't have a Y'CbCr encoding, and must use full + * range quantization. + */ + if (ycbcrEncoding != YcbcrEncoding::None) { + ycbcrEncoding = YcbcrEncoding::None; + adjusted = true; + } + + if (range != Range::Full) { + range = Range::Full; + adjusted = true; + } + break; + + case PixelFormatInfo::ColourEncodingYUV: + if (ycbcrEncoding != YcbcrEncoding::None) + break; + + /* + * YUV formats must have a Y'CbCr encoding. Infer the most + * probable option from the transfer function and primaries. + */ + switch (transferFunction) { + case TransferFunction::Linear: + /* + * Linear YUV is not used in any standard color space, + * pick the widely supported and used Rec601 as default. + */ + ycbcrEncoding = YcbcrEncoding::Rec601; + break; + + case TransferFunction::Rec709: + switch (primaries) { + /* Raw should never happen. */ + case Primaries::Raw: + case Primaries::Smpte170m: + ycbcrEncoding = YcbcrEncoding::Rec601; + break; + case Primaries::Rec709: + ycbcrEncoding = YcbcrEncoding::Rec709; + break; + case Primaries::Rec2020: + ycbcrEncoding = YcbcrEncoding::Rec2020; + break; + } + break; + + case TransferFunction::Srgb: + /* + * Only the sYCC color space uses the sRGB transfer + * function, the corresponding encoding is Rec601. + */ + ycbcrEncoding = YcbcrEncoding::Rec601; + break; + } + + adjusted = true; + break; + } + + return adjusted; +} + /** * \brief Compare color spaces for equality * \return True if the two color spaces are identical, false otherwise From patchwork Tue Aug 30 07:47:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 17255 X-Patchwork-Delegate: umang.jain@ideasonboard.com Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 28BB1C3272 for ; Tue, 30 Aug 2022 07:47:53 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id DB13261FCC; Tue, 30 Aug 2022 09:47:52 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1661845672; bh=Jdj0XGz/2g2ed/6YUcDmE0nB72gTUKyrwSC/zUCODMs=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=le2NdP+qJJj5qwerUpbKLB/1x0gr3QoGujMduXn4X0l/eIJBOplRcQ5zlinU7xrmX aqCZKDXz8MFBECHOnrZxWW94OnTyi+dAiFqRFy5DSWwxyvCQcVoiqwmPrkGsUuJzVF GWTlgUbNBY675hPV0amCRYj3ZNGTJLdyopaLLqZoExkCMGLMt6p0XZ/MSXP247jTiH tmMF/zV6wBzwVcVGjqUdjbq3fdLGywuBSKtWh4p4f/Eyj/dfTC0fS0YeZgsRA+17ol GIJTmlyIsvILKbr8VMPY1PIngLYPJyScSFY0SJ5s16rFusbsOeIQZ24+TW3hSrcbvr X1MEzeDOOzIOQ== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F0F6061FB9 for ; Tue, 30 Aug 2022 09:47:50 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="C0s69qaS"; dkim-atps=neutral Received: from umang.jainideasonboard.com (unknown [IPv6:2401:4900:1f3f:1548:78ac:4a3:edc3:c28a]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 7022C481; Tue, 30 Aug 2022 09:47:49 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1661845670; bh=Jdj0XGz/2g2ed/6YUcDmE0nB72gTUKyrwSC/zUCODMs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=C0s69qaSv/0FBKn1oTL0iV0TCSNfQcdsIDGA3wpzgIVKQ7t2f4ZFfrMsNLbr8Sh8C sH84PLXGACR+KZzhf/ruKi7/ztKfozwQ7Gz+p0Dnhj4swfYWfciUTWTA+2HJuHySRE jdCGSDNsxVbNwTuihdYVaD32b/YKoMMCwCkYN7Mw= To: libcamera-devel@lists.libcamera.org Date: Tue, 30 Aug 2022 13:17:24 +0530 Message-Id: <20220830074725.1059643-7-umang.jain@ideasonboard.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20220830074725.1059643-1-umang.jain@ideasonboard.com> References: <20220830074725.1059643-1-umang.jain@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 6/7] tests: stream: Add a colorspace adjustment test X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Umang Jain via libcamera-devel From: Umang Jain Reply-To: Umang Jain Cc: rishikeshdonadkar@gmail.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" ColorSpace can be adjusted based on the stream's pixelFormat being requested. Add a test to check the adjustment logic defined in ColorSpace::adjust(). Signed-off-by: Umang Jain Reviewed-by: Laurent Pinchart Reviewed-by: Paul Elder --- test/stream/meson.build | 1 + test/stream/stream_colorspace.cpp | 96 +++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 test/stream/stream_colorspace.cpp diff --git a/test/stream/meson.build b/test/stream/meson.build index 73608ffd..89f51c18 100644 --- a/test/stream/meson.build +++ b/test/stream/meson.build @@ -1,6 +1,7 @@ # SPDX-License-Identifier: CC0-1.0 stream_tests = [ + ['stream_colorspace', 'stream_colorspace.cpp'], ['stream_formats', 'stream_formats.cpp'], ] diff --git a/test/stream/stream_colorspace.cpp b/test/stream/stream_colorspace.cpp new file mode 100644 index 00000000..1b7afe65 --- /dev/null +++ b/test/stream/stream_colorspace.cpp @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2022, Ideas on Board Oy. + * + * stream_colorspace.cpp - Stream colorspace adjustment test + */ + +#include + +#include +#include +#include + +#include "test.h" + +using namespace libcamera; +using namespace std; + +class TestCameraConfiguration : public CameraConfiguration +{ +public: + TestCameraConfiguration() + : CameraConfiguration() + { + } + + Status validate() override + { + return validateColorSpaces(); + } +}; + +class StreamColorSpaceTest : public Test +{ +protected: + int run() + { + TestCameraConfiguration config; + + StreamConfiguration cfg; + cfg.size = { 640, 320 }; + cfg.pixelFormat = formats::YUV422; + cfg.colorSpace = ColorSpace::Srgb; + config.addConfiguration(cfg); + + StreamConfiguration &streamCfg = config.at(0); + + /* + * YUV pixelformat with sRGB colorspace should have Y'CbCr encoding + * adjusted. + */ + config.validate(); + if (streamCfg.colorSpace->ycbcrEncoding == ColorSpace::YcbcrEncoding::None) { + cerr << "YUV format must have YCbCr encoding" << endl; + return TestFail; + } + + /* + * For YUV pixelFormat, encoding should be picked up according + * to primaries and transfer function, if 'None' is specified. + */ + streamCfg.pixelFormat = formats::YUV422; + streamCfg.colorSpace = ColorSpace(ColorSpace::Primaries::Rec2020, + ColorSpace::TransferFunction::Rec709, + ColorSpace::YcbcrEncoding::None, + ColorSpace::Range::Limited); + config.validate(); + if (streamCfg.colorSpace->ycbcrEncoding != ColorSpace::YcbcrEncoding::Rec2020) { + cerr << "Failed to adjust colorspace Y'CbCr encoding according" + << " to primaries and transfer function" << endl; + return TestFail; + } + + /* For RGB pixelFormat, Sycc colorspace should get adjusted to sRGB. */ + streamCfg.pixelFormat = formats::RGB888; + streamCfg.colorSpace = ColorSpace::Sycc; + config.validate(); + if (streamCfg.colorSpace != ColorSpace::Srgb) { + cerr << "RGB format's colorspace should be set to Srgb" << endl; + return TestFail; + } + + /* Raw formats should always set colorspace to ColorSpace::Raw. */ + streamCfg.pixelFormat = formats::SBGGR8; + streamCfg.colorSpace = ColorSpace::Rec709; + config.validate(); + if (streamCfg.colorSpace != ColorSpace::Raw) { + cerr << "Raw format must always have Raw colorspace" << endl; + return TestFail; + } + + return TestPass; + } +}; + +TEST_REGISTER(StreamColorSpaceTest) From patchwork Tue Aug 30 07:47:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 17256 X-Patchwork-Delegate: umang.jain@ideasonboard.com Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 87BE3C3272 for ; Tue, 30 Aug 2022 07:47:55 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4636061FD3; Tue, 30 Aug 2022 09:47:55 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1661845675; bh=wrbpnVP0vGiTrYDPblaT32z3hJA2Ngi8FxRXo+nqjoQ=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=BRp5qgIe4yyUn4S7l3ww4vCiarGRrm++C3Dc93bWhLibufycj39/NbQumKcTiN0ac mZtLYzK3Gqf/KysTzdqPWDaEtnvtxd+bkdRy9fExJjN9rhL9o+3JhI+ogE7EXS+53E O/EQZBhyQlsWkswbhCKZj64dOgoQGrWkkHuUwWL24VE0gZYZtXxqvh0Sd3T1lTA+pk PgPN/tdhghYjrqbsnhm7f3zHDLZVPzqokrDgIDvVuUSaAEel2sZKC0qw5lXimeT5e1 wy2EHMyMb81xjOV3TpBI72PC4haBuFhBrmJ5sl0pvOfrJZyHoBzB0bhSOn06ZaSLuT /NRu2Opeo1FIA== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BA65A61FB9 for ; Tue, 30 Aug 2022 09:47:53 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="p7KbQvW8"; dkim-atps=neutral Received: from umang.jainideasonboard.com (unknown [IPv6:2401:4900:1f3f:1548:78ac:4a3:edc3:c28a]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id C673D481; Tue, 30 Aug 2022 09:47:51 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1661845673; bh=wrbpnVP0vGiTrYDPblaT32z3hJA2Ngi8FxRXo+nqjoQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=p7KbQvW8ApawQi4wAd40uj7AqMFwFDptzZj6Hj70riWZ1ZLS/pyJlNRWNZMJeDkU8 1Aj4ys4PAR7+YvqCBEyHtPRArFAVflo/XKLPwxjgBxFijOr4LrN/7XJWCto8+mu9sr q0TnpAk+ZR4waiH150WlU3697y7e5M13mqeH5/Sw= To: libcamera-devel@lists.libcamera.org Date: Tue, 30 Aug 2022 13:17:25 +0530 Message-Id: <20220830074725.1059643-8-umang.jain@ideasonboard.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20220830074725.1059643-1-umang.jain@ideasonboard.com> References: <20220830074725.1059643-1-umang.jain@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 7/7] gstreamer: Provide colorimetry <> ColorSpace mappings X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Umang Jain via libcamera-devel From: Umang Jain Reply-To: Umang Jain Cc: rishikeshdonadkar@gmail.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Rishikesh Donadkar Provide colorimetry <=> libcamera::ColorSpace mappings via: - GstVideoColorimetry colorimetry_from_colorspace(colorspace); - ColorSpace colorspace_from_colorimetry(colorimetry); Read the colorimetry field from caps into the stream configuration. After stream validation, the sensor supported colorimetry will be retrieved and the caps will be updated accordingly. Colorimetry support for gstlibcamera currently undertakes only one argument. Multiple colorimetry support shall be introduced in subsequent commits. Signed-off-by: Rishikesh Donadkar Signed-off-by: Umang Jain Reviewed-by: Laurent Pinchart Reviewed-by: Umang Jain Reviewed-by: Paul Elder --- src/gstreamer/gstlibcamera-utils.cpp | 169 +++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) diff --git a/src/gstreamer/gstlibcamera-utils.cpp b/src/gstreamer/gstlibcamera-utils.cpp index 5a21a391..c7b44a8e 100644 --- a/src/gstreamer/gstlibcamera-utils.cpp +++ b/src/gstreamer/gstlibcamera-utils.cpp @@ -57,6 +57,152 @@ static struct { /* \todo NV42 is used in libcamera but is not mapped in GStreamer yet. */ }; +static GstVideoColorimetry +colorimetry_from_colorspace(const ColorSpace &colorSpace) +{ + GstVideoColorimetry colorimetry; + + switch (colorSpace.primaries) { + case ColorSpace::Primaries::Raw: + colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_UNKNOWN; + break; + case ColorSpace::Primaries::Smpte170m: + colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_SMPTE170M; + break; + case ColorSpace::Primaries::Rec709: + colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT709; + break; + case ColorSpace::Primaries::Rec2020: + colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT2020; + break; + } + + switch (colorSpace.transferFunction) { + case ColorSpace::TransferFunction::Linear: + colorimetry.transfer = GST_VIDEO_TRANSFER_GAMMA10; + break; + case ColorSpace::TransferFunction::Srgb: + colorimetry.transfer = GST_VIDEO_TRANSFER_SRGB; + break; + case ColorSpace::TransferFunction::Rec709: + colorimetry.transfer = GST_VIDEO_TRANSFER_BT709; + break; + } + + switch (colorSpace.ycbcrEncoding) { + case ColorSpace::YcbcrEncoding::None: + colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_RGB; + break; + case ColorSpace::YcbcrEncoding::Rec601: + colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601; + break; + case ColorSpace::YcbcrEncoding::Rec709: + colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT709; + break; + case ColorSpace::YcbcrEncoding::Rec2020: + colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT2020; + break; + } + + switch (colorSpace.range) { + case ColorSpace::Range::Full: + colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255; + break; + case ColorSpace::Range::Limited: + colorimetry.range = GST_VIDEO_COLOR_RANGE_16_235; + break; + } + + return colorimetry; +} + +static std::optional +colorspace_from_colorimetry(const GstVideoColorimetry &colorimetry) +{ + std::optional colorspace; + + switch (colorimetry.primaries) { + case GST_VIDEO_COLOR_PRIMARIES_UNKNOWN: + /* Unknown primaries map to raw colorspace in gstreamer */ + return ColorSpace::Raw; + case GST_VIDEO_COLOR_PRIMARIES_SMPTE170M: + colorspace->primaries = ColorSpace::Primaries::Smpte170m; + break; + case GST_VIDEO_COLOR_PRIMARIES_BT709: + colorspace->primaries = ColorSpace::Primaries::Rec709; + break; + case GST_VIDEO_COLOR_PRIMARIES_BT2020: + colorspace->primaries = ColorSpace::Primaries::Rec2020; + break; + default: + GST_WARNING("Colorimetry primaries %d not mapped in gstlibcamera", + colorimetry.primaries); + return std::nullopt; + } + + switch (colorimetry.transfer) { + /* Transfer function mappings inspired from v4l2src plugin */ + case GST_VIDEO_TRANSFER_GAMMA18: + case GST_VIDEO_TRANSFER_GAMMA20: + case GST_VIDEO_TRANSFER_GAMMA22: + case GST_VIDEO_TRANSFER_GAMMA28: + GST_WARNING("GAMMA 18, 20, 22, 28 transfer functions not supported"); + /* fallthrough */ + case GST_VIDEO_TRANSFER_GAMMA10: + colorspace->transferFunction = ColorSpace::TransferFunction::Linear; + break; + case GST_VIDEO_TRANSFER_SRGB: + colorspace->transferFunction = ColorSpace::TransferFunction::Srgb; + break; + case GST_VIDEO_TRANSFER_BT601: + case GST_VIDEO_TRANSFER_BT2020_12: + case GST_VIDEO_TRANSFER_BT2020_10: + case GST_VIDEO_TRANSFER_BT709: + colorspace->transferFunction = ColorSpace::TransferFunction::Rec709; + break; + default: + GST_WARNING("Colorimetry transfer function %d not mapped in gstlibcamera", + colorimetry.transfer); + return std::nullopt; + } + + switch (colorimetry.matrix) { + case GST_VIDEO_COLOR_MATRIX_RGB: + colorspace->ycbcrEncoding = ColorSpace::YcbcrEncoding::None; + break; + /* FCC is about the same as BT601 with less digit */ + case GST_VIDEO_COLOR_MATRIX_FCC: + case GST_VIDEO_COLOR_MATRIX_BT601: + colorspace->ycbcrEncoding = ColorSpace::YcbcrEncoding::Rec601; + break; + case GST_VIDEO_COLOR_MATRIX_BT709: + colorspace->ycbcrEncoding = ColorSpace::YcbcrEncoding::Rec709; + break; + case GST_VIDEO_COLOR_MATRIX_BT2020: + colorspace->ycbcrEncoding = ColorSpace::YcbcrEncoding::Rec2020; + break; + default: + GST_WARNING("Colorimetry matrix %d not mapped in gstlibcamera", + colorimetry.matrix); + return std::nullopt; + } + + switch (colorimetry.range) { + case GST_VIDEO_COLOR_RANGE_0_255: + colorspace->range = ColorSpace::Range::Full; + break; + case GST_VIDEO_COLOR_RANGE_16_235: + colorspace->range = ColorSpace::Range::Limited; + break; + default: + GST_WARNING("Colorimetry range %d not mapped in gstlibcamera", + colorimetry.range); + return std::nullopt; + } + + return colorspace; +} + static GstVideoFormat pixel_format_to_gst_format(const PixelFormat &format) { @@ -151,6 +297,18 @@ gst_libcamera_stream_configuration_to_caps(const StreamConfiguration &stream_cfg "width", G_TYPE_INT, stream_cfg.size.width, "height", G_TYPE_INT, stream_cfg.size.height, nullptr); + + if (stream_cfg.colorSpace) { + GstVideoColorimetry colorimetry = colorimetry_from_colorspace(stream_cfg.colorSpace.value()); + gchar *colorimetry_str = gst_video_colorimetry_to_string(&colorimetry); + + if (colorimetry_str) + gst_structure_set(s, "colorimetry", G_TYPE_STRING, colorimetry_str, nullptr); + else + g_error("Got invalid colorimetry from ColorSpace: %s", + ColorSpace::toString(stream_cfg.colorSpace).c_str()); + } + gst_caps_append_structure(caps, s); return caps; @@ -234,6 +392,17 @@ gst_libcamera_configure_stream_from_caps(StreamConfiguration &stream_cfg, gst_structure_get_int(s, "height", &height); stream_cfg.size.width = width; stream_cfg.size.height = height; + + /* Configure colorimetry */ + if (gst_structure_has_field(s, "colorimetry")) { + const gchar *colorimetry_str = gst_structure_get_string(s, "colorimetry"); + GstVideoColorimetry colorimetry; + + if (!gst_video_colorimetry_from_string(&colorimetry, colorimetry_str)) + g_critical("Invalid colorimetry %s", colorimetry_str); + + stream_cfg.colorSpace = colorspace_from_colorimetry(colorimetry); + } } #if !GST_CHECK_VERSION(1, 17, 1)