Show a patch.

GET /api/1.1/patches/18105/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 18105,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/18105/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/18105/",
    "project": {
        "id": 1,
        "url": "https://patchwork.libcamera.org/api/1.1/projects/1/?format=api",
        "name": "libcamera",
        "link_name": "libcamera",
        "list_id": "libcamera_core",
        "list_email": "libcamera-devel@lists.libcamera.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": ""
    },
    "msgid": "<20230112121044.28003-3-david.plowman@raspberrypi.com>",
    "date": "2023-01-12T12:10:44",
    "name": "[libcamera-devel,v3,2/2] pipeline: raspberrypi: Fix handling of colour spaces",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "76eeb80f1a03b930a7197b8dd1e9e8dcc874f4aa",
    "submitter": {
        "id": 42,
        "url": "https://patchwork.libcamera.org/api/1.1/people/42/?format=api",
        "name": "David Plowman",
        "email": "david.plowman@raspberrypi.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/18105/mbox/",
    "series": [
        {
            "id": 3706,
            "url": "https://patchwork.libcamera.org/api/1.1/series/3706/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=3706",
            "date": "2023-01-12T12:10:42",
            "name": "Fix colour spaces on Raspberry Pi",
            "version": 3,
            "mbox": "https://patchwork.libcamera.org/series/3706/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/18105/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/18105/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "<libcamera-devel-bounces@lists.libcamera.org>",
        "X-Original-To": "parsemail@patchwork.libcamera.org",
        "Delivered-To": "parsemail@patchwork.libcamera.org",
        "Received": [
            "from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id AA0A8C3240\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 12 Jan 2023 12:10:51 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 71206625D0;\n\tThu, 12 Jan 2023 13:10:50 +0100 (CET)",
            "from mail-wr1-x434.google.com (mail-wr1-x434.google.com\n\t[IPv6:2a00:1450:4864:20::434])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 77E3E625D0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 12 Jan 2023 13:10:48 +0100 (CET)",
            "by mail-wr1-x434.google.com with SMTP id h16so17865688wrz.12\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 12 Jan 2023 04:10:48 -0800 (PST)",
            "from pi4-davidp.pitowers.org\n\t([2a00:1098:3142:14:e4a2:3070:eea4:e434])\n\tby smtp.gmail.com with ESMTPSA id\n\tl7-20020a5d6747000000b002b57bae7174sm16318578wrw.5.2023.01.12.04.10.47\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tThu, 12 Jan 2023 04:10:47 -0800 (PST)"
        ],
        "DKIM-Signature": [
            "v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1673525450;\n\tbh=hizRl+QQXRusQc9M2VGOo2HO8oWrMuXiKXH7ZL/mdhk=;\n\th=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:\n\tFrom;\n\tb=VdVp7ZrpScQ8ni8YQ1iUyHD4C0ga9JmKKTMGqQFRxWAXFDoMCT6+R9cC8yvd5aaZM\n\tzmAU4UrRXoqD8gjb6GW5139X+mhycVKERCdKNwvSgBJpbdXxrcAafuPCY7xZqADK4p\n\tkLt3ec0RpZo9YpXIj33jCijUY6LTM3lQZpNenx+XPTsP7iU1aACGfpbKVTZ7BZHRRZ\n\trvbY2rb1aVdta3c5nrWXK9VW9IDkPgDLckZv6zB0+A0cEmS2pGyPVoYA7NwxK6H1W4\n\toILf8KXc0+33dG7K+lEf+Lm6v146r1AkqVtVxSMadJb5NC6l5PZ1BXkia9eudapjKh\n\t4CWhQbTyIo0+w==",
            "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google;\n\th=content-transfer-encoding:mime-version:references:in-reply-to\n\t:message-id:date:subject:cc:to:from:from:to:cc:subject:date\n\t:message-id:reply-to;\n\tbh=tSvScteCJTU51CG11US5YExJOPxoCn3drjUiubOkSBc=;\n\tb=Sb600y+wGGkxbxvdZib8R13ysvwjHYx1N654XI2oBgzr3I2r8nHPktfr8h1LOXYMUe\n\tM3RxoBnffkojHMeT9mZpKeQEETxpNwrEIQEVw6/CjTpiS0vl69ZUfdQsfjQq8URXCkjh\n\tJ53X95rZgy0ZQ1Qb13L9GjKBU8HhGKQIzsulN/xjggKgkTOxbecK5ZRtBmaT+tCKI2YE\n\tbZVBEUjnsvQN1Qys4FsXbrU9lxaO7yOQUwPiDmjIipQtaqqN/E+FEgBe6wzMnbxTSb0y\n\tHhJYfuWJkLEK0Aex7uZvS332ornVde1dc9ks3l0EFu5feLxnTs9Qc+ExAlhCubY4DKuZ\n\t27Bw=="
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected) header.d=raspberrypi.com\n\theader.i=@raspberrypi.com\n\theader.b=\"Sb600y+w\"; dkim-atps=neutral",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112;\n\th=content-transfer-encoding:mime-version:references:in-reply-to\n\t:message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc\n\t:subject:date:message-id:reply-to;\n\tbh=tSvScteCJTU51CG11US5YExJOPxoCn3drjUiubOkSBc=;\n\tb=r45z+hVFpTwHZ0+IEFFvcofSG54Os2WPXP/VmQMleYNsOjcwYuQG5UWOeevAy4Xsvh\n\t/1eInz3+YLWu/DkvjGM736lfy/VG31zmD6yJTADl9/7GrDS5WMzyCXSSih5ysCzhbnnz\n\t1qGUgfxkWApTNjR3k6z+BkYZ6gk61GR1ITPZFEVXlCP9D82fKPRR5OAzDFTmSOqBzUPb\n\t6NKXKsKkQjhb9lsrkPyV5MqCo1Xlw4SDQ7u7oF4dEHVagjjmlHL1dOenMOGsSD2z9L25\n\tDF7DVFtTPVsNdBO/ci811y27yWgq7V1GWVFobIqT3dgBaH956Yv1m7EYUgJ7YyAQLUAM\n\tXklg==",
        "X-Gm-Message-State": "AFqh2kpcC5oyNDBklfwQaGf1DRW93vX/xyni5w7CTXFXHMAQiSOc0GNk\n\t86stVVS0qpd8S32JzPxRAXpf9eLYnOhuUahK",
        "X-Google-Smtp-Source": "AMrXdXs6eyzKbht06BKq9zbbQwOcZ/yiMsZ778jfjcaAm6ZuV0YYTDtHdp+OQmjge4yYZlatocuJ7A==",
        "X-Received": "by 2002:a5d:5506:0:b0:2bb:dd02:46ef with SMTP id\n\tb6-20020a5d5506000000b002bbdd0246efmr10536038wrv.52.1673525447823; \n\tThu, 12 Jan 2023 04:10:47 -0800 (PST)",
        "To": "libcamera-devel@lists.libcamera.org",
        "Date": "Thu, 12 Jan 2023 12:10:44 +0000",
        "Message-Id": "<20230112121044.28003-3-david.plowman@raspberrypi.com>",
        "X-Mailer": "git-send-email 2.30.2",
        "In-Reply-To": "<20230112121044.28003-1-david.plowman@raspberrypi.com>",
        "References": "<20230112121044.28003-1-david.plowman@raspberrypi.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[libcamera-devel] [PATCH v3 2/2] pipeline: raspberrypi: Fix\n\thandling of colour spaces",
        "X-BeenThere": "libcamera-devel@lists.libcamera.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "<libcamera-devel.lists.libcamera.org>",
        "List-Unsubscribe": "<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>",
        "List-Archive": "<https://lists.libcamera.org/pipermail/libcamera-devel/>",
        "List-Post": "<mailto:libcamera-devel@lists.libcamera.org>",
        "List-Help": "<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>",
        "List-Subscribe": "<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>",
        "From": "David Plowman via libcamera-devel <libcamera-devel@lists.libcamera.org>",
        "Reply-To": "David Plowman <david.plowman@raspberrypi.com>",
        "Errors-To": "libcamera-devel-bounces@lists.libcamera.org",
        "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"
    },
    "content": "We implement a custom validateColorSpaces method that forces all\n(non-raw) streams to same colour space, whilst distinguishing RGB\nstreams from YUV ones, as the former must have the YCbCr encoding and\nrange over-written.\n\nWhen we apply the colour space, we always send the full YUV version as\nthat gets converted correctly to what our hardware drivers expect. It\nis also careful to check what comes back as the YCbCr information gets\noverwritten again on the way back.\n\nSigned-off-by: David Plowman <david.plowman@raspberrypi.com>\nReviewed-by: Naushir Patuck <naush@raspberrypi.com>\n---\n .../pipeline/raspberrypi/raspberrypi.cpp      | 99 ++++++++++++++++++-\n 1 file changed, 98 insertions(+), 1 deletion(-)",
    "diff": "diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\nindex 8569df17..135024e7 100644\n--- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n+++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n@@ -310,6 +310,7 @@ class RPiCameraConfiguration : public CameraConfiguration\n public:\n \tRPiCameraConfiguration(const RPiCameraData *data);\n \n+\tCameraConfiguration::Status validateColorSpaces(ColorSpaceFlags flags);\n \tStatus validate() override;\n \n \t/* Cache the combinedTransform_ that will be applied to the sensor */\n@@ -317,6 +318,13 @@ public:\n \n private:\n \tconst RPiCameraData *data_;\n+\n+\t/*\n+\t * Store the colour spaces that all our streams will have. RGB format streams\n+\t * will be the same but need the YCbCr fields cleared.\n+\t */\n+\tstd::optional<ColorSpace> yuvColorSpace_;\n+\tstd::optional<ColorSpace> rgbColorSpace_;\n };\n \n class PipelineHandlerRPi : public PipelineHandler\n@@ -357,6 +365,89 @@ RPiCameraConfiguration::RPiCameraConfiguration(const RPiCameraData *data)\n {\n }\n \n+static const std::vector<ColorSpace> validColorSpaces = {\n+\tColorSpace::Sycc,\n+\tColorSpace::Smpte170m,\n+\tColorSpace::Rec709\n+};\n+\n+static std::optional<ColorSpace> findValidColorSpace(const ColorSpace &colourSpace)\n+{\n+\tfor (auto cs : validColorSpaces) {\n+\t\tif (colourSpace.primaries == cs.primaries &&\n+\t\t    colourSpace.transferFunction == cs.transferFunction)\n+\t\t\treturn cs;\n+\t}\n+\n+\treturn std::nullopt;\n+}\n+\n+static bool isRgb(const PixelFormat &pixFmt)\n+{\n+\tconst PixelFormatInfo &info = PixelFormatInfo::info(pixFmt);\n+\treturn info.colourEncoding == PixelFormatInfo::ColourEncodingRGB;\n+}\n+\n+static bool isYuv(const PixelFormat &pixFmt)\n+{\n+\t/* The code below would return true for raw mono streams, so weed those out first. */\n+\tif (isRaw(pixFmt))\n+\t\treturn false;\n+\n+\tconst PixelFormatInfo &info = PixelFormatInfo::info(pixFmt);\n+\treturn info.colourEncoding == PixelFormatInfo::ColourEncodingYUV;\n+}\n+\n+CameraConfiguration::Status RPiCameraConfiguration::validateColorSpaces([[maybe_unused]] ColorSpaceFlags flags)\n+{\n+\tStatus status = Valid;\n+\tyuvColorSpace_.reset();\n+\n+\tfor (auto cfg : config_) {\n+\t\t/* First fix up raw streams to have the \"raw\" colour space. */\n+\t\tif (isRaw(cfg.pixelFormat) && cfg.colorSpace != ColorSpace::Raw) {\n+\t\t\t/* If there was no value here, that doesn't count as \"adjusted\". */\n+\t\t\tif (cfg.colorSpace)\n+\t\t\t\tstatus = Adjusted;\n+\t\t\tcfg.colorSpace = ColorSpace::Raw;\n+\t\t}\n+\n+\t\t/* Next we need to find our shared colour space. The first valid one will do. */\n+\t\tif (cfg.colorSpace && cfg.colorSpace != ColorSpace::Raw && !yuvColorSpace_)\n+\t\t\tyuvColorSpace_ = findValidColorSpace(cfg.colorSpace.value());\n+\t}\n+\n+\t/* If no colour space was given anywhere, choose sYCC. */\n+\tif (!yuvColorSpace_)\n+\t\tyuvColorSpace_ = ColorSpace::Sycc;\n+\n+\t/* Note the version of this that any RGB streams will have to use. */\n+\trgbColorSpace_ = yuvColorSpace_;\n+\trgbColorSpace_->ycbcrEncoding = ColorSpace::YcbcrEncoding::None;\n+\trgbColorSpace_->range = ColorSpace::Range::Full;\n+\n+\t/* Go through the streams again and force everyone to the same colour space. */\n+\tfor (auto cfg : config_) {\n+\t\tif (cfg.colorSpace == ColorSpace::Raw)\n+\t\t\tcontinue;\n+\n+\t\tif (isYuv(cfg.pixelFormat) && cfg.colorSpace != yuvColorSpace_) {\n+\t\t\t/* Again, no value means \"not adjusted\". */\n+\t\t\tif (cfg.colorSpace)\n+\t\t\t\tstatus = Adjusted;\n+\t\t\tcfg.colorSpace = yuvColorSpace_;\n+\t\t}\n+\t\tif (isRgb(cfg.pixelFormat) && cfg.colorSpace != rgbColorSpace_) {\n+\t\t\t/* Be nice, and let the YUV version count as non-adjusted too. */\n+\t\t\tif (cfg.colorSpace && cfg.colorSpace != yuvColorSpace_)\n+\t\t\t\tstatus = Adjusted;\n+\t\t\tcfg.colorSpace = rgbColorSpace_;\n+\t\t}\n+\t}\n+\n+\treturn status;\n+}\n+\n CameraConfiguration::Status RPiCameraConfiguration::validate()\n {\n \tStatus status = Valid;\n@@ -533,7 +624,8 @@ CameraConfiguration::Status RPiCameraConfiguration::validate()\n \t\tV4L2DeviceFormat format;\n \t\tformat.fourcc = dev->toV4L2PixelFormat(cfg.pixelFormat);\n \t\tformat.size = cfg.size;\n-\t\tformat.colorSpace = cfg.colorSpace;\n+\t\t/* We want to send the associated YCbCr info through to the driver. */\n+\t\tformat.colorSpace = yuvColorSpace_;\n \n \t\tLOG(RPI, Debug)\n \t\t\t<< \"Try color space \" << ColorSpace::toString(cfg.colorSpace);\n@@ -542,6 +634,11 @@ CameraConfiguration::Status RPiCameraConfiguration::validate()\n \t\tif (ret)\n \t\t\treturn Invalid;\n \n+\t\t/*\n+\t\t * But for RGB streams, the YCbCr info gets overwritten on the way back\n+\t\t * so we must check against what the stream cfg says, not what we actually\n+\t\t * requested (which carefully included the YCbCr info)!\n+\t\t */\n \t\tif (cfg.colorSpace != format.colorSpace) {\n \t\t\tstatus = Adjusted;\n \t\t\tLOG(RPI, Debug)\n",
    "prefixes": [
        "libcamera-devel",
        "v3",
        "2/2"
    ]
}