[libcamera-devel,RFC,v2,1/5] libcamera: pipeline: uvcvideo: Add UVC metadata node
diff mbox series

Message ID 20230821131039.127370-2-gabbymg94@gmail.com
State New
Headers show
Series
  • Add UVC Metadata buffer timestamp support
Related show

Commit Message

Gabrielle George Aug. 21, 2023, 1:10 p.m. UTC
Identify and open the UVC metadata's video node. This will give us
access to metadata associated with the video stream of the uvc camera.
The user will not have access to this video node and will not need to
manage its data in any way.

Signed-off-by: Gabby George <gabbymg94@gmail.com>
---
 src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 42 ++++++++++++++++++++
 1 file changed, 42 insertions(+)

Comments

Vedant Paranjape Aug. 21, 2023, 1:48 p.m. UTC | #1
Hello Gabby,

Thanks for your patch.

On Mon, Aug 21, 2023 at 6:40 PM Gabby George <gabbymg94@gmail.com> wrote:
>
> Identify and open the UVC metadata's video node. This will give us
> access to metadata associated with the video stream of the uvc camera.
> The user will not have access to this video node and will not need to
> manage its data in any way.
>
> Signed-off-by: Gabby George <gabbymg94@gmail.com>
> ---
>  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 42 ++++++++++++++++++++
>  1 file changed, 42 insertions(+)
>
> diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> index 38f48a5d..dbe0cc8c 100644
> --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> @@ -49,10 +49,13 @@ public:
>         const std::string &id() const { return id_; }
>
>         std::unique_ptr<V4L2VideoDevice> video_;
> +       std::unique_ptr<V4L2VideoDevice> metadata_;
>         Stream stream_;
>         std::map<PixelFormat, std::vector<SizeRange>> formats_;
>
>  private:
> +       int initMetadata(MediaDevice *media);
> +
>         bool generateId();
>
>         std::string id_;
> @@ -411,6 +414,39 @@ bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
>         return true;
>  }
>
> +int UVCCameraData::initMetadata(MediaDevice *media)
> +{
> +       int ret;
> +
> +       const std::vector<MediaEntity *> &entities = media->entities();
> +       std::string dev_node_name = video_->deviceNode();
> +       auto metadata = std::find_if(entities.begin(), entities.end(),
> +                                    [&dev_node_name](MediaEntity *e) {
> +                                            return e->type() == MediaEntity::Type::V4L2VideoDevice
> +                                                       && !(e->flags() & MEDIA_ENT_FL_DEFAULT);
> +                                    });
> +
> +       if (metadata == entities.end()) {
> +               return -ENODEV;
> +       }
> +
> +       /* configure the metadata node */
> +       metadata_ = std::make_unique<V4L2VideoDevice>(*metadata);
> +       ret = metadata_->open();

Should we check for validity of metadata_ with a simple if (metadata_)
? or is it overengineering ?

> +       if (ret)
> +               return ret;
> +
> +       if (!(metadata_->caps().isMeta())) {
> +               /*
> +                * UVC Devices are usually only anticipated to expose two
> +         * devices, so we assume the non-default device is the metadata
> +         * device node
> +                */

The comment seems misaligned in indentation, please fix it.

> +               return -EINVAL;
> +       }
> +       return 0;
> +}
> +
>  int UVCCameraData::init(MediaDevice *media)
>  {
>         int ret;
> @@ -512,6 +548,12 @@ int UVCCameraData::init(MediaDevice *media)
>
>         controlInfo_ = ControlInfoMap(std::move(ctrls), controls::controls);
>
> +       ret = initMetadata(media);
> +       if (ret) {
> +               metadata_ = nullptr;

I think, you are leaking metadata_ if the initMetadata function
returns from failure of
<snip>
> +       ret = metadata_->open();
> +       if (ret)
> +               return ret;
</snip>

> +               LOG(UVC, Error) << "Could not find a metadata video device.";
> +       }
> +
>         return 0;
>  }
>
> --
> 2.34.1
>

Regards,
Vedant Paranjape

On Mon, Aug 21, 2023 at 6:40 PM Gabby George <gabbymg94@gmail.com> wrote:
>
> Identify and open the UVC metadata's video node. This will give us
> access to metadata associated with the video stream of the uvc camera.
> The user will not have access to this video node and will not need to
> manage its data in any way.
>
> Signed-off-by: Gabby George <gabbymg94@gmail.com>
> ---
>  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 42 ++++++++++++++++++++
>  1 file changed, 42 insertions(+)
>
> diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> index 38f48a5d..dbe0cc8c 100644
> --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> @@ -49,10 +49,13 @@ public:
>         const std::string &id() const { return id_; }
>
>         std::unique_ptr<V4L2VideoDevice> video_;
> +       std::unique_ptr<V4L2VideoDevice> metadata_;
>         Stream stream_;
>         std::map<PixelFormat, std::vector<SizeRange>> formats_;
>
>  private:
> +       int initMetadata(MediaDevice *media);
> +
>         bool generateId();
>
>         std::string id_;
> @@ -411,6 +414,39 @@ bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
>         return true;
>  }
>
> +int UVCCameraData::initMetadata(MediaDevice *media)
> +{
> +       int ret;
> +
> +       const std::vector<MediaEntity *> &entities = media->entities();
> +       std::string dev_node_name = video_->deviceNode();
> +       auto metadata = std::find_if(entities.begin(), entities.end(),
> +                                    [&dev_node_name](MediaEntity *e) {
> +                                            return e->type() == MediaEntity::Type::V4L2VideoDevice
> +                                                       && !(e->flags() & MEDIA_ENT_FL_DEFAULT);
> +                                    });
> +
> +       if (metadata == entities.end()) {
> +               return -ENODEV;
> +       }
> +
> +       /* configure the metadata node */
> +       metadata_ = std::make_unique<V4L2VideoDevice>(*metadata);
> +       ret = metadata_->open();
> +       if (ret)
> +               return ret;
> +
> +       if (!(metadata_->caps().isMeta())) {
> +               /*
> +                * UVC Devices are usually only anticipated to expose two
> +         * devices, so we assume the non-default device is the metadata
> +         * device node
> +                */
> +               return -EINVAL;
> +       }
> +       return 0;
> +}
> +
>  int UVCCameraData::init(MediaDevice *media)
>  {
>         int ret;
> @@ -512,6 +548,12 @@ int UVCCameraData::init(MediaDevice *media)
>
>         controlInfo_ = ControlInfoMap(std::move(ctrls), controls::controls);
>
> +       ret = initMetadata(media);
> +       if (ret) {
> +               metadata_ = nullptr;
> +               LOG(UVC, Error) << "Could not find a metadata video device.";
> +       }
> +
>         return 0;
>  }
>
> --
> 2.34.1
>
Gabrielle George Aug. 27, 2023, 4:29 a.m. UTC | #2
On Mon, Aug 21, 2023 at 6:49 AM Vedant Paranjape <
vedantparanjape160201@gmail.com> wrote:

