[libcamera-devel] [PATCH 04/10] libcamera: device_enumerator: Reference-count MediaDevice instances
Niklas Söderlund
niklas.soderlund at ragnatech.se
Thu Jan 24 18:00:04 CET 2019
Hi Laurent,
Thanks for your work.
On 2019-01-24 12:16:45 +0200, Laurent Pinchart wrote:
> The MediaDevice class will be the entry point to hot-unplug, as it
> corresponds to the kernel devices that will report device removal
> events. The class will signal media device disconnection to pipeline
> handlers, which will clean up resources as a result.
>
> This can't be performed synchronously as references may exist to the
> related Camera objects in applications. The MediaDevice object thus
> needs to be reference-counted in order to support unplugging, as
> otherwise pipeline handlers would be required to drop all the references
> to the media device they have borrowed synchronously with the
> disconnection signal handler, which would be very error prone (if even
> possible at all in a sane way).
>
> Handle MedieDevice instances with std::shared_ptr<> to support this.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>
> ---
> src/libcamera/device_enumerator.cpp | 23 ++++++++++----------
> src/libcamera/include/device_enumerator.h | 4 ++--
> src/libcamera/pipeline/ipu3/ipu3.cpp | 11 ++++------
> src/libcamera/pipeline/uvcvideo.cpp | 4 ++--
> src/libcamera/pipeline/vimc.cpp | 4 ++--
> test/media_device/media_device_link_test.cpp | 2 +-
> test/pipeline/ipu3/ipu3_pipeline_test.cpp | 2 +-
> 7 files changed, 23 insertions(+), 27 deletions(-)
>
> diff --git a/src/libcamera/device_enumerator.cpp b/src/libcamera/device_enumerator.cpp
> index 8100972a8d04..149ffbf9aea6 100644
> --- a/src/libcamera/device_enumerator.cpp
> +++ b/src/libcamera/device_enumerator.cpp
> @@ -166,12 +166,10 @@ std::unique_ptr<DeviceEnumerator> DeviceEnumerator::create()
>
> DeviceEnumerator::~DeviceEnumerator()
> {
> - for (MediaDevice *dev : devices_) {
> - if (dev->busy())
> + for (std::shared_ptr<MediaDevice> media : devices_) {
> + if (media->busy())
> LOG(DeviceEnumerator, Error)
> << "Removing media device while still in use";
> -
> - delete dev;
> }
> }
>
> @@ -211,7 +209,7 @@ DeviceEnumerator::~DeviceEnumerator()
> */
> int DeviceEnumerator::addDevice(const std::string &deviceNode)
> {
> - MediaDevice *media = new MediaDevice(deviceNode);
> + std::shared_ptr<MediaDevice> media = std::make_shared<MediaDevice>(deviceNode);
>
> int ret = media->open();
> if (ret < 0)
> @@ -243,9 +241,10 @@ int DeviceEnumerator::addDevice(const std::string &deviceNode)
> return ret;
> }
>
> - devices_.push_back(media);
> media->close();
>
> + devices_.push_back(std::move(media));
> +
> return 0;
> }
>
> @@ -260,17 +259,17 @@ int DeviceEnumerator::addDevice(const std::string &deviceNode)
> *
> * \return pointer to the matching MediaDevice, or nullptr if no match is found
> */
> -MediaDevice *DeviceEnumerator::search(const DeviceMatch &dm)
> +std::shared_ptr<MediaDevice> DeviceEnumerator::search(const DeviceMatch &dm)
> {
> - for (MediaDevice *dev : devices_) {
> - if (dev->busy())
> + for (std::shared_ptr<MediaDevice> media : devices_) {
> + if (media->busy())
> continue;
>
> - if (dm.match(dev)) {
> + if (dm.match(media.get())) {
> LOG(DeviceEnumerator, Debug)
> << "Successful match for media device \""
> - << dev->driver() << "\"";
> - return dev;
> + << media->driver() << "\"";
> + return std::move(media);
> }
> }
>
> diff --git a/src/libcamera/include/device_enumerator.h b/src/libcamera/include/device_enumerator.h
> index 40c7750b49fc..3f87a6255303 100644
> --- a/src/libcamera/include/device_enumerator.h
> +++ b/src/libcamera/include/device_enumerator.h
> @@ -42,13 +42,13 @@ public:
> virtual int init() = 0;
> virtual int enumerate() = 0;
>
> - MediaDevice *search(const DeviceMatch &dm);
> + std::shared_ptr<MediaDevice> search(const DeviceMatch &dm);
>
> protected:
> int addDevice(const std::string &deviceNode);
>
> private:
> - std::vector<MediaDevice *> devices_;
> + std::vector<std::shared_ptr<MediaDevice>> devices_;
>
> virtual std::string lookupDeviceNode(int major, int minor) = 0;
> };
> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
> index 13ff7da4c99e..9831f74fe53f 100644
> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
> @@ -29,8 +29,8 @@ public:
> bool match(DeviceEnumerator *enumerator);
>
> private:
> - MediaDevice *cio2_;
> - MediaDevice *imgu_;
> + std::shared_ptr<MediaDevice> cio2_;
> + std::shared_ptr<MediaDevice> imgu_;
>
> void registerCameras();
> };
> @@ -47,9 +47,6 @@ PipelineHandlerIPU3::~PipelineHandlerIPU3()
>
> if (imgu_)
> imgu_->release();
> -
> - cio2_ = nullptr;
> - imgu_ = nullptr;
> }
>
> bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator)
> @@ -78,11 +75,11 @@ bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator)
> imgu_dm.add("ipu3-imgu 1 viewfinder");
> imgu_dm.add("ipu3-imgu 1 3a stat");
>
> - cio2_ = enumerator->search(cio2_dm);
> + cio2_ = std::move(enumerator->search(cio2_dm));
> if (!cio2_)
> return false;
>
> - imgu_ = enumerator->search(imgu_dm);
> + imgu_ = std::move(enumerator->search(imgu_dm));
> if (!imgu_)
> return false;
>
> diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp
> index 3ebc074093ab..73bad6714bb4 100644
> --- a/src/libcamera/pipeline/uvcvideo.cpp
> +++ b/src/libcamera/pipeline/uvcvideo.cpp
> @@ -23,7 +23,7 @@ public:
> bool match(DeviceEnumerator *enumerator);
>
> private:
> - MediaDevice *dev_;
> + std::shared_ptr<MediaDevice> dev_;
> };
>
> PipelineHandlerUVC::PipelineHandlerUVC(CameraManager *manager)
> @@ -41,7 +41,7 @@ bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
> {
> DeviceMatch dm("uvcvideo");
>
> - dev_ = enumerator->search(dm);
> + dev_ = std::move(enumerator->search(dm));
>
> if (!dev_)
> return false;
> diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp
> index 68bfe9b12ab6..521b20d3a120 100644
> --- a/src/libcamera/pipeline/vimc.cpp
> +++ b/src/libcamera/pipeline/vimc.cpp
> @@ -23,7 +23,7 @@ public:
> bool match(DeviceEnumerator *enumerator);
>
> private:
> - MediaDevice *dev_;
> + std::shared_ptr<MediaDevice> dev_;
> };
>
> PipeHandlerVimc::PipeHandlerVimc(CameraManager *manager)
> @@ -51,7 +51,7 @@ bool PipeHandlerVimc::match(DeviceEnumerator *enumerator)
> dm.add("RGB/YUV Input");
> dm.add("Scaler");
>
> - dev_ = enumerator->search(dm);
> + dev_ = std::move(enumerator->search(dm));
> if (!dev_)
> return false;
>
> diff --git a/test/media_device/media_device_link_test.cpp b/test/media_device/media_device_link_test.cpp
> index ac5b632f8ed1..58a55cdfee63 100644
> --- a/test/media_device/media_device_link_test.cpp
> +++ b/test/media_device/media_device_link_test.cpp
> @@ -240,7 +240,7 @@ class MediaDeviceLinkTest : public Test
>
> private:
> unique_ptr<DeviceEnumerator> enumerator;
> - MediaDevice *dev_;
> + shared_ptr<MediaDevice> dev_;
> };
>
> TEST_REGISTER(MediaDeviceLinkTest);
> diff --git a/test/pipeline/ipu3/ipu3_pipeline_test.cpp b/test/pipeline/ipu3/ipu3_pipeline_test.cpp
> index 482c12499a86..953f0233cde4 100644
> --- a/test/pipeline/ipu3/ipu3_pipeline_test.cpp
> +++ b/test/pipeline/ipu3/ipu3_pipeline_test.cpp
> @@ -65,7 +65,7 @@ int IPU3PipelineTest::init()
> return TestSkip;
> }
>
> - MediaDevice *cio2 = enumerator->search(cio2_dm);
> + std::shared_ptr<MediaDevice> cio2 = enumerator->search(cio2_dm);
> if (!cio2) {
> cerr << "Failed to find IPU3 CIO2: test skip" << endl;
> return TestSkip;
> --
> Regards,
>
> Laurent Pinchart
>
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel at lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel
--
Regards,
Niklas Söderlund
More information about the libcamera-devel
mailing list