diff options
-rw-r--r-- | include/libcamera/camera_manager.h | 6 | ||||
-rw-r--r-- | src/libcamera/camera_manager.cpp | 61 | ||||
-rw-r--r-- | src/libcamera/include/pipeline_handler.h | 3 | ||||
-rw-r--r-- | 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..a71caf85 100644 --- a/src/libcamera/camera_manager.cpp +++ b/src/libcamera/camera_manager.cpp @@ -181,14 +181,41 @@ std::shared_ptr<Camera> CameraManager::get(const std::string &name) } /** + * \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 = 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() << "'"; + + 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); + + 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); } /** |