Show a patch.

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

{
    "id": 18947,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/18947/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/18947/",
    "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": "<20230821131039.127370-5-gabbymg94@gmail.com>",
    "date": "2023-08-21T13:10:38",
    "name": "[libcamera-devel,RFC,v2,4/5] libcamera: pipeline: uvcvideo: Allocate metadata buffers",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "fbba457d967c3383af45eb582900769aaa7d5e43",
    "submitter": {
        "id": 160,
        "url": "https://patchwork.libcamera.org/api/1.1/people/160/?format=api",
        "name": "Gabrielle George",
        "email": "gabbymg94@gmail.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/18947/mbox/",
    "series": [
        {
            "id": 4004,
            "url": "https://patchwork.libcamera.org/api/1.1/series/4004/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=4004",
            "date": "2023-08-21T13:10:34",
            "name": "Add UVC Metadata buffer timestamp support",
            "version": 2,
            "mbox": "https://patchwork.libcamera.org/series/4004/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/18947/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/18947/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 0FE42BF415\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 21 Aug 2023 13:10:52 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id A5BE3628D2;\n\tMon, 21 Aug 2023 15:10:51 +0200 (CEST)",
            "from mail-oa1-x2f.google.com (mail-oa1-x2f.google.com\n\t[IPv6:2001:4860:4864:20::2f])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 1D70661E09\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 21 Aug 2023 15:10:47 +0200 (CEST)",
            "by mail-oa1-x2f.google.com with SMTP id\n\t586e51a60fabf-1c4b4c40281so2370819fac.1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 21 Aug 2023 06:10:47 -0700 (PDT)",
            "from localhost.localdomain (97-115-76-16.ptld.qwest.net.\n\t[97.115.76.16]) by smtp.gmail.com with ESMTPSA id\n\tci1-20020a056871c48100b001bb51450d85sm4160283oac.4.2023.08.21.06.10.44\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tMon, 21 Aug 2023 06:10:45 -0700 (PDT)"
        ],
        "DKIM-Signature": [
            "v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1692623451;\n\tbh=rPAqqsyOSUamSnOAgOEB1nNiDlbbH8F5K4TXQGSNDmc=;\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=sUo540ObJSr8FW6SD6b3QyA0zh6jXmUCkLqnv0iRVKSa+cHBOOS2FiNIyImHQD2pu\n\t11r+KhB8LeuUKo04cTo8pNkguFoMmKk/ia94/fNTDsM6hkaYGgLA0vEIWerP49Dq05\n\t+vfqwkJjBZeiDG6oei6YiwvYKH2rSKXo2KaC2zplIwO0XisXzzO3bKhtRRiDi8n88/\n\tyhwvXMjW9Lly/g3G+Q0tAErCAYSfs44On1c4taVgXRvK4z6E4x6uup68zg5r4eOFgZ\n\trL1sCSx1S5iARcJwtUWyCSIg4VaLfXjTeHn4J/A3to41gTrhrr7XcjE9u6zQpX1Nb/\n\te/XBBcf1HX0Ow==",
            "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=gmail.com; s=20221208; t=1692623445; x=1693228245;\n\th=content-transfer-encoding:mime-version:references:in-reply-to\n\t:message-id:date:subject:to:from:from:to:cc:subject:date:message-id\n\t:reply-to; bh=EU6t+fl/QqCK94Dhs7LxVZPCFNQK/h1wuTeKXag0jbU=;\n\tb=XAz0LZjj4dTHE/R1BR7lULrWmujiUM98d4ZkfHUU3t/tvnzGJ4I5Pa7EQibsBw63Bg\n\t3mSD1gBz4uh7R5+M/GsDexOmIzTmdFJU8ORzC9/yC0nMUXYpDOkvjfGQ4BqX2INIfuEo\n\tyFTZevWacZ51RcgViD1EZxJFausOglLubc/JtOl41wi8M/VvBJzfKel4/B81ieaLGXD7\n\t/VYvVwBFLbkQgJtEQi540DktT+2Y0v9/ckXoLt/OCzn9DtxlHYIhhrCfvrHfDGFl0Ldr\n\tYAu7Ol7NTa+KM5VqsSBK/Nu7MG67phcq+ke8VN8EjHzMpsyZQ2Xt3qHZdLnVEPi843Mp\n\tFM2w=="
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected) header.d=gmail.com header.i=@gmail.com\n\theader.b=\"XAz0LZjj\"; dkim-atps=neutral",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20221208; t=1692623445; x=1693228245;\n\th=content-transfer-encoding:mime-version:references:in-reply-to\n\t:message-id:date:subject:to:from:x-gm-message-state:from:to:cc\n\t:subject:date:message-id:reply-to;\n\tbh=EU6t+fl/QqCK94Dhs7LxVZPCFNQK/h1wuTeKXag0jbU=;\n\tb=GSm+YBU69C583HUJaMm/ZXgTgniGKHJUGfpaQ75Glapu1/KGwztgDZUN4Sc9XhgYeT\n\t6FE1SF7c3vnGE+XoBXLoZXv3XNmGuAugWDeNMzeS4LKFFimz6e6SvFohSzdXGE+B1CFu\n\tcYk/xbwErW5Ka3UcqYqXEqppUDYVQLZ6hi6pkv95sy//J1HW16vIBkfpHwVVT9m+RfbJ\n\tJks7UHRf9qMYzSiwZYdh3Wj+Q3IK1wrq4KhGSvtDGI6p4A/9IERdVLRGUg0rt+zI/B/9\n\tEPmzHpumku9upv41F+kBbcpZQUfpByXwxvA5Z9JXwicvG/yD9IUliq0Q3DocZ/QvNa3p\n\tha0Q==",
        "X-Gm-Message-State": "AOJu0YyuOfnvSPLslurOkzjIPer0E5Pb2/TeF7RDcrbWjNKgII80TQju\n\tOP/hPrGlvYDb+6vjdyAEgjt52CvMyTc=",
        "X-Google-Smtp-Source": "AGHT+IGpoqNewMqbPmpHwQMEdvahBu2zXq1QIDCtHpvenaN8k9yyPlgf6IpgEGPAyaWHPWHOyGEO0g==",
        "X-Received": "by 2002:a05:6870:2198:b0:1b7:273d:780a with SMTP id\n\tl24-20020a056870219800b001b7273d780amr4653240oae.22.1692623445541; \n\tMon, 21 Aug 2023 06:10:45 -0700 (PDT)",
        "To": "libcamera-devel@lists.libcamera.org, kieran.bingham@ideasonboard.com,\n\tvedantparanjape160201@gmail.com, gabbymg94@gmail.com",
        "Date": "Mon, 21 Aug 2023 06:10:38 -0700",
        "Message-Id": "<20230821131039.127370-5-gabbymg94@gmail.com>",
        "X-Mailer": "git-send-email 2.34.1",
        "In-Reply-To": "<20230821131039.127370-1-gabbymg94@gmail.com>",
        "References": "<20230821131039.127370-1-gabbymg94@gmail.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[libcamera-devel] [RFC PATCH v2 4/5] libcamera: pipeline: uvcvideo:\n\tAllocate metadata buffers",
        "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": "Gabby George via libcamera-devel <libcamera-devel@lists.libcamera.org>",
        "Reply-To": "Gabby George <gabbymg94@gmail.com>",
        "Errors-To": "libcamera-devel-bounces@lists.libcamera.org",
        "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"
    },
    "content": "Perform the allocation and mapping of metadata buffers into\nlibcamera's virtual address space.  UVC metadata buffers cannot be\nexported as DMA buffer file descriptors, so use the MappedFrameBuffer\nclass to map them into memory directly.  This will give the UVC\npipeline access to buffer data to extract timestamp information.\n\nMetadata buffers are internal to the UVC pipeline, so buffer memory\nshould not be exposed to the user.\n\nSigned-off-by: Gabby George <gabbymg94@gmail.com>\n---\n src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 98 +++++++++++++++++++-\n 1 file changed, 96 insertions(+), 2 deletions(-)",
    "diff": "diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\nindex dbe0cc8c..c8d6633f 100644\n--- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n+++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n@@ -24,6 +24,7 @@\n \n #include \"libcamera/internal/camera.h\"\n #include \"libcamera/internal/device_enumerator.h\"\n+#include \"libcamera/internal/mapped_framebuffer.h\"\n #include \"libcamera/internal/media_device.h\"\n #include \"libcamera/internal/pipeline_handler.h\"\n #include \"libcamera/internal/sysfs.h\"\n@@ -51,6 +52,9 @@ public:\n \tstd::unique_ptr<V4L2VideoDevice> video_;\n \tstd::unique_ptr<V4L2VideoDevice> metadata_;\n \tStream stream_;\n+\tstd::vector<std::unique_ptr<FrameBuffer>> metadataBuffers_;\n+\tstd::map<unsigned int, MappedFrameBuffer> mappedMetadataBuffers_;\n+\n \tstd::map<PixelFormat, std::vector<SizeRange>> formats_;\n \n private:\n@@ -96,6 +100,10 @@ private:\n \t\t\t   const ControlValue &value);\n \tint processControls(UVCCameraData *data, Request *request);\n \n+\tint createMetadataBuffers(Camera *camera, unsigned int count);\n+\tint cleanupMetadataBuffers(Camera *camera);\n+\tint cleanup(Camera *camera);\n+\n \tUVCCameraData *cameraData(Camera *camera)\n \t{\n \t\treturn static_cast<UVCCameraData *>(camera->_d());\n@@ -225,10 +233,67 @@ int PipelineHandlerUVC::configure(Camera *camera, CameraConfiguration *config)\n \t\treturn -EINVAL;\n \n \tcfg.setStream(&data->stream_);\n+\treturn 0;\n+}\n+\n+int PipelineHandlerUVC::cleanupMetadataBuffers(Camera *camera)\n+{\n+\tint ret = 0;\n+\tUVCCameraData *data = cameraData(camera);\n+\n+\tif (data->metadata_)\n+\t\tdata->metadata_->releaseBuffers();\n+\tdata->metadataBuffers_.clear();\n+\tdata->mappedMetadataBuffers_.clear();\n+\tdata->metadata_ = nullptr;\n \n+\treturn ret;\n+}\n+\n+int PipelineHandlerUVC::cleanup(Camera *camera)\n+{\n+\tUVCCameraData *data = cameraData(camera);\n+\tcleanupMetadataBuffers(camera);\n+\tdata->video_->releaseBuffers();\n \treturn 0;\n }\n \n+/**\n+ * UVC Metadata stream does not support exporting buffers via EXPBUF,\n+ * so it is necessary to create and store mmap-ed addresses.\n+ * Metadata buffers are internal to libcamera. They are not, and\n+ * cannot be, exposed to the user.\n+ *\n+ * Returns the number of buffers allocated and mapped.\n+ *\n+ * \\return The number of buffers allocated, or a negative error code if\n+ * the number of buffers allocated was not equal to \"count\"\n+ * \\retval -EINVAL if \"count\" buffers were not successfully allocated.\n+ * \\retval MappedFrameBuffer::error()\n+ */\n+int PipelineHandlerUVC::createMetadataBuffers(Camera *camera, unsigned int count)\n+{\n+\tUVCCameraData *data = cameraData(camera);\n+\tint ret = data->metadata_->allocateBuffers(count, &data->metadataBuffers_);\n+\tif (ret < 0)\n+\t\treturn -EINVAL;\n+\n+\tfor (unsigned int i = 0; i < count; i++) {\n+\t\tMappedFrameBuffer mappedBuffer(data->metadataBuffers_[i].get(),\n+\t\t\t\t\t       MappedFrameBuffer::MapFlag::Read, true);\n+\t\tif (!mappedBuffer.isValid()) {\n+\t\t\tLOG(UVC, Warning)\n+\t\t\t\t<< \"Failed to mmap metadata buffer: \"\n+\t\t\t\t<< strerror(mappedBuffer.error());\n+\t\t\treturn mappedBuffer.error();\n+\t\t}\n+\n+\t\tdata->mappedMetadataBuffers_.emplace(i, std::move(mappedBuffer));\n+\t\tdata->metadataBuffers_[i]->setCookie(i);\n+\t}\n+\treturn ret;\n+}\n+\n int PipelineHandlerUVC::exportFrameBuffers(Camera *camera, Stream *stream,\n \t\t\t\t\t   std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n {\n@@ -249,18 +314,47 @@ int PipelineHandlerUVC::start(Camera *camera, [[maybe_unused]] const ControlList\n \n \tret = data->video_->streamOn();\n \tif (ret < 0) {\n-\t\tdata->video_->releaseBuffers();\n+\t\tcleanup(camera);\n \t\treturn ret;\n \t}\n \n+\t/*\n+\t * If metadata allocation fails, exit this function but\n+\t * do not return a failure as video started successfully.\n+\t * Fall back on using driver timestamps.\n+\t */\n+\tif (data->metadata_) {\n+\t\tif (createMetadataBuffers(camera, count) < 0 ||\n+\t\t    data->metadata_->streamOn()) {\n+\t\t\tLOG(UVC, Warning)\n+\t\t\t\t<< \"Metadata stream unavailable.  Using driver timestamps.\";\n+\t\t\tdata->metadata_ = nullptr;\n+\t\t\treturn 0;\n+\t\t}\n+\n+\t\tfor (std::unique_ptr<FrameBuffer> &buf : data->metadataBuffers_) {\n+\t\t\tret = data->metadata_->queueBuffer(buf.get());\n+\t\t\tif (ret < 0) {\n+\t\t\t\tLOG(UVC, Warning)\n+\t\t\t\t\t<< \"Metadata stream unavailable.  Using driver timestamps.\";\n+\t\t\t\tcleanupMetadataBuffers(camera);\n+\t\t\t\treturn 0;\n+\t\t\t}\n+\t\t}\n+\t}\n \treturn 0;\n }\n \n void PipelineHandlerUVC::stopDevice(Camera *camera)\n {\n \tUVCCameraData *data = cameraData(camera);\n+\n \tdata->video_->streamOff();\n-\tdata->video_->releaseBuffers();\n+\n+\tif (data->metadata_)\n+\t\tdata->metadata_->streamOff();\n+\n+\tcleanup(camera);\n }\n \n int PipelineHandlerUVC::processControl(ControlList *controls, unsigned int id,\n",
    "prefixes": [
        "libcamera-devel",
        "RFC",
        "v2",
        "4/5"
    ]
}