Show a patch.

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

{
    "id": 18012,
    "url": "https://patchwork.libcamera.org/api/patches/18012/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/18012/",
    "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": "<20221214155218.419497-2-xavier.roumegue@oss.nxp.com>",
    "date": "2022-12-14T15:52:18",
    "name": "[libcamera-devel,v5,2/2] libcamera: pipeline: simple: converter: Use generic converter interface",
    "commit_ref": "5a8271ad70fb30460aa0aefb85fbaca484fceb01",
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "7d774648ab51113791348ea468e1de577fc52435",
    "submitter": {
        "id": 107,
        "url": "https://patchwork.libcamera.org/api/people/107/?format=api",
        "name": "Xavier Roumegue",
        "email": "xavier.roumegue@oss.nxp.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/18012/mbox/",
    "series": [
        {
            "id": 3673,
            "url": "https://patchwork.libcamera.org/api/series/3673/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=3673",
            "date": "2022-12-14T15:52:17",
            "name": "[libcamera-devel,v5,1/2] libcamera: Declare generic converter interface",
            "version": 5,
            "mbox": "https://patchwork.libcamera.org/series/3673/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/18012/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/18012/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 52F26C328E\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 14 Dec 2022 15:52:41 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6EA9A6335E;\n\tWed, 14 Dec 2022 16:52:40 +0100 (CET)",
            "from EUR03-VI1-obe.outbound.protection.outlook.com\n\t(mail-vi1eur03on2084.outbound.protection.outlook.com [40.107.103.84])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id E8E2A63354\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 14 Dec 2022 16:52:37 +0100 (CET)",
            "from PAXPR04MB8703.eurprd04.prod.outlook.com\n\t(2603:10a6:102:21e::22)\n\tby DU0PR04MB9694.eurprd04.prod.outlook.com (2603:10a6:10:312::8) with\n\tMicrosoft SMTP Server (version=TLS1_2,\n\tcipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5880.14;\n\tWed, 14 Dec 2022 15:52:34 +0000",
            "from PAXPR04MB8703.eurprd04.prod.outlook.com\n\t([fe80::14d3:8e4:cf07:810d]) by\n\tPAXPR04MB8703.eurprd04.prod.outlook.com\n\t([fe80::14d3:8e4:cf07:810d%3]) with mapi id 15.20.5880.019;\n\tWed, 14 Dec 2022 15:52:34 +0000"
        ],
        "DKIM-Signature": [
            "v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1671033160;\n\tbh=asBEg9gu/6xz561UUWgnChpzK4x7mHo658WhVKwaZ/o=;\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:Cc:\n\tFrom;\n\tb=GqGSyUsDuA9oHg7VOc925+Fo9zkv3bQLrnSEwGidxK+MusyvolFAludSC2/KMvHkT\n\tdEImkjiET6vnDHiL4O8j3JZo+5JNQU53Xum5LmzUVgwI1euRz5eYLC2/jZzYCqg1p2\n\tuJX80SGAJ7kZIHs5cyu58KiT+ypU0D1EQUvyAfq9n/Ui0S3CJ8imXeQXQX6nnPSaOA\n\trgUeKegsriubLGzbFdqFH9umSo60PsSfMS9TZzCAqYsbKfK/qyfHioS0gWqRs/+hcq\n\t42Td+oGlttgHO89K/zPRu53nSzRNS8nkTVswettA/RQBY5WSQdzozZWKnSPnFW/4NB\n\txWtv5UlVAcnrg==",
            "v=1; a=rsa-sha256; c=relaxed/relaxed; d=NXP1.onmicrosoft.com;\n\ts=selector2-NXP1-onmicrosoft-com;\n\th=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n\tbh=o4JZjBUhhllRAwizgfQIWWv6qMtEq+ttX0q3VpWkPzI=;\n\tb=NvP6B1ziggXsSPt/igkNZyjmCtVnU+bXbsaaW6FYN0NJcHD8iZRarzixSNUnGD9V7ET0WGcHeqvObNDA/aN+BBODQrf6NsQhtLTLcvWaUGVChaECNDPl3OSbUo4VJl61z2js8Jeb2WXj1mzFp/pkoLXY7J5GtRio4NjbdQswB0c="
        ],
        "Authentication-Results": [
            "lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=NXP1.onmicrosoft.com\n\theader.i=@NXP1.onmicrosoft.com\n\theader.b=\"NvP6B1zi\"; dkim-atps=neutral",
            "dkim=none (message not signed)\n\theader.d=none;dmarc=none action=none header.from=oss.nxp.com;"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n\tb=aK9VkVzDbNnSBE+Ka2JdN1BZ4bg380yIpxZUq+HbMWWWSaMcU8h6FhyeAJFKvzb6uKiwmq2LjXPa0H6uReGDJK3OjOmybfngfc+VZRHIyuLQ/TI4Z0MlurwHv5ZgkTBkXS41IT1LuIDnSWsiKajW7gd52gUZYBrJ6ltPD4iPMPYK/hMSfM/KGUTb4lHYbipQCM7IbmLwJ9UfA3/yCeU2JWbRC43m8lLpARJBcNlN7lUPIkyHt0IrUwpB59fqWNyobd/T+MuRWxM1yBKIDFeQTDkfGcmL7zsOoP2ODzbES9R6JYOqIc4PD7Y+xNArMUZoJD7tiMij/cUb4fPcpORx4w==",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;\n\ts=arcselector9901;\n\th=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;\n\tbh=o4JZjBUhhllRAwizgfQIWWv6qMtEq+ttX0q3VpWkPzI=;\n\tb=BjfiFpqEjaOaropZlUFLp/Ym/s/pPjO2Dvn+iKNL9lt5Np4m/VeIHLrXD+YhfuXkC3nnhfZcYsnBluuPMyxuer3J4dWwitbgdl/78Fe9YpFhYrc5BVKXHCgb8CaCvcf4yd+IzOtCxGW1DPNa/UzfrTgoBRZ96jqoCOreraEA01MO8vlvNo8pBXEU3sa3PuZFUwLOYfzKR9TIW0yRhtr4gfx6rt7MrfNd/kF3t/9b/WtTuEVL8CV7WUq2bdzgUN5IDD0BFGkwqNtSIwUDTXJNB8dIUqgSbNd4DEokfx9z3hN4sIV3uEt6a5Wr0w2zhZpFchJigGHvnUQImADFFnJt5g==",
        "ARC-Authentication-Results": "i=1; mx.microsoft.com 1; spf=pass\n\tsmtp.mailfrom=oss.nxp.com;\n\tdmarc=pass action=none header.from=oss.nxp.com; \n\tdkim=pass header.d=oss.nxp.com; arc=none",
        "To": "jacopo@jmondi.org, laurent.pinchart@ideasonboard.com,\n\tkieran.bingham@ideasonboard.com",
        "Date": "Wed, 14 Dec 2022 16:52:18 +0100",
        "Message-Id": "<20221214155218.419497-2-xavier.roumegue@oss.nxp.com>",
        "X-Mailer": "git-send-email 2.38.1",
        "In-Reply-To": "<20221214155218.419497-1-xavier.roumegue@oss.nxp.com>",
        "References": "<20221214155218.419497-1-xavier.roumegue@oss.nxp.com>",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain",
        "X-ClientProxiedBy": "PA7P264CA0049.FRAP264.PROD.OUTLOOK.COM\n\t(2603:10a6:102:34a::7) To PAXPR04MB8703.eurprd04.prod.outlook.com\n\t(2603:10a6:102:21e::22)",
        "MIME-Version": "1.0",
        "X-MS-Exchange-MessageSentRepresentingType": "1",
        "X-MS-PublicTrafficType": "Email",
        "X-MS-TrafficTypeDiagnostic": "PAXPR04MB8703:EE_|DU0PR04MB9694:EE_",
        "X-MS-Office365-Filtering-Correlation-Id": "05362614-4694-4b0a-2c44-08daddeb373a",
        "X-MS-Exchange-SharedMailbox-RoutingAgent-Processed": "True",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "BCL:0;",
        "X-Microsoft-Antispam-Message-Info": "mt+2xTrEUA3o8QTo3yFPWCIKGMNUAF5hmOk304kQvtRonKGw6ft0/lr503932g+kkKKCaCNvFo7mZOl5OERUHg4JMEOnk6FdXcBSPNIgx4mXDPpM1SKs1IcJzBpYh14aqnc/cigxeW1qgkz7T7ol7XYFJCJe6rh734RxRNAYBkB1bY8JNGMYz/1XZUAnQNZlNDDhiH/ReLI/pAEZ3P+60iv7aN5Zrky2qd+ULRrMZUL7bmVQPr+4Dsba0jNE39+9Ev9Ywv3NCH2slLGzwqtdHCAROhp92mtfJ2jLVunZVg3FAmEvCcf7AVnI52+YFUm//y8KhrML9lO8P3ktdrpJP6MxFtO/X0etZ1XSLTX7SuRsBfCYKoLf8wHVoCcCKw8SG6ijGC4tcnosaVu3Lib5dq/06W4Bkc1MhJP6M9VWaBHqlsPGYUMaidxzZeeiHKnWV4clrI61RNgQs84BdSMULpfdAPDNExwTROYXPi3lsuiWYTR1OYlPqEpNojayB5yZbDDzjPVGTNue51zLnyOCjuOjERAYiG+T4180JlOZX4623ixKONDRU4geWDvMSSJDqi+Stf1chk9U4r6PoLthRYb0S+haGx51dDPcJoGr8mDwBmIoiU+U2buZQCZMYcKDngrACldBUuZmLTcqNwFscJCxW3Xk140fVjqZ5OAMivFGUXh/KYsYoyx0E49PuRsq",
        "X-Forefront-Antispam-Report": "CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:;\n\tIPV:NLI; SFV:NSPM; H:PAXPR04MB8703.eurprd04.prod.outlook.com; PTR:;\n\tCAT:NONE; \n\tSFS:(13230022)(4636009)(396003)(39860400002)(346002)(366004)(136003)(376002)(451199015)(6666004)(86362001)(52116002)(6486002)(38100700002)(6506007)(478600001)(6512007)(83380400001)(2906002)(8936002)(316002)(186003)(66556008)(66476007)(1076003)(66946007)(5660300002)(44832011)(41300700001)(2616005)(4326008)(8676002)(30864003)(41533002);\n\tDIR:OUT; SFP:1101; ",
        "X-MS-Exchange-AntiSpam-MessageData-ChunkCount": "1",
        "X-MS-Exchange-AntiSpam-MessageData-0": "s3Rk0D15v/z3FhJY3a1XqfYLZRwViDVpBOugN2P6i4F3XFgL7TFQeBAP8icoV5+43q9owvOxEizhBBSJKXvIgSzBVe+97kd9OfhmnloziWB0JXVngax0+PJWEwoFxou6y2bwQNQHYXqfICpOACsdZOsZz/EHHJF09hxa5tL5nRaeLu3WVORLaqBqdgYMEXiEEAt85MW+ktml1xyDLlprkq6s0z77KelTrOUP7Za18niCQK3poDcyMqfnx/D0aOwFfPJkvytyGsQRXfeP+nxjS/JNu2K8wGctiSxQ/hj2nwItLg5iiHte/wfp3OgzE5tQVpr2sTSPa1jcHzNfP/55fF6Tvq8ZJJGc7XNBWvE3P0f/NOc0YrG15hiATJO/mlGplZAqdLvD4dqqNqaJpuHA1CkF/tj7KW2yJfmUHQ7Z9J1CQQo7ogJY0/iewQeJ29zj2EwAJoZ0Jikctnn1k0Au42bOAJhcaeQX7UBs1Gjxl/gb+bhY1L652zugV8Lcmwk1KRWvscoe/MXEr5s42d7ovQ9rZrolzmEr/TSuIneZsdIoC+BRrbIIf6SWMTLWlFRMfkC8eP92yzoyXAm4LP0OyxjsCJHQuBfoCUgtWhf/OV1krb0JkG0787ELnOp9f3MdEd4JMpVXGvbuEtGAPTw45PoiQa26XQEdDL8Y5kM5eDj7ZZisGxyU/SuHmzV+c3AJldU2QVwFLXOf+kJ/cnNVQQx3hknSm8r/7jFoIUgGMscfphvBchhpsGEcifbucTPxCXxBn+c7DklcPAOgArtflUp9AQm7aFKO8LdSj6v/rwrnBLK9Q+ViOqfBb5TZJcWS50URGsK8pUDKPmKC3OiOSrA1pmZlHCGatENcSVRcL59oFcP3canuANBfZbMW9xcIE0rcKmvQ5np3USv/OWNmnLHEvxJbsPFaTTy9gTiJGRznhugBj66YG0ol7nl7lh6HFzOSF/Ogi9VCk/3UCSCfAWpwf8K5pZpalj/QfQwZUDDvZafXujibIjZ7X2AZGuc3XkslxB9wNUNS3SSWmkqRwQ4aIPhAxNrmyjvwwKSCaHlxm4hhTm/txtKr07gWz5dLxlnmd/RT0frwXUW6NLFZ2EWOstGtEMbaxa4LTRDwRFOczTYpP90iL8Qheb49ZiR9Lvwlywobafc9Sy/gkjefiHs/wqnCMrUxhafZi5nU9L4HPQjC73159TAbH/JH1revsXKoasG2K4XMse+PLtUgpsQajr69uE6jlnlbswld3URLPesfcjF5qutNSd2BTsW8iVFeMuOYRsYf0JiJ4kcTUcO7FKdbabhbVTqGxj1Nz8eAljibcCpxibBfz4fU+FSUcEdOHhsAcpl/LXnQXXtM/zwpYRxAkhNv6ad727h+DH31nqHgLXbM53WyzbOqWLjdMa+kT13sLgWO3+unKNyUxDqg+UPRGjbny1XwqFj5azA4lUpAtRTBku5oYnLUbtZuNtm0LJdA/FqDTZMYIBkI2N6kfO77FRvSRSl/W3XGltGLKbrMZeP6aobi1RQYC84ttWsEuqtVUNdp93s3RXVHRvhoMUi1JZYZ4HgKyU3qztBF/mVt65yltNULeDjKFXunLzAGcoTp4HPK4RCrH68X2lmdQwV2rmQveKukhHszXN173CmBfJ0UXGegC+WjKYRzQkrjlwnKKZPzxAo6XuESmA==",
        "X-OriginatorOrg": "oss.nxp.com",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "05362614-4694-4b0a-2c44-08daddeb373a",
        "X-MS-Exchange-CrossTenant-AuthSource": "PAXPR04MB8703.eurprd04.prod.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Internal",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "14 Dec 2022 15:52:34.2302\n\t(UTC)",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "Hosted",
        "X-MS-Exchange-CrossTenant-Id": "686ea1d3-bc2b-4c6f-a92c-d99c5c301635",
        "X-MS-Exchange-CrossTenant-MailboxType": "HOSTED",
        "X-MS-Exchange-CrossTenant-UserPrincipalName": "B5Ek7OuYCp6166HZ26JcYRvt9PsvGTN9MxwaVzT0kPMYxMYY5F8Y1/oGTGnk+G9V30RQRXUlezDXjOcqEVNNkw==",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "DU0PR04MB9694",
        "Subject": "[libcamera-devel] [PATCH v5 2/2] libcamera: pipeline: simple:\n\tconverter: Use generic converter interface",
        "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": "Xavier Roumegue via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>",
        "Reply-To": "Xavier Roumegue <xavier.roumegue@oss.nxp.com>",
        "Cc": "libcamera-devel@lists.libcamera.org",
        "Errors-To": "libcamera-devel-bounces@lists.libcamera.org",
        "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"
    },
    "content": "Move the simple converter implementation to a generic V4L2 M2M class\nderived from the converter interface. This latter could be used by\nother pipeline implementations and as base class for customized V4L2 M2M\nconverters.\n\nSigned-off-by: Xavier Roumegue <xavier.roumegue@oss.nxp.com>\nReviewed-by: Jacopo Mondi <jacopo@jmondi.org>\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n---\n .../internal/converter/converter_v4l2_m2m.h   |  22 +--\n .../libcamera/internal/converter/meson.build  |   5 +\n include/libcamera/internal/meson.build        |   2 +\n .../converter_v4l2_m2m.cpp}                   | 156 ++++++++++++------\n src/libcamera/converter/meson.build           |   5 +\n src/libcamera/meson.build                     |   1 +\n src/libcamera/pipeline/simple/meson.build     |   1 -\n src/libcamera/pipeline/simple/simple.cpp      |   6 +-\n 8 files changed, 129 insertions(+), 69 deletions(-)\n rename src/libcamera/pipeline/simple/converter.h => include/libcamera/internal/converter/converter_v4l2_m2m.h (83%)\n create mode 100644 include/libcamera/internal/converter/meson.build\n rename src/libcamera/{pipeline/simple/converter.cpp => converter/converter_v4l2_m2m.cpp} (67%)\n create mode 100644 src/libcamera/converter/meson.build",
    "diff": "diff --git a/src/libcamera/pipeline/simple/converter.h b/include/libcamera/internal/converter/converter_v4l2_m2m.h\nsimilarity index 83%\nrename from src/libcamera/pipeline/simple/converter.h\nrename to include/libcamera/internal/converter/converter_v4l2_m2m.h\nindex f0ebe2e0..815916d0 100644\n--- a/src/libcamera/pipeline/simple/converter.h\n+++ b/include/libcamera/internal/converter/converter_v4l2_m2m.h\n@@ -1,8 +1,9 @@\n /* SPDX-License-Identifier: LGPL-2.1-or-later */\n /*\n  * Copyright (C) 2020, Laurent Pinchart\n+ * Copyright 2022 NXP\n  *\n- * converter.h - Format converter for simple pipeline handler\n+ * converter_v4l2_m2m.h - V4l2 M2M Format converter interface\n  */\n \n #pragma once\n@@ -14,11 +15,13 @@\n #include <tuple>\n #include <vector>\n \n-#include <libcamera/pixel_format.h>\n-\n #include <libcamera/base/log.h>\n #include <libcamera/base/signal.h>\n \n+#include <libcamera/pixel_format.h>\n+\n+#include \"libcamera/internal/converter.h\"\n+\n namespace libcamera {\n \n class FrameBuffer;\n@@ -28,11 +31,12 @@ class SizeRange;\n struct StreamConfiguration;\n class V4L2M2MDevice;\n \n-class SimpleConverter\n+class V4L2M2MConverter : public Converter\n {\n public:\n-\tSimpleConverter(MediaDevice *media);\n+\tV4L2M2MConverter(MediaDevice *media);\n \n+\tint loadConfiguration([[maybe_unused]] const std::string &filename) { return 0; }\n \tbool isValid() const { return m2m_ != nullptr; }\n \n \tstd::vector<PixelFormat> formats(PixelFormat input);\n@@ -52,14 +56,11 @@ public:\n \tint queueBuffers(FrameBuffer *input,\n \t\t\t const std::map<unsigned int, FrameBuffer *> &outputs);\n \n-\tSignal<FrameBuffer *> inputBufferReady;\n-\tSignal<FrameBuffer *> outputBufferReady;\n-\n private:\n \tclass Stream : protected Loggable\n \t{\n \tpublic:\n-\t\tStream(SimpleConverter *converter, unsigned int index);\n+\t\tStream(V4L2M2MConverter *converter, unsigned int index);\n \n \t\tbool isValid() const { return m2m_ != nullptr; }\n \n@@ -80,7 +81,7 @@ private:\n \t\tvoid captureBufferReady(FrameBuffer *buffer);\n \t\tvoid outputBufferReady(FrameBuffer *buffer);\n \n-\t\tSimpleConverter *converter_;\n+\t\tV4L2M2MConverter *converter_;\n \t\tunsigned int index_;\n \t\tstd::unique_ptr<V4L2M2MDevice> m2m_;\n \n@@ -88,7 +89,6 @@ private:\n \t\tunsigned int outputBufferCount_;\n \t};\n \n-\tstd::string deviceNode_;\n \tstd::unique_ptr<V4L2M2MDevice> m2m_;\n \n \tstd::vector<Stream> streams_;\ndiff --git a/include/libcamera/internal/converter/meson.build b/include/libcamera/internal/converter/meson.build\nnew file mode 100644\nindex 00000000..891e79e7\n--- /dev/null\n+++ b/include/libcamera/internal/converter/meson.build\n@@ -0,0 +1,5 @@\n+# SPDX-License-Identifier: CC0-1.0\n+\n+libcamera_internal_headers += files([\n+    'converter_v4l2_m2m.h',\n+])\ndiff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build\nindex 341af8a2..d7508805 100644\n--- a/include/libcamera/internal/meson.build\n+++ b/include/libcamera/internal/meson.build\n@@ -45,3 +45,5 @@ libcamera_internal_headers = files([\n     'v4l2_videodevice.h',\n     'yaml_parser.h',\n ])\n+\n+subdir('converter')\ndiff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/converter/converter_v4l2_m2m.cpp\nsimilarity index 67%\nrename from src/libcamera/pipeline/simple/converter.cpp\nrename to src/libcamera/converter/converter_v4l2_m2m.cpp\nindex acaaa64c..2a4d1d99 100644\n--- a/src/libcamera/pipeline/simple/converter.cpp\n+++ b/src/libcamera/converter/converter_v4l2_m2m.cpp\n@@ -1,11 +1,12 @@\n /* SPDX-License-Identifier: LGPL-2.1-or-later */\n /*\n  * Copyright (C) 2020, Laurent Pinchart\n+ * Copyright 2022 NXP\n  *\n- * converter.cpp - Format converter for simple pipeline handler\n+ * converter_v4l2_m2m.cpp - V4L2 M2M Format converter\n  */\n \n-#include \"converter.h\"\n+#include \"libcamera/internal/converter/converter_v4l2_m2m.h\"\n \n #include <algorithm>\n #include <limits.h>\n@@ -21,18 +22,23 @@\n #include \"libcamera/internal/media_device.h\"\n #include \"libcamera/internal/v4l2_videodevice.h\"\n \n+/**\n+ * \\file internal/converter/converter_v4l2_m2m.h\n+ * \\brief V4L2 M2M based converter\n+ */\n+\n namespace libcamera {\n \n-LOG_DECLARE_CATEGORY(SimplePipeline)\n+LOG_DECLARE_CATEGORY(Converter)\n \n /* -----------------------------------------------------------------------------\n- * SimpleConverter::Stream\n+ * V4L2M2MConverter::Stream\n  */\n \n-SimpleConverter::Stream::Stream(SimpleConverter *converter, unsigned int index)\n+V4L2M2MConverter::Stream::Stream(V4L2M2MConverter *converter, unsigned int index)\n \t: converter_(converter), index_(index)\n {\n-\tm2m_ = std::make_unique<V4L2M2MDevice>(converter->deviceNode_);\n+\tm2m_ = std::make_unique<V4L2M2MDevice>(converter->deviceNode());\n \n \tm2m_->output()->bufferReady.connect(this, &Stream::outputBufferReady);\n \tm2m_->capture()->bufferReady.connect(this, &Stream::captureBufferReady);\n@@ -42,8 +48,8 @@ SimpleConverter::Stream::Stream(SimpleConverter *converter, unsigned int index)\n \t\tm2m_.reset();\n }\n \n-int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg,\n-\t\t\t\t       const StreamConfiguration &outputCfg)\n+int V4L2M2MConverter::Stream::configure(const StreamConfiguration &inputCfg,\n+\t\t\t\t\tconst StreamConfiguration &outputCfg)\n {\n \tV4L2PixelFormat videoFormat =\n \t\tm2m_->output()->toV4L2PixelFormat(inputCfg.pixelFormat);\n@@ -56,14 +62,14 @@ int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg,\n \n \tint ret = m2m_->output()->setFormat(&format);\n \tif (ret < 0) {\n-\t\tLOG(SimplePipeline, Error)\n+\t\tLOG(Converter, Error)\n \t\t\t<< \"Failed to set input format: \" << strerror(-ret);\n \t\treturn ret;\n \t}\n \n \tif (format.fourcc != videoFormat || format.size != inputCfg.size ||\n \t    format.planes[0].bpl != inputCfg.stride) {\n-\t\tLOG(SimplePipeline, Error)\n+\t\tLOG(Converter, Error)\n \t\t\t<< \"Input format not supported (requested \"\n \t\t\t<< inputCfg.size << \"-\" << videoFormat\n \t\t\t<< \", got \" << format << \")\";\n@@ -78,13 +84,13 @@ int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg,\n \n \tret = m2m_->capture()->setFormat(&format);\n \tif (ret < 0) {\n-\t\tLOG(SimplePipeline, Error)\n+\t\tLOG(Converter, Error)\n \t\t\t<< \"Failed to set output format: \" << strerror(-ret);\n \t\treturn ret;\n \t}\n \n \tif (format.fourcc != videoFormat || format.size != outputCfg.size) {\n-\t\tLOG(SimplePipeline, Error)\n+\t\tLOG(Converter, Error)\n \t\t\t<< \"Output format not supported\";\n \t\treturn -EINVAL;\n \t}\n@@ -95,13 +101,13 @@ int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg,\n \treturn 0;\n }\n \n-int SimpleConverter::Stream::exportBuffers(unsigned int count,\n-\t\t\t\t\t   std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n+int V4L2M2MConverter::Stream::exportBuffers(unsigned int count,\n+\t\t\t\t\t    std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n {\n \treturn m2m_->capture()->exportBuffers(count, buffers);\n }\n \n-int SimpleConverter::Stream::start()\n+int V4L2M2MConverter::Stream::start()\n {\n \tint ret = m2m_->output()->importBuffers(inputBufferCount_);\n \tif (ret < 0)\n@@ -128,7 +134,7 @@ int SimpleConverter::Stream::start()\n \treturn 0;\n }\n \n-void SimpleConverter::Stream::stop()\n+void V4L2M2MConverter::Stream::stop()\n {\n \tm2m_->capture()->streamOff();\n \tm2m_->output()->streamOff();\n@@ -136,8 +142,7 @@ void SimpleConverter::Stream::stop()\n \tm2m_->output()->releaseBuffers();\n }\n \n-int SimpleConverter::Stream::queueBuffers(FrameBuffer *input,\n-\t\t\t\t\t  FrameBuffer *output)\n+int V4L2M2MConverter::Stream::queueBuffers(FrameBuffer *input, FrameBuffer *output)\n {\n \tint ret = m2m_->output()->queueBuffer(input);\n \tif (ret < 0)\n@@ -150,12 +155,12 @@ int SimpleConverter::Stream::queueBuffers(FrameBuffer *input,\n \treturn 0;\n }\n \n-std::string SimpleConverter::Stream::logPrefix() const\n+std::string V4L2M2MConverter::Stream::logPrefix() const\n {\n \treturn \"stream\" + std::to_string(index_);\n }\n \n-void SimpleConverter::Stream::outputBufferReady(FrameBuffer *buffer)\n+void V4L2M2MConverter::Stream::outputBufferReady(FrameBuffer *buffer)\n {\n \tauto it = converter_->queue_.find(buffer);\n \tif (it == converter_->queue_.end())\n@@ -167,32 +172,34 @@ void SimpleConverter::Stream::outputBufferReady(FrameBuffer *buffer)\n \t}\n }\n \n-void SimpleConverter::Stream::captureBufferReady(FrameBuffer *buffer)\n+void V4L2M2MConverter::Stream::captureBufferReady(FrameBuffer *buffer)\n {\n \tconverter_->outputBufferReady.emit(buffer);\n }\n \n /* -----------------------------------------------------------------------------\n- * SimpleConverter\n+ * V4L2M2MConverter\n+ */\n+\n+/**\n+ * \\class libcamera::V4L2M2MConverter\n+ * \\brief The V4L2 M2M converter implements the converter interface based on\n+ * V4L2 M2M device.\n+*/\n+\n+/**\n+ * \\fn V4L2M2MConverter::V4L2M2MConverter\n+ * \\brief Construct a V4L2M2MConverter instance\n+ * \\param[in] media The media device implementing the converter\n  */\n \n-SimpleConverter::SimpleConverter(MediaDevice *media)\n+V4L2M2MConverter::V4L2M2MConverter(MediaDevice *media)\n+\t: Converter(media)\n {\n-\t/*\n-\t * Locate the video node. There's no need to validate the pipeline\n-\t * further, the caller guarantees that this is a V4L2 mem2mem device.\n-\t */\n-\tconst std::vector<MediaEntity *> &entities = media->entities();\n-\tauto it = std::find_if(entities.begin(), entities.end(),\n-\t\t\t       [](MediaEntity *entity) {\n-\t\t\t\t       return entity->function() == MEDIA_ENT_F_IO_V4L;\n-\t\t\t       });\n-\tif (it == entities.end())\n+\tif (deviceNode().empty())\n \t\treturn;\n \n-\tdeviceNode_ = (*it)->deviceNode();\n-\n-\tm2m_ = std::make_unique<V4L2M2MDevice>(deviceNode_);\n+\tm2m_ = std::make_unique<V4L2M2MDevice>(deviceNode());\n \tint ret = m2m_->open();\n \tif (ret < 0) {\n \t\tm2m_.reset();\n@@ -200,7 +207,21 @@ SimpleConverter::SimpleConverter(MediaDevice *media)\n \t}\n }\n \n-std::vector<PixelFormat> SimpleConverter::formats(PixelFormat input)\n+/**\n+ * \\fn libcamera::V4L2M2MConverter::loadConfiguration\n+ * \\details \\copydetails libcamera::Converter::loadConfiguration\n+ */\n+\n+/**\n+ * \\fn libcamera::V4L2M2MConverter::isValid\n+ * \\details \\copydetails libcamera::Converter::isValid\n+ */\n+\n+/**\n+ * \\fn libcamera::V4L2M2MConverter::formats\n+ * \\details \\copydetails libcamera::Converter::formats\n+ */\n+std::vector<PixelFormat> V4L2M2MConverter::formats(PixelFormat input)\n {\n \tif (!m2m_)\n \t\treturn {};\n@@ -215,13 +236,13 @@ std::vector<PixelFormat> SimpleConverter::formats(PixelFormat input)\n \n \tint ret = m2m_->output()->setFormat(&v4l2Format);\n \tif (ret < 0) {\n-\t\tLOG(SimplePipeline, Error)\n+\t\tLOG(Converter, Error)\n \t\t\t<< \"Failed to set format: \" << strerror(-ret);\n \t\treturn {};\n \t}\n \n \tif (v4l2Format.fourcc != m2m_->output()->toV4L2PixelFormat(input)) {\n-\t\tLOG(SimplePipeline, Debug)\n+\t\tLOG(Converter, Debug)\n \t\t\t<< \"Input format \" << input << \" not supported.\";\n \t\treturn {};\n \t}\n@@ -237,7 +258,10 @@ std::vector<PixelFormat> SimpleConverter::formats(PixelFormat input)\n \treturn pixelFormats;\n }\n \n-SizeRange SimpleConverter::sizes(const Size &input)\n+/**\n+ * \\copydoc libcamera::Converter::sizes\n+ */\n+SizeRange V4L2M2MConverter::sizes(const Size &input)\n {\n \tif (!m2m_)\n \t\treturn {};\n@@ -252,7 +276,7 @@ SizeRange SimpleConverter::sizes(const Size &input)\n \n \tint ret = m2m_->output()->setFormat(&format);\n \tif (ret < 0) {\n-\t\tLOG(SimplePipeline, Error)\n+\t\tLOG(Converter, Error)\n \t\t\t<< \"Failed to set format: \" << strerror(-ret);\n \t\treturn {};\n \t}\n@@ -262,7 +286,7 @@ SizeRange SimpleConverter::sizes(const Size &input)\n \tformat.size = { 1, 1 };\n \tret = m2m_->capture()->setFormat(&format);\n \tif (ret < 0) {\n-\t\tLOG(SimplePipeline, Error)\n+\t\tLOG(Converter, Error)\n \t\t\t<< \"Failed to set format: \" << strerror(-ret);\n \t\treturn {};\n \t}\n@@ -272,7 +296,7 @@ SizeRange SimpleConverter::sizes(const Size &input)\n \tformat.size = { UINT_MAX, UINT_MAX };\n \tret = m2m_->capture()->setFormat(&format);\n \tif (ret < 0) {\n-\t\tLOG(SimplePipeline, Error)\n+\t\tLOG(Converter, Error)\n \t\t\t<< \"Failed to set format: \" << strerror(-ret);\n \t\treturn {};\n \t}\n@@ -282,9 +306,12 @@ SizeRange SimpleConverter::sizes(const Size &input)\n \treturn sizes;\n }\n \n+/**\n+ * \\copydoc libcamera::Converter::strideAndFrameSize\n+ */\n std::tuple<unsigned int, unsigned int>\n-SimpleConverter::strideAndFrameSize(const PixelFormat &pixelFormat,\n-\t\t\t\t    const Size &size)\n+V4L2M2MConverter::strideAndFrameSize(const PixelFormat &pixelFormat,\n+\t\t\t\t     const Size &size)\n {\n \tV4L2DeviceFormat format;\n \tformat.fourcc = m2m_->capture()->toV4L2PixelFormat(pixelFormat);\n@@ -297,8 +324,11 @@ SimpleConverter::strideAndFrameSize(const PixelFormat &pixelFormat,\n \treturn std::make_tuple(format.planes[0].bpl, format.planes[0].size);\n }\n \n-int SimpleConverter::configure(const StreamConfiguration &inputCfg,\n-\t\t\t       const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs)\n+/**\n+ * \\copydoc libcamera::Converter::configure\n+ */\n+int V4L2M2MConverter::configure(const StreamConfiguration &inputCfg,\n+\t\t\t\tconst std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs)\n {\n \tint ret = 0;\n \n@@ -309,7 +339,7 @@ int SimpleConverter::configure(const StreamConfiguration &inputCfg,\n \t\tStream &stream = streams_.emplace_back(this, i);\n \n \t\tif (!stream.isValid()) {\n-\t\t\tLOG(SimplePipeline, Error)\n+\t\t\tLOG(Converter, Error)\n \t\t\t\t<< \"Failed to create stream \" << i;\n \t\t\tret = -EINVAL;\n \t\t\tbreak;\n@@ -328,8 +358,11 @@ int SimpleConverter::configure(const StreamConfiguration &inputCfg,\n \treturn 0;\n }\n \n-int SimpleConverter::exportBuffers(unsigned int output, unsigned int count,\n-\t\t\t\t   std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n+/**\n+ * \\copydoc libcamera::Converter::exportBuffers\n+ */\n+int V4L2M2MConverter::exportBuffers(unsigned int output, unsigned int count,\n+\t\t\t\t    std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n {\n \tif (output >= streams_.size())\n \t\treturn -EINVAL;\n@@ -337,7 +370,10 @@ int SimpleConverter::exportBuffers(unsigned int output, unsigned int count,\n \treturn streams_[output].exportBuffers(count, buffers);\n }\n \n-int SimpleConverter::start()\n+/**\n+ * \\copydoc libcamera::Converter::start\n+ */\n+int V4L2M2MConverter::start()\n {\n \tint ret;\n \n@@ -352,14 +388,20 @@ int SimpleConverter::start()\n \treturn 0;\n }\n \n-void SimpleConverter::stop()\n+/**\n+ * \\copydoc libcamera::Converter::stop\n+ */\n+void V4L2M2MConverter::stop()\n {\n \tfor (Stream &stream : utils::reverse(streams_))\n \t\tstream.stop();\n }\n \n-int SimpleConverter::queueBuffers(FrameBuffer *input,\n-\t\t\t\t  const std::map<unsigned int, FrameBuffer *> &outputs)\n+/**\n+ * \\copydoc libcamera::Converter::queueBuffers\n+ */\n+int V4L2M2MConverter::queueBuffers(FrameBuffer *input,\n+\t\t\t\t   const std::map<unsigned int, FrameBuffer *> &outputs)\n {\n \tunsigned int mask = 0;\n \tint ret;\n@@ -402,4 +444,10 @@ int SimpleConverter::queueBuffers(FrameBuffer *input,\n \treturn 0;\n }\n \n+static std::initializer_list<std::string> compatibles = {\n+\t\"pxp\",\n+};\n+\n+REGISTER_CONVERTER(\"v4l2_m2m\", V4L2M2MConverter, compatibles)\n+\n } /* namespace libcamera */\ndiff --git a/src/libcamera/converter/meson.build b/src/libcamera/converter/meson.build\nnew file mode 100644\nindex 00000000..2aa72fe4\n--- /dev/null\n+++ b/src/libcamera/converter/meson.build\n@@ -0,0 +1,5 @@\n+# SPDX-License-Identifier: CC0-1.0\n+\n+libcamera_sources += files([\n+        'converter_v4l2_m2m.cpp'\n+])\ndiff --git a/src/libcamera/meson.build b/src/libcamera/meson.build\nindex e9d0324e..ffc294f3 100644\n--- a/src/libcamera/meson.build\n+++ b/src/libcamera/meson.build\n@@ -62,6 +62,7 @@ libatomic = cc.find_library('atomic', required : false)\n libthreads = dependency('threads')\n \n subdir('base')\n+subdir('converter')\n subdir('ipa')\n subdir('pipeline')\n subdir('proxy')\ndiff --git a/src/libcamera/pipeline/simple/meson.build b/src/libcamera/pipeline/simple/meson.build\nindex 9c99b32f..42b0896d 100644\n--- a/src/libcamera/pipeline/simple/meson.build\n+++ b/src/libcamera/pipeline/simple/meson.build\n@@ -1,6 +1,5 @@\n # SPDX-License-Identifier: CC0-1.0\n \n libcamera_sources += files([\n-    'converter.cpp',\n     'simple.cpp',\n ])\ndiff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp\nindex a32de7f3..24ded4db 100644\n--- a/src/libcamera/pipeline/simple/simple.cpp\n+++ b/src/libcamera/pipeline/simple/simple.cpp\n@@ -30,13 +30,13 @@\n \n #include \"libcamera/internal/camera.h\"\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-#include \"converter.h\"\n \n namespace libcamera {\n \n@@ -266,7 +266,7 @@ public:\n \tstd::vector<Configuration> configs_;\n \tstd::map<PixelFormat, std::vector<const Configuration *>> formats_;\n \n-\tstd::unique_ptr<SimpleConverter> converter_;\n+\tstd::unique_ptr<Converter> converter_;\n \tstd::vector<std::unique_ptr<FrameBuffer>> converterBuffers_;\n \tbool useConverter_;\n \tstd::queue<std::map<unsigned int, FrameBuffer *>> converterQueue_;\n@@ -492,7 +492,7 @@ int SimpleCameraData::init()\n \t/* Open the converter, if any. */\n \tMediaDevice *converter = pipe->converter();\n \tif (converter) {\n-\t\tconverter_ = std::make_unique<SimpleConverter>(converter);\n+\t\tconverter_ = ConverterFactoryBase::create(converter);\n \t\tif (!converter_->isValid()) {\n \t\t\tLOG(SimplePipeline, Warning)\n \t\t\t\t<< \"Failed to create converter, disabling format conversion\";\n",
    "prefixes": [
        "libcamera-devel",
        "v5",
        "2/2"
    ]
}