[PATCH v3 1/1] pipeline: simple: Fix matching with empty media graphs
Kieran Bingham
kieran.bingham at ideasonboard.com
Mon May 26 10:58:41 CEST 2025
Quoting Paul Elder (2025-05-13 14:37:51)
> The match() function currently reports that it is not possible to create
> any cameras if it encounters an empty media graph.
>
> Fix this by looping over all media graphs and only returning false when
> all of them fail to create a camera.
>
> It is worth noting that an issue does exist when on a partial match that
> ends in an invalid match, any media devices that were acquired will stay
> acquired. This is not a new issue though, as any acquired media devices
> in general are not released until pipeline handler deconstruction. This
> requires a rework of how we do matching and pipeline handler
> construction, so it is captured in a comment.
>
> In the meantime, this fix fixes a problem without increasing the net
> number of problems.
>
> Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
>
> ---
> Changes in v3:
> - removed clearMediaDevices()
> - the reason is elaborated on in both the commit message and the todo
> comment
I think this is the best we can do until we have a rework of the
DeviceEnumerator...
Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
>
> Changes in v2:
> - added clearMediaDevices()
> ---
> src/libcamera/pipeline/simple/simple.cpp | 62 +++++++++++++++++-------
> 1 file changed, 45 insertions(+), 17 deletions(-)
>
> diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
> index efb07051b..4323472e1 100644
> --- a/src/libcamera/pipeline/simple/simple.cpp
> +++ b/src/libcamera/pipeline/simple/simple.cpp
> @@ -427,6 +427,9 @@ private:
> return static_cast<SimpleCameraData *>(camera->_d());
> }
>
> + bool matchDevice(MediaDevice *media, const SimplePipelineInfo &info,
> + DeviceEnumerator *enumerator);
> +
> std::vector<MediaEntity *> locateSensors(MediaDevice *media);
> static int resetRoutingTable(V4L2Subdevice *subdev);
>
> @@ -1660,25 +1663,13 @@ int SimplePipelineHandler::resetRoutingTable(V4L2Subdevice *subdev)
> return 0;
> }
>
> -bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
> +bool SimplePipelineHandler::matchDevice(MediaDevice *media,
> + const SimplePipelineInfo &info,
> + DeviceEnumerator *enumerator)
> {
> - const SimplePipelineInfo *info = nullptr;
> unsigned int numStreams = 1;
> - MediaDevice *media;
>
> - for (const SimplePipelineInfo &inf : supportedDevices) {
> - DeviceMatch dm(inf.driver);
> - media = acquireMediaDevice(enumerator, dm);
> - if (media) {
> - info = &inf;
> - break;
> - }
> - }
> -
> - if (!media)
> - return false;
> -
> - for (const auto &[name, streams] : info->converters) {
> + for (const auto &[name, streams] : info.converters) {
> DeviceMatch converterMatch(name);
> converter_ = acquireMediaDevice(enumerator, converterMatch);
> if (converter_) {
> @@ -1687,7 +1678,7 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
> }
> }
>
> - swIspEnabled_ = info->swIspEnabled;
> + swIspEnabled_ = info.swIspEnabled;
>
> /* Locate the sensors. */
> std::vector<MediaEntity *> sensors = locateSensors(media);
> @@ -1806,6 +1797,43 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
> return registered;
> }
>
> +bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
> +{
> + MediaDevice *media;
> +
> + for (const SimplePipelineInfo &inf : supportedDevices) {
> + DeviceMatch dm(inf.driver);
> + while ((media = acquireMediaDevice(enumerator, dm))) {
> + /*
> + * If match succeeds, return true to let match() be
> + * called again on a new instance of the pipeline
> + * handler. Otherwise keep looping until we do
> + * successfully match one (or run out).
> + */
> + if (matchDevice(media, inf, enumerator)) {
> + LOG(SimplePipeline, Debug)
> + << "Matched on device: "
> + << media->deviceNode();
> + return true;
> + }
> +
> + /*
> + * \todo We need to clear the list of media devices
> + * that we've already acquired in the event that we
> + * fail to create a camera. This requires a rework of
> + * DeviceEnumerator, or even how we create pipelines
> + * handlers. This is because at the moment acquired
> + * media devices are only released on pipeline handler
> + * deconstruction, and if we release them any earlier
> + * then DeviceEnumerator::search() will keep returning
> + * the same media devices.
> + */
> + }
> + }
> +
> + return false;
> +}
> +
> V4L2VideoDevice *SimplePipelineHandler::video(const MediaEntity *entity)
> {
> auto iter = entities_.find(entity);
> --
> 2.39.2
>
More information about the libcamera-devel
mailing list