> Hello Gabby,
>
> Thanks for your patch.
>
> On Mon, Aug 21, 2023 at 6:40 PM Gabby George <gabbymg94@gmail.com> wrote:
> >
> > Identify and open the UVC metadata's video node. This will give us
> > access to metadata associated with the video stream of the uvc camera.
> > The user will not have access to this video node and will not need to
> > manage its data in any way.
> >
> > Signed-off-by: Gabby George <gabbymg94@gmail.com>
> > ---
> >  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 42 ++++++++++++++++++++
> >  1 file changed, 42 insertions(+)
> >
> > diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> > index 38f48a5d..dbe0cc8c 100644
> > --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> > +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> > @@ -49,10 +49,13 @@ public:
> >         const std::string &id() const { return id_; }
> >
> >         std::unique_ptr<V4L2VideoDevice> video_;
> > +       std::unique_ptr<V4L2VideoDevice> metadata_;
> >         Stream stream_;
> >         std::map<PixelFormat, std::vector<SizeRange>> formats_;
> >
> >  private:
> > +       int initMetadata(MediaDevice *media);
> > +
> >         bool generateId();
> >
> >         std::string id_;
> > @@ -411,6 +414,39 @@ bool PipelineHandlerUVC::match(DeviceEnumerator
> *enumerator)
> >         return true;
> >  }
> >
> > +int UVCCameraData::initMetadata(MediaDevice *media)
> > +{
> > +       int ret;
> > +
> > +       const std::vector<MediaEntity *> &entities = media->entities();
> > +       std::string dev_node_name = video_->deviceNode();
> > +       auto metadata = std::find_if(entities.begin(), entities.end(),
> > +                                    [&dev_node_name](MediaEntity *e) {
> > +                                            return e->type() ==
> MediaEntity::Type::V4L2VideoDevice
> > +                                                       && !(e->flags()
> & MEDIA_ENT_FL_DEFAULT);
> > +                                    });
> > +
> > +       if (metadata == entities.end()) {
> > +               return -ENODEV;
> > +       }
> > +
> > +       /* configure the metadata node */
> > +       metadata_ = std::make_unique<V4L2VideoDevice>(*metadata);
> > +       ret = metadata_->open();
>
> Should we check for validity of metadata_ with a simple if (metadata_)
> ? or is it overengineering ?
>

Good call! I think we should.

>
> > +       if (ret)
> > +               return ret;
> > +
> > +       if (!(metadata_->caps().isMeta())) {
> > +               /*
> > +                * UVC Devices are usually only anticipated to expose two
> > +         * devices, so we assume the non-default device is the metadata
> > +         * device node
> > +                */
>
> The comment seems misaligned in indentation, please fix it.
>

I'll make sure it's correct in the next patch.

>
> > +               return -EINVAL;
> > +       }
> > +       return 0;
> > +}
> > +
> >  int UVCCameraData::init(MediaDevice *media)
> >  {
> >         int ret;
> > @@ -512,6 +548,12 @@ int UVCCameraData::init(MediaDevice *media)
> >
> >         controlInfo_ = ControlInfoMap(std::move(ctrls),
> controls::controls);
> >
> > +       ret = initMetadata(media);
> > +       if (ret) {
> > +               metadata_ = nullptr;
>
> I think, you are leaking metadata_ if the initMetadata function
> returns from failure of
>

I thought assigning null to smart pointers initiates the normal cleanup
routine of the objects they point to.  Is this the leak you're talking
about, or should I clean up something else too?

> <snip>
> > +       ret = metadata_->open();
> > +       if (ret)
> > +               return ret;
> </snip>
>
> > +               LOG(UVC, Error) << "Could not find a metadata video
> device.";
> > +       }
> > +
> >         return 0;
> >  }
> >
> > --
> > 2.34.1
> >
>
> Regards,
> Vedant Paranjape
>

Thanks for the suggestions!

>
> On Mon, Aug 21, 2023 at 6:40 PM Gabby George <gabbymg94@gmail.com> wrote:
> >
> > Identify and open the UVC metadata's video node. This will give us
> > access to metadata associated with the video stream of the uvc camera.
> > The user will not have access to this video node and will not need to
> > manage its data in any way.
> >
> > Signed-off-by: Gabby George <gabbymg94@gmail.com>
> > ---
> >  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 42 ++++++++++++++++++++
> >  1 file changed, 42 insertions(+)
> >
> > diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> > index 38f48a5d..dbe0cc8c 100644
> > --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> > +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> > @@ -49,10 +49,13 @@ public:
> >         const std::string &id() const { return id_; }
> >
> >         std::unique_ptr<V4L2VideoDevice> video_;
> > +       std::unique_ptr<V4L2VideoDevice> metadata_;
> >         Stream stream_;
> >         std::map<PixelFormat, std::vector<SizeRange>> formats_;
> >
> >  private:
> > +       int initMetadata(MediaDevice *media);
> > +
> >         bool generateId();
> >
> >         std::string id_;
> > @@ -411,6 +414,39 @@ bool PipelineHandlerUVC::match(DeviceEnumerator
> *enumerator)
> >         return true;
> >  }
> >
> > +int UVCCameraData::initMetadata(MediaDevice *media)
> > +{
> > +       int ret;
> > +
> > +       const std::vector<MediaEntity *> &entities = media->entities();
> > +       std::string dev_node_name = video_->deviceNode();
> > +       auto metadata = std::find_if(entities.begin(), entities.end(),
> > +                                    [&dev_node_name](MediaEntity *e) {
> > +                                            return e->type() ==
> MediaEntity::Type::V4L2VideoDevice
> > +                                                       && !(e->flags()
> & MEDIA_ENT_FL_DEFAULT);
> > +                                    });
> > +
> > +       if (metadata == entities.end()) {
> > +               return -ENODEV;
> > +       }
> > +
> > +       /* configure the metadata node */
> > +       metadata_ = std::make_unique<V4L2VideoDevice>(*metadata);
> > +       ret = metadata_->open();
> > +       if (ret)
> > +               return ret;
> > +
> > +       if (!(metadata_->caps().isMeta())) {
> > +               /*
> > +                * UVC Devices are usually only anticipated to expose two
> > +         * devices, so we assume the non-default device is the metadata
> > +         * device node
> > +                */
> > +               return -EINVAL;
> > +       }
> > +       return 0;
> > +}
> > +
> >  int UVCCameraData::init(MediaDevice *media)
> >  {
> >         int ret;
> > @@ -512,6 +548,12 @@ int UVCCameraData::init(MediaDevice *media)
> >
> >         controlInfo_ = ControlInfoMap(std::move(ctrls),
> controls::controls);
> >
> > +       ret = initMetadata(media);
> > +       if (ret) {
> > +               metadata_ = nullptr;
> > +               LOG(UVC, Error) << "Could not find a metadata video
> device.";
> > +       }
> > +
> >         return 0;
> >  }
> >
> > --
> > 2.34.1
> >
>
Vedant Paranjape Aug. 27, 2023, 6:58 p.m. UTC | #3
Hello Gabby,

