Show a patch.

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

{
    "id": 16888,
    "url": "https://patchwork.libcamera.org/api/patches/16888/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/16888/",
    "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": "<20220801000543.3501-12-laurent.pinchart@ideasonboard.com>",
    "date": "2022-08-01T00:05:41",
    "name": "[libcamera-devel,11/13] libcamera: pipeline: simple: Walk pipeline using subdev internal routing",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "375527cb605d4b18669829b2cb6f872484468e7c",
    "submitter": {
        "id": 2,
        "url": "https://patchwork.libcamera.org/api/people/2/?format=api",
        "name": "Laurent Pinchart",
        "email": "laurent.pinchart@ideasonboard.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/16888/mbox/",
    "series": [
        {
            "id": 3352,
            "url": "https://patchwork.libcamera.org/api/series/3352/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=3352",
            "date": "2022-08-01T00:05:30",
            "name": "libcamera: pipeline: simple: Support the NXP i.MX8 ISI",
            "version": 1,
            "mbox": "https://patchwork.libcamera.org/series/3352/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/16888/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/16888/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 9E9A4BE173\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon,  1 Aug 2022 00:06:06 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 5CF1663334;\n\tMon,  1 Aug 2022 02:06:06 +0200 (CEST)",
            "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 67B696332B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  1 Aug 2022 02:06:04 +0200 (CEST)",
            "from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id F27709AA;\n\tMon,  1 Aug 2022 02:06:03 +0200 (CEST)"
        ],
        "DKIM-Signature": [
            "v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1659312366;\n\tbh=Q0ycWuajOKqpBySnWU4MdW4Tobq1XcuKtocizErXEy0=;\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:\n\tFrom;\n\tb=2btSRQt1xXIlbZ02AxQF+e8N/U5+Xcfkug7YfjFF8Ghu9GTSZOMNTH0eb/yJXzePI\n\tOxl8gdCRu6rn20rvqolH0F6/7Noqe2W/2UNnspgodxAm9p3rOW6TEvoI6EsOPy7646\n\tzHapPLfJSZqoOTYZTxIJLS57rg5oj6qv4gzCwVuAkyq3kN8Obq93sJNuLk5sQHCCcI\n\tBxf84tCabd0B+zvVhKb8xEIkE2onFSTqNnG3VMHY/vntnd8JN05YKLiznARVODZvkN\n\tsyC6aWcsDsjZKMa0cc+qp2wvNGYnuQc/xxRbq1AdZGSg5AIDSncAm75jV8gUasMDRq\n\tApitYVpX+FxpQ==",
            "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1659312364;\n\tbh=Q0ycWuajOKqpBySnWU4MdW4Tobq1XcuKtocizErXEy0=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=J1HM0qlB9skTTze6CIqTJYySmg0zdDze+fzwyhq3NqaI/dX1kR6lO0sHMOC50BhLJ\n\tKtX8983pSnzl64MYcWMe5l4RWOsySv7EwXui96nSNfiGoEPYLA29Wlelw0PH8C1zRs\n\tauLAAIeDUTxMs6KuvMMBGS/ORJPeS4oXWmNxAe/U="
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"J1HM0qlB\"; dkim-atps=neutral",
        "To": "libcamera-devel@lists.libcamera.org",
        "Date": "Mon,  1 Aug 2022 03:05:41 +0300",
        "Message-Id": "<20220801000543.3501-12-laurent.pinchart@ideasonboard.com>",
        "X-Mailer": "git-send-email 2.35.1",
        "In-Reply-To": "<20220801000543.3501-1-laurent.pinchart@ideasonboard.com>",
        "References": "<20220801000543.3501-1-laurent.pinchart@ideasonboard.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[libcamera-devel] [PATCH 11/13] libcamera: pipeline: simple: Walk\n\tpipeline using subdev internal routing",
        "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": "Laurent Pinchart via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>",
        "Reply-To": "Laurent Pinchart <laurent.pinchart@ideasonboard.com>",
        "Errors-To": "libcamera-devel-bounces@lists.libcamera.org",
        "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"
    },
    "content": "From: Phi-Bang Nguyen <pnguyen@baylibre.com>\n\nWhen traversing the media graph to discover a pipeline from the camera\nsensor to a video node, all sink-to-source paths inside subdevs are\nconsidered. This can lead to invalid paths being followed, when a subdev\nhas restrictions on its internal routing.\n\nThe V4L2 API supports exposing subdev internal routing to userspace.\nMake use if this feature, when implemented by a subdev, to restrict the\ninternal paths to the currently active routes. If a subdev doesn't\nimplement the internal routing operations, all source pads are\nconsidered, as done today.\n\nThis change is needed to properly support multiple sensors with devices\nsuch as the NXP i.MX8 ISI or the MediaTek i350 and i500 SENINF. Support\nfor changing routes dynamically will be added later when required.\n\nSigned-off-by: Phi-Bang Nguyen <pnguyen@baylibre.com>\nSigned-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n---\n src/libcamera/pipeline/simple/simple.cpp | 73 ++++++++++++++++++++++--\n 1 file changed, 67 insertions(+), 6 deletions(-)",
    "diff": "diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp\nindex 4bde9caa7254..2a8811183907 100644\n--- a/src/libcamera/pipeline/simple/simple.cpp\n+++ b/src/libcamera/pipeline/simple/simple.cpp\n@@ -100,8 +100,14 @@ LOG_DEFINE_CATEGORY(SimplePipeline)\n  *\n  * During the breadth-first search, the pipeline is traversed from entity to\n  * entity, by following media graph links from source to sink, starting at the\n- * camera sensor. When reaching an entity (on its sink side), all its source\n- * pads are considered to continue the graph traversal.\n+ * camera sensor.\n+ *\n+ * When reaching an entity (on its sink side), if the entity is a V4L2 subdev\n+ * that supports the streams API, the subdev internal routes are followed to\n+ * find the connected source pads. Otherwise all of the entity's source pads\n+ * are considered to continue the graph traversal. The pipeline handler\n+ * currently considers the default internal routes only and doesn't attempt to\n+ * setup custom routes. This can be extended if needed.\n  *\n  * The shortest path between the camera sensor and a video node is stored in\n  * SimpleCameraData::entities_ as a list of SimpleCameraData::Entity structures,\n@@ -261,6 +267,7 @@ public:\n \n private:\n \tvoid tryPipeline(unsigned int code, const Size &size);\n+\tstatic std::vector<const MediaPad *> routedSourcePads(MediaPad *sink);\n \n \tvoid converterInputDone(FrameBuffer *buffer);\n \tvoid converterOutputDone(FrameBuffer *buffer);\n@@ -387,12 +394,29 @@ SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe,\n \t\t\tbreak;\n \t\t}\n \n-\t\t/* The actual breadth-first search algorithm. */\n \t\tvisited.insert(entity);\n-\t\tfor (MediaPad *pad : entity->pads()) {\n-\t\t\tif (!(pad->flags() & MEDIA_PAD_FL_SOURCE))\n-\t\t\t\tcontinue;\n \n+\t\t/*\n+\t\t * Add direct downstream entities to the search queue. If the\n+\t\t * current entity supports the subdev internal routing API,\n+\t\t * restrict the search to downstream entities reachable through\n+\t\t * active routes.\n+\t\t */\n+\n+\t\tstd::vector<const MediaPad *> pads;\n+\n+\t\tif (sinkPad)\n+\t\t\tpads = routedSourcePads(sinkPad);\n+\n+\t\tif (pads.empty()) {\n+\t\t\tfor (const MediaPad *pad : entity->pads()) {\n+\t\t\t\tif (!(pad->flags() & MEDIA_PAD_FL_SOURCE))\n+\t\t\t\t\tcontinue;\n+\t\t\t\tpads.push_back(pad);\n+\t\t\t}\n+\t\t}\n+\n+\t\tfor (const MediaPad *pad : pads) {\n \t\t\tfor (MediaLink *link : pad->links()) {\n \t\t\t\tMediaEntity *next = link->sink()->entity();\n \t\t\t\tif (visited.find(next) == visited.end()) {\n@@ -782,6 +806,43 @@ void SimpleCameraData::converterOutputDone(FrameBuffer *buffer)\n \t\tpipe->completeRequest(request);\n }\n \n+/* Retrieve all source pads connected to a sink pad through active routes. */\n+std::vector<const MediaPad *> SimpleCameraData::routedSourcePads(MediaPad *sink)\n+{\n+\tMediaEntity *entity = sink->entity();\n+\tstd::unique_ptr<V4L2Subdevice> subdev =\n+\t\tstd::make_unique<V4L2Subdevice>(entity);\n+\n+\tint ret = subdev->open();\n+\tif (ret < 0)\n+\t\treturn {};\n+\n+\tV4L2Subdevice::Routing routing = {};\n+\tret = subdev->getRouting(&routing, V4L2Subdevice::ActiveFormat);\n+\tif (ret < 0)\n+\t\treturn {};\n+\n+\tstd::vector<const MediaPad *> pads;\n+\n+\tfor (const struct v4l2_subdev_route &route : routing) {\n+\t\tif (sink->index() != route.sink_pad ||\n+\t\t    !(route.flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE))\n+\t\t\tcontinue;\n+\n+\t\tconst MediaPad *pad = entity->getPadByIndex(route.source_pad);\n+\t\tif (!pad) {\n+\t\t\tLOG(SimplePipeline, Warning)\n+\t\t\t\t<< \"Entity \" << entity->name()\n+\t\t\t\t<< \" has invalid route source pad \"\n+\t\t\t\t<< route.source_pad;\n+\t\t}\n+\n+\t\tpads.push_back(pad);\n+\t}\n+\n+\treturn pads;\n+}\n+\n /* -----------------------------------------------------------------------------\n  * Camera Configuration\n  */\n",
    "prefixes": [
        "libcamera-devel",
        "11/13"
    ]
}