[libcamera-devel] [RFC 8/9] libcamera: pipeline_handler: Add function to acquire a USB device
Jacopo Mondi
jacopo.mondi at ideasonboard.com
Tue Aug 8 14:52:27 CEST 2023
Add a function to the PipelineHandler base class to acquire a USB device
by providing a USBDeviceMatch class instance.
Support multiple CameraDevice derived classes by generalizing whenever
possible the device type in use.
Signed-off-by: Jacopo Mondi <jacopo.mondi at ideasonboard.com>
---
include/libcamera/internal/pipeline_handler.h | 9 ++-
src/libcamera/pipeline_handler.cpp | 69 +++++++++++++++----
2 files changed, 64 insertions(+), 14 deletions(-)
diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h
index 02b2f33727a3..b6b68aab1521 100644
--- a/include/libcamera/internal/pipeline_handler.h
+++ b/include/libcamera/internal/pipeline_handler.h
@@ -26,6 +26,7 @@ namespace libcamera {
class Camera;
class CameraConfiguration;
+class CameraDevice;
class CameraManager;
class DeviceEnumerator;
class MediaDeviceMatch;
@@ -33,6 +34,8 @@ class FrameBuffer;
class MediaDevice;
class PipelineHandler;
class Request;
+class USBDevice;
+class USBDeviceMatch;
class PipelineHandler : public std::enable_shared_from_this<PipelineHandler>,
public Object
@@ -44,6 +47,8 @@ public:
virtual bool match(DeviceEnumerator *enumerator) = 0;
MediaDevice *acquireMediaDevice(DeviceEnumerator *enumerator,
const MediaDeviceMatch &dm);
+ USBDevice *acquireUSBDevice(DeviceEnumerator *enumerator,
+ const USBDeviceMatch &dm);
bool acquire();
void release(Camera *camera);
@@ -82,7 +87,7 @@ protected:
CameraManager *manager_;
private:
- void unlockMediaDevices();
+ void unlockCameraDevices();
void mediaDeviceDisconnected(MediaDevice *media);
virtual void disconnect();
@@ -90,7 +95,7 @@ private:
void doQueueRequest(Request *request);
void doQueueRequests();
- std::vector<std::shared_ptr<MediaDevice>> mediaDevices_;
+ std::vector<std::shared_ptr<CameraDevice>> cameraDevices_;
std::vector<std::weak_ptr<Camera>> cameras_;
std::queue<Request *> waitingRequests_;
diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
index ca177cad985c..0b3e0fd8fa8b 100644
--- a/src/libcamera/pipeline_handler.cpp
+++ b/src/libcamera/pipeline_handler.cpp
@@ -27,6 +27,7 @@
#include "libcamera/internal/media_device.h"
#include "libcamera/internal/request.h"
#include "libcamera/internal/tracepoints.h"
+#include "libcamera/internal/usb_device.h"
/**
* \file pipeline_handler.h
@@ -76,8 +77,8 @@ PipelineHandler::PipelineHandler(CameraManager *manager)
PipelineHandler::~PipelineHandler()
{
- for (std::shared_ptr<MediaDevice> media : mediaDevices_)
- media->release();
+ for (std::shared_ptr<CameraDevice> device : cameraDevices_)
+ device->release();
}
/**
@@ -139,11 +140,42 @@ MediaDevice *PipelineHandler::acquireMediaDevice(DeviceEnumerator *enumerator,
if (!media->acquire())
return nullptr;
- mediaDevices_.push_back(media);
+ cameraDevices_.push_back(media);
return media.get();
}
+/**
+ * \brief Search and acquire a USBDevice matching a device pattern
+ * \param[in] enumerator Enumerator containing all media devices in the system
+ * \param[in] dm Device match pattern
+ *
+ * Search the device \a enumerator for an available USB device matching the
+ * device match pattern \a dm. Matching devices that have previously been
+ * acquired by MediaDevice::acquire() are not considered. If a match is found,
+ * the USB device is acquired and returned. The caller shall not release the
+ * device explicitly, it will be automatically released when the pipeline
+ * handler is destroyed.
+ *
+ * \context This function shall be called from the CameraManager thread.
+ *
+ * \return A pointer to the matching USBDevice, or nullptr if no match is found
+ */
+USBDevice *PipelineHandler::acquireUSBDevice(DeviceEnumerator *enumerator,
+ const USBDeviceMatch &dm)
+{
+ std::shared_ptr<USBDevice> usb = enumerator->search(dm);
+ if (!usb)
+ return nullptr;
+
+ if (!usb->acquire())
+ return nullptr;
+
+ cameraDevices_.push_back(usb);
+
+ return usb.get();
+}
+
/**
* \brief Acquire exclusive access to the pipeline handler for the process
*
@@ -173,9 +205,9 @@ bool PipelineHandler::acquire()
return true;
}
- for (std::shared_ptr<MediaDevice> &media : mediaDevices_) {
- if (!media->lock()) {
- unlockMediaDevices();
+ for (std::shared_ptr<CameraDevice> &device : cameraDevices_) {
+ if (!device->lock()) {
+ unlockCameraDevices();
return false;
}
}
@@ -206,7 +238,7 @@ void PipelineHandler::release(Camera *camera)
ASSERT(useCount_);
- unlockMediaDevices();
+ unlockCameraDevices();
releaseDevice(camera);
@@ -224,10 +256,10 @@ void PipelineHandler::releaseDevice([[maybe_unused]] Camera *camera)
{
}
-void PipelineHandler::unlockMediaDevices()
+void PipelineHandler::unlockCameraDevices()
{
- for (std::shared_ptr<MediaDevice> &media : mediaDevices_)
- media->unlock();
+ for (std::shared_ptr<CameraDevice> &device : cameraDevices_)
+ device->unlock();
}
/**
@@ -606,7 +638,7 @@ void PipelineHandler::registerCamera(std::shared_ptr<Camera> camera)
{
cameras_.push_back(camera);
- if (mediaDevices_.empty())
+ if (cameraDevices_.empty())
LOG(Pipeline, Fatal)
<< "Registering camera with no media devices!";
@@ -615,7 +647,20 @@ void PipelineHandler::registerCamera(std::shared_ptr<Camera> camera)
* to the camera.
*/
std::vector<int64_t> devnums;
- for (const std::shared_ptr<MediaDevice> &media : mediaDevices_) {
+ for (const std::shared_ptr<CameraDevice> &device : cameraDevices_) {
+ /*
+ * Only MediaDevice has entities and devnums.
+ *
+ * FIXME: This code path "abuses" RTTI. In general, conditional
+ * execution based on type information is discouraged and is
+ * a symptom of a fragile design. However this could be
+ * considered a temporary workaround, as USB-based devices
+ * should report devnums as well in future.
+ */
+ MediaDevice *media = dynamic_cast<MediaDevice *>(device.get());
+ if (!media)
+ continue;
+
for (const MediaEntity *entity : media->entities()) {
if (entity->pads().size() == 1 &&
(entity->pads()[0]->flags() & MEDIA_PAD_FL_SINK) &&
--
2.40.1
More information about the libcamera-devel
mailing list