From patchwork Tue Aug 8 12:52:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 18929 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 2F0FABDB13 for ; Tue, 8 Aug 2023 12:52:51 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B409D627F7; Tue, 8 Aug 2023 14:52:50 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1691499170; bh=9UO8Ks6Nkymmev/NMNhwFvpBCxbTK5Z3Uz4dlZfNIhc=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=wsml1F0AIMcvqrgP4qQK+9LkFXCgCR9IYRIs87vHIElmCen0+RaOHXDNUkyTyuVfT YgdzAdCSx5Yq5PNeziAHOwfk7MbSorX2O2F2sFqeoAjFONGqejxVgmRHRL+U6mhVpq k0zN57Ku8p623doKRVT60cn89f5o6rr8Xt5SFFUvEil8pc7TWoy+0HlLDnAnffHrSL SQUM/STSt4Qyd/d1htI+899g0nIcpJjy2Gkw5nH+Ot70nux5p0ncItPeAE27r2A9g5 R47vSWXYmq85Mwsav6Uy/bWfjz3vhg0P2Jrlh/Gb4uOpHgqcyEEeqoZ3NKcU8KQAMM eZcfjecdqkMOg== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D2DFB627EE for ; Tue, 8 Aug 2023 14:52:47 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="DNeXDtwE"; dkim-atps=neutral Received: from uno.localdomain (mob-5-90-60-22.net.vodafone.it [5.90.60.22]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 9182738DA; Tue, 8 Aug 2023 14:51:39 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1691499100; bh=9UO8Ks6Nkymmev/NMNhwFvpBCxbTK5Z3Uz4dlZfNIhc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DNeXDtwERuGDarBmMEuV2L0RDuVYrFfbukBOTfoYFc2TDC9cIbDi9hLVKw53FNofP SE0e5DOAUkGzZBljD92As6f7adn7H9IMJVZx7XTI3aPTmZ2YNRH2KeFQ9AoqaVGQ9I BbuhLCUVxcrQ4LkUSUoRLJsMISLWhoIZrx5ZN2r0= To: libcamera-devel@lists.libcamera.org, Sophie Friedrich Date: Tue, 8 Aug 2023 14:52:21 +0200 Message-Id: <20230808125228.29043-3-jacopo.mondi@ideasonboard.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230808125228.29043-1-jacopo.mondi@ideasonboard.com> References: <20230808125228.29043-1-jacopo.mondi@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC 2/9] libcamera: Define and use MediaDeviceMatch X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Cc: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" 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 --- 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(-) diff --git a/Documentation/guides/pipeline-handler.rst b/Documentation/guides/pipeline-handler.rst index 10b9c75c2a7f..c3b21a885e19 100644 --- a/Documentation/guides/pipeline-handler.rst +++ b/Documentation/guides/pipeline-handler.rst @@ -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 `_: +- `MediaDeviceMatch `_: 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), diff --git a/include/libcamera/internal/device_enumerator.h b/include/libcamera/internal/device_enumerator.h index 259a9e4621ea..2afb9fa0dea8 100644 --- a/include/libcamera/internal/device_enumerator.h +++ b/include/libcamera/internal/device_enumerator.h @@ -29,7 +29,7 @@ public: virtual int init() = 0; virtual int enumerate() = 0; - std::shared_ptr search(const DeviceMatch &dm); + std::shared_ptr search(const MediaDeviceMatch &dm); Signal<> devicesAdded; diff --git a/include/libcamera/internal/device_match.h b/include/libcamera/internal/device_match.h index 9f190f0c8a84..6df7dece1031 100644 --- a/include/libcamera/internal/device_match.h +++ b/include/libcamera/internal/device_match.h @@ -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_; diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h index c96944f4ecc4..02b2f33727a3 100644 --- a/include/libcamera/internal/pipeline_handler.h +++ b/include/libcamera/internal/pipeline_handler.h @@ -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); diff --git a/src/libcamera/device_enumerator.cpp b/src/libcamera/device_enumerator.cpp index 49afd7834db2..3dda08380e6e 100644 --- a/src/libcamera/device_enumerator.cpp +++ b/src/libcamera/device_enumerator.cpp @@ -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 DeviceEnumerator::search(const DeviceMatch &dm) +std::shared_ptr DeviceEnumerator::search(const MediaDeviceMatch &dm) { for (std::shared_ptr &media : devices_) { if (media->busy()) diff --git a/src/libcamera/device_match.cpp b/src/libcamera/device_match.cpp index a51b9081d398..17937d435c88 100644 --- a/src/libcamera/device_match.cpp +++ b/src/libcamera/device_match.cpp @@ -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; diff --git a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp index 9bdfff0b155e..b7670a3cad8c 100644 --- a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp +++ b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp @@ -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"); diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index a81c817a1255..5eca9eb0b922 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -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"); diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 6efa79f29f66..5855c9d3cacc 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -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"); diff --git a/src/libcamera/pipeline/rpi/vc4/vc4.cpp b/src/libcamera/pipeline/rpi/vc4/vc4.cpp index 018cf4881d0e..78fd392256e1 100644 --- a/src/libcamera/pipeline/rpi/vc4/vc4.cpp +++ b/src/libcamera/pipeline/rpi/vc4/vc4.cpp @@ -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) { diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 05ba76bce630..88159a0c4197 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -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; diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp index 38f48a5d9269..2114d48a2a66 100644 --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp @@ -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) diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp index 00e6f4c6a51f..f97209ba26b0 100644 --- a/src/libcamera/pipeline/vimc/vimc.cpp +++ b/src/libcamera/pipeline/vimc/vimc.cpp @@ -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"); diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp index 9c74c6cfda70..ca177cad985c 100644 --- a/src/libcamera/pipeline_handler.cpp +++ b/src/libcamera/pipeline_handler.cpp @@ -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 media = enumerator->search(dm); if (!media) diff --git a/test/camera-sensor.cpp b/test/camera-sensor.cpp index 2a17cc79ea76..e35126ca1831 100644 --- a/test/camera-sensor.cpp +++ b/test/camera-sensor.cpp @@ -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; diff --git a/test/delayed_controls.cpp b/test/delayed_controls.cpp index a8ce9828d73d..9063ef3e7a20 100644 --- a/test/delayed_controls.cpp +++ b/test/delayed_controls.cpp @@ -38,7 +38,7 @@ protected: return TestFail; } - DeviceMatch dm("vivid"); + MediaDeviceMatch dm("vivid"); dm.add("vivid-000-vid-cap"); media_ = enumerator_->search(dm); diff --git a/test/libtest/buffer_source.cpp b/test/libtest/buffer_source.cpp index dde11f365e43..8cb6f6353b99 100644 --- a/test/libtest/buffer_source.cpp +++ b/test/libtest/buffer_source.cpp @@ -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); diff --git a/test/media_device/media_device_test.cpp b/test/media_device/media_device_test.cpp index 1397d1236697..8189e068212c 100644 --- a/test/media_device/media_device_test.cpp +++ b/test/media_device/media_device_test.cpp @@ -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; diff --git a/test/v4l2_subdevice/v4l2_subdevice_test.cpp b/test/v4l2_subdevice/v4l2_subdevice_test.cpp index d8fbfd9f6b0f..56e5cc8377c4 100644 --- a/test/v4l2_subdevice/v4l2_subdevice_test.cpp +++ b/test/v4l2_subdevice/v4l2_subdevice_test.cpp @@ -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; diff --git a/test/v4l2_videodevice/v4l2_m2mdevice.cpp b/test/v4l2_videodevice/v4l2_m2mdevice.cpp index c45f581a8653..0effbf191966 100644 --- a/test/v4l2_videodevice/v4l2_m2mdevice.cpp +++ b/test/v4l2_videodevice/v4l2_m2mdevice.cpp @@ -65,7 +65,7 @@ protected: return TestFail; } - DeviceMatch dm("vim2m"); + MediaDeviceMatch dm("vim2m"); dm.add("vim2m-source"); dm.add("vim2m-sink"); diff --git a/test/v4l2_videodevice/v4l2_videodevice_test.cpp b/test/v4l2_videodevice/v4l2_videodevice_test.cpp index 125aafd65041..addc47d2b62a 100644 --- a/test/v4l2_videodevice/v4l2_videodevice_test.cpp +++ b/test/v4l2_videodevice/v4l2_videodevice_test.cpp @@ -30,7 +30,7 @@ int V4L2VideoDeviceTest::init() return TestFail; } - DeviceMatch dm(driver_); + MediaDeviceMatch dm(driver_); dm.add(entity_); media_ = enumerator_->search(dm);