Patch Detail
Show a patch.
GET /api/patches/22125/?format=api
{ "id": 22125, "url": "https://patchwork.libcamera.org/api/patches/22125/?format=api", "web_url": "https://patchwork.libcamera.org/patch/22125/", "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": "<20241127144655.1074720-2-isaac.scott@ideasonboard.com>", "date": "2024-11-27T14:46:54", "name": "[RFC,1/2] libcamera: bitdepth: Add BitDepth implementation", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "ca56c4623e03538ae69707ecc955285af1954627", "submitter": { "id": 215, "url": "https://patchwork.libcamera.org/api/people/215/?format=api", "name": "Isaac Scott", "email": "isaac.scott@ideasonboard.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/22125/mbox/", "series": [ { "id": 4830, "url": "https://patchwork.libcamera.org/api/series/4830/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=4830", "date": "2024-11-27T14:46:53", "name": "Add BitDepthValue for simplified bit depth conversion", "version": 1, "mbox": "https://patchwork.libcamera.org/series/4830/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/22125/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/22125/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 12759C3200\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 27 Nov 2024 14:47:11 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 909F9660E5;\n\tWed, 27 Nov 2024 15:47:08 +0100 (CET)", "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 71AAB660C6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 27 Nov 2024 15:47:04 +0100 (CET)", "from isaac-ThinkPad-T16-Gen-2.lan\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 47AF81230;\n\tWed, 27 Nov 2024 15:46:41 +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=\"EnYZwTcX\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1732718801;\n\tbh=qmLKoFdXCOTxCkS4DjH2PXsgg53UpRfNC7pxpZIgm4g=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=EnYZwTcX6W0jHpRTm2vpr3wCm9eP35Y975n6y1srVeAt77VEobFGNqbEdIU+zZnTU\n\tNgzv7/llyEB3+3FU1PIZM53HOZfPXRQ4kLZyw+ZDA+tsqeFE4P6EN4++2dkBQcf98+\n\tuGU+xZPxle2ifTioyuMq4mGoevztLLaHBeew96lk=", "From": "Isaac Scott <isaac.scott@ideasonboard.com>", "To": "libcamera devel <libcamera-devel@lists.libcamera.org>", "Cc": "Isaac Scott <isaac.scott@ideasonboard.com>", "Subject": "[RFC PATCH 1/2] libcamera: bitdepth: Add BitDepth implementation", "Date": "Wed, 27 Nov 2024 14:46:54 +0000", "Message-ID": "<20241127144655.1074720-2-isaac.scott@ideasonboard.com>", "X-Mailer": "git-send-email 2.43.0", "In-Reply-To": "<20241127144655.1074720-1-isaac.scott@ideasonboard.com>", "References": "<20241127144655.1074720-1-isaac.scott@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": "Add a class template that simplifies bit depth conversion. This\nfunctionality allows users to avoid having to perform inline bitshifting\nto convert values of one bit depth to another.\n\nFor example, this makes it easier to input values from datasheets, where\na value may be expressed in a certain bit depth. It also removes the\npotential for human errors when making these conversions manually, and\nin a lot of cases makes bit depth conversions more readable.\n\nSigned-off-by: Isaac Scott <isaac.scott@ideasonboard.com>\n---\n src/ipa/libipa/bitdepth.h | 86 ++++++++++++++++++++++++++++\n test/ipa/libipa/bitdepth.cpp | 107 +++++++++++++++++++++++++++++++++++\n 2 files changed, 193 insertions(+)\n create mode 100644 src/ipa/libipa/bitdepth.h\n create mode 100644 test/ipa/libipa/bitdepth.cpp", "diff": "diff --git a/src/ipa/libipa/bitdepth.h b/src/ipa/libipa/bitdepth.h\nnew file mode 100644\nindex 00000000..145ee093\n--- /dev/null\n+++ b/src/ipa/libipa/bitdepth.h\n@@ -0,0 +1,86 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2024 Ideas On Board Oy.\n+ *\n+ * BitDepth class to abstract bit shift operations\n+ */\n+\n+#pragma once\n+\n+template<unsigned int BitDepth>\n+class BitDepthValue\n+{\n+public:\n+\tstatic_assert(BitDepth > 0, \"Bit depth must be positive\");\n+\n+\tBitDepthValue()\n+\t\t: value_(0) {}\n+\n+\tBitDepthValue(int value)\n+\t\t: value_(value) {}\n+\n+\tBitDepthValue(unsigned int value)\n+\t\t: value_(value) {}\n+\n+\ttemplate<unsigned int TargetBitDepth>\n+\tBitDepthValue<TargetBitDepth> convert() const\n+\t{\n+\t\tstatic_assert(TargetBitDepth > 0, \"Bit depth must be positive\");\n+\n+\t\tunsigned int shift;\n+\n+\t\tif constexpr (BitDepth > TargetBitDepth) {\n+\t\t\tshift = BitDepth - TargetBitDepth;\n+\t\t\treturn BitDepthValue<TargetBitDepth>(value_ >> shift);\n+\t\t} else if constexpr (BitDepth < TargetBitDepth) {\n+\t\t\tshift = TargetBitDepth - BitDepth;\n+\t\t\treturn BitDepthValue<TargetBitDepth>(value_ << shift);\n+\t\t} else {\n+\t\t\treturn BitDepthValue<TargetBitDepth>(value_);\n+\t\t}\n+\t}\n+\n+\tunsigned int value() const\n+\t{\n+\t\treturn value_;\n+\t}\n+\n+\ttemplate<unsigned int TargetBitDepth>\n+\toperator BitDepthValue<TargetBitDepth>() const\n+\t{\n+\t\treturn convert<TargetBitDepth>();\n+\t}\n+\n+\toperator unsigned int() const\n+\t{\n+\t\treturn value_;\n+\t}\n+\n+private:\n+\tunsigned int value_;\n+};\n+\n+inline BitDepthValue<8> operator\"\" _8bit(unsigned long long value)\n+{\n+\treturn BitDepthValue<8>(static_cast<unsigned int>(value));\n+}\n+\n+inline BitDepthValue<10> operator\"\" _10bit(unsigned long long value)\n+{\n+\treturn BitDepthValue<10>(static_cast<unsigned int>(value));\n+}\n+\n+inline BitDepthValue<12> operator\"\" _12bit(unsigned long long value)\n+{\n+\treturn BitDepthValue<12>(static_cast<unsigned int>(value));\n+}\n+\n+inline BitDepthValue<14> operator\"\" _14bit(unsigned long long value)\n+{\n+\treturn BitDepthValue<14>(static_cast<unsigned int>(value));\n+}\n+\n+inline BitDepthValue<16> operator\"\" _16bit(unsigned long long value)\n+{\n+\treturn BitDepthValue<16>(static_cast<unsigned int>(value));\n+}\ndiff --git a/test/ipa/libipa/bitdepth.cpp b/test/ipa/libipa/bitdepth.cpp\nnew file mode 100644\nindex 00000000..d854637d\n--- /dev/null\n+++ b/test/ipa/libipa/bitdepth.cpp\n@@ -0,0 +1,107 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2024 Ideas On Board Oy.\n+ *\n+ * BitDepth converter tests\n+ */\n+\n+#include \"../../../src/ipa/libipa/bitdepth.h\"\n+\n+#include <cmath>\n+#include <iostream>\n+#include <map>\n+#include <stdint.h>\n+#include <stdio.h>\n+#include <stdlib.h>\n+\n+#include <libcamera/base/log.h>\n+\n+#include \"../../libtest/test.h\"\n+using namespace std;\n+\n+#define ASSERT_EQ(a, b) \\\n+\tif ((a) != (b)) { \\\n+\t\tprintf(#a \" != \" #b \"\\n\"); \\\n+\t\treturn TestFail; \\\n+\t}\n+\n+class BitDepthConverterTest : public Test\n+{\n+protected:\n+\tint run()\n+\t{\n+\t\t/* 10-bit to 16-bit conversion */\n+\t\tBitDepthValue<10> value10bit = 64_10bit;\n+\t\tBitDepthValue<16> value16bit = value10bit.convert<16>();\n+\t\tASSERT_EQ(value16bit.value(), 4096);\n+\n+\t\t/* Convert implicitly from another BitDepthValue */\n+\t\tvalue10bit = BitDepthValue<8>(16);\n+\t\tASSERT_EQ(value10bit.value(), 64);\n+\t\tvalue10bit = 1_8bit;\n+\t\tASSERT_EQ(value10bit.value(), 4);\n+\n+\t\t/* Read value explicity and implicitly */\n+\t\tvalue10bit = BitDepthValue<10>(64);\n+\t\tASSERT_EQ(value10bit.value(), 64);\n+\t\tASSERT_EQ(value10bit, 64);\n+\n+\t\t/* 12-bit to 8-bit conversion */\n+\t\tBitDepthValue<12> value12bit = 4096_12bit;\n+\t\tBitDepthValue<8> value8bit = value12bit.convert<8>();\n+\t\tASSERT_EQ(value8bit.value(), 256);\n+\n+\t\t/* Explicit bit depth assignment and conversion */\n+\t\tvalue16bit = 32768_16bit;\n+\t\tvalue12bit = value16bit.convert<12>();\n+\t\tASSERT_EQ(value12bit.value(), 2048);\n+\n+\t\t/* Test hex conversion */\n+\t\tvalue8bit = 0xFF_8bit;\n+\t\tASSERT_EQ(value8bit, 255);\n+\n+\t\t/* Test conversion to same bit depth makes no difference */\n+\t\tvalue16bit = 255_16bit;\n+\t\tvalue16bit = value16bit.convert<16>();\n+\t\tASSERT_EQ(value16bit, 255);\n+\n+\t\t/* Implicit bit depth assignment */\n+\t\tvalue12bit = 10;\n+\t\tASSERT_EQ(value12bit.value(), 10);\n+\n+\t\t/* 8-bit to 12-bit conversion */\n+\t\tvalue8bit = 128_8bit;\n+\t\tvalue12bit = value8bit.convert<12>();\n+\t\tASSERT_EQ(value12bit.value(), 2048);\n+\n+\t\t/* 16-bit to 8-bit conversion */\n+\t\tvalue16bit = 65535_16bit;\n+\t\tvalue8bit = value16bit.convert<8>();\n+\t\tASSERT_EQ(value8bit.value(), 255);\n+\n+\t\t/* Implicit assignment with int */\n+\t\tvalue8bit = 200;\n+\t\tASSERT_EQ(value8bit.value(), 200);\n+\n+\t\t/* 8-bit to 16-bit and back again */\n+\t\tvalue8bit = 150_8bit;\n+\t\tvalue16bit = value8bit.convert<16>();\n+\t\tvalue8bit = value16bit.convert<8>();\n+\t\tASSERT_EQ(value8bit.value(), 150);\n+\n+\t\t/* 12-bit to 16-bit and back again */\n+\t\tvalue12bit = 3000_12bit;\n+\t\tvalue16bit = value12bit.convert<16>();\n+\t\tASSERT_EQ(value12bit, 3000);\n+\t\tASSERT_EQ(value16bit, 48000)\n+\t\tvalue12bit = value16bit.convert<12>();\n+\t\tASSERT_EQ(value12bit.value(), 3000);\n+\n+\t\t/* Test negatives fail */\n+\t\t//value12bit = BitDepthValue<-1>;\n+\n+\t\treturn TestPass;\n+\t}\n+};\n+\n+TEST_REGISTER(BitDepthConverterTest)\n", "prefixes": [ "RFC", "1/2" ] }