From patchwork Thu Jan 13 10:25:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 15277 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 BFD42BE086 for ; Thu, 13 Jan 2022 10:25:39 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7FABE6093F; Thu, 13 Jan 2022 11:25:38 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="T5crmhsK"; dkim-atps=neutral Received: from mail-wr1-x42a.google.com (mail-wr1-x42a.google.com [IPv6:2a00:1450:4864:20::42a]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BF2D1604F4 for ; Thu, 13 Jan 2022 11:25:36 +0100 (CET) Received: by mail-wr1-x42a.google.com with SMTP id q8so9135224wra.12 for ; Thu, 13 Jan 2022 02:25:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=pybYtv+XgN2g1EUB39IWeK5ug3VPIt8Yt9FxyC7pas8=; b=T5crmhsKgvTkga31EM4WLDjN9o1uudC+urANVld8g5RUitzaP7aio6irAXxBansZZJ eHAIyXzULIYk3/6vAP9MtXTFkYCIk78bvLaml9Kmb0L1x93l7+SdpoX0bDCee9pELw0v TIrHhy5hAy1gYUn8LR7wy7XPbUJbPVAev8gKtq9VhjadIVV2G/JQPaUJnBtw5sqRZb3Y lEcu5fQqXW07g4uuLQULd9Nh/ElNBAf95Ma+pje8nkYH2njfbA4QABUYSGNb6F+xrdDT DztIjtgyGGJXLfyWhMJZWaiSiaaD4s5OsX8ho63PaY1EAbE6pKnmk2GFVyAvfwq6qhpO nPAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=pybYtv+XgN2g1EUB39IWeK5ug3VPIt8Yt9FxyC7pas8=; b=NhFmkx8uJyTxWU6azAIWpgtnILIJQRHXxJclO6g8+4zI8N0sxnTLLHTxSR0ee04XBm Apwt40zXiZ16yS3cE047kGlWLAsjTrM8ahRSmRuqqmifNlVoho5OvFqH6xrGXG49ZLtL SF7vvs7Ca/QdPIKwU7sC1JzT1toSGm1mPRnZdxGxvs6VBvctlb1eIPuP3DmjlqLm5WkK zl4oiRG84BLzCmAX2m1PckmxRy4MTtf2GUkhdvA093+42HGl/SOZ/vjd7q2dk/2X49RY zYYznC6Xgvf7cIWkOUB9CBPZK80ojO8SL9KuzmtZPg/K01XInb2WwAUk/a3YQ+P6nxoC Kn5g== X-Gm-Message-State: AOAM531zgrp+Zd1v6kt3kGbhWlsDcwAIp7GHFMpYRu55FrOEQzFnpbQS TMgdVOAbwBz4EQ5M3begqAbmfpyVI0W34dJY X-Google-Smtp-Source: ABdhPJzXWwhlWwbxmmG6LPNWEvjY+8o2ReUqFEWgQoK28xbewYYtgit/aleI8mc2CxxeegH+9RuR7Q== X-Received: by 2002:a5d:4609:: with SMTP id t9mr3506603wrq.551.1642069536159; Thu, 13 Jan 2022 02:25:36 -0800 (PST) Received: from naush-laptop.pitowers.org ([2a00:1098:3142:14:194e:c2b:3339:eb51]) by smtp.gmail.com with ESMTPSA id s22sm6757855wmc.1.2022.01.13.02.25.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 13 Jan 2022 02:25:35 -0800 (PST) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Thu, 13 Jan 2022 10:25:29 +0000 Message-Id: <20220113102529.3163441-3-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220113102529.3163441-1-naush@raspberrypi.com> References: <20220113102529.3163441-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC v1 2/2] pipeline: raspberrypi: Use MediaDevice::enumerateMediaWalks() 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" Use the new MediaDevice::enumerateMediaWalks() helper to enumerate the Unicam MediaDevice, replacing the existing enumerateVideoDevices() function. Signed-off-by: Naushir Patuck Reviewed-by: Kieran Bingham --- .../pipeline/raspberrypi/raspberrypi.cpp | 142 ++++-------------- 1 file changed, 32 insertions(+), 110 deletions(-) diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index 5ee713fe66a6..36f3acf1393a 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -194,8 +194,6 @@ public: int loadIPA(ipa::RPi::SensorConfig *sensorConfig); int configureIPA(const CameraConfiguration *config); - void enumerateVideoDevices(MediaLink *link); - void statsMetadataComplete(uint32_t bufferId, const ControlList &controls); void runIsp(uint32_t bufferId); void embeddedComplete(uint32_t bufferId); @@ -326,7 +324,7 @@ private: return static_cast(camera->_d()); } - int registerCamera(MediaDevice *unicam, MediaDevice *isp, MediaEntity *sensorEntity); + int registerCamera(MediaDevice *unicam, MediaDevice *isp, const MediaDevice::MediaWalk &walk); int queueAllBuffers(Camera *camera); int prepareBuffers(Camera *camera); void freeBuffers(Camera *camera); @@ -1111,30 +1109,34 @@ bool PipelineHandlerRPi::match(DeviceEnumerator *enumerator) return false; } + std::vector walks = unicamDevice->enumerateMediaWalks(); + /* * The loop below is used to register multiple cameras behind one or more * video mux devices that are attached to a particular Unicam instance. * Obviously these cameras cannot be used simultaneously. */ unsigned int numCameras = 0; - for (MediaEntity *entity : unicamDevice->entities()) { - if (entity->function() != MEDIA_ENT_F_CAM_SENSOR) - continue; + for (const MediaDevice::MediaWalk &walk : walks) { + MediaEntity *sensorEntity = walk.front().entity; - int ret = registerCamera(unicamDevice, ispDevice, entity); - if (ret) + int ret = registerCamera(unicamDevice, ispDevice, walk); + if (ret) { LOG(RPI, Error) << "Failed to register camera " - << entity->name() << ": " << ret; - else - numCameras++; + << sensorEntity->name() << ": " << ret; + continue; + } + + numCameras++; } return !!numCameras; } -int PipelineHandlerRPi::registerCamera(MediaDevice *unicam, MediaDevice *isp, MediaEntity *sensorEntity) +int PipelineHandlerRPi::registerCamera(MediaDevice *unicam, MediaDevice *isp, const MediaDevice::MediaWalk &walk) { std::unique_ptr data = std::make_unique(this); + MediaEntity *sensorEntity = walk.front().entity; if (!data->dmaHeap_.isValid()) return -ENOMEM; @@ -1180,12 +1182,24 @@ int PipelineHandlerRPi::registerCamera(MediaDevice *unicam, MediaDevice *isp, Me if (data->sensor_->init()) return -EINVAL; - /* - * Enumerate all the Video Mux/Bridge devices across the sensor -> unicam - * chain. There may be a cascade of devices in this chain! - */ - MediaLink *link = sensorEntity->getPadByIndex(0)->links()[0]; - data->enumerateVideoDevices(link); + /* See if we can auto configure this MC graph. */ + for (auto it = walk.begin() + 1; it < walk.end() - 1; ++it) { + MediaEntity *entity = it->entity; + MediaLink *sinkLink = it->sinkLink; + + /* We only deal with Video Mux and Bridge devices in cascade. */ + if (entity->function() != MEDIA_ENT_F_VID_MUX && + entity->function() != MEDIA_ENT_F_VID_IF_BRIDGE) { + data->bridgeDevices_.clear(); + break; + } + + LOG(RPI, Info) << "Found video mux/bridge device " << entity->name() + << " linked to sink pad " << sinkLink->sink()->index(); + + data->bridgeDevices_.emplace_back(std::make_unique(entity), sinkLink); + data->bridgeDevices_.back().first->open(); + } data->sensorFormats_ = populateSensorFormats(data->sensor_); @@ -1545,98 +1559,6 @@ int RPiCameraData::configureIPA(const CameraConfiguration *config) return 0; } -/* - * enumerateVideoDevices() iterates over the Media Controller topology, starting - * at the sensor and finishing at Unicam. For each sensor, RPiCameraData stores - * a unique list of any intermediate video mux or bridge devices connected in a - * cascade, together with the entity to entity link. - * - * Entity pad configuration and link enabling happens at the end of configure(). - * We first disable all pad links on each entity device in the chain, and then - * selectively enabling the specific links to link sensor to Unicam across all - * intermediate muxes and bridges. - * - * In the cascaded topology below, if Sensor1 is used, the Mux2 -> Mux1 link - * will be disabled, and Sensor1 -> Mux1 -> Unicam links enabled. Alternatively, - * if Sensor3 is used, the Sensor2 -> Mux2 and Sensor1 -> Mux1 links are disabled, - * and Sensor3 -> Mux2 -> Mux1 -> Unicam links are enabled. All other links will - * remain unchanged. - * - * +----------+ - * | Unicam | - * +-----^----+ - * | - * +---+---+ - * | Mux1 <-------+ - * +--^----+ | - * | | - * +-----+---+ +---+---+ - * | Sensor1 | | Mux2 |<--+ - * +---------+ +-^-----+ | - * | | - * +-------+-+ +---+-----+ - * | Sensor2 | | Sensor3 | - * +---------+ +---------+ - */ -void RPiCameraData::enumerateVideoDevices(MediaLink *link) -{ - const MediaPad *sinkPad = link->sink(); - const MediaEntity *entity = sinkPad->entity(); - bool unicamFound = false; - - /* We only deal with Video Mux and Bridge devices in cascade. */ - if (entity->function() != MEDIA_ENT_F_VID_MUX && - entity->function() != MEDIA_ENT_F_VID_IF_BRIDGE) - return; - - /* Find the source pad for this Video Mux or Bridge device. */ - const MediaPad *sourcePad = nullptr; - for (const MediaPad *pad : entity->pads()) { - if (pad->flags() & MEDIA_PAD_FL_SOURCE) { - /* - * We can only deal with devices that have a single source - * pad. If this device has multiple source pads, ignore it - * and this branch in the cascade. - */ - if (sourcePad) - return; - - sourcePad = pad; - } - } - - LOG(RPI, Debug) << "Found video mux device " << entity->name() - << " linked to sink pad " << sinkPad->index(); - - bridgeDevices_.emplace_back(std::make_unique(entity), link); - bridgeDevices_.back().first->open(); - - /* - * Iterate through all the sink pad links down the cascade to find any - * other Video Mux and Bridge devices. - */ - for (MediaLink *l : sourcePad->links()) { - enumerateVideoDevices(l); - /* Once we reach the Unicam entity, we are done. */ - if (l->sink()->entity()->name() == "unicam-image") { - unicamFound = true; - break; - } - } - - /* This identifies the end of our entity enumeration recursion. */ - if (link->source()->entity()->function() == MEDIA_ENT_F_CAM_SENSOR) { - /* - * If Unicam is not at the end of this cascade, we cannot configure - * this topology automatically, so remove all entity references. - */ - if (!unicamFound) { - LOG(RPI, Warning) << "Cannot automatically configure this MC topology!"; - bridgeDevices_.clear(); - } - } -} - void RPiCameraData::statsMetadataComplete(uint32_t bufferId, const ControlList &controls) { if (state_ == State::Stopped)