Patch Detail
Show a patch.
GET /api/patches/24566/?format=api
{ "id": 24566, "url": "https://patchwork.libcamera.org/api/patches/24566/?format=api", "web_url": "https://patchwork.libcamera.org/patch/24566/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/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": "<20251007102747.2746478-2-paul.elder@ideasonboard.com>", "date": "2025-10-07T10:27:43", "name": "[v2,1/2] libcamera: control_serializer: Add array info to serialized ControlValue", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "9e964a9e7b0e6b46df43ee4789f9f0f61e069f85", "submitter": { "id": 17, "url": "https://patchwork.libcamera.org/api/people/17/?format=api", "name": "Paul Elder", "email": "paul.elder@ideasonboard.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/24566/mbox/", "series": [ { "id": 5479, "url": "https://patchwork.libcamera.org/api/series/5479/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5479", "date": "2025-10-07T10:27:42", "name": "Fix ControlSerializer deserializing array controls", "version": 2, "mbox": "https://patchwork.libcamera.org/series/5479/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/24566/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/24566/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 02E82BF415\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 7 Oct 2025 10:28:05 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id DCF826B5F9;\n\tTue, 7 Oct 2025 12:28:02 +0200 (CEST)", "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 351D16B5AA\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 7 Oct 2025 12:28:00 +0200 (CEST)", "from neptunite.hamster-moth.ts.net (unknown\n\t[IPv6:2404:7a81:160:2100:859f:ca72:88bf:8f12])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 0F1ADEB5;\n\tTue, 7 Oct 2025 12:26:25 +0200 (CEST)" ], "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"NbnZUeL8\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1759832787;\n\tbh=ZK499pj8Jsi7nEuwyLKsBr+PNimy3AgfGwuqd00xnew=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=NbnZUeL8CKPa0tz78BIfLdwywOjfcoNt0OavJcjL8AizaU/BXrZBQ1Ibyp1e5XiTb\n\t44sepgu6bOrksNOJOS6vCtZDGtQJavujUYZKdeUTLn+t4UbbgMjecKwsyNb87TBo4B\n\tmDm/bQeYzgrtSBg4hn7YJX6Hly2sMMlk82vM5DQU=", "From": "Paul Elder <paul.elder@ideasonboard.com>", "To": "libcamera-devel@lists.libcamera.org", "Cc": "Paul Elder <paul.elder@ideasonboard.com>", "Subject": "[PATCH v2 1/2] libcamera: control_serializer: Add array info to\n\tserialized ControlValue", "Date": "Tue, 7 Oct 2025 19:27:43 +0900", "Message-ID": "<20251007102747.2746478-2-paul.elder@ideasonboard.com>", "X-Mailer": "git-send-email 2.47.2", "In-Reply-To": "<20251007102747.2746478-1-paul.elder@ideasonboard.com>", "References": "<20251007102747.2746478-1-paul.elder@ideasonboard.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "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": "Array controls (eg. ColourCorrectionMatrix, FrameDurationLimits,\nColourGains) are serialized properly by the ControlSerializer, but are\nnot deserialized properly. This is because their arrayness and size are\nnot considered during deserialization.\n\nFix this by adding arrayness and size to the serialized form of all\nControlValues.\n\nThis was not noticed before as the default value of the ControlInfo of\nother array controls had been set to scalar values similar to min/max,\nand ColourCorrectionMatrix was the first control to properly define a\nnon-scalar default value.\n\nOther array controls that define a scalar default value need to be\nfixed to define a properly sized default ControlInfo value.\n\nBug: https://bugs.libcamera.org/show_bug.cgi?id=285\nSigned-off-by: Paul Elder <paul.elder@ideasonboard.com>\n\n---\nChanges in v2:\n- make it so that the *serialized form* of ControlValue includes\n arrayness and size instead\n - Compared to v1, this ties the arrayness and size information to\n ControlValue instead of ControlId, which as a side effect allows us\n to support scalar and array min/max values, not just def values.\n This also gives us support for variable-length arrays\n---\n .../libcamera/internal/control_serializer.h | 8 +++--\n src/libcamera/control_serializer.cpp | 30 ++++++++++++++-----\n 2 files changed, 29 insertions(+), 9 deletions(-)", "diff": "diff --git a/include/libcamera/internal/control_serializer.h b/include/libcamera/internal/control_serializer.h\nindex 8a63ae44a13e..683bb13df92f 100644\n--- a/include/libcamera/internal/control_serializer.h\n+++ b/include/libcamera/internal/control_serializer.h\n@@ -41,14 +41,18 @@ public:\n \tbool isCached(const ControlInfoMap &infoMap);\n \n private:\n+\tstruct ControlValueHeader {\n+\t\tbool isArray;\n+\t\tstd::size_t numElements;\n+\t};\n+\n \tstatic size_t binarySize(const ControlValue &value);\n \tstatic size_t binarySize(const ControlInfo &info);\n \n \tstatic void store(const ControlValue &value, ByteStreamBuffer &buffer);\n \tstatic void store(const ControlInfo &info, ByteStreamBuffer &buffer);\n \n-\tControlValue loadControlValue(ByteStreamBuffer &buffer,\n-\t\t\t\t bool isArray = false, unsigned int count = 1);\n+\tControlValue loadControlValue(ByteStreamBuffer &buffer);\n \tControlInfo loadControlInfo(ByteStreamBuffer &buffer);\n \n \tunsigned int serial_;\ndiff --git a/src/libcamera/control_serializer.cpp b/src/libcamera/control_serializer.cpp\nindex 050f8512bd52..463f6ab9118d 100644\n--- a/src/libcamera/control_serializer.cpp\n+++ b/src/libcamera/control_serializer.cpp\n@@ -144,7 +144,12 @@ void ControlSerializer::reset()\n \n size_t ControlSerializer::binarySize(const ControlValue &value)\n {\n-\treturn sizeof(ControlType) + value.data().size_bytes();\n+\t/*\n+\t * Allocate extra space to save isArray and the number of elements, to\n+\t * support array-type ControlValues.\n+\t */\n+\treturn sizeof(ControlType) + sizeof(ControlValueHeader) +\n+\t value.data().size_bytes();\n }\n \n size_t ControlSerializer::binarySize(const ControlInfo &info)\n@@ -197,6 +202,13 @@ void ControlSerializer::store(const ControlValue &value,\n {\n \tconst ControlType type = value.type();\n \tbuffer.write(&type);\n+\n+\tControlValueHeader cvh = {\n+\t\tvalue.isArray(),\n+\t\tvalue.numElements(),\n+\t};\n+\tbuffer.write(&cvh);\n+\n \tbuffer.write(value.data());\n }\n \n@@ -368,6 +380,10 @@ int ControlSerializer::serialize(const ControlList &list,\n \t\tstruct ipa_control_value_entry entry;\n \t\tentry.id = id;\n \t\tentry.type = value.type();\n+\t\t/*\n+\t\t * .is_array and .count are now unused as these have been moved\n+\t\t * to ControlSerializer::store(const ControlValue &, ByteStreamBuffer &)\n+\t\t */\n \t\tentry.is_array = value.isArray();\n \t\tentry.count = value.numElements();\n \t\tentry.offset = values.offset();\n@@ -382,16 +398,16 @@ int ControlSerializer::serialize(const ControlList &list,\n \treturn 0;\n }\n \n-ControlValue ControlSerializer::loadControlValue(ByteStreamBuffer &buffer,\n-\t\t\t\t\t\t bool isArray,\n-\t\t\t\t\t\t unsigned int count)\n+ControlValue ControlSerializer::loadControlValue(ByteStreamBuffer &buffer)\n {\n \tControlType type;\n \tbuffer.read(&type);\n \n-\tControlValue value;\n+\tControlValueHeader cvh;\n+\tbuffer.read(&cvh);\n \n-\tvalue.reserve(type, isArray, count);\n+\tControlValue value;\n+\tvalue.reserve(type, cvh.isArray, cvh.numElements);\n \tbuffer.read(value.data());\n \n \treturn value;\n@@ -633,7 +649,7 @@ ControlList ControlSerializer::deserialize<ControlList>(ByteStreamBuffer &buffer\n \t\t}\n \n \t\tctrls.set(entry->id,\n-\t\t\t loadControlValue(values, entry->is_array, entry->count));\n+\t\t\t loadControlValue(values));\n \t}\n \n \treturn ctrls;\n", "prefixes": [ "v2", "1/2" ] }