From patchwork Tue Aug 2 18:57:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 16918 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 17AEBC3275 for ; Tue, 2 Aug 2022 18:57:33 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id AEA2E63317; Tue, 2 Aug 2022 20:57:32 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1659466652; bh=mFbQuwMkfn3ZjgGgGsMXPZqDOEOCiI4vwkTD+aI3SYs=; 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=teO4VnZTJABLtHgL8BkrcTGn8vtEF0tHkTMAuN8RL7Xv+KtpREJBx0GolLCLhmcqT 2dV7otYGOedx/k/rvuNrOBfitPdBfNaNC82fD776PmVQJ6QitnFfX4ATD8ASXnO3nx VsH6MMoPwGBTeHCiyXfwQgMGH+CE7Bv07tvlz66pv7QHk0y0vGfkEqrOa8QUI6BqZT 4L4UInVCU5QlxgORZB3KjqqxSrXrv2FhQVY2gEXsRlY482Tmg/dDTfatywvH/S2Y8D SoHE6bVvSZfkQIHkh/2akclHBq42HkjAS7w1NYh7LTYUhO0rj3MKcE4FtdGRZ/L0S8 Gn2j/w+s4Q8nw== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 44FD1603E7 for ; Tue, 2 Aug 2022 20:57:30 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ds1bVcF/"; dkim-atps=neutral Received: from perceval.ideasonboard.com (unknown [IPv6:2401:4900:1f3f:85c2:5ee8:5bb8:aca7:5517]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id C886025B; Tue, 2 Aug 2022 20:57:28 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1659466650; bh=mFbQuwMkfn3ZjgGgGsMXPZqDOEOCiI4vwkTD+aI3SYs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ds1bVcF/uzH1/1wGyk6adEYhLhcSS7oqK48JyM2pP5dFS4WmUkQH/wsf20/tiDdfv h7HQs4Ef15TRFrInto8XPXCohwvJ9pMyzwWBY2hDoX3lcc0gpZNIEOM5zUcQyntMy3 q7W8RSVs1dSkAoHFDp+Izq0R8/sSA5Gquc6m8XYk= To: libcamera-devel@lists.libcamera.org Date: Wed, 3 Aug 2022 00:27:16 +0530 Message-Id: <20220802185719.380855-2-umang.jain@ideasonboard.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20220802185719.380855-1-umang.jain@ideasonboard.com> References: <20220802185719.380855-1-umang.jain@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC PATCH 1/4] libcamera: colorspace: Rectify 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. Signed-off-by: Umang Jain --- src/libcamera/color_space.cpp | 9 +++------ src/libcamera/v4l2_device.cpp | 2 -- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/libcamera/color_space.cpp b/src/libcamera/color_space.cpp index caf39760..73148228 100644 --- a/src/libcamera/color_space.cpp +++ b/src/libcamera/color_space.cpp @@ -254,16 +254,13 @@ const ColorSpace ColorSpace::Jpeg = { }; /** - * \brief A constant representing the sRGB color space - * - * This is identical to the JPEG color space except that the Y'CbCr - * range is limited rather than full. + * \brief A constant representing the sRGB color space (non-YUV format) */ 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 3fc8438f..a4446fbf 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -746,7 +746,6 @@ void V4L2Device::eventAvailable() static const std::map v4l2ToColorSpace = { { V4L2_COLORSPACE_RAW, ColorSpace::Raw }, { V4L2_COLORSPACE_JPEG, ColorSpace::Jpeg }, - { V4L2_COLORSPACE_SRGB, ColorSpace::Srgb }, { V4L2_COLORSPACE_SMPTE170M, ColorSpace::Smpte170m }, { V4L2_COLORSPACE_REC709, ColorSpace::Rec709 }, { V4L2_COLORSPACE_BT2020, ColorSpace::Rec2020 }, @@ -772,7 +771,6 @@ static const std::map v4l2ToRange = { static const std::vector> colorSpaceToV4l2 = { { ColorSpace::Raw, V4L2_COLORSPACE_RAW }, { ColorSpace::Jpeg, V4L2_COLORSPACE_JPEG }, - { ColorSpace::Srgb, V4L2_COLORSPACE_SRGB }, { ColorSpace::Smpte170m, V4L2_COLORSPACE_SMPTE170M }, { ColorSpace::Rec709, V4L2_COLORSPACE_REC709 }, { ColorSpace::Rec2020, V4L2_COLORSPACE_BT2020 }, From patchwork Tue Aug 2 18:57:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 16919 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 92296C3275 for ; Tue, 2 Aug 2022 18:57:34 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5189463312; Tue, 2 Aug 2022 20:57:34 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1659466654; bh=TEGpV3flB5XViFvlMSyN0wI+yMDxiS/1IVfJrpNnqtg=; 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=K39bGTetJ1ulgIhCgN7HYQwLwykLyQPW2EvKZAux4IxBEfIvgckVnGHMtSf1ioUOl X0NasYi5XpcFfWnr3QPD+phOowvIzCtCA2WzDOmXjwbht7DbewEVMB/h3CN3cBLVGM F/H/0WOofRvphPp66B2pTQDE7vB+VvMXE4bfXK6NZBbN/7c8FGo2qaAb8CiV6R2hH0 R6JpvGdsZI+surdsgJXnKSHZ/UwNdnad/6InMlz+P7OmHxO2QS5g6pv7fbt6n1f1wy UvBAEqLZRdik4RF5WNAwFPnQ/8SJIQKk8pKbiQ8zOEERoNBPqSYGC/xoNSEf6BQy7H lcftq4oxDxn3g== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 93D45603E7 for ; Tue, 2 Aug 2022 20:57:32 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="OHvS77um"; dkim-atps=neutral Received: from perceval.ideasonboard.com (unknown [IPv6:2401:4900:1f3f:85c2:5ee8:5bb8:aca7:5517]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 044B525B; Tue, 2 Aug 2022 20:57:30 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1659466652; bh=TEGpV3flB5XViFvlMSyN0wI+yMDxiS/1IVfJrpNnqtg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=OHvS77umUzTOXl1NOBlRC75cXxUzuffkTHvTdXp8BxiWFr9drr99TGUQMsLsQp/pU Eq613wkYcTJ/kYNQka3iF3rHMowKGqnSNR6n4Itm3/EDqhP6Aw+W3ZjUxzyXz9CUxo tD6yIpyGeIwk3mFgBHUPhcNOzXKkKTzsRUTk1Y3E= To: libcamera-devel@lists.libcamera.org Date: Wed, 3 Aug 2022 00:27:17 +0530 Message-Id: <20220802185719.380855-3-umang.jain@ideasonboard.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20220802185719.380855-1-umang.jain@ideasonboard.com> References: <20220802185719.380855-1-umang.jain@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC PATCH 2/4] libcamera: colorspace: Adjust colorspace of YUV streams 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" If a YUV stream is requested with no Y'Cbcr encoding, we need to adjust it to provide a Y'Cbcr encoding. Depending on the transfer function and primaries specified, a Y'Cbcr encoding is picked up. Signed-off-by: Umang Jain --- include/libcamera/color_space.h | 6 ++++ src/libcamera/camera.cpp | 11 ++++++ src/libcamera/color_space.cpp | 61 +++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) diff --git a/include/libcamera/color_space.h b/include/libcamera/color_space.h index 0d39fbc0..113e2715 100644 --- a/include/libcamera/color_space.h +++ b/include/libcamera/color_space.h @@ -12,6 +12,8 @@ namespace libcamera { +struct StreamConfiguration; + class ColorSpace { public: @@ -59,6 +61,10 @@ public: std::string toString() const; static std::string toString(const std::optional &colorSpace); + ColorSpace adjust(const StreamConfiguration &cfg); + +private: + ColorSpace adjustYuv(const StreamConfiguration &cfg); }; bool operator==(const ColorSpace &lhs, const ColorSpace &rhs); diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp index 3910915c..05135d16 100644 --- a/src/libcamera/camera.cpp +++ b/src/libcamera/camera.cpp @@ -386,6 +386,17 @@ CameraConfiguration::Status CameraConfiguration::validateColorSpaces(ColorSpaceF if (index < 0 || !(flags & ColorSpaceFlag::StreamsShareColorSpace)) return status; + /* + * \todo Question StreamsShareColorSpace <> an adjusted colorspace + * interation. + */ + if (config_[index].colorSpace) { + ColorSpace oldColorspace = config_[index].colorSpace.value(); + ColorSpace newColorspace = oldColorspace.adjust(config_[index]); + if (oldColorspace != newColorspace) + config_[index].colorSpace = newColorspace; + } + /* Make all output color spaces the same, if requested. */ for (auto &cfg : config_) { if (!isRaw(cfg.pixelFormat) && diff --git a/src/libcamera/color_space.cpp b/src/libcamera/color_space.cpp index 73148228..ff3f76d9 100644 --- a/src/libcamera/color_space.cpp +++ b/src/libcamera/color_space.cpp @@ -13,6 +13,10 @@ #include #include +#include + +#include "libcamera/internal/formats.h" + /** * \file color_space.h * \brief Class and enums to represent color spaces @@ -193,6 +197,63 @@ std::string ColorSpace::toString() const return ss.str(); } +/** + * \brief Adjust colospace when stream configuration contains YUV stream + * \param[in] config Stream configuration + * + * This function adjust the stream's colorspace if it consists a YUV stream + * and has no Y'Cbcr encoding specified. The function shall update the + * Y'Cbcr encoding based on the transfer function and primaries fields. + * + * \return The adjusted colorspace + */ +ColorSpace +ColorSpace::adjustYuv(const StreamConfiguration &cfg) +{ + ColorSpace cs = *this; + bool isYUV = (PixelFormatInfo::info(cfg.pixelFormat).colourEncoding == + PixelFormatInfo::ColourEncodingYUV); + + if (isYUV && cs.ycbcrEncoding == YcbcrEncoding::None) { + if (cs.transferFunction == TransferFunction::Rec709) { + switch (cs.primaries) { + /* Raw should never happen */ + case Primaries::Raw: + case Primaries::Smpte170m: + cs.ycbcrEncoding = YcbcrEncoding::Rec601; + break; + case Primaries::Rec709: + cs.ycbcrEncoding = YcbcrEncoding::Rec709; + break; + case Primaries::Rec2020: + cs.ycbcrEncoding = YcbcrEncoding::Rec2020; + break; + } + } else if (cs.transferFunction == TransferFunction::Srgb) { + cs.ycbcrEncoding = YcbcrEncoding::Rec601; + } + + /* \todo: Determine if range needs to be adjusted in some cases? */ + } + + return cs; +} + +/** + * \brief Adjust the colorspace depending on the stream configuration + * \param[in] config Stream configuration + * + * This function adjust the stream's colorspace depending on various factors + * as reflected by the \a config. + * + * \return The adjusted colorspace according to the stream configuration + */ +ColorSpace +ColorSpace::adjust(const StreamConfiguration &config) +{ + return adjustYuv(config); +} + /** * \brief Assemble and return a readable string representation of an * optional ColorSpace From patchwork Tue Aug 2 18:57:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 16920 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 F15CBC3275 for ; Tue, 2 Aug 2022 18:57:36 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id BF74363316; Tue, 2 Aug 2022 20:57:36 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1659466656; bh=p4UcN+mdL4/pKtc5ZnC3kX4FFsnQ9RXd+SNOwB3OrL4=; 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=mZUV56fY7AT8kqYq+yP81m8GW325kEeeECtT9buhH+nzD4JjN154gtm14l4etoRqZ jARFxNuED1drGN+IFelOIKXdnkdIX+BTN2AmOHtIy+68PUgNZrjU+6AZUQsYw5H4r1 RxPL9bgS6pY4rq8+/KzvHYx++x7CbKmbWIIE+nGOsI4j6bsKuTPzrxSvUpbTJ+S6lr PEhqLRpCRzr1fC8VuKCLeGs2/hlQBMPndY0OzjtzZbl6KKr1CUh35yGvJeOFkAUzN7 VZbBYFYPVrISRBTqBeI7zyGiqmBRryTHRqGhRBAu24VSQ690mFRkD0SxRIR/cSFLzS f3HWaRr6Ah+DA== 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 B47CD603E7 for ; Tue, 2 Aug 2022 20:57:34 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="pelhQINk"; dkim-atps=neutral Received: from perceval.ideasonboard.com (unknown [IPv6:2401:4900:1f3f:85c2:5ee8:5bb8:aca7:5517]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 4FE4825B; Tue, 2 Aug 2022 20:57:33 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1659466654; bh=p4UcN+mdL4/pKtc5ZnC3kX4FFsnQ9RXd+SNOwB3OrL4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=pelhQINkFhAtnEsXgEqiDWKD2LgWnAFZqX37rA72IiandH8Lz2eVj7B0SFmvfvmCX WXMPalyjq89Wrb8FqCg4yXmsgjLEMEGTDh0Z82yQVPTYVpl91Hz2vldzcbt5HK9MSf gQHB4oFEEzHwU5+iH5PPHtNoGZNIik0p4AQWjTyU= To: libcamera-devel@lists.libcamera.org Date: Wed, 3 Aug 2022 00:27:18 +0530 Message-Id: <20220802185719.380855-4-umang.jain@ideasonboard.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20220802185719.380855-1-umang.jain@ideasonboard.com> References: <20220802185719.380855-1-umang.jain@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC PATCH 3/4] 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. Signed-off-by: Umang Jain --- test/stream/meson.build | 1 + test/stream/stream_colorspace.cpp | 57 +++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 test/stream/stream_colorspace.cpp diff --git a/test/stream/meson.build b/test/stream/meson.build index 73608ffd..bf78ddfe 100644 --- a/test/stream/meson.build +++ b/test/stream/meson.build @@ -2,6 +2,7 @@ stream_tests = [ ['stream_formats', 'stream_formats.cpp'], + ['stream_colorspace', 'stream_colorspace.cpp'], ] foreach t : stream_tests diff --git a/test/stream/stream_colorspace.cpp b/test/stream/stream_colorspace.cpp new file mode 100644 index 00000000..e8ac17d3 --- /dev/null +++ b/test/stream/stream_colorspace.cpp @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2022, Ideas on Board Oy. + * + * stream_colorspace.cpp - Stream colorspace tests + */ + +#include + +#include +#include + +#include "test.h" + +using namespace libcamera; + +class StreamColorSpaceTest : public Test +{ +protected: + int run() + { + StreamConfiguration cfg; + cfg.size = { 640, 320 }; + cfg.pixelFormat = formats::YUV422; + cfg.colorSpace = ColorSpace::Srgb; + + /* YUV stream with sRGB colorspace should have y'cbcr encoding adjusted */ + ColorSpace adjColorSpace = cfg.colorSpace->adjust(cfg); + if (adjColorSpace.ycbcrEncoding == ColorSpace::YcbcrEncoding::None) + return TestFail; + + /* For RGB pixelFormat, sRGB colorspace shouldn't get adjusted */ + cfg.pixelFormat = formats::RGB888; + adjColorSpace = cfg.colorSpace->adjust(cfg); + if (adjColorSpace == ColorSpace::Srgb) + ; + else + return TestFail; + + /* + * For YUV pixelFormat, encoding should picked up according to + * primaries. + */ + cfg.pixelFormat = formats::YUV422; + cfg.colorSpace = ColorSpace(ColorSpace::Primaries::Rec2020, + ColorSpace::TransferFunction::Rec709, + ColorSpace::YcbcrEncoding::None, + ColorSpace::Range::Limited); + adjColorSpace = cfg.colorSpace->adjust(cfg); + if (adjColorSpace.ycbcrEncoding != ColorSpace::YcbcrEncoding::Rec2020) + return TestFail; + + return TestPass; + } +}; + +TEST_REGISTER(StreamColorSpaceTest) From patchwork Tue Aug 2 18:57: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: 16921 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 75810C3275 for ; Tue, 2 Aug 2022 18:57:38 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2CE1363321; Tue, 2 Aug 2022 20:57:38 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1659466658; bh=gJbheLKf31de0tLpAjAn9d1/Gz2SFtEbeEgZFJs4Ijw=; 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=RFikW6Zt9xqXQIhKLEdUen7TZBZGAj+GrKGr9Z/7GKBkqqdQdwj0D+JPg6XM7zWu7 SB20k4REdzszrxnnHQMbo/Oz4eko6vBDZLKNKPyX4OMqgr6mpdcsh09jwaN+wPMwtk h8Mh1Z13sZJFG837/C1O0j+NYROnfd9poW5idHUgVQNQhyCDkmsEuEgmEm8lVerYF7 6fwnH5706fjoTEi4cm6gVkpcyXmtAhlT2o742rbvHVUizdHtGfkFIQpArB4qdJ+pKH zxRPBlOYQeKcN5NtcYLyBJiw5diHMKMBhkzcvM3Oy35hG8FPfIpJ6u+fmmUSy5+HvZ PKcQu/n5A4DwA== 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 657C5603E7 for ; Tue, 2 Aug 2022 20:57:37 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="l0pDU3yt"; dkim-atps=neutral Received: from perceval.ideasonboard.com (unknown [IPv6:2401:4900:1f3f:85c2:5ee8:5bb8:aca7:5517]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id E0FF4593; Tue, 2 Aug 2022 20:57:35 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1659466657; bh=gJbheLKf31de0tLpAjAn9d1/Gz2SFtEbeEgZFJs4Ijw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=l0pDU3ytPMhEGUKXKAaNcHnGlfcAWzqOFLkS1dDsXMLM7jJinXLo5nV77+Lnqmyjz 0pgpjdGxfgV4EArZl1x6Y4+OwqTbZRAWfOzE2/Fq4fZx5DEQW3U2Qo/y3/lN+JG0Du bzxqD3XG1AadbN7CzpCKreHDGKX1jAaT28mB48W4= To: libcamera-devel@lists.libcamera.org Date: Wed, 3 Aug 2022 00:27:19 +0530 Message-Id: <20220802185719.380855-5-umang.jain@ideasonboard.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20220802185719.380855-1-umang.jain@ideasonboard.com> References: <20220802185719.380855-1-umang.jain@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [v3 PATCH 4/4] 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 --- - Sort mappings - Handle un-mapped situation without hard-abort - Fix SRGB mappings --- src/gstreamer/gstlibcamera-utils.cpp | 176 +++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) diff --git a/src/gstreamer/gstlibcamera-utils.cpp b/src/gstreamer/gstlibcamera-utils.cpp index c97c0d43..d895a67d 100644 --- a/src/gstreamer/gstlibcamera-utils.cpp +++ b/src/gstreamer/gstlibcamera-utils.cpp @@ -45,6 +45,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 ColorSpace +colorspace_from_colorimetry(const GstVideoColorimetry &colorimetry) +{ + ColorSpace colorspace = ColorSpace::Raw; + + 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 ColorSpace::Raw; + } + + 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 ColorSpace::Raw; + } + + 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 ColorSpace::Raw; + } + + 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 ColorSpace::Raw; + } + + return colorspace; +} + static GstVideoFormat pixel_format_to_gst_format(const PixelFormat &format) { @@ -139,6 +285,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; @@ -222,6 +380,24 @@ 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); + /* Check if colorimetry had any identifiers which did not map */ + if (colorimetry.primaries != GST_VIDEO_COLOR_PRIMARIES_UNKNOWN && + stream_cfg.colorSpace == ColorSpace::Raw) { + GST_ERROR("One or more identifiers could not be mapped for %s colorimetry", + colorimetry_str); + stream_cfg.colorSpace = std::nullopt; + } + } } #if !GST_CHECK_VERSION(1, 17, 1)