On Sun, Aug 27, 2023 at 9:59 AM Gabrielle George <gabbymg94@gmail.com> wrote:
>
>
>
> On Mon, Aug 21, 2023 at 6:49 AM Vedant Paranjape <vedantparanjape160201@gmail.com> wrote:
>>
>> Hello Gabby,
>>
>> Thanks for your patch.
>>
>> On Mon, Aug 21, 2023 at 6:40 PM Gabby George <gabbymg94@gmail.com> wrote:
>> >
>> > Identify and open the UVC metadata's video node. This will give us
>> > access to metadata associated with the video stream of the uvc camera.
>> > The user will not have access to this video node and will not need to
>> > manage its data in any way.
>> >
>> > Signed-off-by: Gabby George <gabbymg94@gmail.com>
>> > ---
>> >  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 42 ++++++++++++++++++++
>> >  1 file changed, 42 insertions(+)
>> >
>> > diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
>> > index 38f48a5d..dbe0cc8c 100644
>> > --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
>> > +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
>> > @@ -49,10 +49,13 @@ public:
>> >         const std::string &id() const { return id_; }
>> >
>> >         std::unique_ptr<V4L2VideoDevice> video_;
>> > +       std::unique_ptr<V4L2VideoDevice> metadata_;
>> >         Stream stream_;
>> >         std::map<PixelFormat, std::vector<SizeRange>> formats_;
>> >
>> >  private:
>> > +       int initMetadata(MediaDevice *media);
>> > +
>> >         bool generateId();
>> >
>> >         std::string id_;
>> > @@ -411,6 +414,39 @@ bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
>> >         return true;
>> >  }
>> >
>> > +int UVCCameraData::initMetadata(MediaDevice *media)
>> > +{
>> > +       int ret;
>> > +
>> > +       const std::vector<MediaEntity *> &entities = media->entities();
>> > +       std::string dev_node_name = video_->deviceNode();
>> > +       auto metadata = std::find_if(entities.begin(), entities.end(),
>> > +                                    [&dev_node_name](MediaEntity *e) {
>> > +                                            return e->type() == MediaEntity::Type::V4L2VideoDevice
>> > +                                                       && !(e->flags() & MEDIA_ENT_FL_DEFAULT);
>> > +                                    });
>> > +
>> > +       if (metadata == entities.end()) {
>> > +               return -ENODEV;
>> > +       }
>> > +
>> > +       /* configure the metadata node */
>> > +       metadata_ = std::make_unique<V4L2VideoDevice>(*metadata);
>> > +       ret = metadata_->open();
>>
>> Should we check for validity of metadata_ with a simple if (metadata_)
>> ? or is it overengineering ?
>
>
> Good call! I think we should.
>>
>>
>> > +       if (ret)
>> > +               return ret;
>> > +
>> > +       if (!(metadata_->caps().isMeta())) {
>> > +               /*
>> > +                * UVC Devices are usually only anticipated to expose two
>> > +         * devices, so we assume the non-default device is the metadata
>> > +         * device node
>> > +                */
>>
>> The comment seems misaligned in indentation, please fix it.
>
>
> I'll make sure it's correct in the next patch.
>>
>>
>> > +               return -EINVAL;
>> > +       }
>> > +       return 0;
>> > +}
>> > +
>> >  int UVCCameraData::init(MediaDevice *media)
>> >  {
>> >         int ret;
>> > @@ -512,6 +548,12 @@ int UVCCameraData::init(MediaDevice *media)
>> >
>> >         controlInfo_ = ControlInfoMap(std::move(ctrls), controls::controls);
>> >
>> > +       ret = initMetadata(media);
>> > +       if (ret) {
>> > +               metadata_ = nullptr;
>>
>> I think, you are leaking metadata_ if the initMetadata function
>> returns from failure of
>
>
> I thought assigning null to smart pointers initiates the normal cleanup routine of the objects they point to.  Is this the leak you're talking about, or should I clean up something else too?

https://godbolt.org/z/rhx886abY

I tried doing something similar, check the godbolt link, assigning
null has no effect on the allocated memory. (cc: @Laurent Pinchart and
@Kieran Bingham can you guys have a look once)

>>
>> <snip>
>> > +       ret = metadata_->open();
>> > +       if (ret)
>> > +               return ret;
>> </snip>
>>
>> > +               LOG(UVC, Error) << "Could not find a metadata video device.";
>> > +       }
>> > +
>> >         return 0;
>> >  }
>> >
>> > --
>> > 2.34.1
>> >
>>
>> Regards,
>> Vedant Paranjape
>
>
> Thanks for the suggestions!
>>
>>
>> On Mon, Aug 21, 2023 at 6:40 PM Gabby George <gabbymg94@gmail.com> wrote:
>> >
>> > Identify and open the UVC metadata's video node. This will give us
>> > access to metadata associated with the video stream of the uvc camera.
>> > The user will not have access to this video node and will not need to
>> > manage its data in any way.
>> >
>> > Signed-off-by: Gabby George <gabbymg94@gmail.com>
>> > ---
>> >  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 42 ++++++++++++++++++++
>> >  1 file changed, 42 insertions(+)
>> >
>> > diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
>> > index 38f48a5d..dbe0cc8c 100644
>> > --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
>> > +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
>> > @@ -49,10 +49,13 @@ public:
>> >         const std::string &id() const { return id_; }
>> >
>> >         std::unique_ptr<V4L2VideoDevice> video_;
>> > +       std::unique_ptr<V4L2VideoDevice> metadata_;
>> >         Stream stream_;
>> >         std::map<PixelFormat, std::vector<SizeRange>> formats_;
>> >
>> >  private:
>> > +       int initMetadata(MediaDevice *media);
>> > +
>> >         bool generateId();
>> >
>> >         std::string id_;
>> > @@ -411,6 +414,39 @@ bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
>> >         return true;
>> >  }
>> >
>> > +int UVCCameraData::initMetadata(MediaDevice *media)
>> > +{
>> > +       int ret;
>> > +
>> > +       const std::vector<MediaEntity *> &entities = media->entities();
>> > +       std::string dev_node_name = video_->deviceNode();
>> > +       auto metadata = std::find_if(entities.begin(), entities.end(),
>> > +                                    [&dev_node_name](MediaEntity *e) {
>> > +                                            return e->type() == MediaEntity::Type::V4L2VideoDevice
>> > +                                                       && !(e->flags() & MEDIA_ENT_FL_DEFAULT);
>> > +                                    });
>> > +
>> > +       if (metadata == entities.end()) {
>> > +               return -ENODEV;
>> > +       }
>> > +
>> > +       /* configure the metadata node */
>> > +       metadata_ = std::make_unique<V4L2VideoDevice>(*metadata);
>> > +       ret = metadata_->open();
>> > +       if (ret)
>> > +               return ret;
>> > +
>> > +       if (!(metadata_->caps().isMeta())) {
>> > +               /*
>> > +                * UVC Devices are usually only anticipated to expose two
>> > +         * devices, so we assume the non-default device is the metadata
>> > +         * device node
>> > +                */
>> > +               return -EINVAL;
>> > +       }
>> > +       return 0;
>> > +}
>> > +
>> >  int UVCCameraData::init(MediaDevice *media)
>> >  {
>> >         int ret;
>> > @@ -512,6 +548,12 @@ int UVCCameraData::init(MediaDevice *media)
>> >
>> >         controlInfo_ = ControlInfoMap(std::move(ctrls), controls::controls);
>> >
>> > +       ret = initMetadata(media);
>> > +       if (ret) {
>> > +               metadata_ = nullptr;
>> > +               LOG(UVC, Error) << "Could not find a metadata video device.";
>> > +       }
>> > +
>> >         return 0;
>> >  }
>> >
>> > --
>> > 2.34.1
>> >

