[EXT] Re: [PATCH] libcamera: simple: Check all media devices matched the pipeline
Hui Fang
hui.fang at nxp.com
Fri Feb 28 07:17:38 CET 2025
Hi, Bingham
Thanks for your reminding.
The patch is to fix below issue:
wevk_8mq has 2 camera slots, if just 1 slot plug sensor, if may mis-discovered.
There's 2 media deivces, suggest mediaA(with sensor), mediaB(no sensor). If mediaB is in the 1st place (depends of readdir()) of the enumerator,
pipe->match(enumerator_.get() return false and mediaA has no chance to be discovered.
Ref code in camera_manager.cpp
void CameraManager::Private::pipelineFactoryMatch(const PipelineHandlerFactoryBase *factory)
{
CameraManager *const o = LIBCAMERA_O_PTR();
/* Provide as many matching pipelines as possible. */
while (1) {
std::shared_ptr<PipelineHandler> pipe = factory->create(o);
if (!pipe->match(enumerator_.get()))
break;
LOG(Camera, Debug)
<< "Pipeline handler \"" << factory->name()
<< "\" matched";
}
}
I tested on android, APP/CTS just switch back/front camera, no case to use 2 cameras at same time.
Since the specific "Camera" is register to CameraManager and passed to SimplePipelineHandler, so no issue.
But if there's case to use 2 cameras at same time, should have issue.
Maybe the best resolution is in driver, don't create a media device if no sensor plugged in the media graph.
BRs,
Fang Hui
> -----Original Message-----
> From: Kieran Bingham <kieran.bingham at ideasonboard.com>
> Sent: 2025年2月28日 3:57
> To: Hui Fang <hui.fang at nxp.com>; libcamera-devel at lists.libcamera.org
> Cc: jacopo.mondi at ideasonboard.com; mzamazal at redhat.com;
> dan.scally at ideasonboard.com; Hui Fang <hui.fang at nxp.com>; Antoine
> Bouyer <antoine.bouyer at nxp.com>
> Subject: [EXT] Re: [PATCH] libcamera: simple: Check all media devices
> matched the pipeline
>
> Caution: This is an external email. Please take care when clicking links or
> opening attachments. When in doubt, report the message using the 'Report
> this email' button
>
>
> Hi Fang,
>
> Quoting Fang Hui (2025-02-25 02:10:23)
> > The current implementation of SimplePipelineHandler::match() will
> > return false once meet an un-complete media device such as no sensor
> > plugged. Thus the rest media devices will lost the chance to be discovered.
> > To discover all the cameras present, this change instanciates the
> > cameras discovery procedure for each media device that contains a
> supported camera port.
> >
> > Signed-off-by: Fang Hui <hui.fang at nxp.com>
> > ---
> > src/libcamera/pipeline/simple/simple.cpp | 50
> > +++++++++++++++++-------
> > 1 file changed, 35 insertions(+), 15 deletions(-)
> >
> > diff --git a/src/libcamera/pipeline/simple/simple.cpp
> > b/src/libcamera/pipeline/simple/simple.cpp
> > index 6e039bf3..134f0a07 100644
> > --- a/src/libcamera/pipeline/simple/simple.cpp
> > +++ b/src/libcamera/pipeline/simple/simple.cpp
> > @@ -379,6 +379,8 @@ private:
> > const MediaPad *acquirePipeline(SimpleCameraData *data);
> > void releasePipeline(SimpleCameraData *data);
> >
> > + bool matchMedia(DeviceEnumerator *enumerator, const
> > + SimplePipelineInfo *info, MediaDevice *media);
> > +
> > std::map<const MediaEntity *, EntityData> entities_;
> >
> > MediaDevice *converter_;
> > @@ -1532,23 +1534,9 @@ int
> SimplePipelineHandler::resetRoutingTable(V4L2Subdevice *subdev)
> > return 0;
> > }
> >
> > -bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
> > +bool SimplePipelineHandler::matchMedia(DeviceEnumerator *enumerator,
> > +const SimplePipelineInfo *info, MediaDevice *media)
> > {
> > - 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) {
> > DeviceMatch converterMatch(name); @@ -1678,6
> +1666,38
> > @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
> > return registered;
> > }
> >
> > +bool SimplePipelineHandler::match(DeviceEnumerator *enumerator) {
> > + MediaDevice *media;
> > + std::map<MediaDevice *, const SimplePipelineInfo *>
> > +mediaDevices;
> > +
> > + for (const SimplePipelineInfo &inf : supportedDevices) {
> > + LOG(SimplePipeline, Debug) << "check simple pipeline "
> << inf.driver;
> > + DeviceMatch dm(inf.driver);
> > +
> > + do {
> > + media = acquireMediaDevice(enumerator,
> dm);
> > + if (media) {
> > + mediaDevices[media] = &inf;
> > + LOG(SimplePipeline, Debug) <<
> "found media " << media->deviceNode();
> > + }
> > + } while (media);
> > + }
> > +
> > + bool matched = false;
> > +
> > + for (auto it = mediaDevices.begin(); it != mediaDevices.end(); it++)
> {
> > + MediaDevice *media = it->first;
> > + const SimplePipelineInfo *info = it->second;
> > + LOG(SimplePipeline, Debug)
> > + << "call matchMedia for pipeline "
> > + << info->driver << ", media " <<
> media->deviceNode();
> > + matched |= matchMedia(enumerator, info, media);
> > + }
>
> I'm not 100% sure I understand the implications here. I also tried to tackle this
> topic at
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatch
> work.libcamera.org%2Fpatch%2F20849%2F&data=05%7C02%7Chui.fang%40
> nxp.com%7C7df77e1abad34fc20d4908dd5768dfd0%7C686ea1d3bc2b4c6fa9
> 2cd99c5c301635%7C0%7C0%7C638762830140008274%7CUnknown%7CTW
> FpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW
> 4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=Y1vZOi
> FLPsKslaQ9QjnsgWzAXfVdy6NZ%2BpZc1Gedl%2Fo%3D&reserved=0, and I
> see your version differs slightly that first you will try to find all compatible
> graphs, but then match each of the successfully acquired ones.
>
> But I think this will be problematic as you will then register (or try to register)
> multiple graphs in a single pipeline handler ?
>
> Have you checked what happens here if there are more than one simple
> pipeline handler supported in the system ?
>
>
>
> > +
> > + return matched;
> > +}
> > +
> > V4L2VideoDevice *SimplePipelineHandler::video(const MediaEntity
> > *entity) {
> > auto iter = entities_.find(entity);
> > --
> > 2.25.1
> >
More information about the libcamera-devel
mailing list