Message ID | 20200103054120.30979-3-paul.elder@ideasonboard.com |
---|---|
State | Superseded |
Headers | show |
Series |
|
Related | show |
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@ideasonboard.com> > Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> > Reviewed-by: Laurent Pinchart <laurent.pinchart@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@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 >
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); + + 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); } /**