Regards,
Vedant Paranjape
Jacopo Mondi Aug. 28, 2023, 8:16 a.m. UTC | #4
Hello

On Mon, Aug 28, 2023 at 12:28:49AM +0530, Vedant Paranjape via libcamera-devel wrote:
> Hello Gabby,
>
> On Sun, Aug 27, 2023 at 9:59 AM Gabrielle George <gabbymg94@gmail.com> wrote:
> >
> >
> >
> > On Mon, Aug 21, 2023 at 6:49 AM Vedant Paranjape <vedantparanjape160201@gmail.com> wrote:
> >>
> >> Hello Gabby,
> >>
> >> Thanks for your patch.
> >>
> >> On Mon, Aug 21, 2023 at 6:40 PM Gabby George <gabbymg94@gmail.com> wrote:
> >> >
> >> > Identify and open the UVC metadata's video node. This will give us
> >> > access to metadata associated with the video stream of the uvc camera.
> >> > The user will not have access to this video node and will not need to
> >> > manage its data in any way.
> >> >
> >> > Signed-off-by: Gabby George <gabbymg94@gmail.com>
> >> > ---
> >> >  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 42 ++++++++++++++++++++
> >> >  1 file changed, 42 insertions(+)
> >> >
> >> > diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> >> > index 38f48a5d..dbe0cc8c 100644
> >> > --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> >> > +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> >> > @@ -49,10 +49,13 @@ public:
> >> >         const std::string &id() const { return id_; }
> >> >
> >> >         std::unique_ptr<V4L2VideoDevice> video_;
> >> > +       std::unique_ptr<V4L2VideoDevice> metadata_;
> >> >         Stream stream_;
> >> >         std::map<PixelFormat, std::vector<SizeRange>> formats_;
> >> >
> >> >  private:
> >> > +       int initMetadata(MediaDevice *media);
> >> > +
> >> >         bool generateId();
> >> >
> >> >         std::string id_;
> >> > @@ -411,6 +414,39 @@ bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
> >> >         return true;
> >> >  }
> >> >
> >> > +int UVCCameraData::initMetadata(MediaDevice *media)
> >> > +{
> >> > +       int ret;
> >> > +
> >> > +       const std::vector<MediaEntity *> &entities = media->entities();
> >> > +       std::string dev_node_name = video_->deviceNode();
> >> > +       auto metadata = std::find_if(entities.begin(), entities.end(),
> >> > +                                    [&dev_node_name](MediaEntity *e) {
> >> > +                                            return e->type() == MediaEntity::Type::V4L2VideoDevice
> >> > +                                                       && !(e->flags() & MEDIA_ENT_FL_DEFAULT);
> >> > +                                    });
> >> > +
> >> > +       if (metadata == entities.end()) {
> >> > +               return -ENODEV;
> >> > +       }
> >> > +
> >> > +       /* configure the metadata node */
> >> > +       metadata_ = std::make_unique<V4L2VideoDevice>(*metadata);
> >> > +       ret = metadata_->open();
> >>
> >> Should we check for validity of metadata_ with a simple if (metadata_)
> >> ? or is it overengineering ?
> >
> >
> > Good call! I think we should.
> >>
> >>
> >> > +       if (ret)
> >> > +               return ret;
> >> > +
> >> > +       if (!(metadata_->caps().isMeta())) {
> >> > +               /*
> >> > +                * UVC Devices are usually only anticipated to expose two
> >> > +         * devices, so we assume the non-default device is the metadata
> >> > +         * device node
> >> > +                */
> >>
> >> The comment seems misaligned in indentation, please fix it.
> >
> >
> > I'll make sure it's correct in the next patch.
> >>
> >>
> >> > +               return -EINVAL;
> >> > +       }
> >> > +       return 0;
> >> > +}
> >> > +
> >> >  int UVCCameraData::init(MediaDevice *media)
> >> >  {
> >> >         int ret;
> >> > @@ -512,6 +548,12 @@ int UVCCameraData::init(MediaDevice *media)
> >> >
> >> >         controlInfo_ = ControlInfoMap(std::move(ctrls), controls::controls);
> >> >
> >> > +       ret = initMetadata(media);
> >> > +       if (ret) {
> >> > +               metadata_ = nullptr;
> >>
> >> I think, you are leaking metadata_ if the initMetadata function
> >> returns from failure of
> >
> >
> > I thought assigning null to smart pointers initiates the normal cleanup routine of the objects they point to.  Is this the leak you're talking about, or should I clean up something else too?

From https://en.cppreference.com/w/cpp/memory/unique_ptr/operator%3D

(3) unique_ptr& operator=( std::nullptr_t ) noexcept;
    3) Effectively the same as calling reset().

https://en.cppreference.com/w/cpp/memory/unique_ptr/reset
        If the old pointer was non-empty, deletes the previously managed
        object if (old_ptr) get_deleter()(old_ptr).

if metadata_ is a unique_ptr, assigning nullptr to it will delete the object
it previously managed.

>
> https://godbolt.org/z/rhx886abY
>
> I tried doing something similar, check the godbolt link, assigning
> null has no effect on the allocated memory. (cc: @Laurent Pinchart and
> @Kieran Bingham can you guys have a look once)
>

Try to use unique_ptr, shared_ptr is harder to follow as it has to do
reference counting. With unique_ptr<> I see

         callq operator delete(void*)@PLT

Thanks
   j


> >>
> >> <snip>
> >> > +       ret = metadata_->open();
> >> > +       if (ret)
> >> > +               return ret;
> >> </snip>
> >>
> >> > +               LOG(UVC, Error) << "Could not find a metadata video device.";
> >> > +       }
> >> > +
> >> >         return 0;
> >> >  }
> >> >
> >> > --
> >> > 2.34.1
> >> >
> >>
> >> Regards,
> >> Vedant Paranjape
> >
> >
> > Thanks for the suggestions!
> >>
> >>
> >> On Mon, Aug 21, 2023 at 6:40 PM Gabby George <gabbymg94@gmail.com> wrote:
> >> >
> >> > Identify and open the UVC metadata's video node. This will give us
> >> > access to metadata associated with the video stream of the uvc camera.
> >> > The user will not have access to this video node and will not need to
> >> > manage its data in any way.
> >> >
> >> > Signed-off-by: Gabby George <gabbymg94@gmail.com>
> >> > ---
> >> >  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 42 ++++++++++++++++++++
> >> >  1 file changed, 42 insertions(+)
> >> >
> >> > diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> >> > index 38f48a5d..dbe0cc8c 100644
> >> > --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> >> > +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> >> > @@ -49,10 +49,13 @@ public:
> >> >         const std::string &id() const { return id_; }
> >> >
> >> >         std::unique_ptr<V4L2VideoDevice> video_;
> >> > +       std::unique_ptr<V4L2VideoDevice> metadata_;
> >> >         Stream stream_;
> >> >         std::map<PixelFormat, std::vector<SizeRange>> formats_;
> >> >
> >> >  private:
> >> > +       int initMetadata(MediaDevice *media);
> >> > +
> >> >         bool generateId();
> >> >
> >> >         std::string id_;
> >> > @@ -411,6 +414,39 @@ bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
> >> >         return true;
> >> >  }
> >> >
> >> > +int UVCCameraData::initMetadata(MediaDevice *media)
> >> > +{
> >> > +       int ret;
> >> > +
> >> > +       const std::vector<MediaEntity *> &entities = media->entities();
> >> > +       std::string dev_node_name = video_->deviceNode();
> >> > +       auto metadata = std::find_if(entities.begin(), entities.end(),
> >> > +                                    [&dev_node_name](MediaEntity *e) {
> >> > +                                            return e->type() == MediaEntity::Type::V4L2VideoDevice
> >> > +                                                       && !(e->flags() & MEDIA_ENT_FL_DEFAULT);
> >> > +                                    });
> >> > +
> >> > +       if (metadata == entities.end()) {
> >> > +               return -ENODEV;
> >> > +       }
> >> > +
> >> > +       /* configure the metadata node */
> >> > +       metadata_ = std::make_unique<V4L2VideoDevice>(*metadata);
> >> > +       ret = metadata_->open();
> >> > +       if (ret)
> >> > +               return ret;
> >> > +
> >> > +       if (!(metadata_->caps().isMeta())) {
> >> > +               /*
> >> > +                * UVC Devices are usually only anticipated to expose two
> >> > +         * devices, so we assume the non-default device is the metadata
> >> > +         * device node
> >> > +                */
> >> > +               return -EINVAL;
> >> > +       }
> >> > +       return 0;
> >> > +}
> >> > +
> >> >  int UVCCameraData::init(MediaDevice *media)
> >> >  {
> >> >         int ret;
> >> > @@ -512,6 +548,12 @@ int UVCCameraData::init(MediaDevice *media)
> >> >
> >> >         controlInfo_ = ControlInfoMap(std::move(ctrls), controls::controls);
> >> >
> >> > +       ret = initMetadata(media);
> >> > +       if (ret) {
> >> > +               metadata_ = nullptr;
> >> > +               LOG(UVC, Error) << "Could not find a metadata video device.";
> >> > +       }
> >> > +
> >> >         return 0;
> >> >  }
> >> >
> >> > --
> >> > 2.34.1
> >> >
>
> Regards,
> Vedant Paranjape
Laurent Pinchart Aug. 28, 2023, 8:33 p.m. UTC | #5
Hello,

