libcamera: device_enumerator: Reference-count MediaDevice instances
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@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
This commit is contained in:
parent
5b02e03199
commit
4f043b05e7
7 changed files with 23 additions and 27 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -240,7 +240,7 @@ class MediaDeviceLinkTest : public Test
|
|||
|
||||
private:
|
||||
unique_ptr<DeviceEnumerator> enumerator;
|
||||
MediaDevice *dev_;
|
||||
shared_ptr<MediaDevice> dev_;
|
||||
};
|
||||
|
||||
TEST_REGISTER(MediaDeviceLinkTest);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue