{"id":23105,"url":"https://patchwork.libcamera.org/api/1.1/patches/23105/?format=json","web_url":"https://patchwork.libcamera.org/patch/23105/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/1.1/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20250402073919.183330-4-paul.elder@ideasonboard.com>","date":"2025-04-02T07:39:18","name":"[v4,3/3] libcamera: pipeline: rkisp1: Convert to use MediaPipeline","commit_ref":null,"pull_url":null,"state":"accepted","archived":false,"hash":"8fd4c20189b50c95965be67dd2e4ce65c923ddd8","submitter":{"id":17,"url":"https://patchwork.libcamera.org/api/1.1/people/17/?format=json","name":"Paul Elder","email":"paul.elder@ideasonboard.com"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/23105/mbox/","series":[{"id":5105,"url":"https://patchwork.libcamera.org/api/1.1/series/5105/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=5105","date":"2025-04-02T07:39:15","name":"MediaPipeline: Complex input device support","version":4,"mbox":"https://patchwork.libcamera.org/series/5105/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/23105/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/23105/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 E10AFC3213\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed,  2 Apr 2025 07:39:41 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 929E368990;\n\tWed,  2 Apr 2025 09:39:41 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 3526A68990\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed,  2 Apr 2025 09:39:39 +0200 (CEST)","from neptunite.flets-east.jp (unknown\n\t[IPv6:2404:7a81:160:2100:c59e:fbfb:58d5:f44f])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 6522AB2B;\n\tWed,  2 Apr 2025 09:37:44 +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=\"SkrmHuXV\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1743579466;\n\tbh=3KboSuF35Gf7ARszST6lSw9A2gtzM8DAZqcLUStWpco=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=SkrmHuXVThiR2jaEIeysSEF24uZ+OiSj4f/dkXHgyHQoJijNYeouQ4t7XUxkO9lxy\n\tCMoIgUilh9Sj15ZYfMlFcSFuVfh8dGJKqfBkgyqQZdQSa3niZ8AXa3EQm7xYiYzzkz\n\thMWCFlS+jxIRvV4jedsAtnb8pjiQP8ukMOPYbkEg=","From":"Paul Elder <paul.elder@ideasonboard.com>","To":"libcamera-devel@lists.libcamera.org","Cc":"Kieran Bingham <kieran.bingham@ideasonboard.com>,\n\tUmang Jain <umang.jain@ideasonboard.com>,\n\tDaniel Scally <dan.scally@ideasonboard.com>,\n\tJacopo Mondi <jacopo.mondi@ideasonboard.com>,\n\tPaul Elder <paul.elder@ideasonboard.com>","Subject":"[PATCH v4 3/3] libcamera: pipeline: rkisp1: Convert to use\n\tMediaPipeline","Date":"Wed,  2 Apr 2025 16:39:18 +0900","Message-ID":"<20250402073919.183330-4-paul.elder@ideasonboard.com>","X-Mailer":"git-send-email 2.47.2","In-Reply-To":"<20250402073919.183330-1-paul.elder@ideasonboard.com>","References":"<20250402073919.183330-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":"From: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\nUse the new MediaPipeline to manage and identify all sensors connected\nto complex pipelines that can connect to the CSI2 receiver before the\nISP.\n\nThis can include chained multiplexors that supply multiple cameras, so\nmake use of the MediaDevice::locateEntities to search for all cameras\nand construct a pipeline for each.\n\nSigned-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\nReviewed-by: Umang Jain <umang.jain@ideasonboard.com>\nReviewed-by: Daniel Scally <dan.scally@ideasonboard.com>\nReviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\nSigned-off-by: Paul Elder <paul.elder@ideasonboard.com>\n---\n src/libcamera/pipeline/rkisp1/rkisp1.cpp | 86 +++++++++---------------\n 1 file changed, 32 insertions(+), 54 deletions(-)","diff":"diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp\nindex 52633fe3cb85..705615b86b0c 100644\n--- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp\n+++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp\n@@ -42,6 +42,7 @@\n #include \"libcamera/internal/framebuffer.h\"\n #include \"libcamera/internal/ipa_manager.h\"\n #include \"libcamera/internal/media_device.h\"\n+#include \"libcamera/internal/media_pipeline.h\"\n #include \"libcamera/internal/pipeline_handler.h\"\n #include \"libcamera/internal/v4l2_subdevice.h\"\n #include \"libcamera/internal/v4l2_videodevice.h\"\n@@ -116,6 +117,11 @@ public:\n \n \tControlInfoMap ipaControls_;\n \n+\t/*\n+\t * All entities in the pipeline, from the camera sensor to the RKISP1.\n+\t */\n+\tMediaPipeline pipe_;\n+\n private:\n \tvoid paramsComputed(unsigned int frame, unsigned int bytesused);\n \tvoid setSensorControls(unsigned int frame,\n@@ -180,8 +186,7 @@ private:\n \tfriend RkISP1CameraConfiguration;\n \tfriend RkISP1Frames;\n \n-\tint initLinks(Camera *camera, const CameraSensor *sensor,\n-\t\t      const RkISP1CameraConfiguration &config);\n+\tint initLinks(Camera *camera, const RkISP1CameraConfiguration &config);\n \tint createCamera(MediaEntity *sensor);\n \tvoid tryCompleteRequest(RkISP1FrameInfo *info);\n \tvoid imageBufferReady(FrameBuffer *buffer);\n@@ -199,7 +204,6 @@ private:\n \tstd::unique_ptr<V4L2Subdevice> isp_;\n \tstd::unique_ptr<V4L2VideoDevice> param_;\n \tstd::unique_ptr<V4L2VideoDevice> stat_;\n-\tstd::unique_ptr<V4L2Subdevice> csi_;\n \n \tbool hasSelfPath_;\n \tbool isRaw_;\n@@ -223,8 +227,6 @@ private:\n \tstd::queue<FrameBuffer *> availableStatBuffers_;\n \n \tCamera *activeCamera_;\n-\n-\tconst MediaPad *ispSink_;\n };\n \n RkISP1Frames::RkISP1Frames(PipelineHandler *pipe)\n@@ -798,7 +800,7 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c)\n \tCameraSensor *sensor = data->sensor_.get();\n \tint ret;\n \n-\tret = initLinks(camera, sensor, *config);\n+\tret = initLinks(camera, *config);\n \tif (ret)\n \t\treturn ret;\n \n@@ -821,12 +823,12 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c)\n \n \tLOG(RkISP1, Debug) << \"Sensor configured with \" << format;\n \n-\tif (csi_) {\n-\t\tret = csi_->setFormat(0, &format);\n-\t\tif (ret < 0)\n-\t\t\treturn ret;\n-\t}\n+\t/* Propagate format through the internal media pipeline up to the ISP */\n+\tret = data->pipe_.configure(sensor, &format);\n+\tif (ret < 0)\n+\t\treturn ret;\n \n+\tLOG(RkISP1, Debug) << \"Configuring ISP with : \" << format;\n \tret = isp_->setFormat(0, &format);\n \tif (ret < 0)\n \t\treturn ret;\n@@ -1201,7 +1203,6 @@ int PipelineHandlerRkISP1::queueRequestDevice(Camera *camera, Request *request)\n  */\n \n int PipelineHandlerRkISP1::initLinks(Camera *camera,\n-\t\t\t\t     const CameraSensor *sensor,\n \t\t\t\t     const RkISP1CameraConfiguration &config)\n {\n \tRkISP1CameraData *data = cameraData(camera);\n@@ -1212,31 +1213,16 @@ int PipelineHandlerRkISP1::initLinks(Camera *camera,\n \t\treturn ret;\n \n \t/*\n-\t * Configure the sensor links: enable the link corresponding to this\n-\t * camera.\n+\t * Configure the sensor links: enable the links corresponding to this\n+\t * pipeline all the way up to the ISP, through any connected CSI receiver.\n \t */\n-\tfor (MediaLink *link : ispSink_->links()) {\n-\t\tif (link->source()->entity() != sensor->entity())\n-\t\t\tcontinue;\n-\n-\t\tLOG(RkISP1, Debug)\n-\t\t\t<< \"Enabling link from sensor '\"\n-\t\t\t<< link->source()->entity()->name()\n-\t\t\t<< \"' to ISP\";\n-\n-\t\tret = link->setEnabled(true);\n-\t\tif (ret < 0)\n-\t\t\treturn ret;\n-\t}\n-\n-\tif (csi_) {\n-\t\tMediaLink *link = isp_->entity()->getPadByIndex(0)->links().at(0);\n-\n-\t\tret = link->setEnabled(true);\n-\t\tif (ret < 0)\n-\t\t\treturn ret;\n+\tret = data->pipe_.initLinks();\n+\tif (ret) {\n+\t\tLOG(RkISP1, Error) << \"Failed to set up pipe links\";\n+\t\treturn ret;\n \t}\n \n+\t/* Configure the paths after the ISP */\n \tfor (const StreamConfiguration &cfg : config) {\n \t\tif (cfg.stream() == &data->mainPathStream_)\n \t\t\tret = data->mainPath_->setEnabled(true);\n@@ -1312,6 +1298,13 @@ int PipelineHandlerRkISP1::createCamera(MediaEntity *sensor)\n \t\tstd::make_unique<RkISP1CameraData>(this, &mainPath_,\n \t\t\t\t\t\t   hasSelfPath_ ? &selfPath_ : nullptr);\n \n+\t/* Identify the pipeline path between the sensor and the rkisp1_isp */\n+\tret = data->pipe_.init(sensor, \"rkisp1_isp\");\n+\tif (ret) {\n+\t\tLOG(RkISP1, Error) << \"Failed to identify path from sensor to sink\";\n+\t\treturn ret;\n+\t}\n+\n \tdata->sensor_ = CameraSensorFactoryBase::create(sensor);\n \tif (!data->sensor_)\n \t\treturn -ENODEV;\n@@ -1347,6 +1340,7 @@ int PipelineHandlerRkISP1::createCamera(MediaEntity *sensor)\n \tconst std::string &id = data->sensor_->id();\n \tstd::shared_ptr<Camera> camera =\n \t\tCamera::create(std::move(data), id, streams);\n+\n \tregisterCamera(std::move(camera));\n \n \treturn 0;\n@@ -1354,8 +1348,6 @@ int PipelineHandlerRkISP1::createCamera(MediaEntity *sensor)\n \n bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator)\n {\n-\tconst MediaPad *pad;\n-\n \tDeviceMatch dm(\"rkisp1\");\n \tdm.add(\"rkisp1_isp\");\n \tdm.add(\"rkisp1_resizer_mainpath\");\n@@ -1380,22 +1372,6 @@ bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator)\n \tif (isp_->open() < 0)\n \t\treturn false;\n \n-\t/* Locate and open the optional CSI-2 receiver. */\n-\tispSink_ = isp_->entity()->getPadByIndex(0);\n-\tif (!ispSink_ || ispSink_->links().empty())\n-\t\treturn false;\n-\n-\tpad = ispSink_->links().at(0)->source();\n-\tif (pad->entity()->function() == MEDIA_ENT_F_VID_IF_BRIDGE) {\n-\t\tcsi_ = std::make_unique<V4L2Subdevice>(pad->entity());\n-\t\tif (csi_->open() < 0)\n-\t\t\treturn false;\n-\n-\t\tispSink_ = csi_->entity()->getPadByIndex(0);\n-\t\tif (!ispSink_)\n-\t\t\treturn false;\n-\t}\n-\n \t/* Locate and open the stats and params video nodes. */\n \tstat_ = V4L2VideoDevice::fromEntityName(media_, \"rkisp1_stats\");\n \tif (stat_->open() < 0)\n@@ -1446,8 +1422,10 @@ bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator)\n \t * camera instance for each of them.\n \t */\n \tbool registered = false;\n-\tfor (MediaLink *link : ispSink_->links()) {\n-\t\tif (!createCamera(link->source()->entity()))\n+\n+\tfor (MediaEntity *entity : media_->locateEntities(MEDIA_ENT_F_CAM_SENSOR)) {\n+\t\tLOG(RkISP1, Debug) << \"Identified \" << entity->name();\n+\t\tif (!createCamera(entity))\n \t\t\tregistered = true;\n \t}\n \n","prefixes":["v4","3/3"]}