On Mon, Aug 28, 2023 at 10:16:13AM +0200, Jacopo Mondi wrote:
> On Mon, Aug 28, 2023 at 12:28:49AM +0530, Vedant Paranjape via libcamera-devel wrote:
> > On Sun, Aug 27, 2023 at 9:59 AM Gabrielle George wrote:
> > > On Mon, Aug 21, 2023 at 6:49 AM Vedant Paranjape wrote:
> > >> On Mon, Aug 21, 2023 at 6:40 PM Gabby George wrote:
> > >> >
> > >> > Identify and open the UVC metadata's video node. This will give us
> > >> > access to metadata associated with the video stream of the uvc camera.

s/uvc/UVC/ (as UVC is an acronym)

> > >> > The user will not have access to this video node and will not need to
> > >> > manage its data in any way.
> > >> >
> > >> > Signed-off-by: Gabby George <gabbymg94@gmail.com>
> > >> > ---
> > >> >  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 42 ++++++++++++++++++++
> > >> >  1 file changed, 42 insertions(+)
> > >> >
> > >> > diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> > >> > index 38f48a5d..dbe0cc8c 100644
> > >> > --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> > >> > +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> > >> > @@ -49,10 +49,13 @@ public:
> > >> >         const std::string &id() const { return id_; }
> > >> >
> > >> >         std::unique_ptr<V4L2VideoDevice> video_;
> > >> > +       std::unique_ptr<V4L2VideoDevice> metadata_;
> > >> >         Stream stream_;
> > >> >         std::map<PixelFormat, std::vector<SizeRange>> formats_;
> > >> >
> > >> >  private:
> > >> > +       int initMetadata(MediaDevice *media);
> > >> > +
> > >> >         bool generateId();
> > >> >
> > >> >         std::string id_;
> > >> > @@ -411,6 +414,39 @@ bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
> > >> >         return true;
> > >> >  }
> > >> >
> > >> > +int UVCCameraData::initMetadata(MediaDevice *media)
> > >> > +{
> > >> > +       int ret;

You can declare ret on first use.

> > >> > +
> > >> > +       const std::vector<MediaEntity *> &entities = media->entities();
> > >> > +       std::string dev_node_name = video_->deviceNode();

devNodeName. We use camelCase. And this should be a const reference to
avoid a copy.

> > >> > +       auto metadata = std::find_if(entities.begin(), entities.end(),
> > >> > +                                    [&dev_node_name](MediaEntity *e) {

You don't use dev_node_name anywhere.

> > >> > +                                            return e->type() == MediaEntity::Type::V4L2VideoDevice
> > >> > +                                                       && !(e->flags() & MEDIA_ENT_FL_DEFAULT);
> > >> > +                                    });

That won't work correctly if the UVC device has multiple image capture
device nodes. Only one of the image capture device nodes will be marked
as default, the other one may get picked by this code.

There's nothing in the kernel uvcvideo driver that currently exposes the
relationship between the image capture device node and the metadata
device node :-S This should be fixed, but that's out of scope for your
current work. Let's thus record this in a comment here:

	/*
	 * \todo The kernel doesn't expose the relationship between image
	 * capture video devices and metadata capture video devices. Until this
	 * gets fixed on the kernel side, do our best by picking one metadata
	 * capture video device.
	 */

As for how to find a metadata capture device node, you can simply check
the number of pads. The entities corresponding to metadata devices
currently have no pad.

> > >> > +
> > >> > +       if (metadata == entities.end()) {
> > >> > +               return -ENODEV;
> > >> > +       }

No need for curly braces.

> > >> > +
> > >> > +       /* configure the metadata node */
> > >> > +       metadata_ = std::make_unique<V4L2VideoDevice>(*metadata);
> > >> > +       ret = metadata_->open();
> > >>
> > >> Should we check for validity of metadata_ with a simple if (metadata_)
> > >> ? or is it overengineering ?
> > >
> > > Good call! I think we should.

As far as I can tell, std::make_unique<>() never returns a null
std::unique_ptr<>.

> > >> > +       if (ret)
> > >> > +               return ret;
> > >> > +
> > >> > +       if (!(metadata_->caps().isMeta())) {

No need for the outer parentheses.

> > >> > +               /*
> > >> > +                * UVC Devices are usually only anticipated to expose two
> > >> > +         * devices, so we assume the non-default device is the metadata
> > >> > +         * device node
> > >> > +                */
> > >>
> > >> The comment seems misaligned in indentation, please fix it.
> > >
> > > I'll make sure it's correct in the next patch.

This should have been caught by checkstyle.py. Are you using it through
the git post-commit hook ?

> > >> > +               return -EINVAL;
> > >> > +       }
> > >> > +       return 0;
> > >> > +}
> > >> > +
> > >> >  int UVCCameraData::init(MediaDevice *media)
> > >> >  {
> > >> >         int ret;
> > >> > @@ -512,6 +548,12 @@ int UVCCameraData::init(MediaDevice *media)
> > >> >
> > >> >         controlInfo_ = ControlInfoMap(std::move(ctrls), controls::controls);
> > >> >
> > >> > +       ret = initMetadata(media);
> > >> > +       if (ret) {
> > >> > +               metadata_ = nullptr;
> > >>
> > >> I think, you are leaking metadata_ if the initMetadata function
> > >> returns from failure of
> > >
> > > I thought assigning null to smart pointers initiates the normal
> > > cleanup routine of the objects they point to.  Is this the leak
> > > you're talking about, or should I clean up something else too?
> 
> From https://en.cppreference.com/w/cpp/memory/unique_ptr/operator%3D
> 
> (3) unique_ptr& operator=( std::nullptr_t ) noexcept;
>     3) Effectively the same as calling reset().
> 
> https://en.cppreference.com/w/cpp/memory/unique_ptr/reset
>         If the old pointer was non-empty, deletes the previously managed
>         object if (old_ptr) get_deleter()(old_ptr).
> 
> if metadata_ is a unique_ptr, assigning nullptr to it will delete the object
> it previously managed.

Correct. I would however move this to the initMetadata() function to
make it self-contained, it's not a good practice to make the caller
aware of the internal implementation of the callee.

> > https://godbolt.org/z/rhx886abY
> >
> > I tried doing something similar, check the godbolt link, assigning
> > null has no effect on the allocated memory. (cc: @Laurent Pinchart and
> > @Kieran Bingham can you guys have a look once)
> 
> Try to use unique_ptr, shared_ptr is harder to follow as it has to do
> reference counting. With unique_ptr<> I see
> 
>          callq operator delete(void*)@PLT
> 
> > >> <snip>
> > >> > +       ret = metadata_->open();
> > >> > +       if (ret)
> > >> > +               return ret;
> > >> </snip>
> > >>
> > >> > +               LOG(UVC, Error) << "Could not find a metadata video device.";
> > >> > +       }
> > >> > +
> > >> >         return 0;
> > >> >  }
> > >> >
> > >
> > > Thanks for the suggestions!
Vedant Paranjape Aug. 29, 2023, 5:59 p.m. UTC | #6
Hello Jacopo,

