Patch Detail
Show a patch.
GET /api/patches/26514/?format=api
{ "id": 26514, "url": "https://patchwork.libcamera.org/api/patches/26514/?format=api", "web_url": "https://patchwork.libcamera.org/patch/26514/", "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": "<20260408115645.12487-4-johannes.goede@oss.qualcomm.com>", "date": "2026-04-08T11:56:45", "name": "[RFC,3/3] camss: Add Offline Processing Engine ISP support", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "a339b1980cf110ffc57a7e763a50f06a578eff30", "submitter": { "id": 242, "url": "https://patchwork.libcamera.org/api/people/242/?format=api", "name": "Hans de Goede", "email": "johannes.goede@oss.qualcomm.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/26514/mbox/", "series": [ { "id": 5878, "url": "https://patchwork.libcamera.org/api/series/5878/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5878", "date": "2026-04-08T11:56:42", "name": "camss: Add CAMSS pipeline handler", "version": 1, "mbox": "https://patchwork.libcamera.org/series/5878/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/26514/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/26514/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 52C86BDCBD\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 8 Apr 2026 11:57:01 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id EB86962E48;\n\tWed, 8 Apr 2026 13:57:00 +0200 (CEST)", "from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com\n\t[205.220.180.131])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 50AF062E4B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 8 Apr 2026 13:56:58 +0200 (CEST)", "from pps.filterd (m0279870.ppops.net [127.0.0.1])\n\tby mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id\n\t6387K0mC2451717 for <libcamera-devel@lists.libcamera.org>;\n\tWed, 8 Apr 2026 11:56:57 GMT", "from mail-qt1-f198.google.com (mail-qt1-f198.google.com\n\t[209.85.160.198])\n\tby mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4ddae6ampm-1\n\t(version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT)\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 08 Apr 2026 11:56:57 +0000 (GMT)", "by mail-qt1-f198.google.com with SMTP id\n\td75a77b69052e-50d8ed08aa4so101260081cf.3\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 08 Apr 2026 04:56:56 -0700 (PDT)", "from t14s\n\t(2001-1c00-0c32-7800-07d4-cca3-ec08-7ac7.cable.dynamic.v6.ziggo.nl.\n\t[2001:1c00:c32:7800:7d4:cca3:ec08:7ac7])\n\tby smtp.gmail.com with ESMTPSA id\n\t4fb4d7f45d1cf-66e7b5ffa64sm3158932a12.21.2026.04.08.04.56.53\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tWed, 08 Apr 2026 04:56:54 -0700 (PDT)" ], "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (2048-bit key;\n\tunprotected) header.d=qualcomm.com header.i=@qualcomm.com\n\theader.b=\"ZVOsSSeC\"; dkim=pass (2048-bit key;\n\tunprotected) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com\n\theader.b=\"ZcF0J1ty\"; dkim-atps=neutral", "DKIM-Signature": [ "v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h=\n\tcc:content-transfer-encoding:date:from:in-reply-to:message-id\n\t:mime-version:references:subject:to; s=qcppdkim1; bh=eYcVgvkZPAu\n\tuUBNRpArbAVWpqRz82YVRKf3jVRDuwr4=; b=ZVOsSSeCPHJ5PgXkHjaqlyRGVtb\n\tAFFG2KLIDPMIPV1tOIeVUfl+3NRR8GS1K3DfEuqIMYSGvaCajiOZo12/K/t+2gAe\n\titMI7Kje87p5BYtaCD9z0O1oA9sY9++RPJVqScNJba9/vR9aa/PjWDBVd4Nz9fIx\n\tD6utqFVWb4R9oeltIKV/CC+ug+lP+stQcYVc2ejRUZvfvts4orPWHne3jLF2DkvM\n\tXPslHk4JCuKPQlW4n6aj4WFaN6NvNFpOUKS3DluPVLFf1czL+ImeivxtW9rywTqn\n\tDMCTXWdymLY7eR79dIiOHv11NCNKLFlsxt6d/B5/uFUgzXLSbAR+vvi1uow==", "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=oss.qualcomm.com; s=google; t=1775649416; x=1776254216;\n\tdarn=lists.libcamera.org; \n\th=content-transfer-encoding:mime-version:references:in-reply-to\n\t:message-id:date:subject:cc:to:from:from:to:cc:subject:date\n\t:message-id:reply-to;\n\tbh=eYcVgvkZPAuuUBNRpArbAVWpqRz82YVRKf3jVRDuwr4=;\n\tb=ZcF0J1tytZoJII+HmGJ+shHNWPsUoGbycCahSpibknIzpzuRlk5o/87tDFWGKcYKH3\n\tm6ToU9MYauRhemkIyiIgJCvk+OP8fPi3AV6VIWrEwwLl8JPtZ0tEkYk3Ks0iPQKU8LKA\n\tyWQiPktbT81bID0AYZzELhdYdRIAAcMTWX3ZO08cu5Vpli1ESU3IFEfkoI2+p6GyY+vy\n\tZawuWaCRG0bzC0yJpI82jEB1crRJ28rfHX/QHHxqx1BR9EDlcjwoWnz/bjFvrHzwvJW8\n\tQHUhx+myeIHNQF9L8qTFj/rLTF/jvr8xgYhb2D7qLoYZPEB+4EsyzI/UaMiOyWAEguxc\n\tsbDA==" ], "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20251104; t=1775649416; x=1776254216;\n\th=content-transfer-encoding:mime-version:references:in-reply-to\n\t:message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n\t:to:cc:subject:date:message-id:reply-to;\n\tbh=eYcVgvkZPAuuUBNRpArbAVWpqRz82YVRKf3jVRDuwr4=;\n\tb=oNtzqOE6W8a79lV5pqvPjZp6IaAy0Mjk6vhnEJY8fM+tZvHhfR2USvXOuTM89UoCy4\n\t9aRztwG4mpO52TlsbFneP/dXbG/kIJoVrfABHCaX8zTcJWXOU6AjIjN81YfsYmJ2Bgob\n\tfuHX8ILq8FsT+vduVGVOGTuwFHMVG1JruzGaTD7y0Q+5XYt6hApxf/fa9rK506HlLeyo\n\tG1fljH3M7eUjVs4HIeDeOxqcK7Kw5e1bshF7Tr6BgXUwM0RL9UJbwpSrn5kRolrbyZ1F\n\t/NBYvjqnAnYSrFj6OkDRhJMitY1Mvg1sljEi+olCnzH/xpPRRuYsgD+Y23rM005+RSCT\n\ttojw==", "X-Gm-Message-State": "AOJu0YxXRX8MW79lje8IilZr3agIbGhImLWOJrtT+VMA8yI1cA+fqN1+\n\t9rsLLBaIK21RxlzSIAT6maeGra3F+dQkgab7hk0XoSXE8Dr2ZwkP0SASwXJqglSIcgQHh+24LVt\n\tjo3Irz7yHah7wqd/17Ew5mUHToCB4L6yXFCm+N3Hl1/xCO1jO5TwN2nEXc7VXVf0bz7HULAlvCb\n\tq9c9kNlyyX", "X-Gm-Gg": "AeBDietxwf8UA1tOh5M7yBj4HiMRP3AxyC7oJ9LFzfOehC93Jji4NpqBA/spuVZsbvZ\n\tkp8GrGLh4UjWPPJwtIgOgk9cNElv7xZ6d3wtWaJvPXGY1htIxICKtTT1gRUZLl10qEfG8xTd5tY\n\tx1RWH2Y8+O9193LXIxK+88S7NYR2uLAk3WfZ0BGpLiAjvOJO/ekAEQGsplZUbnRvjKXSodggDSQ\n\tR/U9f+APIyAvMQQUwv+J24jGELVpoodLpejBw2oQTzSUbqXy2cntz5bhHAOsTdHS9XsCpiHLAs/\n\tybrh969zb+pkXpb2WyIss96r9AgAP8EBf5reOiii2GnovdFXqoyn0gUo/1ZHO6omVbJ7xUMtDzT\n\tGr6b/KjRZZlbqHrrJTrpkJ0fWWaizPE0orE33DZxPNMPgIaMGrj9g+ehksKAWL68A3/Oyhy21e2\n\tAI81sMsmK3qhyS3PzPhIzhiWay3dv09Taw", "X-Received": [ "by 2002:ac8:7fce:0:b0:50d:8dec:eb47 with SMTP id\n\td75a77b69052e-50d8decef8amr171604051cf.45.1775649416007; \n\tWed, 08 Apr 2026 04:56:56 -0700 (PDT)", "by 2002:ac8:7fce:0:b0:50d:8dec:eb47 with SMTP id\n\td75a77b69052e-50d8decef8amr171603801cf.45.1775649415493; \n\tWed, 08 Apr 2026 04:56:55 -0700 (PDT)" ], "From": "Hans de Goede <johannes.goede@oss.qualcomm.com>", "To": "libcamera-devel@lists.libcamera.org", "Cc": "Loic Poulain <loic.poulain@oss.qualcomm.com>,\n\tHans de Goede <johannes.goede@oss.qualcomm.com>", "Subject": "[RFC 3/3] camss: Add Offline Processing Engine ISP support", "Date": "Wed, 8 Apr 2026 13:56:45 +0200", "Message-ID": "<20260408115645.12487-4-johannes.goede@oss.qualcomm.com>", "X-Mailer": "git-send-email 2.53.0", "In-Reply-To": "<20260408115645.12487-1-johannes.goede@oss.qualcomm.com>", "References": "<20260408115645.12487-1-johannes.goede@oss.qualcomm.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "X-Proofpoint-Spam-Details-Enc": "AW1haW4tMjYwNDA4MDExMCBTYWx0ZWRfXzyCayiRkei0B\n\t2MG5Nnuj/7dwnxPxrLa2ap8SWjzxYjejVdhWUlpr7W32NcUHe237hqq0i/cgkauJ19yMO+S58KP\n\tv7NMdePB1nKc5xJPDhzV8J/TaQrwhvVGnqog1HGEZRthgmcbd7wUsa9BnsZ6quYpGTKmx08Rim7\n\tLriL2+PMQGxXRAt094aEAYEWJpWUuchr2qZn8Kqt+eG0+f6N1dgQW2y5MsE/bVOMd2ZpV3pAdBv\n\tsbvdq1srXPRnXwhXMj/wdn3pjqJNuuMvvo2yJBcdwDPgKtCNVbVPOf3C6XflvRz5LbkPISFkXZL\n\tosjpnOR/bitHqXC1dlfEP35lKwNNJhvkbno9EfyGXotG0gz3EW7aSesbGrY+slQep2Ug43fCjmz\n\ttNE3aDwH9q5FCX+3NOVh9vKqWJ+cJHEaazvW2/sxg9tph8120HLAKPHpdyGjsVUTSHLkC6L/wEC\n\tnn1CJAsG99e6JTVMMaw==", "X-Proofpoint-GUID": "MTotPAWfK0DtegnAyOb0Ydaq25anYu9k", "X-Proofpoint-ORIG-GUID": "MTotPAWfK0DtegnAyOb0Ydaq25anYu9k", "X-Authority-Analysis": "v=2.4 cv=K4AS2SWI c=1 sm=1 tr=0 ts=69d64289 cx=c_pps\n\ta=mPf7EqFMSY9/WdsSgAYMbA==:117 a=xqWC_Br6kY4A:10 a=A5OVakUREuEA:10\n\ta=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22\n\ta=gowsoOTTUOVcmtlkKump:22 a=VwQbUJbxAAAA:8 a=EUspDBNiAAAA:8\n\ta=rV9jgqLbh9YbgK17brIA:9 a=dawVfQjAaf238kedN5IG:22", "X-Proofpoint-Virus-Version": "vendor=baseguard\n\tengine=ICAP:2.0.293, Aquarius:18.0.1143, Hydra:6.1.51,\n\tFMLib:17.12.100.49\n\tdefinitions=2026-04-08_03,2026-04-08_01,2025-10-01_01", "X-Proofpoint-Spam-Details": "rule=outbound_notspam policy=outbound score=0\n\tpriorityscore=1501 impostorscore=0 lowpriorityscore=0 clxscore=1015\n\tphishscore=0 malwarescore=0 spamscore=0 bulkscore=0 adultscore=0\n\tsuspectscore=0 classifier=typeunknown authscore=0 authtc= authcc=\n\troute=outbound adjust=0 reason=mlx scancount=1\n\tengine=8.22.0-2604010000\n\tdefinitions=main-2604080110", "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": "This adds support for the OPE through the RFC OPE M2M kernel driver\nposted upstream recently.\n\nThe M2M OPE kernel driver is mainly a RFC driver and this driver will\nneed to be changed into a proper ISP driver with e.g. a second /dev/video#\ninput node for passing parameter-buffers to the ISP.\n\nLikewise this libcamera OPE support should mostly be seen as a proof\nof concept of the CamssIsp virtual base class abstraction and this will\nneed to change / evolve to also grow an IPA and parameter buffer support\nas the kernel driver evolves.\n\nLink: https://lore.kernel.org/linux-media/20260323125824.211615-1-loic.poulain@oss.qualcomm.com/\nSigned-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>\n---\n .../converter/converter_v4l2_m2m.cpp | 1 +\n src/libcamera/pipeline/camss/camss.cpp | 12 +-\n .../pipeline/camss/camss_isp_ope.cpp | 229 ++++++++++++++++++\n src/libcamera/pipeline/camss/camss_isp_ope.h | 59 +++++\n src/libcamera/pipeline/camss/meson.build | 1 +\n 5 files changed, 298 insertions(+), 4 deletions(-)\n create mode 100644 src/libcamera/pipeline/camss/camss_isp_ope.cpp\n create mode 100644 src/libcamera/pipeline/camss/camss_isp_ope.h", "diff": "diff --git a/src/libcamera/converter/converter_v4l2_m2m.cpp b/src/libcamera/converter/converter_v4l2_m2m.cpp\nindex ffba0434e..b705b56e8 100644\n--- a/src/libcamera/converter/converter_v4l2_m2m.cpp\n+++ b/src/libcamera/converter/converter_v4l2_m2m.cpp\n@@ -818,6 +818,7 @@ bool V4L2M2MConverter::supportsRequests()\n static std::initializer_list<std::string> compatibles = {\n \t\"mtk-mdp\",\n \t\"pxp\",\n+\t\"qcom-camss-ope\",\n };\n \n REGISTER_CONVERTER(\"v4l2_m2m\", V4L2M2MConverter, compatibles)\ndiff --git a/src/libcamera/pipeline/camss/camss.cpp b/src/libcamera/pipeline/camss/camss.cpp\nindex 90d7b681e..51951ab20 100644\n--- a/src/libcamera/pipeline/camss/camss.cpp\n+++ b/src/libcamera/pipeline/camss/camss.cpp\n@@ -38,6 +38,7 @@\n #include \"camss_csi.h\"\n #include \"camss_frames.h\"\n #include \"camss_isp.h\"\n+#include \"camss_isp_ope.h\"\n #include \"camss_isp_soft.h\"\n \n namespace libcamera {\n@@ -571,10 +572,13 @@ bool PipelineHandlerCamss::match(DeviceEnumerator *enumerator)\n \t\tdata->delayedCtrls_ =\n \t\t\tstd::make_unique<DelayedControls>(sensor->device(), params);\n \n-\t\tdata->isp_ = std::make_unique<CamssIspSoft>(this, sensor, &data->controlInfo_);\n-\t\tif (!data->isp_->isValid()) {\n-\t\t\tLOG(Camss, Error) << \"Failed to create software ISP\";\n-\t\t\tcontinue;\n+\t\tdata->isp_ = CamssIspOpe::match(this, enumerator, sensor, &data->controlInfo_);\n+\t\tif (data->isp_ == nullptr) {\n+\t\t\tdata->isp_ = std::make_unique<CamssIspSoft>(this, sensor, &data->controlInfo_);\n+\t\t\tif (!data->isp_->isValid()) {\n+\t\t\t\tLOG(Camss, Error) << \"Failed to create software ISP\";\n+\t\t\t\tcontinue;\n+\t\t\t}\n \t\t}\n \n \t\tdata->isp_->inputBufferReady.connect(data->csi_.get(),\ndiff --git a/src/libcamera/pipeline/camss/camss_isp_ope.cpp b/src/libcamera/pipeline/camss/camss_isp_ope.cpp\nnew file mode 100644\nindex 000000000..7d9a831cb\n--- /dev/null\n+++ b/src/libcamera/pipeline/camss/camss_isp_ope.cpp\n@@ -0,0 +1,229 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Qualcomm CAMSS OPE ISP class\n+ *\n+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.\n+ */\n+\n+#include \"camss_isp_ope.h\"\n+\n+#include <libcamera/base/log.h>\n+\n+#include <libcamera/controls.h>\n+#include <libcamera/geometry.h>\n+#include <libcamera/request.h>\n+#include <libcamera/stream.h>\n+\n+#include \"libcamera/internal/camera_sensor.h\"\n+#include \"libcamera/internal/converter.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/v4l2_subdevice.h\"\n+#include \"libcamera/internal/v4l2_videodevice.h\"\n+\n+namespace libcamera {\n+\n+LOG_DECLARE_CATEGORY(Camss)\n+\n+/**\n+ * \\class CamssIspOpe\n+ * \\brief CAMSS ISP class for the Offline Processing Engine (OPE) ISP\n+ */\n+\n+/**\n+ * \\brief Constructs CamssIspOpe object\n+ * \\param[in] pipe The pipeline handler in use\n+ * \\param[in] sensor Pointer to the CameraSensor instance owned by the pipeline\n+ * \\param[out] ControlInfoMap to which to add ISP provided controls\n+ */\n+CamssIspOpe::CamssIspOpe([[maybe_unused]] PipelineHandler *pipe, const CameraSensor *sensor, [[maybe_unused]] ControlInfoMap *ispControls)\n+\t: sensor_(sensor)\n+{\n+#if 0\n+\tswIsp_ = std::make_unique<SoftwareIsp>(pipe, sensor, ispControls);\n+\n+\tswIsp_->ispStatsReady.connect(this,\n+\t\t\t\t [&](uint32_t frame, uint32_t bufferId) {\n+\t\t\t\t\t\tstatsReady.emit(frame, bufferId);\n+\t\t\t\t });\n+\tswIsp_->metadataReady.connect(this,\n+\t\t\t\t [&](uint32_t frame, const ControlList &metadata) {\n+\t\t\t\t\t\tmetadataReady.emit(frame, metadata);\n+\t\t\t\t });\n+\tswIsp_->setSensorControls.connect(this,\n+\t\t\t\t\t [&](const ControlList &sensorControls) {\n+\t\t\t\t\t\tsetSensorControls.emit(sensorControls);\n+\t\t\t\t\t });\n+#endif\n+}\n+\n+CamssIspOpe::~CamssIspOpe() = default;\n+\n+bool CamssIspOpe::isValid()\n+{\n+\treturn true;\n+}\n+\n+StreamConfiguration CamssIspOpe::generateConfiguration(const StreamConfiguration &raw) const\n+{\n+\t/* Converters support the same size-ranges for all output formats */\n+\tstd::vector<PixelFormat> pixelFormats = converter_->formats(raw.pixelFormat);\n+\tSizeRange sizes = converter_->sizes(raw.size);\n+\n+\tif (sizes.max.isNull() || pixelFormats.empty())\n+\t\treturn {};\n+\n+\tstd::vector<SizeRange> sizesVector = { sizes };\n+\tstd::map<PixelFormat, std::vector<SizeRange>> formats;\n+\n+\tfor (unsigned int i = 0; i < pixelFormats.size(); i++)\n+\t\tformats[pixelFormats[i]] = sizesVector;\n+\n+\tStreamConfiguration cfg{ StreamFormats{ formats } };\n+\tcfg.size = sizes.max;\n+\tcfg.pixelFormat = pixelFormats[0];\n+\tcfg.bufferCount = kBufferCount;\n+\n+\treturn cfg;\n+}\n+\n+namespace {\n+\n+/*\n+ * \\todo copy-pasted from src/libcamera/pipeline/simple/simple.cpp turn this\n+ * into a member of SizeRange ?\n+ */\n+static Size adjustSize(const Size &requestedSize, const SizeRange &supportedSizes)\n+{\n+\tASSERT(supportedSizes.min <= supportedSizes.max);\n+\n+\tif (supportedSizes.min == supportedSizes.max)\n+\t\treturn supportedSizes.max;\n+\n+\tunsigned int hStep = supportedSizes.hStep;\n+\tunsigned int vStep = supportedSizes.vStep;\n+\n+\tif (hStep == 0)\n+\t\thStep = supportedSizes.max.width - supportedSizes.min.width;\n+\tif (vStep == 0)\n+\t\tvStep = supportedSizes.max.height - supportedSizes.min.height;\n+\n+\tSize adjusted = requestedSize.boundedTo(supportedSizes.max)\n+\t\t\t\t.expandedTo(supportedSizes.min);\n+\n+\treturn adjusted.shrunkBy(supportedSizes.min)\n+\t\t.alignedDownTo(hStep, vStep)\n+\t\t.grownBy(supportedSizes.min);\n+}\n+\n+} /* namespace */\n+\n+StreamConfiguration CamssIspOpe::validate(const StreamConfiguration &raw, const StreamConfiguration &req) const\n+{\n+\tStreamConfiguration cfg;\n+\n+\tstd::vector<PixelFormat> formats = converter_->formats(raw.pixelFormat);\n+\tSizeRange sizes = converter_->sizes(raw.size);\n+\n+\tcfg.size = adjustSize(req.size, sizes);\n+\n+\tif (cfg.size.isNull() || formats.empty())\n+\t\treturn {};\n+\n+\tfor (unsigned int i = 0; i < formats.size(); i++) {\n+\t\tif (formats[i] == req.pixelFormat)\n+\t\t\tcfg.pixelFormat = req.pixelFormat;\n+\t}\n+\n+\tif (!cfg.pixelFormat.isValid())\n+\t\tcfg.pixelFormat = formats[0];\n+\n+\tstd::tie(cfg.stride, cfg.frameSize) =\n+\t\tconverter_->strideAndFrameSize(cfg.pixelFormat, cfg.size);\n+\n+\tcfg.bufferCount = std::max(kBufferCount, req.bufferCount);\n+\tcfg.setStream(const_cast<Stream *>(&outStream_));\n+\n+\treturn cfg;\n+}\n+\n+int CamssIspOpe::configure(const StreamConfiguration &inputCfg,\n+\t\t\t const StreamConfiguration &outputCfg)\n+{\n+\tstd::vector<std::reference_wrapper<const StreamConfiguration>> outputCfgs;\n+\toutputCfgs.push_back(outputCfg);\n+\n+\tint ret = converter_->configure(inputCfg, outputCfgs);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tconverter_->inputBufferReady.connect(this,\n+\t\t\t\t\t [&](FrameBuffer *f) { inputBufferReady.emit(f); });\n+\tconverter_->outputBufferReady.connect(this,\n+\t\t\t\t\t [&](FrameBuffer *f) {\n+\t\t\t\t\t\t // HACK FIXME\n+\t\t\t\t\t\t metadataReady.emit(f->metadata().sequence, {});\n+\t\t\t\t\t\t outputBufferReady.emit(f);\n+\t\t\t\t\t });\n+\n+\treturn 0;\n+}\n+\n+int CamssIspOpe::exportOutputBuffers(const Stream *stream, unsigned int count,\n+\t\t\t\t std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n+{\n+\treturn converter_->exportBuffers(stream, count, buffers);\n+}\n+\n+void CamssIspOpe::queueBuffers(Request *request, FrameBuffer *input)\n+{\n+\tstd::map<const Stream *, FrameBuffer *> outputs;\n+\tfor (const auto &[stream, outbuffer] : request->buffers()) {\n+\t\tif (stream == &outStream_)\n+\t\t\toutputs[stream] = outbuffer;\n+\t}\n+\n+\t//\tswIsp_->queueRequest(request->sequence(), request->controls());\n+\tconverter_->queueBuffers(input, outputs);\n+}\n+\n+void CamssIspOpe::processStats([[maybe_unused]] const uint32_t frame, [[maybe_unused]] const uint32_t bufferId,\n+\t\t\t [[maybe_unused]] const ControlList &sensorControls)\n+{\n+\t//\tswIsp_->processStats(frame, bufferId, sensorControls);\n+}\n+\n+int CamssIspOpe::start()\n+{\n+\treturn converter_->start();\n+}\n+\n+void CamssIspOpe::stop()\n+{\n+\tconverter_->stop();\n+}\n+\n+std::unique_ptr<CamssIspOpe> CamssIspOpe::match(PipelineHandler *pipe,\n+\t\t\t\t\t\tDeviceEnumerator *enumerator,\n+\t\t\t\t\t\tconst CameraSensor *sensor,\n+\t\t\t\t\t\tControlInfoMap *ispControls)\n+{\n+\tstd::unique_ptr<CamssIspOpe> ope = std::make_unique<CamssIspOpe>(pipe, sensor, ispControls);\n+\n+\tDeviceMatch opeDm(\"qcom-camss-ope\");\n+\n+\tope->opeMediaDev_ = pipe->acquireMediaDevice(enumerator, opeDm);\n+\tif (!ope->opeMediaDev_)\n+\t\treturn nullptr;\n+\n+\tope->converter_ = ConverterFactoryBase::create(ope->opeMediaDev_);\n+\tif (!ope->converter_)\n+\t\treturn nullptr;\n+\n+\tLOG(Camss, Info) << \"Using OPE for \" << sensor->entity()->name();\n+\n+\treturn ope;\n+}\n+\n+} /* namespace libcamera */\ndiff --git a/src/libcamera/pipeline/camss/camss_isp_ope.h b/src/libcamera/pipeline/camss/camss_isp_ope.h\nnew file mode 100644\nindex 000000000..4324e4c0a\n--- /dev/null\n+++ b/src/libcamera/pipeline/camss/camss_isp_ope.h\n@@ -0,0 +1,59 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Qualcomm CAMSS OPE ISP class\n+ *\n+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.\n+ */\n+\n+#pragma once\n+\n+#include <memory>\n+#include <vector>\n+\n+#include \"camss_isp.h\"\n+\n+namespace libcamera {\n+\n+class CameraSensor;\n+class ControlInfoMap;\n+class Converter;\n+class DeviceEnumerator;\n+class MediaDevice;\n+class PipelineHandler;\n+class SoftwareIsp;\n+\n+class CamssIspOpe : public CamssIsp\n+{\n+public:\n+\tstatic std::unique_ptr<CamssIspOpe> match(PipelineHandler *pipe,\n+\t\t\t\t\t\t DeviceEnumerator *enumerator,\n+\t\t\t\t\t\t const CameraSensor *sensor,\n+\t\t\t\t\t\t ControlInfoMap *ispControls);\n+\n+\tCamssIspOpe(PipelineHandler *pipe, const CameraSensor *sensor, ControlInfoMap *ispControls);\n+\t~CamssIspOpe() override;\n+\n+\tbool isValid() override;\n+\n+\tStreamConfiguration generateConfiguration(const StreamConfiguration &raw) const override;\n+\tStreamConfiguration validate(const StreamConfiguration &raw, const StreamConfiguration &req) const override;\n+\tint configure(const StreamConfiguration &inputCfg,\n+\t\t const StreamConfiguration &outputCfg) override;\n+\n+\tint exportOutputBuffers(const Stream *stream, unsigned int count,\n+\t\t\t\tstd::vector<std::unique_ptr<FrameBuffer>> *buffers) override;\n+\tvoid queueBuffers(Request *request, FrameBuffer *input) override;\n+\n+\tvoid processStats(const uint32_t frame, const uint32_t bufferId,\n+\t\t\t const ControlList &sensorControls) override;\n+\n+\tint start() override;\n+\tvoid stop() override;\n+\n+private:\n+\tstd::shared_ptr<MediaDevice> opeMediaDev_;\n+\tstd::unique_ptr<Converter> converter_;\n+\tconst CameraSensor *sensor_;\n+};\n+\n+} /* namespace libcamera */\ndiff --git a/src/libcamera/pipeline/camss/meson.build b/src/libcamera/pipeline/camss/meson.build\nindex 047559789..36478cf7d 100644\n--- a/src/libcamera/pipeline/camss/meson.build\n+++ b/src/libcamera/pipeline/camss/meson.build\n@@ -5,5 +5,6 @@ libcamera_internal_sources += files([\n 'camss_csi.cpp',\n 'camss_frames.cpp',\n 'camss_isp.cpp',\n+ 'camss_isp_ope.cpp',\n 'camss_isp_soft.cpp',\n ])\n", "prefixes": [ "RFC", "3/3" ] }