Show a patch.

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

{
    "id": 14200,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/14200/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/14200/",
    "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": "<20211020110825.12902-8-david.plowman@raspberrypi.com>",
    "date": "2021-10-20T11:08:25",
    "name": "[libcamera-devel,v3,7/7] libcamera: pipeline: raspberrypi: Support color spaces",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "99a38d46429b3bae5e693a2cab74499c236af341",
    "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/14200/mbox/",
    "series": [
        {
            "id": 2641,
            "url": "https://patchwork.libcamera.org/api/1.1/series/2641/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=2641",
            "date": "2021-10-20T11:08:18",
            "name": "Colour spaces",
            "version": 3,
            "mbox": "https://patchwork.libcamera.org/series/2641/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/14200/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/14200/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 BE392C324F\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 20 Oct 2021 11:08:37 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6ABC268F74;\n\tWed, 20 Oct 2021 13:08:37 +0200 (CEST)",
            "from mail-wm1-x32f.google.com (mail-wm1-x32f.google.com\n\t[IPv6:2a00:1450:4864:20::32f])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 61AD868F5E\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 20 Oct 2021 13:08:32 +0200 (CEST)",
            "by mail-wm1-x32f.google.com with SMTP id\n\t186-20020a1c01c3000000b0030d8315b593so639165wmb.5\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 20 Oct 2021 04:08:32 -0700 (PDT)",
            "from pi4-davidp.pitowers.org\n\t([2a00:1098:3142:14:1ce1:9965:4328:89c4])\n\tby smtp.gmail.com with ESMTPSA id\n\tf20sm1929654wmq.38.2021.10.20.04.08.31\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tWed, 20 Oct 2021 04:08:31 -0700 (PDT)"
        ],
        "Authentication-Results": "lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=raspberrypi.com header.i=@raspberrypi.com\n\theader.b=\"qe/MpdsA\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references\n\t:mime-version:content-transfer-encoding;\n\tbh=nqj/cQjosr/odg0+Bg8Q+LeBCBQcpdKOTyrPJkxixCs=;\n\tb=qe/MpdsABGaMHKvggm2TRjbIaouNVVfPEoY5ZdCCOU1ie9KUZUcQ8Wzcn7YdYqirIu\n\t948Lcl3xAVfTvyaRzt8kpkERF+ovIVzschuTyE6NymWR/IHDMsPMvabvmdL/JMAl7dOF\n\tEy8BvzRdrj6nrnERAAi1u9IhUp8LpSQOxRZPTwhtcoTdeB7gdl0FDIUHTJyiigEQioVK\n\tm3kI4EAWEkZW7uK8I5R5FtSSZc2InZoxWxjiyif2tYJ38GdaTCYe2AhiBYH47dnAkIM5\n\t0ERKTQSPWzaCcB0E8e+00DA987WOVt5wEwMPgQikslW2W0uak6FRypSfOiohLtoWcVhC\n\txfVA==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20210112;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references:mime-version:content-transfer-encoding;\n\tbh=nqj/cQjosr/odg0+Bg8Q+LeBCBQcpdKOTyrPJkxixCs=;\n\tb=BKq6lDoxPloeOSqiNCZkR4zFNBnBbaBOPh1beE7Byzb5ZDMSV8D7Exn3C9FIKwtxbS\n\tKkRsOlQZbfMTug36Fz8IIXhy0YZrUhBUo2RHpadeRk63RcCBff7WbwxNMJuoxWGMJrdF\n\tClb7zP6kn394MOjTsqvh1cJrEdMkLT18rVpJqxmSJBluMwnSgT9ZG7Q13kmH+DMAg0oQ\n\tGC1z63Wfq+htR0jNgFx3v2zA1vPXvsb63+1eBgQIumUU8gfJyq3PGj2iyBZyWyDBTWWs\n\tIn2wfIMPtyed3VE6pQTvhupx585H/lFUas5AvoMRLm0d071qPQQ929xijgJyTRppDViS\n\timNw==",
        "X-Gm-Message-State": "AOAM530j7oK3aYkEPlVv04ZdTgZKHxWXRYiRxWh3pSuaDE/40hFAyQRF\n\tKsikJpoY2i0j44zESanfuIQJK6wFmcjdbQ==",
        "X-Google-Smtp-Source": "ABdhPJzM5yQ7TLMQNieurpSbb6JOkI8FrGNn4luqig+T9RSyIstiDp4dx6EqtsJoyAD6Aj3MbuppfA==",
        "X-Received": "by 2002:a1c:2395:: with SMTP id\n\tj143mr12974805wmj.107.1634728111885; \n\tWed, 20 Oct 2021 04:08:31 -0700 (PDT)",
        "From": "David Plowman <david.plowman@raspberrypi.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Date": "Wed, 20 Oct 2021 12:08:25 +0100",
        "Message-Id": "<20211020110825.12902-8-david.plowman@raspberrypi.com>",
        "X-Mailer": "git-send-email 2.20.1",
        "In-Reply-To": "<20211020110825.12902-1-david.plowman@raspberrypi.com>",
        "References": "<20211020110825.12902-1-david.plowman@raspberrypi.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[libcamera-devel] [PATCH v3 7/7] libcamera: pipeline: raspberrypi:\n\tSupport color 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>",
        "Errors-To": "libcamera-devel-bounces@lists.libcamera.org",
        "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"
    },
    "content": "The Raspberry Pi pipeline handler now sets color spaces correctly.\n\nIn generateConfiguration() it sets them to reasonable default values\nbased on the stream role.\n\nvalidate() now calls validateColorSpaces() to ensure that the\nrequested color spaces are sensible, before proceeding to check what\nthe hardware can deliver.\n\nSigned-off-by: David Plowman <david.plowman@raspberrypi.com>\n---\n .../pipeline/raspberrypi/raspberrypi.cpp      | 42 +++++++++++++++++++\n 1 file changed, 42 insertions(+)",
    "diff": "diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\nindex 1634ca98..22db54ce 100644\n--- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n+++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n@@ -288,6 +288,8 @@ CameraConfiguration::Status RPiCameraConfiguration::validate()\n \tif (config_.empty())\n \t\treturn Invalid;\n \n+\tstatus = validateColorSpaces(true);\n+\n \t/*\n \t * What if the platform has a non-90 degree rotation? We can't even\n \t * \"adjust\" the configuration and carry on. Alternatively, raising an\n@@ -354,6 +356,7 @@ CameraConfiguration::Status RPiCameraConfiguration::validate()\n \t\t\t */\n \t\t\tV4L2VideoDevice::Formats fmts = data_->unicam_[Unicam::Image].dev()->formats();\n \t\t\tV4L2DeviceFormat sensorFormat = findBestMode(fmts, cfg.size);\n+\t\t\tsensorFormat.colorSpace = ColorSpace::Raw;\n \t\t\tint ret = data_->unicam_[Unicam::Image].dev()->tryFormat(&sensorFormat);\n \t\t\tif (ret)\n \t\t\t\treturn Invalid;\n@@ -449,10 +452,21 @@ CameraConfiguration::Status RPiCameraConfiguration::validate()\n \t\tV4L2DeviceFormat format;\n \t\tformat.fourcc = V4L2PixelFormat::fromPixelFormat(cfg.pixelFormat);\n \t\tformat.size = cfg.size;\n+\t\tformat.colorSpace = cfg.requestedColorSpace;\n+\t\tLOG(RPI, Debug)\n+\t\t\t<< \"Try color space \" << cfg.requestedColorSpace.toString();\n \n \t\tint ret = dev->tryFormat(&format);\n \t\tif (ret)\n \t\t\treturn Invalid;\n+\t\tcfg.actualColorSpace = format.colorSpace;\n+\t\tif (cfg.actualColorSpace != cfg.requestedColorSpace) {\n+\t\t\tstatus = Adjusted;\n+\t\t\tLOG(RPI, Warning)\n+\t\t\t\t<< \"Color space changed from \"\n+\t\t\t\t<< cfg.requestedColorSpace.toString() << \" to \"\n+\t\t\t\t<< cfg.actualColorSpace.toString();\n+\t\t}\n \n \t\tcfg.stride = format.planes[0].bpl;\n \t\tcfg.frameSize = format.planes[0].size;\n@@ -477,6 +491,7 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n \tPixelFormat pixelFormat;\n \tV4L2VideoDevice::Formats fmts;\n \tSize size;\n+\tColorSpace colorSpace;\n \n \tif (roles.empty())\n \t\treturn config;\n@@ -491,6 +506,7 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n \t\t\tsensorFormat = findBestMode(fmts, size);\n \t\t\tpixelFormat = sensorFormat.fourcc.toPixelFormat();\n \t\t\tASSERT(pixelFormat.isValid());\n+\t\t\tcolorSpace = ColorSpace::Raw;\n \t\t\tbufferCount = 2;\n \t\t\trawCount++;\n \t\t\tbreak;\n@@ -498,6 +514,7 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n \t\tcase StreamRole::StillCapture:\n \t\t\tfmts = data->isp_[Isp::Output0].dev()->formats();\n \t\t\tpixelFormat = formats::NV12;\n+\t\t\tcolorSpace = ColorSpace::Jpeg;\n \t\t\t/* Return the largest sensor resolution. */\n \t\t\tsize = data->sensor_->resolution();\n \t\t\tbufferCount = 1;\n@@ -515,6 +532,8 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n \t\t\t */\n \t\t\tfmts = data->isp_[Isp::Output0].dev()->formats();\n \t\t\tpixelFormat = formats::YUV420;\n+\t\t\t/* This will be reasonable for many applications. */\n+\t\t\tcolorSpace = ColorSpace::Rec709;\n \t\t\tsize = { 1920, 1080 };\n \t\t\tbufferCount = 4;\n \t\t\toutCount++;\n@@ -523,6 +542,7 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n \t\tcase StreamRole::Viewfinder:\n \t\t\tfmts = data->isp_[Isp::Output0].dev()->formats();\n \t\t\tpixelFormat = formats::ARGB8888;\n+\t\t\tcolorSpace = ColorSpace::Jpeg;\n \t\t\tsize = { 800, 600 };\n \t\t\tbufferCount = 4;\n \t\t\toutCount++;\n@@ -554,6 +574,7 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,\n \t\tStreamConfiguration cfg(formats);\n \t\tcfg.size = size;\n \t\tcfg.pixelFormat = pixelFormat;\n+\t\tcfg.requestedColorSpace = colorSpace;\n \t\tcfg.bufferCount = bufferCount;\n \t\tconfig->addConfiguration(cfg);\n \t}\n@@ -601,6 +622,7 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config)\n \t/* First calculate the best sensor mode we can use based on the user request. */\n \tV4L2VideoDevice::Formats fmts = data->unicam_[Unicam::Image].dev()->formats();\n \tV4L2DeviceFormat sensorFormat = findBestMode(fmts, rawStream ? sensorSize : maxSize);\n+\tsensorFormat.colorSpace = ColorSpace::Raw;\n \n \t/*\n \t * Unicam image output format. The ISP input format gets set at start,\n@@ -650,6 +672,7 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config)\n \t\tV4L2PixelFormat fourcc = V4L2PixelFormat::fromPixelFormat(cfg.pixelFormat);\n \t\tformat.size = cfg.size;\n \t\tformat.fourcc = fourcc;\n+\t\tformat.colorSpace = cfg.requestedColorSpace;\n \n \t\tLOG(RPI, Debug) << \"Setting \" << stream->name() << \" to \"\n \t\t\t\t<< format.toString();\n@@ -665,6 +688,23 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config)\n \t\t\treturn -EINVAL;\n \t\t}\n \n+\t\tif (cfg.actualColorSpace != format.colorSpace) {\n+\t\t\t/*\n+\t\t\t * We should have been through validate() before so this\n+\t\t\t * shouldn't be possible, but we mustn't sweep color space\n+\t\t\t * problems under the carpet.\n+\t\t\t */\n+\t\t\tLOG(RPI, Warning)\n+\t\t\t\t<< \"Unexpected color space change (\"\n+\t\t\t\t<< cfg.actualColorSpace.toString() << \" to \"\n+\t\t\t\t<< format.colorSpace.toString() << \") in stream \"\n+\t\t\t\t<< stream->name();\n+\t\t\tcfg.actualColorSpace = format.colorSpace;\n+\t\t}\n+\t\tLOG(RPI, Debug)\n+\t\t\t<< \"Stream \" << stream->name() << \" has color space \"\n+\t\t\t<< cfg.actualColorSpace.toString();\n+\n \t\tcfg.setStream(stream);\n \t\tstream->setExternal(true);\n \n@@ -689,6 +729,8 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config)\n \t\tformat = {};\n \t\tformat.size = maxSize;\n \t\tformat.fourcc = V4L2PixelFormat::fromPixelFormat(formats::YUV420);\n+\t\t/* No one asked for output, so the color space doesn't matter. */\n+\t\tformat.colorSpace = ColorSpace::Jpeg;\n \t\tret = data->isp_[Isp::Output0].dev()->setFormat(&format);\n \t\tif (ret) {\n \t\t\tLOG(RPI, Error)\n",
    "prefixes": [
        "libcamera-devel",
        "v3",
        "7/7"
    ]
}