This is new, thanks for the info. Need to read the fineprint :)

Regards,
Vedant Paranjape

On Mon, Aug 28, 2023 at 1:46 PM Jacopo Mondi <jacopo.mondi@ideasonboard.com>
wrote:

> Hello
>
> On Mon, Aug 28, 2023 at 12:28:49AM +0530, Vedant Paranjape via
> libcamera-devel wrote:
> > Hello Gabby,
> >
> > On Sun, Aug 27, 2023 at 9:59 AM Gabrielle George <gabbymg94@gmail.com>
> wrote:
> > >
> > >
> > >
> > > On Mon, Aug 21, 2023 at 6:49 AM Vedant Paranjape <
> vedantparanjape160201@gmail.com> wrote:
> > >>
> > >> Hello Gabby,
> > >>
> > >> Thanks for your patch.
> > >>
> > >> On Mon, Aug 21, 2023 at 6:40 PM Gabby George <gabbymg94@gmail.com>
> wrote:
> > >> >
> > >> > Identify and open the UVC metadata's video node. This will give us
> > >> > access to metadata associated with the video stream of the uvc
> camera.
> > >> > The user will not have access to this video node and will not need
> to
> > >> > manage its data in any way.
> > >> >
> > >> > Signed-off-by: Gabby George <gabbymg94@gmail.com>
> > >> > ---
> > >> >  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 42
> ++++++++++++++++++++
> > >> >  1 file changed, 42 insertions(+)
> > >> >
> > >> > diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> > >> > index 38f48a5d..dbe0cc8c 100644
> > >> > --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> > >> > +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> > >> > @@ -49,10 +49,13 @@ public:
> > >> >         const std::string &id() const { return id_; }
> > >> >
> > >> >         std::unique_ptr<V4L2VideoDevice> video_;
> > >> > +       std::unique_ptr<V4L2VideoDevice> metadata_;
> > >> >         Stream stream_;
> > >> >         std::map<PixelFormat, std::vector<SizeRange>> formats_;
> > >> >
> > >> >  private:
> > >> > +       int initMetadata(MediaDevice *media);
> > >> > +
> > >> >         bool generateId();
> > >> >
> > >> >         std::string id_;
> > >> > @@ -411,6 +414,39 @@ bool
> PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
> > >> >         return true;
> > >> >  }
> > >> >
> > >> > +int UVCCameraData::initMetadata(MediaDevice *media)
> > >> > +{
> > >> > +       int ret;
> > >> > +
> > >> > +       const std::vector<MediaEntity *> &entities =
> media->entities();
> > >> > +       std::string dev_node_name = video_->deviceNode();
> > >> > +       auto metadata = std::find_if(entities.begin(),
> entities.end(),
> > >> > +                                    [&dev_node_name](MediaEntity
> *e) {
> > >> > +                                            return e->type() ==
> MediaEntity::Type::V4L2VideoDevice
> > >> > +                                                       &&
> !(e->flags() & MEDIA_ENT_FL_DEFAULT);
> > >> > +                                    });
> > >> > +
> > >> > +       if (metadata == entities.end()) {
> > >> > +               return -ENODEV;
> > >> > +       }
> > >> > +
> > >> > +       /* configure the metadata node */
> > >> > +       metadata_ = std::make_unique<V4L2VideoDevice>(*metadata);
> > >> > +       ret = metadata_->open();
> > >>
> > >> Should we check for validity of metadata_ with a simple if (metadata_)
> > >> ? or is it overengineering ?
> > >
> > >
> > > Good call! I think we should.
> > >>
> > >>
> > >> > +       if (ret)
> > >> > +               return ret;
> > >> > +
> > >> > +       if (!(metadata_->caps().isMeta())) {
> > >> > +               /*
> > >> > +                * UVC Devices are usually only anticipated to
> expose two
> > >> > +         * devices, so we assume the non-default device is the
> metadata
> > >> > +         * device node
> > >> > +                */
> > >>
> > >> The comment seems misaligned in indentation, please fix it.
> > >
> > >
> > > I'll make sure it's correct in the next patch.
> > >>
> > >>
> > >> > +               return -EINVAL;
> > >> > +       }
> > >> > +       return 0;
> > >> > +}
> > >> > +
> > >> >  int UVCCameraData::init(MediaDevice *media)
> > >> >  {
> > >> >         int ret;
> > >> > @@ -512,6 +548,12 @@ int UVCCameraData::init(MediaDevice *media)
> > >> >
> > >> >         controlInfo_ = ControlInfoMap(std::move(ctrls),
> controls::controls);
> > >> >
> > >> > +       ret = initMetadata(media);
> > >> > +       if (ret) {
> > >> > +               metadata_ = nullptr;
> > >>
> > >> I think, you are leaking metadata_ if the initMetadata function
> > >> returns from failure of
> > >
> > >
> > > I thought assigning null to smart pointers initiates the normal
> cleanup routine of the objects they point to.  Is this the leak you're
> talking about, or should I clean up something else too?
>
> From https://en.cppreference.com/w/cpp/memory/unique_ptr/operator%3D
>
> (3) unique_ptr& operator=( std::nullptr_t ) noexcept;
>     3) Effectively the same as calling reset().
>
> https://en.cppreference.com/w/cpp/memory/unique_ptr/reset
>         If the old pointer was non-empty, deletes the previously managed
>         object if (old_ptr) get_deleter()(old_ptr).
>
> if metadata_ is a unique_ptr, assigning nullptr to it will delete the
> object
> it previously managed.
>
> >
> > https://godbolt.org/z/rhx886abY
> >
> > I tried doing something similar, check the godbolt link, assigning
> > null has no effect on the allocated memory. (cc: @Laurent Pinchart and
> > @Kieran Bingham can you guys have a look once)
> >
>
> Try to use unique_ptr, shared_ptr is harder to follow as it has to do
> reference counting. With unique_ptr<> I see
>
>          callq operator delete(void*)@PLT
>
> Thanks
>    j
>
>
> > >>
> > >> <snip>
> > >> > +       ret = metadata_->open();
> > >> > +       if (ret)
> > >> > +               return ret;
> > >> </snip>
> > >>
> > >> > +               LOG(UVC, Error) << "Could not find a metadata video
> device.";
> > >> > +       }
> > >> > +
> > >> >         return 0;
> > >> >  }
> > >> >
> > >> > --
> > >> > 2.34.1
> > >> >
> > >>
> > >> Regards,
> > >> Vedant Paranjape
> > >
> > >
> > > Thanks for the suggestions!
> > >>
> > >>
> > >> On Mon, Aug 21, 2023 at 6:40 PM Gabby George <gabbymg94@gmail.com>
> wrote:
> > >> >
> > >> > Identify and open the UVC metadata's video node. This will give us
> > >> > access to metadata associated with the video stream of the uvc
> camera.
> > >> > The user will not have access to this video node and will not need
> to
> > >> > manage its data in any way.
> > >> >
> > >> > Signed-off-by: Gabby George <gabbymg94@gmail.com>
> > >> > ---
> > >> >  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 42
> ++++++++++++++++++++
> > >> >  1 file changed, 42 insertions(+)
> > >> >
> > >> > diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> > >> > index 38f48a5d..dbe0cc8c 100644
> > >> > --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> > >> > +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> > >> > @@ -49,10 +49,13 @@ public:
> > >> >         const std::string &id() const { return id_; }
> > >> >
> > >> >         std::unique_ptr<V4L2VideoDevice> video_;
> > >> > +       std::unique_ptr<V4L2VideoDevice> metadata_;
> > >> >         Stream stream_;
> > >> >         std::map<PixelFormat, std::vector<SizeRange>> formats_;
> > >> >
> > >> >  private:
> > >> > +       int initMetadata(MediaDevice *media);
> > >> > +
> > >> >         bool generateId();
> > >> >
> > >> >         std::string id_;
> > >> > @@ -411,6 +414,39 @@ bool
> PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
> > >> >         return true;
> > >> >  }
> > >> >
> > >> > +int UVCCameraData::initMetadata(MediaDevice *media)
> > >> > +{
> > >> > +       int ret;
> > >> > +
> > >> > +       const std::vector<MediaEntity *> &entities =
> media->entities();
> > >> > +       std::string dev_node_name = video_->deviceNode();
> > >> > +       auto metadata = std::find_if(entities.begin(),
> entities.end(),
> > >> > +                                    [&dev_node_name](MediaEntity
> *e) {
> > >> > +                                            return e->type() ==
> MediaEntity::Type::V4L2VideoDevice
> > >> > +                                                       &&
> !(e->flags() & MEDIA_ENT_FL_DEFAULT);
> > >> > +                                    });
> > >> > +
> > >> > +       if (metadata == entities.end()) {
> > >> > +               return -ENODEV;
> > >> > +       }
> > >> > +
> > >> > +       /* configure the metadata node */
> > >> > +       metadata_ = std::make_unique<V4L2VideoDevice>(*metadata);
> > >> > +       ret = metadata_->open();
> > >> > +       if (ret)
> > >> > +               return ret;
> > >> > +
> > >> > +       if (!(metadata_->caps().isMeta())) {
> > >> > +               /*
> > >> > +                * UVC Devices are usually only anticipated to
> expose two
> > >> > +         * devices, so we assume the non-default device is the
> metadata
> > >> > +         * device node
> > >> > +                */
> > >> > +               return -EINVAL;
> > >> > +       }
> > >> > +       return 0;
> > >> > +}
> > >> > +
> > >> >  int UVCCameraData::init(MediaDevice *media)
> > >> >  {
> > >> >         int ret;
> > >> > @@ -512,6 +548,12 @@ int UVCCameraData::init(MediaDevice *media)
> > >> >
> > >> >         controlInfo_ = ControlInfoMap(std::move(ctrls),
> controls::controls);
> > >> >
> > >> > +       ret = initMetadata(media);
> > >> > +       if (ret) {
> > >> > +               metadata_ = nullptr;
> > >> > +               LOG(UVC, Error) << "Could not find a metadata video
> device.";
> > >> > +       }
> > >> > +
> > >> >         return 0;
> > >> >  }
> > >> >
> > >> > --
> > >> > 2.34.1
> > >> >
> >
> > Regards,
> > Vedant Paranjape
>

