@@ -90,7 +90,7 @@ functionalities described above. Below is a brief overview of each of those:
registered with it, by creating instances of the ``MediaDevice`` class and
storing them.
-- `DeviceMatch <https://libcamera.org/api-html/classlibcamera_1_1DeviceMatch.html>`_:
+- `MediaDeviceMatch <https://libcamera.org/api-html/classlibcamera_1_1MediaDeviceMatch.html>`_:
Describes a media device search pattern using entity names, or other
properties.
@@ -316,10 +316,10 @@ Matching devices
~~~~~~~~~~~~~~~~
Each pipeline handler registered in libcamera gets tested against the current
-system configuration, by matching a ``DeviceMatch`` with the system
-``DeviceEnumerator``. A successful match makes sure all the requested components
-have been registered in the system and allows the pipeline handler to be
-initialized.
+system configuration, by matching an instance of a class derived from
+``DeviceMatch`` with the system ``DeviceEnumerator``. A successful match makes
+sure all the requested components have been registered in the system and allows
+the pipeline handler to be initialized.
The main entry point of a pipeline handler is the `match()`_ class member
function. When the ``CameraManager`` is started (using the `start()`_ function),
@@ -29,7 +29,7 @@ public:
virtual int init() = 0;
virtual int enumerate() = 0;
- std::shared_ptr<MediaDevice> search(const DeviceMatch &dm);
+ std::shared_ptr<MediaDevice> search(const MediaDeviceMatch &dm);
Signal<> devicesAdded;
@@ -17,11 +17,16 @@ class MediaDevice;
class DeviceMatch
{
public:
- DeviceMatch(const std::string &driver);
+ virtual bool match(const MediaDevice *device) const = 0;
+};
+class MediaDeviceMatch : public DeviceMatch
+{
+public:
void add(const std::string &entity);
+ MediaDeviceMatch(const std::string &driver);
- bool match(const MediaDevice *device) const;
+ bool match(const MediaDevice *device) const override;
private:
std::string driver_;
@@ -28,7 +28,7 @@ class Camera;
class CameraConfiguration;
class CameraManager;
class DeviceEnumerator;
-class DeviceMatch;
+class MediaDeviceMatch;
class FrameBuffer;
class MediaDevice;
class PipelineHandler;
@@ -43,7 +43,7 @@ public:
virtual bool match(DeviceEnumerator *enumerator) = 0;
MediaDevice *acquireMediaDevice(DeviceEnumerator *enumerator,
- const DeviceMatch &dm);
+ const MediaDeviceMatch &dm);
bool acquire();
void release(Camera *camera);
@@ -229,7 +229,7 @@ void DeviceEnumerator::removeDevice(const std::string &deviceNode)
*
* \return pointer to the matching MediaDevice, or nullptr if no match is found
*/
-std::shared_ptr<MediaDevice> DeviceEnumerator::search(const DeviceMatch &dm)
+std::shared_ptr<MediaDevice> DeviceEnumerator::search(const MediaDeviceMatch &dm)
{
for (std::shared_ptr<MediaDevice> &media : devices_) {
if (media->busy())
@@ -18,21 +18,38 @@ namespace libcamera {
/**
* \class DeviceMatch
+ * \brief Pure virtual base class for device serch pattern
+ *
+ * The DeviceMatch class defines the interface to implement device search
+ * patterns to allow searching and matching different device typologies, such as
+ * media devices for V4L2/MC cameras, USB for cameras controlled through the USB
+ * protocol which do not implement the UVC specification and for virtual
+ * cameras.
+ *
+ * Pipeline handlers are expected to instantiate the correct derived class
+ * depending on the device type they support and populate it with their desired
+ * matching criteria. Derived classes of DeviceMatch override the pure virtual
+ * match() function to implement custom matching criteria based on the device
+ * type they represent.
+ */
+
+/**
+ * \class MediaDeviceMatch
* \brief Description of a media device search pattern
*
- * The DeviceMatch class describes a media device using properties from the
+ * The MediaDeviceMatch class describes a media device using properties from the
* Media Controller struct media_device_info, entity names in the media graph
* or other properties that can be used to identify a media device.
*
* The description is meant to be filled by pipeline managers and passed to a
* device enumerator to find matching media devices.
*
- * A DeviceMatch is created with a specific Linux device driver in mind,
+ * A MediaDeviceMatch is created with a specific Linux device driver in mind,
* therefore the name of the driver is a required property. One or more Entity
* names can be added as match criteria.
*
- * Pipeline handlers are recommended to add entities to DeviceMatch as
- * appropriare to ensure that the media device they need can be uniquely
+ * Pipeline handlers are recommended to add entities to MediaDeviceMatch as
+ * appropriate to ensure that the media device they need can be uniquely
* identified. This is useful when the corresponding kernel driver can produce
* different graphs, for instance as a result of different driver versions or
* hardware configurations, and not all those graphs are suitable for a pipeline
@@ -43,7 +60,7 @@ namespace libcamera {
* \brief Construct a media device search pattern
* \param[in] driver The Linux device driver name that created the media device
*/
-DeviceMatch::DeviceMatch(const std::string &driver)
+MediaDeviceMatch::MediaDeviceMatch(const std::string &driver)
: driver_(driver)
{
}
@@ -52,7 +69,7 @@ DeviceMatch::DeviceMatch(const std::string &driver)
* \brief Add a media entity name to the search pattern
* \param[in] entity The name of the entity in the media graph
*/
-void DeviceMatch::add(const std::string &entity)
+void MediaDeviceMatch::add(const std::string &entity)
{
entities_.push_back(entity);
}
@@ -67,7 +84,7 @@ void DeviceMatch::add(const std::string &entity)
*
* \return True if the media device matches the search pattern, false otherwise
*/
-bool DeviceMatch::match(const MediaDevice *device) const
+bool MediaDeviceMatch::match(const MediaDevice *device) const
{
if (driver_ != device->driver())
return false;
@@ -971,7 +971,7 @@ int PipelineHandlerISI::queueRequestDevice(Camera *camera, Request *request)
bool PipelineHandlerISI::match(DeviceEnumerator *enumerator)
{
- DeviceMatch dm("mxc-isi");
+ MediaDeviceMatch dm("mxc-isi");
dm.add("crossbar");
dm.add("mxc_isi.0");
dm.add("mxc_isi.0.capture");
@@ -846,7 +846,7 @@ bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator)
{
int ret;
- DeviceMatch cio2_dm("ipu3-cio2");
+ MediaDeviceMatch cio2_dm("ipu3-cio2");
cio2_dm.add("ipu3-csi2 0");
cio2_dm.add("ipu3-cio2 0");
cio2_dm.add("ipu3-csi2 1");
@@ -856,7 +856,7 @@ bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator)
cio2_dm.add("ipu3-csi2 3");
cio2_dm.add("ipu3-cio2 3");
- DeviceMatch imgu_dm("ipu3-imgu");
+ MediaDeviceMatch imgu_dm("ipu3-imgu");
imgu_dm.add("ipu3-imgu 0");
imgu_dm.add("ipu3-imgu 0 input");
imgu_dm.add("ipu3-imgu 0 parameters");
@@ -1155,7 +1155,7 @@ bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator)
{
const MediaPad *pad;
- DeviceMatch dm("rkisp1");
+ MediaDeviceMatch dm("rkisp1");
dm.add("rkisp1_isp");
dm.add("rkisp1_resizer_mainpath");
dm.add("rkisp1_mainpath");
@@ -175,7 +175,7 @@ bool PipelineHandlerVc4::match(DeviceEnumerator *enumerator)
* device nodes due to a sensor subdevice failure.
*/
for (unsigned int i = 0; i < numUnicamDevices; i++) {
- DeviceMatch unicam("unicam");
+ MediaDeviceMatch unicam("unicam");
MediaDevice *unicamDevice = acquireMediaDevice(enumerator, unicam);
if (!unicamDevice) {
@@ -183,7 +183,7 @@ bool PipelineHandlerVc4::match(DeviceEnumerator *enumerator)
continue;
}
- DeviceMatch isp("bcm2835-isp");
+ MediaDeviceMatch isp("bcm2835-isp");
MediaDevice *ispDevice = acquireMediaDevice(enumerator, isp);
if (!ispDevice) {
@@ -1398,7 +1398,7 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
unsigned int numStreams = 1;
for (const SimplePipelineInfo &inf : supportedDevices) {
- DeviceMatch dm(inf.driver);
+ MediaDeviceMatch dm(inf.driver);
media_ = acquireMediaDevice(enumerator, dm);
if (media_) {
info = &inf;
@@ -1410,7 +1410,7 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
return false;
for (const auto &[name, streams] : info->converters) {
- DeviceMatch converterMatch(name);
+ MediaDeviceMatch converterMatch(name);
converter_ = acquireMediaDevice(enumerator, converterMatch);
if (converter_) {
numStreams = streams;
@@ -387,7 +387,7 @@ int PipelineHandlerUVC::queueRequestDevice(Camera *camera, Request *request)
bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
{
MediaDevice *media;
- DeviceMatch dm("uvcvideo");
+ MediaDeviceMatch dm("uvcvideo");
media = acquireMediaDevice(enumerator, dm);
if (!media)
@@ -442,7 +442,7 @@ int PipelineHandlerVimc::queueRequestDevice(Camera *camera, Request *request)
bool PipelineHandlerVimc::match(DeviceEnumerator *enumerator)
{
- DeviceMatch dm("vimc");
+ MediaDeviceMatch dm("vimc");
dm.add("Raw Capture 0");
dm.add("Raw Capture 1");
@@ -22,6 +22,7 @@
#include "libcamera/internal/camera.h"
#include "libcamera/internal/camera_manager.h"
#include "libcamera/internal/device_enumerator.h"
+#include "libcamera/internal/device_match.h"
#include "libcamera/internal/framebuffer.h"
#include "libcamera/internal/media_device.h"
#include "libcamera/internal/request.h"
@@ -129,7 +130,7 @@ PipelineHandler::~PipelineHandler()
* \return A pointer to the matching MediaDevice, or nullptr if no match is found
*/
MediaDevice *PipelineHandler::acquireMediaDevice(DeviceEnumerator *enumerator,
- const DeviceMatch &dm)
+ const MediaDeviceMatch &dm)
{
std::shared_ptr<MediaDevice> media = enumerator->search(dm);
if (!media)
@@ -39,7 +39,7 @@ protected:
return TestFail;
}
- DeviceMatch dm("vimc");
+ MediaDeviceMatch dm("vimc");
media_ = enumerator_->search(dm);
if (!media_) {
cerr << "Unable to find \'vimc\' media device node" << endl;
@@ -38,7 +38,7 @@ protected:
return TestFail;
}
- DeviceMatch dm("vivid");
+ MediaDeviceMatch dm("vivid");
dm.add("vivid-000-vid-cap");
media_ = enumerator_->search(dm);
@@ -43,7 +43,7 @@ int BufferSource::allocate(const StreamConfiguration &config)
return TestFail;
}
- DeviceMatch dm("vivid");
+ MediaDeviceMatch dm("vivid");
dm.add(videoDeviceName);
media_ = enumerator->search(dm);
@@ -25,7 +25,7 @@ int MediaDeviceTest::init()
return TestFail;
}
- DeviceMatch dm("vimc");
+ MediaDeviceMatch dm("vimc");
media_ = enumerator_->search(dm);
if (!media_) {
cerr << "No VIMC media device found: skip test" << endl;
@@ -39,7 +39,7 @@ int V4L2SubdeviceTest::init()
return TestFail;
}
- DeviceMatch dm("vimc");
+ MediaDeviceMatch dm("vimc");
media_ = enumerator_->search(dm);
if (!media_) {
cerr << "Unable to find \'vimc\' media device node" << endl;
@@ -65,7 +65,7 @@ protected:
return TestFail;
}
- DeviceMatch dm("vim2m");
+ MediaDeviceMatch dm("vim2m");
dm.add("vim2m-source");
dm.add("vim2m-sink");
@@ -30,7 +30,7 @@ int V4L2VideoDeviceTest::init()
return TestFail;
}
- DeviceMatch dm(driver_);
+ MediaDeviceMatch dm(driver_);
dm.add(entity_);
media_ = enumerator_->search(dm);
The xistingdevice search and match criteria implemented by libcamera only supports 'media device' based cameras, which are supported in the Linux kernel by the usage of the V4L2/MC API. Define a MediaDeviceMatch class derived from DeviceMatch and use it wherever DeviceMatch was used in order to later introduce new derived classes to support searching and matching devices of a different type. Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> --- Documentation/guides/pipeline-handler.rst | 10 +++--- .../libcamera/internal/device_enumerator.h | 2 +- include/libcamera/internal/device_match.h | 9 ++++-- include/libcamera/internal/pipeline_handler.h | 4 +-- src/libcamera/device_enumerator.cpp | 2 +- src/libcamera/device_match.cpp | 31 ++++++++++++++----- src/libcamera/pipeline/imx8-isi/imx8-isi.cpp | 2 +- src/libcamera/pipeline/ipu3/ipu3.cpp | 4 +-- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 2 +- src/libcamera/pipeline/rpi/vc4/vc4.cpp | 4 +-- src/libcamera/pipeline/simple/simple.cpp | 4 +-- src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 2 +- src/libcamera/pipeline/vimc/vimc.cpp | 2 +- src/libcamera/pipeline_handler.cpp | 3 +- test/camera-sensor.cpp | 2 +- test/delayed_controls.cpp | 2 +- test/libtest/buffer_source.cpp | 2 +- test/media_device/media_device_test.cpp | 2 +- test/v4l2_subdevice/v4l2_subdevice_test.cpp | 2 +- test/v4l2_videodevice/v4l2_m2mdevice.cpp | 2 +- .../v4l2_videodevice_test.cpp | 2 +- 21 files changed, 59 insertions(+), 36 deletions(-)