From patchwork Thu Aug 5 22:24:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13232 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 E25E4C3235 for ; Thu, 5 Aug 2021 22:25:00 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id EAAF268823; Fri, 6 Aug 2021 00:24:58 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="EO60FyGZ"; 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 2DD43687CF for ; Fri, 6 Aug 2021 00:24:56 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id B6D5AE1A for ; Fri, 6 Aug 2021 00:24:55 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1628202295; bh=QMEiIVBdtXgbvP804wCtcYHU33xqlB3J4uzUIu/Jzqo=; h=From:To:Subject:Date:In-Reply-To:References:From; b=EO60FyGZHg4ISnEDIP5aYPBZAEnQ9pMlb0yZKgQEQLXYQ83PXDgXj29e0zzUg1Fdv jzedOiiy70dpfMq1w5tpBW6tWUwQqtcpICA3Z5OmZY9qYrxwBpsgeAJBwXLwUAmiZm /4m+0sxZXY3xiA737QEqMv0d/ycLo8Pym0cHcEUY= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Fri, 6 Aug 2021 01:24:27 +0300 Message-Id: <20210805222436.6263-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210805222436.6263-1-laurent.pinchart@ideasonboard.com> References: <20210805222436.6263-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 01/10] libcamera: media_object: Expose entity type 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" Add a new field to the MediaEntity class to tell the type of interface it exposes to userspace. The MediaEntity constructor is changed to take a media_v2_interface pointer instead of just the device node major and minor to have access to the interface type. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham --- include/libcamera/internal/media_object.h | 11 ++++- src/libcamera/media_device.cpp | 9 +--- src/libcamera/media_object.cpp | 50 +++++++++++++++++++++-- 3 files changed, 57 insertions(+), 13 deletions(-) diff --git a/include/libcamera/internal/media_object.h b/include/libcamera/internal/media_object.h index 2f5d33e1903e..6ae22c679cc5 100644 --- a/include/libcamera/internal/media_object.h +++ b/include/libcamera/internal/media_object.h @@ -88,9 +88,17 @@ private: class MediaEntity : public MediaObject { public: + enum class Type { + Invalid, + MediaEntity, + V4L2Subdevice, + V4L2VideoDevice, + }; + const std::string &name() const { return name_; } unsigned int function() const { return function_; } unsigned int flags() const { return flags_; } + Type type() const { return type_; } const std::string &deviceNode() const { return deviceNode_; } unsigned int deviceMajor() const { return major_; } unsigned int deviceMinor() const { return minor_; } @@ -108,13 +116,14 @@ private: friend class MediaDevice; MediaEntity(MediaDevice *dev, const struct media_v2_entity *entity, - unsigned int major = 0, unsigned int minor = 0); + const struct media_v2_interface *iface); void addPad(MediaPad *pad); std::string name_; unsigned int function_; unsigned int flags_; + Type type_; std::string deviceNode_; unsigned int major_; unsigned int minor_; diff --git a/src/libcamera/media_device.cpp b/src/libcamera/media_device.cpp index fa50264fa253..4d7cb1f566c4 100644 --- a/src/libcamera/media_device.cpp +++ b/src/libcamera/media_device.cpp @@ -652,14 +652,7 @@ bool MediaDevice::populateEntities(const struct media_v2_topology &topology) */ struct media_v2_interface *iface = findInterface(topology, ent->id); - - MediaEntity *entity; - if (iface) - entity = new MediaEntity(this, ent, - iface->devnode.major, - iface->devnode.minor); - else - entity = new MediaEntity(this, ent); + MediaEntity *entity = new MediaEntity(this, ent, iface); if (!addObject(entity)) { delete entity; diff --git a/src/libcamera/media_object.cpp b/src/libcamera/media_object.cpp index 815edc8e3b2d..f425d0447241 100644 --- a/src/libcamera/media_object.cpp +++ b/src/libcamera/media_object.cpp @@ -247,6 +247,23 @@ void MediaPad::addLink(MediaLink *link) * may expose a deviceNode(). */ +/** + * \enum MediaEntity::Type + * \brief The type of the interface exposed by the entity to userspace + * + * \var MediaEntity::Type::Invalid + * \brief Invalid or unsupported entity type + * + * \var MediaEntity::Type::MediaEntity + * \brief Plain media entity with no userspace interface + * + * \var MediaEntity::Type::V4L2VideoDevice + * \brief V4L2 video device with a V4L2 video device node + * + * \var MediaEntity::Type::V4L2Subdevice + * \brief V4L2 subdevice with a V4L2 subdev device node + */ + /** * \fn MediaEntity::name() * \brief Retrieve the entity name @@ -273,6 +290,15 @@ void MediaPad::addLink(MediaLink *link) * \return The entity's flags */ +/** + * \fn MediaEntity::type() + * \brief Retrieve the entity's type + * + * The entity type identifies the type of interface exposed to userspace. + * + * \return The entity's type + */ + /** * \fn MediaEntity::deviceNode() * \brief Retrieve the entity's device node path, if any @@ -356,16 +382,32 @@ int MediaEntity::setDeviceNode(const std::string &deviceNode) * \brief Construct a MediaEntity * \param[in] dev The media device this entity belongs to * \param[in] entity The media entity kernel data - * \param[in] major The major number of the entity associated interface - * \param[in] minor The minor number of the entity associated interface + * \param[in] iface The entity interface data (may be null) */ MediaEntity::MediaEntity(MediaDevice *dev, const struct media_v2_entity *entity, - unsigned int major, unsigned int minor) + const struct media_v2_interface *iface) : MediaObject(dev, entity->id), name_(entity->name), function_(entity->function), flags_(entity->flags), - major_(major), minor_(minor) + type_(Type::MediaEntity), major_(0), minor_(0) { + if (!iface) + return; + + switch (iface->intf_type) { + case MEDIA_INTF_T_V4L_VIDEO: + type_ = Type::V4L2VideoDevice; + break; + case MEDIA_INTF_T_V4L_SUBDEV: + type_ = Type::V4L2Subdevice; + break; + default: + type_ = Type::Invalid; + return; + } + + major_ = iface->devnode.major; + minor_ = iface->devnode.minor; } /** From patchwork Thu Aug 5 22:24:28 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13233 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 D2ACEC3238 for ; Thu, 5 Aug 2021 22:25:01 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6A36E68888; Fri, 6 Aug 2021 00:24:59 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="efA7V7Pv"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 688396880D for ; Fri, 6 Aug 2021 00:24:56 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 10D3EE6B for ; Fri, 6 Aug 2021 00:24:56 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1628202296; bh=Dv6AGKiQbU1IefbMdrQivJnjZwPcTQwEyUhtER1M2OE=; h=From:To:Subject:Date:In-Reply-To:References:From; b=efA7V7PvZD7bZF2VsCqnCagMeQMP87Bx0V2n9gLaAf3MdzydyxmzJx22QsiTX0MqE 55zMXCfkXP/ThntoxiN6Jpf69B4vMIprvXuI6GKlB5EcPzPOrJbA91VuIS7xy1sktu SvuE67CBYGm2EdYwydIZezzkAytCCWCqNfH9tIu4= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Fri, 6 Aug 2021 01:24:28 +0300 Message-Id: <20210805222436.6263-3-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210805222436.6263-1-laurent.pinchart@ideasonboard.com> References: <20210805222436.6263-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 02/10] libcamera: pipeline: simple: Add sink and source pads to entity data 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" Record the sink and source pads through which an entity is traversed in the list of entities stored in the camera data. This prepares for implementing mutually exclusive access to entities between cameras. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham --- src/libcamera/pipeline/simple/simple.cpp | 38 ++++++++++++++++++++---- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index b29fff9820e5..e0695d052629 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -166,7 +166,22 @@ public: } struct Entity { + /* The media entity, always valid. */ MediaEntity *entity; + /* + * The local sink pad connected to the upstream entity, null for + * the camera sensor at the beginning of the pipeline. + */ + const MediaPad *sink; + /* + * The local source pad connected to the downstream entity, null + * for the video node at the end of the pipeline. + */ + const MediaPad *source; + /* + * The link to the downstream entity, null for the video node at + * the end of the pipeline. + */ MediaLink *link; }; @@ -288,16 +303,18 @@ SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe, * encoders and image converters, and will end in a CSI capture device. */ std::unordered_set visited; - std::queue queue; + std::queue> queue; /* Remember at each entity where we came from. */ std::unordered_map parents; MediaEntity *entity = nullptr; - queue.push(sensor); + queue.push({ sensor, nullptr }); while (!queue.empty()) { - entity = queue.front(); + MediaPad *sinkPad; + + std::tie(entity, sinkPad) = queue.front(); queue.pop(); /* Found the capture device. */ @@ -317,8 +334,8 @@ SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe, for (MediaLink *link : pad->links()) { MediaEntity *next = link->sink()->entity(); if (visited.find(next) == visited.end()) { - queue.push(next); - parents.insert({ next, { entity, link } }); + queue.push({ next, link->sink() }); + parents.insert({ next, { entity, sinkPad, pad, link } }); } } } @@ -349,7 +366,16 @@ SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe, LOG(SimplePipeline, Debug) << "Found pipeline: " << utils::join(entities_, " -> ", - [](const Entity &e) { return e.entity->name(); }); + [](const Entity &e) { + std::string s = "["; + if (e.sink) + s += std::to_string(e.sink->index()) + "|"; + s += e.entity->name(); + if (e.source) + s += "|" + std::to_string(e.source->index()); + s += "]"; + return s; + }); } int SimpleCameraData::init() From patchwork Thu Aug 5 22:24:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13234 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 80741C3235 for ; Thu, 5 Aug 2021 22:25:02 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id AFBF96888B; Fri, 6 Aug 2021 00:24:59 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ZgukgEu4"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B893D68811 for ; Fri, 6 Aug 2021 00:24:56 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 60D874FB for ; Fri, 6 Aug 2021 00:24:56 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1628202296; bh=cED4Slz0594G/5GZEExCd3pstt5tHhUSAFRaF8FPMmg=; h=From:To:Subject:Date:In-Reply-To:References:From; b=ZgukgEu4AzIc55q1dQTVBKsUt1psEHmWDpsG9yiae2K4VcD+kglarLfzu06STXAQk n13JWPFe5DbCjOfJ3FEgj5lD+zF1MXTLTPatIg26Vu+1ys9fPhQr0n/CKPeNpH0SKB AwIWswb1XsWuf0x0joOJRJGsDrSOul3ZFdikgRY8= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Fri, 6 Aug 2021 01:24:29 +0300 Message-Id: <20210805222436.6263-4-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210805222436.6263-1-laurent.pinchart@ideasonboard.com> References: <20210805222436.6263-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 03/10] libcamera: pipeline: simple: Delay opening of video device until init() 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 video device is currently opened in the SimpleCameraData constructor. This requires opening the video devices on-demand the first time they're accessed, which gets in the way of refactoring of per-entity data storage in the pipeline handler. Move opening of the video device to the SimpleCameraData::init() function. The on-demand open mechanism isn't touched yet, it will be refactored later. Signed-off-by: Laurent Pinchart --- src/libcamera/pipeline/simple/simple.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index e0695d052629..744f842dbfe6 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -308,6 +308,7 @@ SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe, /* Remember at each entity where we came from. */ std::unordered_map parents; MediaEntity *entity = nullptr; + MediaEntity *video = nullptr; queue.push({ sensor, nullptr }); @@ -321,7 +322,7 @@ SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe, if (entity->function() == MEDIA_ENT_F_IO_V4L) { LOG(SimplePipeline, Debug) << "Found capture device " << entity->name(); - video_ = pipe->video(entity); + video = entity; break; } @@ -341,7 +342,7 @@ SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe, } } - if (!video_) + if (!video) return; /* @@ -384,6 +385,12 @@ int SimpleCameraData::init() SimpleConverter *converter = pipe->converter(); int ret; + video_ = pipe->video(entities_.back().entity); + if (!video_) { + LOG(SimplePipeline, Error) << "Failed to open video device"; + return -ENODEV; + } + /* * Setup links first as some subdev drivers take active links into * account to propagate TRY formats. Such is life :-( From patchwork Thu Aug 5 22:24:30 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13235 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 4F5BDC3239 for ; Thu, 5 Aug 2021 22:25:03 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1B0CB6888E; Fri, 6 Aug 2021 00:25:00 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="V/G+tvud"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 244AC6880D for ; Fri, 6 Aug 2021 00:24:57 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id AEFCBE1A for ; Fri, 6 Aug 2021 00:24:56 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1628202296; bh=EI8EOkLoNvotyI11OoGreFBjJlAWkJbuG/qu6UTgkS0=; h=From:To:Subject:Date:In-Reply-To:References:From; b=V/G+tvud1zrNZWX7+63z+pPa3dqWx916hz/BYZqREQmIjBXjxi6pDcfnkjqSSHRDJ kfZ3pPt6fEpm85keAmTfQCDTH5rERc085mXAE4muzFk4/dZXFWM5rII4cBbQfPNlxI iH1s0e7TI4Hzg6r7NSQDjvI1Rm0IZpd5Cn59mvuY= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Fri, 6 Aug 2021 01:24:30 +0300 Message-Id: <20210805222436.6263-5-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210805222436.6263-1-laurent.pinchart@ideasonboard.com> References: <20210805222436.6263-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 04/10] libcamera: pipeline: simple: Store video node entity in camera data 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" Store the entity corresponding to the video node at the end of the pipeline in the SimpleCameraData::entities_ list. This requires special handling of the video node in the loops that iterate over all entities, but will be useful to implement mutually exclusive access to entities for concurrent camera usage. Signed-off-by: Laurent Pinchart --- src/libcamera/pipeline/simple/simple.cpp | 29 ++++++++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 744f842dbfe6..99ecd640349c 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -194,8 +194,13 @@ public: }; std::vector streams_; - std::unique_ptr sensor_; + + /* + * All entities in the pipeline, from the camera sensor to the video + * node. + */ std::list entities_; + std::unique_ptr sensor_; V4L2VideoDevice *video_; std::vector configs_; @@ -309,12 +314,11 @@ SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe, std::unordered_map parents; MediaEntity *entity = nullptr; MediaEntity *video = nullptr; + MediaPad *sinkPad; queue.push({ sensor, nullptr }); while (!queue.empty()) { - MediaPad *sinkPad; - std::tie(entity, sinkPad) = queue.front(); queue.pop(); @@ -347,8 +351,11 @@ SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe, /* * With the parents, we can follow back our way from the capture device - * to the sensor. + * to the sensor. Store all the entities in the pipeline, from the + * camera sensor to the video node, in entities_. */ + entities_.push_front({ entity, sinkPad, nullptr, nullptr }); + for (auto it = parents.find(entity); it != parents.end(); it = parents.find(entity)) { const Entity &e = it->second; @@ -484,6 +491,9 @@ int SimpleCameraData::setupLinks() * want to enable) before enabling the pipeline link. */ for (SimpleCameraData::Entity &e : entities_) { + if (!e.link) + break; + MediaEntity *remote = e.link->sink()->entity(); for (MediaPad *pad : remote->pads()) { for (MediaLink *link : pad->links()) { @@ -524,6 +534,9 @@ int SimpleCameraData::setupFormats(V4L2SubdeviceFormat *format, return ret; for (const Entity &e : entities_) { + if (!e.link) + break; + MediaLink *link = e.link; MediaPad *source = link->source(); MediaPad *sink = link->sink(); @@ -1050,8 +1063,14 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator) if (entities.empty()) return false; - /* Create and open V4L2Subdev instances for all the entities. */ + /* + * Create and open V4L2Subdevice instances for all entities + * corresponding to a V4L2 subdevice. + */ for (MediaEntity *entity : entities) { + if (entity->type() != MediaEntity::Type::V4L2Subdevice) + continue; + auto elem = subdevs_.emplace(std::piecewise_construct, std::forward_as_tuple(entity), std::forward_as_tuple(entity)); From patchwork Thu Aug 5 22:24:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13236 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 C2DACC323A for ; Thu, 5 Aug 2021 22:25:03 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 66E1968895; Fri, 6 Aug 2021 00:25:00 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="VHxV8Dfp"; 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 655BD68822 for ; Fri, 6 Aug 2021 00:24:57 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 0E5A54FB for ; Fri, 6 Aug 2021 00:24:57 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1628202297; bh=tA70Jm1PhQtLiTq4CyO7ypsCxUHXhDkeVN832Xlpx54=; h=From:To:Subject:Date:In-Reply-To:References:From; b=VHxV8DfpUKQ6zhWRGxjaX/SH1w1ZmPXvH0qIQjfr3RHFlI2m/4ALhFii92P/GVt3p KT4V0FOEvtYL4ogk1fKwGvlIrIAN32Kr3CuCJpADazfX9Qt+DpVOKcqP+vDe7lWxma OtyrR5qTpyKNMzglnOXNCsqnsbOkJ1Iq5dqKPErI= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Fri, 6 Aug 2021 01:24:31 +0300 Message-Id: <20210805222436.6263-6-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210805222436.6263-1-laurent.pinchart@ideasonboard.com> References: <20210805222436.6263-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 05/10] libcamera: pipeline: simple: Store all entity devices in common map 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" Merge the SimplePipelineHandler videos_ and subdevs_ maps, which respectively store V4L2 video devices and subdevices associated with entities, into a single entities_ map that contains an EntityData structure. This gathers all data about entities in a single place, allowing for easy extension of entity data in the future. Signed-off-by: Laurent Pinchart --- src/libcamera/pipeline/simple/simple.cpp | 63 +++++++++++++----------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 99ecd640349c..6b808bfbe6fa 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -265,6 +265,11 @@ protected: private: static constexpr unsigned int kNumInternalBuffers = 3; + struct EntityData { + std::unique_ptr video; + std::unique_ptr subdev; + }; + SimpleCameraData *cameraData(const Camera *camera) { return static_cast( @@ -278,8 +283,7 @@ private: void converterOutputDone(FrameBuffer *buffer); MediaDevice *media_; - std::map> videos_; - std::map subdevs_; + std::map entities_; std::unique_ptr converter_; @@ -1064,24 +1068,25 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator) return false; /* - * Create and open V4L2Subdevice instances for all entities - * corresponding to a V4L2 subdevice. + * Insert all entities in the global entities list. Create and open + * V4L2Subdevice instances for each entity corresponding to a V4L2 + * subdevice. */ for (MediaEntity *entity : entities) { - if (entity->type() != MediaEntity::Type::V4L2Subdevice) - continue; + std::unique_ptr subdev; - auto elem = subdevs_.emplace(std::piecewise_construct, - std::forward_as_tuple(entity), - std::forward_as_tuple(entity)); - V4L2Subdevice *subdev = &elem.first->second; - int ret = subdev->open(); - if (ret < 0) { - LOG(SimplePipeline, Error) - << "Failed to open " << subdev->deviceNode() - << ": " << strerror(-ret); - return false; + if (entity->type() == MediaEntity::Type::V4L2Subdevice) { + subdev = std::make_unique(entity); + int ret = subdev->open(); + if (ret < 0) { + LOG(SimplePipeline, Error) + << "Failed to open " << subdev->deviceNode() + << ": " << strerror(-ret); + return false; + } } + + entities_[entity] = { nullptr, std::move(subdev) }; } /* Initialize each pipeline and register a corresponding camera. */ @@ -1114,28 +1119,30 @@ V4L2VideoDevice *SimplePipelineHandler::video(const MediaEntity *entity) * by constructing a new one. */ - auto iter = videos_.find(entity); - if (iter != videos_.end()) - return iter->second.get(); + auto iter = entities_.find(entity); + if (iter == entities_.end()) + return nullptr; + + EntityData &data = iter->second; + if (data.video) + return data.video.get(); - std::unique_ptr video = - std::make_unique(entity); - if (video->open() < 0) + data.video = std::make_unique(entity); + if (data.video->open() < 0) return nullptr; - video->bufferReady.connect(this, &SimplePipelineHandler::bufferReady); + data.video->bufferReady.connect(this, &SimplePipelineHandler::bufferReady); - auto element = videos_.emplace(entity, std::move(video)); - return element.first->second.get(); + return data.video.get(); } V4L2Subdevice *SimplePipelineHandler::subdev(const MediaEntity *entity) { - auto iter = subdevs_.find(entity); - if (iter == subdevs_.end()) + auto iter = entities_.find(entity); + if (iter == entities_.end()) return nullptr; - return &iter->second; + return iter->second.subdev.get(); } /* ----------------------------------------------------------------------------- From patchwork Thu Aug 5 22:24:32 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13237 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 CF089C323B for ; Thu, 5 Aug 2021 22:25:03 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4D3A16880D; Fri, 6 Aug 2021 00:25:01 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="UPGz/zFT"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B47CA68822 for ; Fri, 6 Aug 2021 00:24:57 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 5BFD7E1A for ; Fri, 6 Aug 2021 00:24:57 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1628202297; bh=qtwKVVw6o3QY11H21TZbG8ItJRpU+4xczObphMxatmc=; h=From:To:Subject:Date:In-Reply-To:References:From; b=UPGz/zFTrZ3+Z+n44zntNRs6Yl8RoLOKrYtXt+SYrh3iyi0HgsqK/8uYbMTHOTCK1 VVsS6gKkBRL0LE1wOIi1YtK2DKz3p5JKNVqDBosRZvn1yt7ApYVCAGRrJJliAFbr6K BhuebcnahO7L7M7dmdgWuPfb10cX0t00eCTpVbsA= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Fri, 6 Aug 2021 01:24:32 +0300 Message-Id: <20210805222436.6263-7-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210805222436.6263-1-laurent.pinchart@ideasonboard.com> References: <20210805222436.6263-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 06/10] libcamera: pipeline: simple: Open all video devices at match() time 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" Move opening of video devices at match() time, the same way as subdevs are opened, to make the handling of V4L2 video devices and subdevices more consistent. Signed-off-by: Laurent Pinchart --- src/libcamera/pipeline/simple/simple.cpp | 67 ++++++++++++------------ 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 6b808bfbe6fa..17ef3f43ad41 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -82,14 +82,12 @@ LOG_DEFINE_CATEGORY(SimplePipeline) * handled by this heuristic. * * Once the camera data instances have been created, the match() function - * creates a V4L2Subdevice instance for each entity used by any of the cameras - * and stores the instances in SimplePipelineHandler::subdevs_, accessible by - * the SimpleCameraData class through the SimplePipelineHandler::subdev() - * function. This avoids duplication of subdev instances between different - * cameras when the same entity is used in multiple paths. A similar mechanism - * is used for V4L2VideoDevice instances, but instances are in this case created - * on demand when accessed through SimplePipelineHandler::video() instead of all - * in one go at initialization time. + * creates a V4L2VideoDevice or V4L2Subdevice instance for each entity used by + * any of the cameras and stores them in SimplePipelineHandler::entities_, + * accessible by the SimpleCameraData class through the + * SimplePipelineHandler::subdev() and SimplePipelineHandler::video() functions. + * This avoids duplication of subdev instances between different cameras when + * the same entity is used in multiple paths. * * Finally, all camera data instances are initialized to gather information * about the possible pipeline configurations for the corresponding camera. If @@ -397,10 +395,7 @@ int SimpleCameraData::init() int ret; video_ = pipe->video(entities_.back().entity); - if (!video_) { - LOG(SimplePipeline, Error) << "Failed to open video device"; - return -ENODEV; - } + ASSERT(video_); /* * Setup links first as some subdev drivers take active links into @@ -1069,24 +1064,44 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator) /* * Insert all entities in the global entities list. Create and open - * V4L2Subdevice instances for each entity corresponding to a V4L2 - * subdevice. + * V4L2VideoDevice and V4L2Subdevice instances for the corresponding + * entities. */ for (MediaEntity *entity : entities) { + std::unique_ptr video; std::unique_ptr subdev; + int ret; - if (entity->type() == MediaEntity::Type::V4L2Subdevice) { + switch (entity->type()) { + case MediaEntity::Type::V4L2VideoDevice: + video = std::make_unique(entity); + ret = video->open(); + if (ret < 0) { + LOG(SimplePipeline, Error) + << "Failed to open " << video->deviceNode() + << ": " << strerror(-ret); + return false; + } + + video->bufferReady.connect(this, &SimplePipelineHandler::bufferReady); + break; + + case MediaEntity::Type::V4L2Subdevice: subdev = std::make_unique(entity); - int ret = subdev->open(); + ret = subdev->open(); if (ret < 0) { LOG(SimplePipeline, Error) << "Failed to open " << subdev->deviceNode() << ": " << strerror(-ret); return false; } + break; + + default: + break; } - entities_[entity] = { nullptr, std::move(subdev) }; + entities_[entity] = { std::move(video), std::move(subdev) }; } /* Initialize each pipeline and register a corresponding camera. */ @@ -1113,27 +1128,11 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator) V4L2VideoDevice *SimplePipelineHandler::video(const MediaEntity *entity) { - /* - * Return the V4L2VideoDevice corresponding to the media entity, either - * as a previously constructed device if available from the cache, or - * by constructing a new one. - */ - auto iter = entities_.find(entity); if (iter == entities_.end()) return nullptr; - EntityData &data = iter->second; - if (data.video) - return data.video.get(); - - data.video = std::make_unique(entity); - if (data.video->open() < 0) - return nullptr; - - data.video->bufferReady.connect(this, &SimplePipelineHandler::bufferReady); - - return data.video.get(); + return iter->second.video.get(); } V4L2Subdevice *SimplePipelineHandler::subdev(const MediaEntity *entity) From patchwork Thu Aug 5 22:24:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13238 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 1C1EFC323C for ; Thu, 5 Aug 2021 22:25:04 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 073D0688CA; Fri, 6 Aug 2021 00:25:02 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="kwEcaz9A"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 127186884E for ; Fri, 6 Aug 2021 00:24:58 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id AF7DE4FB for ; Fri, 6 Aug 2021 00:24:57 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1628202297; bh=yLlL0DLW9bNfQFknGVf71ywNPPHIqC9SNrVsLNOSPlE=; h=From:To:Subject:Date:In-Reply-To:References:From; b=kwEcaz9AjdHgHb2J3Ajr3UhbyNK29Hj/VgIzkzniKeDnmNRVd9vSfya4DYJVbBYEY dRkat+FoMs4tLr2kZb9s0vcGwUzVdFSk88olw5UbRvhpbmDCO1jcPaq/zWeGhqnMvA Qx861dVKFq0rnzu71x2uXYAt+efbSRSZHCNjvt0k= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Fri, 6 Aug 2021 01:24:33 +0300 Message-Id: <20210805222436.6263-8-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210805222436.6263-1-laurent.pinchart@ideasonboard.com> References: <20210805222436.6263-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 07/10] libcamera: pipeline: simple: Add pipeline pad reservation mechanism 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 cameras created by the same pipeline handler instance may share hardware resources, prohibiting usage of multiple cameras concurrently. Implement a heuristic to reserve resources and handle mutual exclusiong in a generic way. Signed-off-by: Laurent Pinchart --- src/libcamera/pipeline/simple/simple.cpp | 95 +++++++++++++++++++++++- 1 file changed, 93 insertions(+), 2 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 17ef3f43ad41..b32369cae701 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -121,6 +121,28 @@ LOG_DEFINE_CATEGORY(SimplePipeline) * the pixel formats and sizes that the converter can produce for the output of * the capture video node, and stores the information in the outputFormats and * outputSizes of the SimpleCameraData::Configuration structure. + * + * Concurrent Access to Cameras + * ---------------------------- + * + * The cameras created by the same pipeline handler instance may share hardware + * resources. For instances, a platform may have multiple CSI-2 receivers but a + * single DMA engine, prohibiting usage of multiple cameras concurrently. This + * depends heavily on the hardware architecture, which the simple pipeline + * handler has no a priori knowledge of. The pipeline handler thus implements a + * heuristic to handle sharing of hardware resources in a generic fashion. + * + * Two cameras are considered to be mutually exclusive if their share common + * pads along the pipeline from the camera sensor to the video node. An entity + * can thus be used concurrently by multiple cameras, as long as pads are + * distinct. + * + * A resource reservation mechanism is implemented by the SimplePipelineHandler + * acquirePipeline() and releasePipeline() functions to manage exclusive access + * to pads. A camera reserves all the pads present in its pipeline when it is + * started, and the start() function returns an error if any of the required + * pads is already in use. When the camera is stopped, the pads it has reserved + * are released. */ class SimplePipelineHandler; @@ -266,6 +288,7 @@ private: struct EntityData { std::unique_ptr video; std::unique_ptr subdev; + std::map owners; }; SimpleCameraData *cameraData(const Camera *camera) @@ -276,6 +299,9 @@ private: std::vector locateSensors(); + const MediaPad *acquirePipeline(SimpleCameraData *data); + void releasePipeline(SimpleCameraData *data); + void bufferReady(FrameBuffer *buffer); void converterInputDone(FrameBuffer *buffer); void converterOutputDone(FrameBuffer *buffer); @@ -841,6 +867,14 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL V4L2VideoDevice *video = data->video_; int ret; + const MediaPad *pad = acquirePipeline(data); + if (pad) { + LOG(SimplePipeline, Info) + << "Failed to acquire pipeline, entity " + << pad->entity()->name() << " in use"; + return -EBUSY; + } + if (data->useConverter_) { /* * When using the converter allocate a fixed number of internal @@ -853,8 +887,10 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL Stream *stream = &data->streams_[0]; ret = video->importBuffers(stream->configuration().bufferCount); } - if (ret < 0) + if (ret < 0) { + releasePipeline(data); return ret; + } ret = video->streamOn(); if (ret < 0) { @@ -892,6 +928,8 @@ void SimplePipelineHandler::stop(Camera *camera) data->converterBuffers_.clear(); activeCamera_ = nullptr; + + releasePipeline(data); } int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request) @@ -1101,7 +1139,7 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator) break; } - entities_[entity] = { std::move(video), std::move(subdev) }; + entities_[entity] = { std::move(video), std::move(subdev), {} }; } /* Initialize each pipeline and register a corresponding camera. */ @@ -1144,6 +1182,59 @@ V4L2Subdevice *SimplePipelineHandler::subdev(const MediaEntity *entity) return iter->second.subdev.get(); } +/** + * \brief Acquire all resources needed by the camera pipeline + * \return nullptr on success, a pointer to the contended pad on error + */ +const MediaPad *SimplePipelineHandler::acquirePipeline(SimpleCameraData *data) +{ + for (const SimpleCameraData::Entity &entity : data->entities_) { + const EntityData &edata = entities_[entity.entity]; + + if (entity.sink) { + auto iter = edata.owners.find(entity.sink); + if (iter != edata.owners.end() && iter->second != data) + return entity.sink; + } + + if (entity.source) { + auto iter = edata.owners.find(entity.source); + if (iter != edata.owners.end() && iter->second != data) + return entity.source; + } + } + + for (const SimpleCameraData::Entity &entity : data->entities_) { + EntityData &edata = entities_[entity.entity]; + + if (entity.sink) + edata.owners[entity.sink] = data; + if (entity.source) + edata.owners[entity.source] = data; + } + + return nullptr; +} + +void SimplePipelineHandler::releasePipeline(SimpleCameraData *data) +{ + for (const SimpleCameraData::Entity &entity : data->entities_) { + EntityData &edata = entities_[entity.entity]; + + if (entity.sink) { + auto iter = edata.owners.find(entity.sink); + ASSERT(iter->second == data); + edata.owners.erase(iter); + } + + if (entity.source) { + auto iter = edata.owners.find(entity.source); + ASSERT(iter->second == data); + edata.owners.erase(iter); + } + } +} + /* ----------------------------------------------------------------------------- * Buffer Handling */ From patchwork Thu Aug 5 22:24:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13239 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 2EA3CC323D for ; Thu, 5 Aug 2021 22:25:04 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id ABE8168892; Fri, 6 Aug 2021 00:25:02 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="CP+Z1Cqj"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5E441687CF for ; Fri, 6 Aug 2021 00:24:58 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 0977EE1A for ; Fri, 6 Aug 2021 00:24:57 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1628202298; bh=bxrBrcn4L9y9oMNwRh/dP4+Egnd/J4qfdrqUrnhjIy8=; h=From:To:Subject:Date:In-Reply-To:References:From; b=CP+Z1Cqj135uemp0Ny04gQb6GT4IgImm0cjbnLaJ7dq4CglHWKmRATipek+PqavaK llNFaYIxFqFRTpdGJizozosBJkuTqO3BSib/aUK8Qy51YhFk8MkuRw55PtSbvVIFog nkc1R+U5CbFKwBfEtsEqKoLyjYBNEn5gHbV2Pq6w= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Fri, 6 Aug 2021 01:24:34 +0300 Message-Id: <20210805222436.6263-9-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210805222436.6263-1-laurent.pinchart@ideasonboard.com> References: <20210805222436.6263-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 08/10] libcamera: pipeline: simple: Move converter to SimpleCameraData 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" To use multiple cameras at the same time, each camera instance will need its own converter. Store the converter in SimpleCameraData, and open it in init(). Signed-off-by: Laurent Pinchart --- src/libcamera/pipeline/simple/simple.cpp | 106 +++++++++++------------ 1 file changed, 51 insertions(+), 55 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index b32369cae701..961262b7803d 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -226,9 +226,14 @@ public: std::vector configs_; std::map formats_; + std::unique_ptr converter_; std::vector> converterBuffers_; bool useConverter_; std::queue> converterQueue_; + +private: + void converterInputDone(FrameBuffer *buffer); + void converterOutputDone(FrameBuffer *buffer); }; class SimpleCameraConfiguration : public CameraConfiguration @@ -277,7 +282,7 @@ public: V4L2VideoDevice *video(const MediaEntity *entity); V4L2Subdevice *subdev(const MediaEntity *entity); - SimpleConverter *converter() { return converter_.get(); } + MediaDevice *converter() { return converter_; } protected: int queueRequestDevice(Camera *camera, Request *request) override; @@ -303,13 +308,11 @@ private: void releasePipeline(SimpleCameraData *data); void bufferReady(FrameBuffer *buffer); - void converterInputDone(FrameBuffer *buffer); - void converterOutputDone(FrameBuffer *buffer); MediaDevice *media_; std::map entities_; - std::unique_ptr converter_; + MediaDevice *converter_; Camera *activeCamera_; }; @@ -417,9 +420,22 @@ SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe, int SimpleCameraData::init() { SimplePipelineHandler *pipe = static_cast(pipe_); - SimpleConverter *converter = pipe->converter(); int ret; + /* Open the converter, if any. */ + MediaDevice *converter = pipe->converter(); + if (converter) { + converter_ = std::make_unique(converter); + if (!converter_->isValid()) { + LOG(SimplePipeline, Warning) + << "Failed to create converter, disabling format conversion"; + converter_.reset(); + } else { + converter_->inputBufferReady.connect(this, &SimpleCameraData::converterInputDone); + converter_->outputBufferReady.connect(this, &SimpleCameraData::converterOutputDone); + } + } + video_ = pipe->video(entities_.back().entity); ASSERT(video_); @@ -471,12 +487,12 @@ int SimpleCameraData::init() config.captureFormat = pixelFormat; config.captureSize = format.size; - if (!converter) { + if (!converter_) { config.outputFormats = { pixelFormat }; config.outputSizes = config.captureSize; } else { - config.outputFormats = converter->formats(pixelFormat); - config.outputSizes = converter->sizes(format.size); + config.outputFormats = converter_->formats(pixelFormat); + config.outputSizes = converter_->sizes(format.size); } configs_.push_back(config); @@ -605,6 +621,20 @@ int SimpleCameraData::setupFormats(V4L2SubdeviceFormat *format, return 0; } +void SimpleCameraData::converterInputDone(FrameBuffer *buffer) +{ + /* Queue the input buffer back for capture. */ + video_->queueBuffer(buffer); +} + +void SimpleCameraData::converterOutputDone(FrameBuffer *buffer) +{ + /* Complete the buffer and the request. */ + Request *request = buffer->request(); + if (pipe_->completeBuffer(request, buffer)) + pipe_->completeRequest(request); +} + /* ----------------------------------------------------------------------------- * Camera Configuration */ @@ -650,11 +680,9 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() } } - /* Adjust the requested streams. */ - SimplePipelineHandler *pipe = static_cast(data_->pipe_); - SimpleConverter *converter = pipe->converter(); - /* + * Adjust the requested streams. + * * Enable usage of the converter when producing multiple streams, as * the video capture device can't capture to multiple buffers. * @@ -700,7 +728,8 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() /* Set the stride, frameSize and bufferCount. */ if (needConversion_) { std::tie(cfg.stride, cfg.frameSize) = - converter->strideAndFrameSize(cfg.pixelFormat, cfg.size); + data_->converter_->strideAndFrameSize(cfg.pixelFormat, + cfg.size); if (cfg.stride == 0) return Invalid; } else { @@ -727,7 +756,7 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() */ SimplePipelineHandler::SimplePipelineHandler(CameraManager *manager) - : PipelineHandler(manager) + : PipelineHandler(manager), converter_(nullptr) { } @@ -841,7 +870,7 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) inputCfg.stride = captureFormat.planes[0].bpl; inputCfg.bufferCount = kNumInternalBuffers; - return converter_->configure(inputCfg, outputCfgs); + return data->converter_->configure(inputCfg, outputCfgs); } int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream, @@ -855,8 +884,8 @@ int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream, * whether the converter is used or not. */ if (data->useConverter_) - return converter_->exportBuffers(data->streamIndex(stream), - count, buffers); + return data->converter_->exportBuffers(data->streamIndex(stream), + count, buffers); else return data->video_->exportBuffers(count, buffers); } @@ -899,7 +928,7 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL } if (data->useConverter_) { - ret = converter_->start(); + ret = data->converter_->start(); if (ret < 0) { stop(camera); return ret; @@ -921,7 +950,7 @@ void SimplePipelineHandler::stop(Camera *camera) V4L2VideoDevice *video = data->video_; if (data->useConverter_) - converter_->stop(); + data->converter_->stop(); video->streamOff(); video->releaseBuffers(); @@ -1028,7 +1057,6 @@ std::vector SimplePipelineHandler::locateSensors() bool SimplePipelineHandler::match(DeviceEnumerator *enumerator) { const SimplePipelineInfo *info = nullptr; - MediaDevice *converter = nullptr; unsigned int numStreams = 1; for (const SimplePipelineInfo &inf : supportedDevices) { @@ -1045,8 +1073,8 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator) for (const auto &[name, streams] : info->converters) { DeviceMatch converterMatch(name); - converter = acquireMediaDevice(enumerator, converterMatch); - if (converter) { + converter_ = acquireMediaDevice(enumerator, converterMatch); + if (converter_) { numStreams = streams; break; } @@ -1059,19 +1087,6 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator) return false; } - /* Open the converter, if any. */ - if (converter) { - converter_ = std::make_unique(converter); - if (!converter_->isValid()) { - LOG(SimplePipeline, Warning) - << "Failed to create converter, disabling format conversion"; - converter_.reset(); - } else { - converter_->inputBufferReady.connect(this, &SimplePipelineHandler::converterInputDone); - converter_->outputBufferReady.connect(this, &SimplePipelineHandler::converterOutputDone); - } - } - /* * Create one camera data instance for each sensor and gather all * entities in all pipelines. @@ -1317,7 +1332,7 @@ void SimplePipelineHandler::bufferReady(FrameBuffer *buffer) return; } - converter_->queueBuffers(buffer, data->converterQueue_.front()); + data->converter_->queueBuffers(buffer, data->converterQueue_.front()); data->converterQueue_.pop(); return; } @@ -1327,25 +1342,6 @@ void SimplePipelineHandler::bufferReady(FrameBuffer *buffer) completeRequest(request); } -void SimplePipelineHandler::converterInputDone(FrameBuffer *buffer) -{ - ASSERT(activeCamera_); - SimpleCameraData *data = cameraData(activeCamera_); - - /* Queue the input buffer back for capture. */ - data->video_->queueBuffer(buffer); -} - -void SimplePipelineHandler::converterOutputDone(FrameBuffer *buffer) -{ - ASSERT(activeCamera_); - - /* Complete the buffer and the request. */ - Request *request = buffer->request(); - if (completeBuffer(request, buffer)) - completeRequest(request); -} - REGISTER_PIPELINE_HANDLER(SimplePipelineHandler) } /* namespace libcamera */ From patchwork Thu Aug 5 22:24:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13240 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 8AF6FC323E for ; Thu, 5 Aug 2021 22:25:04 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6BBCC68823; Fri, 6 Aug 2021 00:25:03 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="kz1g+d6s"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AF6CA68864 for ; Fri, 6 Aug 2021 00:24:58 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 5891D4FB for ; Fri, 6 Aug 2021 00:24:58 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1628202298; bh=rk2i+0Hbv2WpzF5aFkIirl35cpNkySJgXP5j1JzuCCc=; h=From:To:Subject:Date:In-Reply-To:References:From; b=kz1g+d6sF7Y4fX5ajgjudC36ilxZQr77YphAXFBphYNDZ3UWE9M0bCCi3jXyTEkl2 F46UiV6FibG1Kbvrd8f9mC+9h9HjHww8TJb5084fIQUiconmxtjI4MfS1V6pu3+8LN o+EK95pvTrhy2oHgQKu17DxlWzvqE9jKmzHseZVE= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Fri, 6 Aug 2021 01:24:35 +0300 Message-Id: <20210805222436.6263-10-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210805222436.6263-1-laurent.pinchart@ideasonboard.com> References: <20210805222436.6263-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 09/10] libcamera: pipeline: simple: Move bufferReady handler to SimpleCameraData 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" To use multiple cameras at the same time, a per-camera buffer ready handler is needed. Move the bufferReady() function connected to the V4L2VideoDevice bufferReady signal from the SimplePipelineHandler class to the SimpleCameraData class. Signed-off-by: Laurent Pinchart --- src/libcamera/pipeline/simple/simple.cpp | 186 +++++++++++------------ 1 file changed, 90 insertions(+), 96 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 961262b7803d..aa4542ed26b1 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -179,6 +179,7 @@ public: int setupLinks(); int setupFormats(V4L2SubdeviceFormat *format, V4L2Subdevice::Whence whence); + void bufferReady(FrameBuffer *buffer); unsigned int streamIndex(const Stream *stream) const { @@ -307,8 +308,6 @@ private: const MediaPad *acquirePipeline(SimpleCameraData *data); void releasePipeline(SimpleCameraData *data); - void bufferReady(FrameBuffer *buffer); - MediaDevice *media_; std::map entities_; @@ -621,6 +620,91 @@ int SimpleCameraData::setupFormats(V4L2SubdeviceFormat *format, return 0; } +void SimpleCameraData::bufferReady(FrameBuffer *buffer) +{ + /* + * If an error occurred during capture, or if the buffer was cancelled, + * complete the request, even if the converter is in use as there's no + * point converting an erroneous buffer. + */ + if (buffer->metadata().status != FrameMetadata::FrameSuccess) { + if (!useConverter_) { + /* No conversion, just complete the request. */ + Request *request = buffer->request(); + pipe_->completeBuffer(request, buffer); + pipe_->completeRequest(request); + return; + } + + /* + * The converter is in use. Requeue the internal buffer for + * capture (unless the stream is being stopped), and complete + * the request with all the user-facing buffers. + */ + if (buffer->metadata().status != FrameMetadata::FrameCancelled) + video_->queueBuffer(buffer); + + if (converterQueue_.empty()) + return; + + Request *request = nullptr; + for (auto &item : converterQueue_.front()) { + FrameBuffer *outputBuffer = item.second; + request = outputBuffer->request(); + pipe_->completeBuffer(request, outputBuffer); + } + converterQueue_.pop(); + + if (request) + pipe_->completeRequest(request); + return; + } + + /* + * Record the sensor's timestamp in the request metadata. The request + * needs to be obtained from the user-facing buffer, as internal + * buffers are free-wheeling and have no request associated with them. + * + * \todo The sensor timestamp should be better estimated by connecting + * to the V4L2Device::frameStart signal if the platform provides it. + */ + Request *request = buffer->request(); + + if (useConverter_ && !converterQueue_.empty()) { + const std::map &outputs = + converterQueue_.front(); + if (!outputs.empty()) { + FrameBuffer *outputBuffer = outputs.begin()->second; + if (outputBuffer) + request = outputBuffer->request(); + } + } + + if (request) + request->metadata().set(controls::SensorTimestamp, + buffer->metadata().timestamp); + + /* + * Queue the captured and the request buffer to the converter if format + * conversion is needed. If there's no queued request, just requeue the + * captured buffer for capture. + */ + if (useConverter_) { + if (converterQueue_.empty()) { + video_->queueBuffer(buffer); + return; + } + + converter_->queueBuffers(buffer, converterQueue_.front()); + converterQueue_.pop(); + return; + } + + /* Otherwise simply complete the request. */ + pipe_->completeBuffer(request, buffer); + pipe_->completeRequest(request); +} + void SimpleCameraData::converterInputDone(FrameBuffer *buffer) { /* Queue the input buffer back for capture. */ @@ -921,6 +1005,8 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL return ret; } + video->bufferReady.connect(data, &SimpleCameraData::bufferReady); + ret = video->streamOn(); if (ret < 0) { stop(camera); @@ -955,6 +1041,8 @@ void SimplePipelineHandler::stop(Camera *camera) video->streamOff(); video->releaseBuffers(); + video->bufferReady.disconnect(data, &SimpleCameraData::bufferReady); + data->converterBuffers_.clear(); activeCamera_ = nullptr; @@ -1135,8 +1223,6 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator) << ": " << strerror(-ret); return false; } - - video->bufferReady.connect(this, &SimplePipelineHandler::bufferReady); break; case MediaEntity::Type::V4L2Subdevice: @@ -1250,98 +1336,6 @@ void SimplePipelineHandler::releasePipeline(SimpleCameraData *data) } } -/* ----------------------------------------------------------------------------- - * Buffer Handling - */ - -void SimplePipelineHandler::bufferReady(FrameBuffer *buffer) -{ - ASSERT(activeCamera_); - SimpleCameraData *data = cameraData(activeCamera_); - - /* - * If an error occurred during capture, or if the buffer was cancelled, - * complete the request, even if the converter is in use as there's no - * point converting an erroneous buffer. - */ - if (buffer->metadata().status != FrameMetadata::FrameSuccess) { - if (!data->useConverter_) { - /* No conversion, just complete the request. */ - Request *request = buffer->request(); - completeBuffer(request, buffer); - completeRequest(request); - return; - } - - /* - * The converter is in use. Requeue the internal buffer for - * capture (unless the stream is being stopped), and complete - * the request with all the user-facing buffers. - */ - if (buffer->metadata().status != FrameMetadata::FrameCancelled) - data->video_->queueBuffer(buffer); - - if (data->converterQueue_.empty()) - return; - - Request *request = nullptr; - for (auto &item : data->converterQueue_.front()) { - FrameBuffer *outputBuffer = item.second; - request = outputBuffer->request(); - completeBuffer(request, outputBuffer); - } - data->converterQueue_.pop(); - - if (request) - completeRequest(request); - return; - } - - /* - * Record the sensor's timestamp in the request metadata. The request - * needs to be obtained from the user-facing buffer, as internal - * buffers are free-wheeling and have no request associated with them. - * - * \todo The sensor timestamp should be better estimated by connecting - * to the V4L2Device::frameStart signal if the platform provides it. - */ - Request *request = buffer->request(); - - if (data->useConverter_ && !data->converterQueue_.empty()) { - const std::map &outputs = - data->converterQueue_.front(); - if (!outputs.empty()) { - FrameBuffer *outputBuffer = outputs.begin()->second; - if (outputBuffer) - request = outputBuffer->request(); - } - } - - if (request) - request->metadata().set(controls::SensorTimestamp, - buffer->metadata().timestamp); - - /* - * Queue the captured and the request buffer to the converter if format - * conversion is needed. If there's no queued request, just requeue the - * captured buffer for capture. - */ - if (data->useConverter_) { - if (data->converterQueue_.empty()) { - data->video_->queueBuffer(buffer); - return; - } - - data->converter_->queueBuffers(buffer, data->converterQueue_.front()); - data->converterQueue_.pop(); - return; - } - - /* Otherwise simply complete the request. */ - completeBuffer(request, buffer); - completeRequest(request); -} - REGISTER_PIPELINE_HANDLER(SimplePipelineHandler) } /* namespace libcamera */ From patchwork Thu Aug 5 22:24:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13241 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 8C58EC323F for ; Thu, 5 Aug 2021 22:25:04 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id BE65E688C4; Fri, 6 Aug 2021 00:25:03 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="BbRA8H/9"; 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 161776026E for ; Fri, 6 Aug 2021 00:24:59 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id A7B8EE1A for ; Fri, 6 Aug 2021 00:24:58 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1628202298; bh=onBRKaLyfm/6CNuVZw+yrSXTsWxSPIsGaRDjGdCdkdE=; h=From:To:Subject:Date:In-Reply-To:References:From; b=BbRA8H/9fqBC4OIzrkFqrpiV0oJb7oBegCRrV22tCReBBJyDMqOlXK5pJvJJS3HXf kkMulstepF7dVnOH0I5ldE1pjJ62XDBbsQsM6kT/+8TOD5TPTC9Bpz/txsDXI5382n NBVX9jVdNhXG5HPNl6SWMe0lW5y+bJTFxyfxufY4= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Fri, 6 Aug 2021 01:24:36 +0300 Message-Id: <20210805222436.6263-11-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210805222436.6263-1-laurent.pinchart@ideasonboard.com> References: <20210805222436.6263-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 10/10] libcamera: pipeline: simple: Remove SimplePipelineHandler::activeCamera_ 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 SimplePipelineHandler activeCamera_ member pointer is set but never used. Drop it. Signed-off-by: Laurent Pinchart --- src/libcamera/pipeline/simple/simple.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index aa4542ed26b1..7e89e3921dbe 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -312,8 +312,6 @@ private: std::map entities_; MediaDevice *converter_; - - Camera *activeCamera_; }; /* ----------------------------------------------------------------------------- @@ -1025,8 +1023,6 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL video->queueBuffer(buffer.get()); } - activeCamera_ = camera; - return 0; } @@ -1044,7 +1040,6 @@ void SimplePipelineHandler::stop(Camera *camera) video->bufferReady.disconnect(data, &SimpleCameraData::bufferReady); data->converterBuffers_.clear(); - activeCamera_ = nullptr; releasePipeline(data); }