Patch
diff mbox series

diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
index 38f48a5d..dbe0cc8c 100644
--- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
+++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
@@ -49,10 +49,13 @@  public:
 	const std::string &id() const { return id_; }
 
 	std::unique_ptr<V4L2VideoDevice> video_;
+	std::unique_ptr<V4L2VideoDevice> metadata_;
 	Stream stream_;
 	std::map<PixelFormat, std::vector<SizeRange>> formats_;
 
 private:
+	int initMetadata(MediaDevice *media);
+
 	bool generateId();
 
 	std::string id_;
@@ -411,6 +414,39 @@  bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
 	return true;
 }
 
+int UVCCameraData::initMetadata(MediaDevice *media)
+{
+	int ret;
+
+	const std::vector<MediaEntity *> &entities = media->entities();
+	std::string dev_node_name = video_->deviceNode();
+	auto metadata = std::find_if(entities.begin(), entities.end(),
+				     [&dev_node_name](MediaEntity *e) {
+					     return e->type() == MediaEntity::Type::V4L2VideoDevice
+							&& !(e->flags() & MEDIA_ENT_FL_DEFAULT);
+				     });
+
+	if (metadata == entities.end()) {
+		return -ENODEV;
+	}
+
+	/* configure the metadata node */
+	metadata_ = std::make_unique<V4L2VideoDevice>(*metadata);
+	ret = metadata_->open();
+	if (ret)
+		return ret;
+
+	if (!(metadata_->caps().isMeta())) {
+		/*
+		 * UVC Devices are usually only anticipated to expose two
+         * devices, so we assume the non-default device is the metadata
+         * device node
+		 */
+		return -EINVAL;
+	}
+	return 0;
+}
+
 int UVCCameraData::init(MediaDevice *media)
 {
 	int ret;
@@ -512,6 +548,12 @@  int UVCCameraData::init(MediaDevice *media)
 
 	controlInfo_ = ControlInfoMap(std::move(ctrls), controls::controls);
 
+	ret = initMetadata(media);
+	if (ret) {
+		metadata_ = nullptr;
+		LOG(UVC, Error) << "Could not find a metadata video device.";
+	}
+
 	return 0;
 }