From patchwork Mon Aug 1 00:05:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 16888 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 9E9A4BE173 for ; Mon, 1 Aug 2022 00:06:06 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5CF1663334; Mon, 1 Aug 2022 02:06:06 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1659312366; bh=Q0ycWuajOKqpBySnWU4MdW4Tobq1XcuKtocizErXEy0=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=2btSRQt1xXIlbZ02AxQF+e8N/U5+Xcfkug7YfjFF8Ghu9GTSZOMNTH0eb/yJXzePI Oxl8gdCRu6rn20rvqolH0F6/7Noqe2W/2UNnspgodxAm9p3rOW6TEvoI6EsOPy7646 zHapPLfJSZqoOTYZTxIJLS57rg5oj6qv4gzCwVuAkyq3kN8Obq93sJNuLk5sQHCCcI Bxf84tCabd0B+zvVhKb8xEIkE2onFSTqNnG3VMHY/vntnd8JN05YKLiznARVODZvkN syC6aWcsDsjZKMa0cc+qp2wvNGYnuQc/xxRbq1AdZGSg5AIDSncAm75jV8gUasMDRq ApitYVpX+FxpQ== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 67B696332B for ; Mon, 1 Aug 2022 02:06:04 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="J1HM0qlB"; dkim-atps=neutral Received: from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id F27709AA; Mon, 1 Aug 2022 02:06:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1659312364; bh=Q0ycWuajOKqpBySnWU4MdW4Tobq1XcuKtocizErXEy0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=J1HM0qlB9skTTze6CIqTJYySmg0zdDze+fzwyhq3NqaI/dX1kR6lO0sHMOC50BhLJ KtX8983pSnzl64MYcWMe5l4RWOsySv7EwXui96nSNfiGoEPYLA29Wlelw0PH8C1zRs auLAAIeDUTxMs6KuvMMBGS/ORJPeS4oXWmNxAe/U= 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 Subject: [libcamera-devel] [PATCH 11/13] libcamera: pipeline: simple: Walk pipeline using subdev internal routing X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Phi-Bang Nguyen When traversing the media graph to discover a pipeline from the camera sensor to a video node, all sink-to-source paths inside subdevs are considered. This can lead to invalid paths being followed, when a subdev has restrictions on its internal routing. The V4L2 API supports exposing subdev internal routing to userspace. Make use if this feature, when implemented by a subdev, to restrict the internal paths to the currently active routes. If a subdev doesn't implement the internal routing operations, all source pads are considered, as done today. This change is needed to properly support multiple sensors with devices such as the NXP i.MX8 ISI or the MediaTek i350 and i500 SENINF. Support for changing routes dynamically will be added later when required. Signed-off-by: Phi-Bang Nguyen Signed-off-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- src/libcamera/pipeline/simple/simple.cpp | 73 ++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 6 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 4bde9caa7254..2a8811183907 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -100,8 +100,14 @@ LOG_DEFINE_CATEGORY(SimplePipeline) * * During the breadth-first search, the pipeline is traversed from entity to * entity, by following media graph links from source to sink, starting at the - * camera sensor. When reaching an entity (on its sink side), all its source - * pads are considered to continue the graph traversal. + * camera sensor. + * + * When reaching an entity (on its sink side), if the entity is a V4L2 subdev + * that supports the streams API, the subdev internal routes are followed to + * find the connected source pads. Otherwise all of the entity's source pads + * are considered to continue the graph traversal. The pipeline handler + * currently considers the default internal routes only and doesn't attempt to + * setup custom routes. This can be extended if needed. * * The shortest path between the camera sensor and a video node is stored in * SimpleCameraData::entities_ as a list of SimpleCameraData::Entity structures, @@ -261,6 +267,7 @@ public: private: void tryPipeline(unsigned int code, const Size &size); + static std::vector routedSourcePads(MediaPad *sink); void converterInputDone(FrameBuffer *buffer); void converterOutputDone(FrameBuffer *buffer); @@ -387,12 +394,29 @@ SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe, break; } - /* The actual breadth-first search algorithm. */ visited.insert(entity); - for (MediaPad *pad : entity->pads()) { - if (!(pad->flags() & MEDIA_PAD_FL_SOURCE)) - continue; + /* + * Add direct downstream entities to the search queue. If the + * current entity supports the subdev internal routing API, + * restrict the search to downstream entities reachable through + * active routes. + */ + + std::vector pads; + + if (sinkPad) + pads = routedSourcePads(sinkPad); + + if (pads.empty()) { + for (const MediaPad *pad : entity->pads()) { + if (!(pad->flags() & MEDIA_PAD_FL_SOURCE)) + continue; + pads.push_back(pad); + } + } + + for (const MediaPad *pad : pads) { for (MediaLink *link : pad->links()) { MediaEntity *next = link->sink()->entity(); if (visited.find(next) == visited.end()) { @@ -782,6 +806,43 @@ void SimpleCameraData::converterOutputDone(FrameBuffer *buffer) pipe->completeRequest(request); } +/* Retrieve all source pads connected to a sink pad through active routes. */ +std::vector SimpleCameraData::routedSourcePads(MediaPad *sink) +{ + MediaEntity *entity = sink->entity(); + std::unique_ptr subdev = + std::make_unique(entity); + + int ret = subdev->open(); + if (ret < 0) + return {}; + + V4L2Subdevice::Routing routing = {}; + ret = subdev->getRouting(&routing, V4L2Subdevice::ActiveFormat); + if (ret < 0) + return {}; + + std::vector pads; + + for (const struct v4l2_subdev_route &route : routing) { + if (sink->index() != route.sink_pad || + !(route.flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE)) + continue; + + const MediaPad *pad = entity->getPadByIndex(route.source_pad); + if (!pad) { + LOG(SimplePipeline, Warning) + << "Entity " << entity->name() + << " has invalid route source pad " + << route.source_pad; + } + + pads.push_back(pad); + } + + return pads; +} + /* ----------------------------------------------------------------------------- * Camera Configuration */