From patchwork Wed May 8 15:18:29 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 1174 Return-Path: Received: from bin-mail-out-06.binero.net (bin-mail-out-06.binero.net [195.74.38.229]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5AF1860E66 for ; Wed, 8 May 2019 17:18:57 +0200 (CEST) X-Halon-ID: 97bdfca2-71a4-11e9-8fa2-005056917a89 Authorized-sender: niklas@soderlund.pp.se Received: from localhost.localdomain (unknown [79.138.136.66]) by bin-vsp-out-01.atm.binero.net (Halon) with ESMTPA id 97bdfca2-71a4-11e9-8fa2-005056917a89; Wed, 08 May 2019 17:18:54 +0200 (CEST) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Wed, 8 May 2019 17:18:29 +0200 Message-Id: <20190508151831.12274-10-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190508151831.12274-1-niklas.soderlund@ragnatech.se> References: <20190508151831.12274-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 09/11] libcamera: pipeline_handler: Keep track of MediaDevice X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 08 May 2019 15:18:57 -0000 Instead of requiring each pipeline handle implementation to keep track of calling release() on its media devices upon deletion keep track of them in the base class. Add a helper which pipeline handlers shall use to acquire a media device instead of directly interacting with the DeviceEnumerator. This also means that pipeline handler implementations do no need to keep a shared_ptr<> reference to the media devices it stores locally as the PipelineHandler base class will keep a shared_ptr<> reference to all media devices consumed for the entire lifetime of the pipeline handler implementation. Centrally keeping track of media devices will also be beneficial implementing pipeline exclusive access across processes. Signed-off-by: Niklas Söderlund --- src/libcamera/include/pipeline_handler.h | 4 +++ src/libcamera/pipeline/ipu3/ipu3.cpp | 30 +++++---------------- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 15 ++++------- src/libcamera/pipeline/uvcvideo.cpp | 24 +++++------------ src/libcamera/pipeline/vimc.cpp | 22 +++++----------- src/libcamera/pipeline_handler.cpp | 33 ++++++++++++++++++++++++ 6 files changed, 62 insertions(+), 66 deletions(-) diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h index 5830e53108faa105..4c13496246c2251c 100644 --- a/src/libcamera/include/pipeline_handler.h +++ b/src/libcamera/include/pipeline_handler.h @@ -22,6 +22,7 @@ class Camera; class CameraConfiguration; class CameraManager; class DeviceEnumerator; +class DeviceMatch; class MediaDevice; class PipelineHandler; class Request; @@ -53,6 +54,8 @@ public: virtual ~PipelineHandler(); virtual bool match(DeviceEnumerator *enumerator) = 0; + MediaDevice *tryAcquire(DeviceEnumerator *enumerator, + const DeviceMatch &dm); virtual CameraConfiguration streamConfiguration(Camera *camera, const std::vector &usages) = 0; @@ -84,6 +87,7 @@ private: void mediaDeviceDisconnected(MediaDevice *media); virtual void disconnect(); + std::vector> mediaDevices_; std::vector> cameras_; std::map> cameraData_; }; diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 8a6a0e2721955d15..f1e04db1707a0335 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -149,7 +149,6 @@ class PipelineHandlerIPU3 : public PipelineHandler { public: PipelineHandlerIPU3(CameraManager *manager); - ~PipelineHandlerIPU3(); CameraConfiguration streamConfiguration(Camera *camera, @@ -201,8 +200,8 @@ private: ImgUDevice imgu0_; ImgUDevice imgu1_; - std::shared_ptr cio2MediaDev_; - std::shared_ptr imguMediaDev_; + MediaDevice *cio2MediaDev_; + MediaDevice *imguMediaDev_; }; PipelineHandlerIPU3::PipelineHandlerIPU3(CameraManager *manager) @@ -210,15 +209,6 @@ PipelineHandlerIPU3::PipelineHandlerIPU3(CameraManager *manager) { } -PipelineHandlerIPU3::~PipelineHandlerIPU3() -{ - if (cio2MediaDev_) - cio2MediaDev_->release(); - - if (imguMediaDev_) - imguMediaDev_->release(); -} - CameraConfiguration PipelineHandlerIPU3::streamConfiguration(Camera *camera, const std::vector &usages) @@ -614,20 +604,14 @@ bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator) imgu_dm.add("ipu3-imgu 1 viewfinder"); imgu_dm.add("ipu3-imgu 1 3a stat"); - cio2MediaDev_ = enumerator->search(cio2_dm); + cio2MediaDev_ = tryAcquire(enumerator, cio2_dm); if (!cio2MediaDev_) return false; - if (!cio2MediaDev_->acquire()) - return false; - - imguMediaDev_ = enumerator->search(imgu_dm); + imguMediaDev_ = tryAcquire(enumerator, imgu_dm); if (!imguMediaDev_) return false; - if (!imguMediaDev_->acquire()) - return false; - /* * Disable all links that are enabled by default on CIO2, as camera * creation enables all valid links it finds. @@ -682,11 +666,11 @@ int PipelineHandlerIPU3::registerCameras() { int ret; - ret = imgu0_.init(imguMediaDev_.get(), 0); + ret = imgu0_.init(imguMediaDev_, 0); if (ret) return ret; - ret = imgu1_.init(imguMediaDev_.get(), 1); + ret = imgu1_.init(imguMediaDev_, 1); if (ret) return ret; @@ -705,7 +689,7 @@ int PipelineHandlerIPU3::registerCameras() }; CIO2Device *cio2 = &data->cio2_; - ret = cio2->init(cio2MediaDev_.get(), id); + ret = cio2->init(cio2MediaDev_, id); if (ret) continue; diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index b94d742dd6ec33a4..761d144f514e110f 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -81,7 +81,7 @@ private: int createCamera(MediaEntity *sensor); void bufferReady(Buffer *buffer); - std::shared_ptr media_; + MediaDevice *media_; V4L2Subdevice *dphy_; V4L2Subdevice *isp_; V4L2Device *video_; @@ -100,9 +100,6 @@ PipelineHandlerRkISP1::~PipelineHandlerRkISP1() delete video_; delete isp_; delete dphy_; - - if (media_) - media_->release(); } /* ----------------------------------------------------------------------------- @@ -355,24 +352,22 @@ bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator) dm.add("rkisp1-input-params"); dm.add("rockchip-sy-mipi-dphy"); - media_ = enumerator->search(dm); + media_ = tryAcquire(enumerator, dm); if (!media_) return false; - media_->acquire(); - /* Create the V4L2 subdevices we will need. */ - dphy_ = V4L2Subdevice::fromEntityName(media_.get(), + dphy_ = V4L2Subdevice::fromEntityName(media_, "rockchip-sy-mipi-dphy"); if (dphy_->open() < 0) return false; - isp_ = V4L2Subdevice::fromEntityName(media_.get(), "rkisp1-isp-subdev"); + isp_ = V4L2Subdevice::fromEntityName(media_, "rkisp1-isp-subdev"); if (isp_->open() < 0) return false; /* Locate and open the capture video node. */ - video_ = V4L2Device::fromEntityName(media_.get(), "rkisp1_mainpath"); + video_ = V4L2Device::fromEntityName(media_, "rkisp1_mainpath"); if (video_->open() < 0) return false; diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp index e40b052f4d877d5d..bc4b4ec76a2d869c 100644 --- a/src/libcamera/pipeline/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo.cpp @@ -24,7 +24,6 @@ class PipelineHandlerUVC : public PipelineHandler { public: PipelineHandlerUVC(CameraManager *manager); - ~PipelineHandlerUVC(); CameraConfiguration streamConfiguration(Camera *camera, @@ -70,20 +69,13 @@ private: PipelineHandler::cameraData(camera)); } - std::shared_ptr media_; }; PipelineHandlerUVC::PipelineHandlerUVC(CameraManager *manager) - : PipelineHandler(manager), media_(nullptr) + : PipelineHandler(manager) { } -PipelineHandlerUVC::~PipelineHandlerUVC() -{ - if (media_) - media_->release(); -} - CameraConfiguration PipelineHandlerUVC::streamConfiguration(Camera *camera, const std::vector &usages) @@ -177,19 +169,17 @@ int PipelineHandlerUVC::queueRequest(Camera *camera, Request *request) bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator) { + MediaDevice *media; DeviceMatch dm("uvcvideo"); - media_ = enumerator->search(dm); - if (!media_) - return false; - - if (!media_->acquire()) + media = tryAcquire(enumerator, dm); + if (!media) return false; std::unique_ptr data = utils::make_unique(this); /* Locate and open the default video node. */ - for (MediaEntity *entity : media_->entities()) { + for (MediaEntity *entity : media->entities()) { if (entity->flags() & MEDIA_ENT_FL_DEFAULT) { data->video_ = new V4L2Device(entity); break; @@ -208,11 +198,11 @@ bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator) /* Create and register the camera. */ std::set streams{ &data->stream_ }; - std::shared_ptr camera = Camera::create(this, media_->model(), streams); + std::shared_ptr camera = Camera::create(this, media->model(), streams); registerCamera(std::move(camera), std::move(data)); /* Enable hot-unplug notifications. */ - hotplugMediaDevice(media_.get()); + hotplugMediaDevice(media); return true; } diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp index 7b6ebd4cc0a27e25..730a4c2829c10efe 100644 --- a/src/libcamera/pipeline/vimc.cpp +++ b/src/libcamera/pipeline/vimc.cpp @@ -24,7 +24,6 @@ class PipelineHandlerVimc : public PipelineHandler { public: PipelineHandlerVimc(CameraManager *manager); - ~PipelineHandlerVimc(); CameraConfiguration streamConfiguration(Camera *camera, @@ -69,21 +68,13 @@ private: return static_cast( PipelineHandler::cameraData(camera)); } - - std::shared_ptr media_; }; PipelineHandlerVimc::PipelineHandlerVimc(CameraManager *manager) - : PipelineHandler(manager), media_(nullptr) + : PipelineHandler(manager) { } -PipelineHandlerVimc::~PipelineHandlerVimc() -{ - if (media_) - media_->release(); -} - CameraConfiguration PipelineHandlerVimc::streamConfiguration(Camera *camera, const std::vector &usages) @@ -177,6 +168,8 @@ int PipelineHandlerVimc::queueRequest(Camera *camera, Request *request) bool PipelineHandlerVimc::match(DeviceEnumerator *enumerator) { + MediaDevice *media; + DeviceMatch dm("vimc"); dm.add("Raw Capture 0"); @@ -189,17 +182,14 @@ bool PipelineHandlerVimc::match(DeviceEnumerator *enumerator) dm.add("RGB/YUV Input"); dm.add("Scaler"); - media_ = enumerator->search(dm); - if (!media_) - return false; - - if (!media_->acquire()) + media = tryAcquire(enumerator, dm); + if (!media) return false; std::unique_ptr data = utils::make_unique(this); /* Locate and open the capture video node. */ - data->video_ = new V4L2Device(media_->getEntityByName("Raw Capture 1")); + data->video_ = new V4L2Device(media->getEntityByName("Raw Capture 1")); if (data->video_->open()) return false; diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp index 4ecd6c49efd8ca89..8f50ef51f0c23301 100644 --- a/src/libcamera/pipeline_handler.cpp +++ b/src/libcamera/pipeline_handler.cpp @@ -11,6 +11,7 @@ #include #include +#include "device_enumerator.h" #include "log.h" #include "media_device.h" #include "utils.h" @@ -116,6 +117,8 @@ PipelineHandler::PipelineHandler(CameraManager *manager) PipelineHandler::~PipelineHandler() { + for (std::shared_ptr media : mediaDevices_) + media->release(); }; /** @@ -149,6 +152,36 @@ PipelineHandler::~PipelineHandler() * created, or false otherwise */ +/** + * \brief Try to acquire a MediaDevice from a device pattern + * \param[in] enumerator Enumerator containing all media devices in the system + * \param[in] dm Device match pattern + * + * Search in the enumerated media devices that are not already in use for a + * match described in \a dm. If a match is found acquire it and store it for + * release when the pipeline handler is destroyed. + * + * \return pointer to the matching MediaDevice, or nullptr if no match is found + */ +MediaDevice *PipelineHandler::tryAcquire(DeviceEnumerator *enumerator, + const DeviceMatch &dm) +{ + std::shared_ptr media; + + media = enumerator->search(dm); + if (!media) + goto out; + + if (!media->acquire()) { + media.reset(); + goto out; + } + + mediaDevices_.push_back(media); +out: + return media.get(); +} + /** * \fn PipelineHandler::streamConfiguration() * \brief Retrieve a group of stream configurations for a specified camera