Show a patch.

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

{
    "id": 25211,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/25211/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/25211/",
    "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": "<20251126-cam-control-override-v2-2-305024a1f190@ideasonboard.com>",
    "date": "2025-11-26T09:38:52",
    "name": "[v2,2/3] libcamera: request: Move metadata_ to Private",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "d9e9779c97da6e1ee5278aba1efdc1654f9c0cf7",
    "submitter": {
        "id": 143,
        "url": "https://patchwork.libcamera.org/api/1.1/people/143/?format=api",
        "name": "Jacopo Mondi",
        "email": "jacopo.mondi@ideasonboard.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/25211/mbox/",
    "series": [
        {
            "id": 5614,
            "url": "https://patchwork.libcamera.org/api/1.1/series/5614/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5614",
            "date": "2025-11-26T09:38:50",
            "name": "libcamera: ipc: ControlLists without valid idmap break IPC",
            "version": 2,
            "mbox": "https://patchwork.libcamera.org/series/5614/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/25211/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/25211/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 62880C32EF\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 26 Nov 2025 09:39:14 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 5B33B60AA1;\n\tWed, 26 Nov 2025 10:39:11 +0100 (CET)",
            "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id CEA656069A\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 26 Nov 2025 10:39:06 +0100 (CET)",
            "from [192.168.0.172] (mob-5-90-63-219.net.vodafone.it\n\t[5.90.63.219])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 4437D10D4;\n\tWed, 26 Nov 2025 10:36:57 +0100 (CET)"
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"YaCKX7iY\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1764149817;\n\tbh=QFCYggUnmgJLhzJC16sTgHRAjjav1gL655R+S5+bvto=;\n\th=From:Date:Subject:References:In-Reply-To:To:Cc:From;\n\tb=YaCKX7iY2sPNHZfrwl+U5wrEIbOFXMHWpvP/7FPWrmQ0nYgSnCPOF2uQPdsJ9BXKS\n\tgfw6ghntcmFtLLhHONLOJefvoKclMqfLHdWBP3J9crkaf2CWRIFUwk1VXao9IPhris\n\tEm5Z6/cobbk7Ariz8R9Awt9bSSIny7NBJ1al3Eaw=",
        "From": "Jacopo Mondi <jacopo.mondi@ideasonboard.com>",
        "Date": "Wed, 26 Nov 2025 10:38:52 +0100",
        "Subject": "[PATCH v2 2/3] libcamera: request: Move metadata_ to Private",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "7bit",
        "Message-Id": "<20251126-cam-control-override-v2-2-305024a1f190@ideasonboard.com>",
        "References": "<20251126-cam-control-override-v2-0-305024a1f190@ideasonboard.com>",
        "In-Reply-To": "<20251126-cam-control-override-v2-0-305024a1f190@ideasonboard.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Cc": "Jacopo Mondi <jacopo.mondi@ideasonboard.com>",
        "X-Mailer": "b4 0.14.2",
        "X-Developer-Signature": "v=1; a=openpgp-sha256; l=19843;\n\ti=jacopo.mondi@ideasonboard.com; h=from:subject:message-id;\n\tbh=QFCYggUnmgJLhzJC16sTgHRAjjav1gL655R+S5+bvto=;\n\tb=owEBbQKS/ZANAwAKAXI0Bo8WoVY8AcsmYgBpJsq5FThkeyfaAsBxihvVHhUjC8SeXOlqT526T\n\tfJi6QFnrLCJAjMEAAEKAB0WIQS1xD1IgJogio9YOMByNAaPFqFWPAUCaSbKuQAKCRByNAaPFqFW\n\tPNseD/0eLjxFznNHT/iKhe+VAbhbejN1/CSttqDJtdZ9FhH0aitPuABkE4WuTioeSZIvfYESoC2\n\tZUkjyB0wECaBkZTlIsX6qPzqHjSfC7UhoxFRVIu/g/aG6wnLDiKKTj5hdpmi1bKQ4VE4y3AtvrG\n\t2kUdO/FjlZjeU9ybqFi3IVIP/rDTxfop9SEQBOKxGM36u2iVMnPxtDjy7lgf3Ni5FkGMLHvi1wR\n\tMCx6zJhYeMeWVyB4lDYai5mdyWZOlfbWSk9H/FLo9JKW0OlZX8rAQwAO7IWt3MTAUDQoEO1c6ED\n\tGKKUem9OOmlBnZNtRFueoolltzFTD6GnU7+KM908hZGjSdcDdpmLS4bInlD55oJIihBWS9yk9Ad\n\tVL8XG6trsM4E0015sGIFpc7f4vKVgNTiX7m3idDNK/gjZkNUYNW2G5b3Core2H5IcH+H6G0kCiN\n\tWAf6Z8/WNL41j/v9YoIoe1ToMqHdKlAicTRBeVj93tqeh7fZj8AvrmVl8XrDIOmHQAXF1C8IfLV\n\tzsOPv3vS7XceNwGnMCpoezGmuN7k84d3FuZoWi2yGBf69lSVwptg57OeV6lxj9kMi9NODhdlm3q\n\tRVjS+Vv1t3z8WjTUrWnZaTogm2AdYChS84J2odKSdyaTIT4iVish2BAfFxywkfCFOEN/NxqSJ44\n\tPbXxs9ShSW5Ve5Q==",
        "X-Developer-Key": "i=jacopo.mondi@ideasonboard.com; a=openpgp;\n\tfpr=72392EDC88144A65C701EA9BA5826A2587AD026B",
        "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": "Address a long standing \\todo item that suggested to implement a\nread-only interface for the Request::metadata() accessor and deflect to\nthe internal implementation for the read-write accessor used by pipeline\nhandlers.\n\nSigned-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n---\n include/libcamera/internal/request.h               |  3 ++\n include/libcamera/request.h                        |  3 +-\n src/libcamera/pipeline/imx8-isi/imx8-isi.cpp       |  3 +-\n src/libcamera/pipeline/ipu3/ipu3.cpp               | 16 +++++-----\n src/libcamera/pipeline/mali-c55/mali-c55.cpp       |  2 +-\n src/libcamera/pipeline/rkisp1/rkisp1.cpp           | 10 +++---\n .../pipeline/rpi/common/pipeline_base.cpp          | 13 ++++----\n src/libcamera/pipeline/rpi/common/pipeline_base.h  |  2 +-\n src/libcamera/pipeline/simple/simple.cpp           |  8 ++---\n src/libcamera/pipeline/uvcvideo/uvcvideo.cpp       |  6 ++--\n src/libcamera/pipeline/vimc/vimc.cpp               |  6 ++--\n src/libcamera/pipeline/virtual/virtual.cpp         |  4 +--\n src/libcamera/request.cpp                          | 37 ++++++++++++----------\n 13 files changed, 61 insertions(+), 52 deletions(-)",
    "diff": "diff --git a/include/libcamera/internal/request.h b/include/libcamera/internal/request.h\nindex 78cb99f3604504dfb7145c605835b7493b656ced..643f67cabf5778f7515c0117d06d4e0a3fdec4f8 100644\n--- a/include/libcamera/internal/request.h\n+++ b/include/libcamera/internal/request.h\n@@ -36,6 +36,8 @@ public:\n \tCamera *camera() const { return camera_; }\n \tbool hasPendingBuffers() const;\n \n+\tControlList &metadata() { return *metadata_; }\n+\n \tbool completeBuffer(FrameBuffer *buffer);\n \tvoid complete();\n \tvoid cancel();\n@@ -61,6 +63,7 @@ private:\n \tstd::unordered_set<FrameBuffer *> pending_;\n \tstd::map<FrameBuffer *, EventNotifier> notifiers_;\n \tstd::unique_ptr<Timer> timer_;\n+\tControlList *metadata_;\n };\n \n } /* namespace libcamera */\ndiff --git a/include/libcamera/request.h b/include/libcamera/request.h\nindex 0c5939f7b3336fd089a2fe231f4f6f266cc422f7..c9aeddb62680923dc3490a23dc6c3f70f70cc075 100644\n--- a/include/libcamera/request.h\n+++ b/include/libcamera/request.h\n@@ -50,7 +50,7 @@ public:\n \tvoid reuse(ReuseFlag flags = Default);\n \n \tControlList &controls() { return *controls_; }\n-\tControlList &metadata() { return *metadata_; }\n+\tconst ControlList &metadata() const;\n \tconst BufferMap &buffers() const { return bufferMap_; }\n \tint addBuffer(const Stream *stream, FrameBuffer *buffer,\n \t\t      std::unique_ptr<Fence> &&fence = {});\n@@ -68,7 +68,6 @@ private:\n \tLIBCAMERA_DISABLE_COPY(Request)\n \n \tControlList *controls_;\n-\tControlList *metadata_;\n \tBufferMap bufferMap_;\n \n \tconst uint64_t cookie_;\ndiff --git a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp\nindex 9550f54600c4d98e9d110a5e255d1ac85e2b5660..b0fb117b52e2a00fe9b5289c957442c1142fe7c6 100644\n--- a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp\n+++ b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp\n@@ -26,6 +26,7 @@\n #include \"libcamera/internal/device_enumerator.h\"\n #include \"libcamera/internal/media_device.h\"\n #include \"libcamera/internal/pipeline_handler.h\"\n+#include \"libcamera/internal/request.h\"\n #include \"libcamera/internal/v4l2_subdevice.h\"\n #include \"libcamera/internal/v4l2_videodevice.h\"\n \n@@ -1151,7 +1152,7 @@ void PipelineHandlerISI::bufferReady(FrameBuffer *buffer)\n \tRequest *request = buffer->request();\n \n \t/* Record the sensor's timestamp in the request metadata. */\n-\tControlList &metadata = request->metadata();\n+\tControlList &metadata = request->_d()->metadata();\n \tif (!metadata.contains(controls::SensorTimestamp.id()))\n \t\tmetadata.set(controls::SensorTimestamp,\n \t\t\t     buffer->metadata().timestamp);\ndiff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\nindex d6b7edcb5a7f9fcb4083d4105a193978e265ef67..49df8fe5b41035b164c3a6828b791ef084ff18c8 100644\n--- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n@@ -19,7 +19,6 @@\n #include <libcamera/control_ids.h>\n #include <libcamera/formats.h>\n #include <libcamera/property_ids.h>\n-#include <libcamera/request.h>\n #include <libcamera/stream.h>\n \n #include <libcamera/ipa/ipu3_ipa_interface.h>\n@@ -35,6 +34,7 @@\n #include \"libcamera/internal/ipa_manager.h\"\n #include \"libcamera/internal/media_device.h\"\n #include \"libcamera/internal/pipeline_handler.h\"\n+#include \"libcamera/internal/request.h\"\n \n #include \"cio2.h\"\n #include \"frames.h\"\n@@ -1249,7 +1249,7 @@ void IPU3CameraData::metadataReady(unsigned int id, const ControlList &metadata)\n \t\treturn;\n \n \tRequest *request = info->request;\n-\trequest->metadata().merge(metadata);\n+\trequest->_d()->metadata().merge(metadata);\n \n \tinfo->metadataProcessed = true;\n \tif (frameInfos_.tryComplete(info))\n@@ -1276,12 +1276,12 @@ void IPU3CameraData::imguOutputBufferReady(FrameBuffer *buffer)\n \n \tpipe()->completeBuffer(request, buffer);\n \n-\trequest->metadata().set(controls::draft::PipelineDepth, 3);\n+\trequest->_d()->metadata().set(controls::draft::PipelineDepth, 3);\n \t/* \\todo Actually apply the scaler crop region to the ImgU. */\n \tconst auto &scalerCrop = request->controls().get(controls::ScalerCrop);\n \tif (scalerCrop)\n \t\tcropRegion_ = *scalerCrop;\n-\trequest->metadata().set(controls::ScalerCrop, cropRegion_);\n+\trequest->_d()->metadata().set(controls::ScalerCrop, cropRegion_);\n \n \tif (frameInfos_.tryComplete(info))\n \t\tpipe()->completeRequest(request);\n@@ -1321,8 +1321,8 @@ void IPU3CameraData::cio2BufferReady(FrameBuffer *buffer)\n \t * \\todo The sensor timestamp should be better estimated by connecting\n \t * to the V4L2Device::frameStart signal.\n \t */\n-\trequest->metadata().set(controls::SensorTimestamp,\n-\t\t\t\tbuffer->metadata().timestamp);\n+\trequest->_d()->metadata().set(controls::SensorTimestamp,\n+\t\t\t\t      buffer->metadata().timestamp);\n \n \tinfo->effectiveSensorControls = delayedCtrls_->get(buffer->metadata().sequence);\n \n@@ -1416,8 +1416,8 @@ void IPU3CameraData::frameStart(uint32_t sequence)\n \t\treturn;\n \t}\n \n-\trequest->metadata().set(controls::draft::TestPatternMode,\n-\t\t\t\t*testPatternMode);\n+\trequest->_d()->metadata().set(controls::draft::TestPatternMode,\n+\t\t\t\t      *testPatternMode);\n }\n \n REGISTER_PIPELINE_HANDLER(PipelineHandlerIPU3, \"ipu3\")\ndiff --git a/src/libcamera/pipeline/mali-c55/mali-c55.cpp b/src/libcamera/pipeline/mali-c55/mali-c55.cpp\nindex 38bdc6138ed167a2c05f43ca30e60ed549fd953c..68be4cd66050b56e50805336efa5da8dafa4d3b9 100644\n--- a/src/libcamera/pipeline/mali-c55/mali-c55.cpp\n+++ b/src/libcamera/pipeline/mali-c55/mali-c55.cpp\n@@ -1528,7 +1528,7 @@ void PipelineHandlerMaliC55::statsProcessed(unsigned int requestId,\n \tMaliC55FrameInfo &frameInfo = frameInfoMap_[requestId];\n \n \tframeInfo.statsDone = true;\n-\tframeInfo.request->metadata().merge(metadata);\n+\tframeInfo.request->_d()->metadata().merge(metadata);\n \n \ttryComplete(&frameInfo);\n }\ndiff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp\nindex d7195b6c484d091857a91de709e0e060810c7c32..823160f58d989600ff3213df6bbec2a015d8745f 100644\n--- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp\n+++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp\n@@ -25,7 +25,6 @@\n #include <libcamera/formats.h>\n #include <libcamera/framebuffer.h>\n #include <libcamera/property_ids.h>\n-#include <libcamera/request.h>\n #include <libcamera/stream.h>\n #include <libcamera/transform.h>\n \n@@ -44,6 +43,7 @@\n #include \"libcamera/internal/media_device.h\"\n #include \"libcamera/internal/media_pipeline.h\"\n #include \"libcamera/internal/pipeline_handler.h\"\n+#include \"libcamera/internal/request.h\"\n #include \"libcamera/internal/v4l2_subdevice.h\"\n #include \"libcamera/internal/v4l2_videodevice.h\"\n \n@@ -452,7 +452,7 @@ void RkISP1CameraData::metadataReady(unsigned int frame, const ControlList &meta\n \tif (!info)\n \t\treturn;\n \n-\tinfo->request->metadata().merge(metadata);\n+\tinfo->request->_d()->metadata().merge(metadata);\n \tinfo->metadataProcessed = true;\n \n \tpipe()->tryCompleteRequest(info);\n@@ -1518,8 +1518,8 @@ void PipelineHandlerRkISP1::imageBufferReady(FrameBuffer *buffer)\n \t\t * \\todo The sensor timestamp should be better estimated by connecting\n \t\t * to the V4L2Device::frameStart signal.\n \t\t */\n-\t\trequest->metadata().set(controls::SensorTimestamp,\n-\t\t\t\t\tmetadata.timestamp);\n+\t\trequest->_d()->metadata().set(controls::SensorTimestamp,\n+\t\t\t\t\t      metadata.timestamp);\n \n \t\tif (isRaw_) {\n \t\t\tconst ControlList &ctrls =\n@@ -1602,7 +1602,7 @@ void PipelineHandlerRkISP1::imageBufferReady(FrameBuffer *buffer)\n \t\tLOG(RkISP1, Error) << \"Cannot queue buffers to dewarper: \"\n \t\t\t\t   << strerror(-ret);\n \n-\trequest->metadata().set(controls::ScalerCrop, activeCrop_.value());\n+\trequest->_d()->metadata().set(controls::ScalerCrop, activeCrop_.value());\n }\n \n void PipelineHandlerRkISP1::dewarpBufferReady(FrameBuffer *buffer)\ndiff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp\nindex c209aa596311a7d902e32caedc3f98cfa3da2b09..4a15839afbc32c3e57caff11904484540a61745e 100644\n--- a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp\n+++ b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp\n@@ -1219,7 +1219,7 @@ void CameraData::metadataReady(const ControlList &metadata)\n \t/* Add to the Request metadata buffer what the IPA has provided. */\n \t/* Last thing to do is to fill up the request metadata. */\n \tRequest *request = requestQueue_.front();\n-\trequest->metadata().merge(metadata);\n+\trequest->_d()->metadata().merge(metadata);\n \n \t/*\n \t * Inform the sensor of the latest colour gains if it has the\n@@ -1490,9 +1490,9 @@ void CameraData::checkRequestCompleted()\n void CameraData::fillRequestMetadata(const ControlList &bufferControls, Request *request)\n {\n \tif (auto x = bufferControls.get(controls::SensorTimestamp))\n-\t\trequest->metadata().set(controls::SensorTimestamp, *x);\n+\t\trequest->_d()->metadata().set(controls::SensorTimestamp, *x);\n \tif (auto x = bufferControls.get(controls::FrameWallClock))\n-\t\trequest->metadata().set(controls::FrameWallClock, *x);\n+\t\trequest->_d()->metadata().set(controls::FrameWallClock, *x);\n \n \tif (cropParams_.size()) {\n \t\tstd::vector<Rectangle> crops;\n@@ -1500,10 +1500,11 @@ void CameraData::fillRequestMetadata(const ControlList &bufferControls, Request\n \t\tfor (auto const &[k, v] : cropParams_)\n \t\t\tcrops.push_back(scaleIspCrop(v.ispCrop));\n \n-\t\trequest->metadata().set(controls::ScalerCrop, crops[0]);\n+\t\trequest->_d()->metadata().set(controls::ScalerCrop, crops[0]);\n \t\tif (crops.size() > 1) {\n-\t\t\trequest->metadata().set(controls::rpi::ScalerCrops,\n-\t\t\t\t\t\tSpan<const Rectangle>(crops.data(), crops.size()));\n+\t\t\trequest->_d()->metadata().set(controls::rpi::ScalerCrops,\n+\t\t\t\t\t\t      Span<const Rectangle>(crops.data(),\n+\t\t\t\t\t\t\t\t\t    crops.size()));\n \t\t}\n \t}\n }\ndiff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.h b/src/libcamera/pipeline/rpi/common/pipeline_base.h\nindex 4bce4ec4f978cedd7d10d354ce2231c9296a3e39..d9114f1cb954e541b2a35a748a95cca0af59ebbe 100644\n--- a/src/libcamera/pipeline/rpi/common/pipeline_base.h\n+++ b/src/libcamera/pipeline/rpi/common/pipeline_base.h\n@@ -15,7 +15,6 @@\n #include <vector>\n \n #include <libcamera/controls.h>\n-#include <libcamera/request.h>\n \n #include \"libcamera/internal/bayer_format.h\"\n #include \"libcamera/internal/camera.h\"\n@@ -25,6 +24,7 @@\n #include \"libcamera/internal/media_device.h\"\n #include \"libcamera/internal/media_object.h\"\n #include \"libcamera/internal/pipeline_handler.h\"\n+#include \"libcamera/internal/request.h\"\n #include \"libcamera/internal/v4l2_videodevice.h\"\n #include \"libcamera/internal/yaml_parser.h\"\n \ndiff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp\nindex 97009fbc03c64108a23f9edf6df95177593f9035..58cac390eb5be7231101c92fda1caf8e8b088e63 100644\n--- a/src/libcamera/pipeline/simple/simple.cpp\n+++ b/src/libcamera/pipeline/simple/simple.cpp\n@@ -27,7 +27,6 @@\n #include <libcamera/camera.h>\n #include <libcamera/color_space.h>\n #include <libcamera/control_ids.h>\n-#include <libcamera/request.h>\n #include <libcamera/stream.h>\n \n #include \"libcamera/internal/camera.h\"\n@@ -41,6 +40,7 @@\n #include \"libcamera/internal/global_configuration.h\"\n #include \"libcamera/internal/media_device.h\"\n #include \"libcamera/internal/pipeline_handler.h\"\n+#include \"libcamera/internal/request.h\"\n #include \"libcamera/internal/software_isp/software_isp.h\"\n #include \"libcamera/internal/v4l2_subdevice.h\"\n #include \"libcamera/internal/v4l2_videodevice.h\"\n@@ -926,8 +926,8 @@ void SimpleCameraData::imageBufferReady(FrameBuffer *buffer)\n \t}\n \n \tif (request)\n-\t\trequest->metadata().set(controls::SensorTimestamp,\n-\t\t\t\t\tbuffer->metadata().timestamp);\n+\t\trequest->_d()->metadata().set(controls::SensorTimestamp,\n+\t\t\t\t\t      buffer->metadata().timestamp);\n \n \t/*\n \t * Queue the captured and the request buffer to the converter or Software\n@@ -1014,7 +1014,7 @@ void SimpleCameraData::metadataReady(uint32_t frame, const ControlList &metadata\n \tif (!info)\n \t\treturn;\n \n-\tinfo->request->metadata().merge(metadata);\n+\tinfo->request->_d()->metadata().merge(metadata);\n \tinfo->metadataProcessed = true;\n \ttryCompleteRequest(info->request);\n }\ndiff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\nindex 48d6b39d532009bc32a2148f1d35b3a3be0bc0d4..21f2d28399bdfe97e0d97bf2e025721de36607c8 100644\n--- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n+++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp\n@@ -24,13 +24,13 @@\n #include <libcamera/control_ids.h>\n #include <libcamera/controls.h>\n #include <libcamera/property_ids.h>\n-#include <libcamera/request.h>\n #include <libcamera/stream.h>\n \n #include \"libcamera/internal/camera.h\"\n #include \"libcamera/internal/device_enumerator.h\"\n #include \"libcamera/internal/media_device.h\"\n #include \"libcamera/internal/pipeline_handler.h\"\n+#include \"libcamera/internal/request.h\"\n #include \"libcamera/internal/sysfs.h\"\n #include \"libcamera/internal/v4l2_videodevice.h\"\n \n@@ -895,8 +895,8 @@ void UVCCameraData::imageBufferReady(FrameBuffer *buffer)\n \tRequest *request = buffer->request();\n \n \t/* \\todo Use the UVC metadata to calculate a more precise timestamp */\n-\trequest->metadata().set(controls::SensorTimestamp,\n-\t\t\t\tbuffer->metadata().timestamp);\n+\trequest->_d()->metadata().set(controls::SensorTimestamp,\n+\t\t\t\t      buffer->metadata().timestamp);\n \n \tpipe()->completeBuffer(request, buffer);\n \tpipe()->completeRequest(request);\ndiff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp\nindex 5022101505a15af1ebf6a8be4a52bcefb1fccfa0..9b1cfb090a7a274894b90969c4dad361c6748cea 100644\n--- a/src/libcamera/pipeline/vimc/vimc.cpp\n+++ b/src/libcamera/pipeline/vimc/vimc.cpp\n@@ -24,7 +24,6 @@\n #include <libcamera/formats.h>\n #include <libcamera/framebuffer.h>\n #include <libcamera/geometry.h>\n-#include <libcamera/request.h>\n #include <libcamera/stream.h>\n \n #include <libcamera/ipa/ipa_interface.h>\n@@ -39,6 +38,7 @@\n #include \"libcamera/internal/ipa_manager.h\"\n #include \"libcamera/internal/media_device.h\"\n #include \"libcamera/internal/pipeline_handler.h\"\n+#include \"libcamera/internal/request.h\"\n #include \"libcamera/internal/v4l2_subdevice.h\"\n #include \"libcamera/internal/v4l2_videodevice.h\"\n \n@@ -618,8 +618,8 @@ void VimcCameraData::imageBufferReady(FrameBuffer *buffer)\n \t}\n \n \t/* Record the sensor's timestamp in the request metadata. */\n-\trequest->metadata().set(controls::SensorTimestamp,\n-\t\t\t\tbuffer->metadata().timestamp);\n+\trequest->_d()->metadata().set(controls::SensorTimestamp,\n+\t\t\t\t      buffer->metadata().timestamp);\n \n \tpipe->completeBuffer(request, buffer);\n \tpipe->completeRequest(request);\ndiff --git a/src/libcamera/pipeline/virtual/virtual.cpp b/src/libcamera/pipeline/virtual/virtual.cpp\nindex 7855e8b9db0c3bdfb3662a0b6e71332ed463a0ed..40c35264c5687c0f94458e19a272612cefb76285 100644\n--- a/src/libcamera/pipeline/virtual/virtual.cpp\n+++ b/src/libcamera/pipeline/virtual/virtual.cpp\n@@ -29,13 +29,13 @@\n #include <libcamera/formats.h>\n #include <libcamera/pixel_format.h>\n #include <libcamera/property_ids.h>\n-#include <libcamera/request.h>\n \n #include \"libcamera/internal/camera.h\"\n #include \"libcamera/internal/dma_buf_allocator.h\"\n #include \"libcamera/internal/formats.h\"\n #include \"libcamera/internal/framebuffer.h\"\n #include \"libcamera/internal/pipeline_handler.h\"\n+#include \"libcamera/internal/request.h\"\n #include \"libcamera/internal/yaml_parser.h\"\n \n #include \"pipeline/virtual/config_parser.h\"\n@@ -366,7 +366,7 @@ int PipelineHandlerVirtual::queueRequestDevice([[maybe_unused]] Camera *camera,\n \tVirtualCameraData *data = cameraData(camera);\n \tconst auto timestamp = currentTimestamp();\n \n-\trequest->metadata().set(controls::SensorTimestamp, timestamp);\n+\trequest->_d()->metadata().set(controls::SensorTimestamp, timestamp);\n \tdata->invokeMethod(&VirtualCameraData::processRequest,\n \t\t\t   ConnectionTypeQueued, request);\n \ndiff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp\nindex 2544a059f6984d930ec909c74e0b621c9fe82726..a661b2f5c8ae9ae2bcbab2dcdceeef7dcb8d0930 100644\n--- a/src/libcamera/request.cpp\n+++ b/src/libcamera/request.cpp\n@@ -57,11 +57,16 @@ LOG_DEFINE_CATEGORY(Request)\n Request::Private::Private(Camera *camera)\n \t: camera_(camera), cancelled_(false)\n {\n+\t/**\n+\t * \\todo Add a validator for metadata controls.\n+\t */\n+\tmetadata_ = new ControlList(controls::controls);\n }\n \n Request::Private::~Private()\n {\n \tdoCancelRequest();\n+\tdelete metadata_;\n }\n \n /**\n@@ -82,6 +87,12 @@ bool Request::Private::hasPendingBuffers() const\n \treturn !pending_.empty();\n }\n \n+/**\n+ * \\fn Request::Private::metadata()\n+ * \\brief Retrieve the request's metadata\n+ * \\return The metadata associated with the request\n+ */\n+\n /**\n  * \\brief Complete a buffer for the request\n  * \\param[in] buffer The buffer that has completed\n@@ -359,11 +370,6 @@ Request::Request(Camera *camera, uint64_t cookie)\n \tcontrols_ = new ControlList(camera->controls(),\n \t\t\t\t    camera->_d()->validator());\n \n-\t/**\n-\t * \\todo Add a validator for metadata controls.\n-\t */\n-\tmetadata_ = new ControlList(controls::controls);\n-\n \tLIBCAMERA_TRACEPOINT(request_construct, this);\n \n \tLOG(Request, Debug) << \"Created request - cookie: \" << cookie_;\n@@ -372,8 +378,6 @@ Request::Request(Camera *camera, uint64_t cookie)\n Request::~Request()\n {\n \tLIBCAMERA_TRACEPOINT(request_destroy, this);\n-\n-\tdelete metadata_;\n \tdelete controls_;\n }\n \n@@ -406,7 +410,7 @@ void Request::reuse(ReuseFlag flags)\n \tstatus_ = RequestPending;\n \n \tcontrols_->clear();\n-\tmetadata_->clear();\n+\t_d()->metadata_->clear();\n }\n \n /**\n@@ -425,6 +429,15 @@ void Request::reuse(ReuseFlag flags)\n  * \\return A reference to the ControlList in this request\n  */\n \n+/**\n+ * \\brief Retrieve the request's metadata\n+ * \\return The a const reference to the metadata associated with the request\n+ */\n+const ControlList &Request::metadata() const\n+{\n+\treturn *_d()->metadata_;\n+}\n+\n /**\n  * \\fn Request::buffers()\n  * \\brief Retrieve the request's streams to buffers map\n@@ -525,14 +538,6 @@ FrameBuffer *Request::findBuffer(const Stream *stream) const\n \treturn it->second;\n }\n \n-/**\n- * \\fn Request::metadata()\n- * \\brief Retrieve the request's metadata\n- * \\todo Offer a read-only API towards applications while keeping a read/write\n- * API internally.\n- * \\return The metadata associated with the request\n- */\n-\n /**\n  * \\brief Retrieve the sequence number for the request\n  *\n",
    "prefixes": [
        "v2",
        "2/3"
    ]
}