From patchwork Tue May 13 13:37:51 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 23363 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 E6333C3220 for ; Tue, 13 May 2025 13:38:04 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9665D68B40; Tue, 13 May 2025 15:38:04 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="rZt7tUBR"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9BB316175C for ; Tue, 13 May 2025 15:38:01 +0200 (CEST) Received: from pyrite.lan (unknown [IPv6:2001:861:3a80:3300:4f2f:8c2c:b3ef:17d4]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id E85BC82E; Tue, 13 May 2025 15:37:45 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1747143466; bh=BroYt+ypOh5bI78nhZFSjW05e/Y9KpH6qW/564y6hWA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rZt7tUBRMhv3VzRYgeFK+PYNxdp0YIuibbZAzyw6K1qKcPDryn+Np1ZZV9zK6p3Xd TJf2VuueHyB5gy1va4DAlaB51srMjmlpq+SIrAidw6gMXqFO7H5+MaCtC+qIGPBhgn 1gNlXXQpOpQLfM5j30SHEGqyw0aG7etNtju3PvXc= From: Paul Elder To: libcamera-devel@lists.libcamera.org Cc: Paul Elder , laurent.pinchart@ideasonboard.com, kieran.bingham@ideasonboard.com Subject: [PATCH v3 1/1] pipeline: simple: Fix matching with empty media graphs Date: Tue, 13 May 2025 15:37:51 +0200 Message-Id: <20250513133751.1381724-2-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20250513133751.1381724-1-paul.elder@ideasonboard.com> References: <20250513133751.1381724-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The match() function currently reports that it is not possible to create any cameras if it encounters an empty media graph. Fix this by looping over all media graphs and only returning false when all of them fail to create a camera. It is worth noting that an issue does exist when on a partial match that ends in an invalid match, any media devices that were acquired will stay acquired. This is not a new issue though, as any acquired media devices in general are not released until pipeline handler deconstruction. This requires a rework of how we do matching and pipeline handler construction, so it is captured in a comment. In the meantime, this fix fixes a problem without increasing the net number of problems. Signed-off-by: Paul Elder --- Changes in v3: - removed clearMediaDevices() - the reason is elaborated on in both the commit message and the todo comment Changes in v2: - added clearMediaDevices() --- src/libcamera/pipeline/simple/simple.cpp | 62 +++++++++++++++++------- 1 file changed, 45 insertions(+), 17 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index efb07051b..4323472e1 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -427,6 +427,9 @@ private: return static_cast(camera->_d()); } + bool matchDevice(MediaDevice *media, const SimplePipelineInfo &info, + DeviceEnumerator *enumerator); + std::vector locateSensors(MediaDevice *media); static int resetRoutingTable(V4L2Subdevice *subdev); @@ -1660,25 +1663,13 @@ int SimplePipelineHandler::resetRoutingTable(V4L2Subdevice *subdev) return 0; } -bool SimplePipelineHandler::match(DeviceEnumerator *enumerator) +bool SimplePipelineHandler::matchDevice(MediaDevice *media, + const SimplePipelineInfo &info, + DeviceEnumerator *enumerator) { - const SimplePipelineInfo *info = nullptr; unsigned int numStreams = 1; - MediaDevice *media; - for (const SimplePipelineInfo &inf : supportedDevices) { - DeviceMatch dm(inf.driver); - media = acquireMediaDevice(enumerator, dm); - if (media) { - info = &inf; - break; - } - } - - if (!media) - return false; - - for (const auto &[name, streams] : info->converters) { + for (const auto &[name, streams] : info.converters) { DeviceMatch converterMatch(name); converter_ = acquireMediaDevice(enumerator, converterMatch); if (converter_) { @@ -1687,7 +1678,7 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator) } } - swIspEnabled_ = info->swIspEnabled; + swIspEnabled_ = info.swIspEnabled; /* Locate the sensors. */ std::vector sensors = locateSensors(media); @@ -1806,6 +1797,43 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator) return registered; } +bool SimplePipelineHandler::match(DeviceEnumerator *enumerator) +{ + MediaDevice *media; + + for (const SimplePipelineInfo &inf : supportedDevices) { + DeviceMatch dm(inf.driver); + while ((media = acquireMediaDevice(enumerator, dm))) { + /* + * If match succeeds, return true to let match() be + * called again on a new instance of the pipeline + * handler. Otherwise keep looping until we do + * successfully match one (or run out). + */ + if (matchDevice(media, inf, enumerator)) { + LOG(SimplePipeline, Debug) + << "Matched on device: " + << media->deviceNode(); + return true; + } + + /* + * \todo We need to clear the list of media devices + * that we've already acquired in the event that we + * fail to create a camera. This requires a rework of + * DeviceEnumerator, or even how we create pipelines + * handlers. This is because at the moment acquired + * media devices are only released on pipeline handler + * deconstruction, and if we release them any earlier + * then DeviceEnumerator::search() will keep returning + * the same media devices. + */ + } + } + + return false; +} + V4L2VideoDevice *SimplePipelineHandler::video(const MediaEntity *entity) { auto iter = entities_.find(entity);