[libcamera-devel] [PATCH v5 2/4] libcamera: camera_manager, pipeline_handler: allow retrieving cameras by device numbers
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Fri Jan 3 12:30:03 CET 2020
Hi Paul,
Thank you for the patch.
On Fri, Jan 03, 2020 at 12:41:18AM -0500, Paul Elder wrote:
> The V4L2 compatibility layer will need a way to map device numbers to
> libcamera Camera instances. Expose a method in the camera manager to
> retrieve Camera instances by devnum. The mapping from device numbers to
> Camera instances is optionally declared by pipeline handlers when they
> register cameras with the camera manager.
>
> Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
> Reviewed-by: Jacopo Mondi <jacopo at jmondi.org>
> Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
>
> ---
> Changes in v5:
> - remove devnum -> Camera mapping in CameraManager::removeCamera()
> - other cosmetic changes
>
> Changes in v4:
> - squashed 4/6 from v3
> - simplified registering devnum -> camera mappings
> - old (v3) system: pipeline handlers have their own map, that camera
> manager aggregates
> - new (v4) system: pipeline handlers, when they register the camera
> with the camera manager, (optionally) declare the devnum along with it
>
> New in v3
> ---
> include/libcamera/camera_manager.h | 6 ++-
> src/libcamera/camera_manager.cpp | 61 ++++++++++++++++++++----
> src/libcamera/include/pipeline_handler.h | 3 +-
> src/libcamera/pipeline_handler.cpp | 13 ++++-
> 4 files changed, 69 insertions(+), 14 deletions(-)
>
> diff --git a/include/libcamera/camera_manager.h b/include/libcamera/camera_manager.h
> index 8331898c..09419766 100644
> --- a/include/libcamera/camera_manager.h
> +++ b/include/libcamera/camera_manager.h
> @@ -7,8 +7,10 @@
> #ifndef __LIBCAMERA_CAMERA_MANAGER_H__
> #define __LIBCAMERA_CAMERA_MANAGER_H__
>
> +#include <map>
> #include <memory>
> #include <string>
> +#include <sys/types.h>
> #include <vector>
>
> #include <libcamera/object.h>
> @@ -33,8 +35,9 @@ public:
>
> const std::vector<std::shared_ptr<Camera>> &cameras() const { return cameras_; }
> std::shared_ptr<Camera> get(const std::string &name);
> + std::shared_ptr<Camera> get(dev_t devnum);
>
> - void addCamera(std::shared_ptr<Camera> camera);
> + void addCamera(std::shared_ptr<Camera> camera, dev_t devnum);
> void removeCamera(Camera *camera);
>
> static const std::string &version() { return version_; }
> @@ -46,6 +49,7 @@ private:
> std::unique_ptr<DeviceEnumerator> enumerator_;
> std::vector<std::shared_ptr<PipelineHandler>> pipes_;
> std::vector<std::shared_ptr<Camera>> cameras_;
> + std::map<dev_t, std::weak_ptr<Camera>> camerasByDevnum_;
>
> static const std::string version_;
> static CameraManager *self_;
> diff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp
> index 7c6f72bb..88f8112c 100644
> --- a/src/libcamera/camera_manager.cpp
> +++ b/src/libcamera/camera_manager.cpp
> @@ -180,15 +180,42 @@ std::shared_ptr<Camera> CameraManager::get(const std::string &name)
> return nullptr;
> }
>
> +/**
> + * \brief Retrieve a camera based on device number
> + * \param[in] devnum Device number of camera to get
> + *
> + * This method is meant solely for the use of the V4L2 compatibility
> + * layer, to map device nodes to Camera instances. Applications shall
> + * not use it and shall instead retrieve cameras by name.
> + *
> + * Before calling this function the caller is responsible for ensuring that
> + * the camera manager is running.
> + *
> + * \return Shared pointer to Camera object, which is empty if the camera is
> + * not found
> + */
> +std::shared_ptr<Camera> CameraManager::get(dev_t devnum)
> +{
> + auto iter = camerasByDevnum_.find(devnum);
> + if (iter == camerasByDevnum_.end())
> + return nullptr;
> +
> + return iter->second.lock();
> +}
> +
> /**
> * \brief Add a camera to the camera manager
> * \param[in] camera The camera to be added
> + * \param[in] devnum The device number to associate with \a camera
> *
> * This function is called by pipeline handlers to register the cameras they
> * handle with the camera manager. Registered cameras are immediately made
> * available to the system.
> + *
> + * \a devnum is used by the V4L2 compatibility layer to map V4L2 device nodes
> + * to Camera instances.
> */
> -void CameraManager::addCamera(std::shared_ptr<Camera> camera)
> +void CameraManager::addCamera(std::shared_ptr<Camera> camera, dev_t devnum)
> {
> for (std::shared_ptr<Camera> c : cameras_) {
> if (c->name() == camera->name()) {
> @@ -200,6 +227,11 @@ void CameraManager::addCamera(std::shared_ptr<Camera> camera)
> }
>
> cameras_.push_back(std::move(camera));
> +
> + if (devnum) {
> + unsigned int index = cameras_.size() - 1;
> + camerasByDevnum_[devnum] = cameras_[index];
> + }
> }
>
> /**
> @@ -212,15 +244,24 @@ void CameraManager::addCamera(std::shared_ptr<Camera> camera)
> */
> void CameraManager::removeCamera(Camera *camera)
> {
> - for (auto iter = cameras_.begin(); iter != cameras_.end(); ++iter) {
> - if (iter->get() == camera) {
> - LOG(Camera, Debug)
> - << "Unregistering camera '"
> - << camera->name() << "'";
> - cameras_.erase(iter);
> - return;
> - }
> - }
> + auto iter_d = std::find_if(camerasByDevnum_.begin(), camerasByDevnum_.end(),
> + [camera](const std::pair<dev_t, std::weak_ptr<Camera>> &p) {
> + return p.second.lock().get() == camera;
> + });
> + if (iter_d != camerasByDevnum_.end())
> + camerasByDevnum_.erase(iter_d);
I would move this after the LOG() message, as if the camera isn't found
in cameras_, it's pointless to look it up in camerasByDevnum_.
Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> +
> + auto iter = std::find_if(cameras_.begin(), cameras_.end(),
> + [camera](std::shared_ptr<Camera> &c) {
> + return c.get() == camera;
> + });
> + if (iter == cameras_.end())
> + return;
> +
> + LOG(Camera, Debug)
> + << "Unregistering camera '" << camera->name() << "'";
> +
> + cameras_.erase(iter);
> }
>
> /**
> diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h
> index f3622631..067baef5 100644
> --- a/src/libcamera/include/pipeline_handler.h
> +++ b/src/libcamera/include/pipeline_handler.h
> @@ -12,6 +12,7 @@
> #include <memory>
> #include <set>
> #include <string>
> +#include <sys/sysmacros.h>
> #include <vector>
>
> #include <ipa/ipa_interface.h>
> @@ -86,7 +87,7 @@ public:
>
> protected:
> void registerCamera(std::shared_ptr<Camera> camera,
> - std::unique_ptr<CameraData> data);
> + std::unique_ptr<CameraData> data, dev_t devnum = 0);
> void hotplugMediaDevice(MediaDevice *media);
>
> virtual int queueRequestDevice(Camera *camera, Request *request) = 0;
> diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
> index 5badf31c..698dd525 100644
> --- a/src/libcamera/pipeline_handler.cpp
> +++ b/src/libcamera/pipeline_handler.cpp
> @@ -7,6 +7,8 @@
>
> #include "pipeline_handler.h"
>
> +#include <sys/sysmacros.h>
> +
> #include <libcamera/buffer.h>
> #include <libcamera/camera.h>
> #include <libcamera/camera_manager.h>
> @@ -438,19 +440,26 @@ void PipelineHandler::completeRequest(Camera *camera, Request *request)
> * \brief Register a camera to the camera manager and pipeline handler
> * \param[in] camera The camera to be added
> * \param[in] data Pipeline-specific data for the camera
> + * \param[in] devnum Device number of the camera (optional)
> *
> * This method is called by pipeline handlers to register the cameras they
> * handle with the camera manager. It associates the pipeline-specific \a data
> * with the camera, for later retrieval with cameraData(). Ownership of \a data
> * is transferred to the PipelineHandler.
> + *
> + * \a devnum is the device number (as returned by makedev) that the \a camera
> + * is to be associated with. This is for the V4L2 compatibility layer to map
> + * device nodes to Camera instances based on the device number
> + * registered by this method in \a devnum.
> */
> void PipelineHandler::registerCamera(std::shared_ptr<Camera> camera,
> - std::unique_ptr<CameraData> data)
> + std::unique_ptr<CameraData> data,
> + dev_t devnum)
> {
> data->camera_ = camera.get();
> cameraData_[camera.get()] = std::move(data);
> cameras_.push_back(camera);
> - manager_->addCamera(std::move(camera));
> + manager_->addCamera(std::move(camera), devnum);
> }
>
> /**
> --
> 2.24.1
>
--
Regards,
Laurent Pinchart
More information about the libcamera-devel
mailing list