[PATCH v2 4/6] libcamera: v4l2_videodevice: Update to the new kernel metadata API

Kieran Bingham kieran.bingham at ideasonboard.com
Tue Jan 7 14:57:32 CET 2025


Quoting Jacopo Mondi (2024-11-08 10:51:14)
> From: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> 
> With support for metadata in the streams API, the v4l2_meta_format
> structure has been extended with width, height and bytesperline fields.
> 
> Support them in the V4L2VideoDevice getFormat() and setFormat()
> functions is the video device is meta capture device and if the
> pixel format is one of the generic line-based metadata formats.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> Reviewed-by: Jacopo Mondi <jacopo.mondi at ideasonboard.com>
> Signed-off-by: Jacopo Mondi <jacopo.mondi at ideasonboard.com>
> ---
>  include/libcamera/internal/v4l2_pixelformat.h |  2 +
>  src/libcamera/v4l2_pixelformat.cpp            | 34 +++++++++++++
>  src/libcamera/v4l2_videodevice.cpp            | 51 ++++++++++++++-----
>  3 files changed, 73 insertions(+), 14 deletions(-)
> 
> diff --git a/include/libcamera/internal/v4l2_pixelformat.h b/include/libcamera/internal/v4l2_pixelformat.h
> index c836346bdc04..543eb21b3c07 100644
> --- a/include/libcamera/internal/v4l2_pixelformat.h
> +++ b/include/libcamera/internal/v4l2_pixelformat.h
> @@ -49,6 +49,8 @@ public:
>         static const std::vector<V4L2PixelFormat> &
>         fromPixelFormat(const PixelFormat &pixelFormat);
>  
> +       bool isGenericLineBasedMetadata() const;
> +
>  private:
>         uint32_t fourcc_;
>  };
> diff --git a/src/libcamera/v4l2_pixelformat.cpp b/src/libcamera/v4l2_pixelformat.cpp
> index eb9ac2224fd1..e8b3eb9c1394 100644
> --- a/src/libcamera/v4l2_pixelformat.cpp
> +++ b/src/libcamera/v4l2_pixelformat.cpp
> @@ -372,6 +372,40 @@ V4L2PixelFormat::fromPixelFormat(const PixelFormat &pixelFormat)
>         return info.v4l2Formats;
>  }
>  
> +/**
> + * \brief Test if a V4L2PixelFormat is one of the line based generic metadata
> + * formats
> + *
> + * A limited number of metadata formats, the ones that represents generic
> + * line-based metadata buffers, need to have their width, height and
> + * bytesperline set by userspace.
> + *
> + * This function tests if the current V4L2PixelFormat is one of those.
> + *
> + * Note: It would have been nicer to store this information in a
> + * V4L2PixelFormat::Info instance, but as metadata format are not exposed to
> + * applications, there are no PixelFormat and DRM fourcc codes associated to
> + * them.
> + *
> + * \return True if the V4L2PixelFormat() is a generic line based format, false
> + * otherwise
> + */
> +bool V4L2PixelFormat::isGenericLineBasedMetadata() const
> +{
> +       switch (fourcc_) {
> +       case V4L2_META_FMT_GENERIC_8:
> +       case V4L2_META_FMT_GENERIC_CSI2_10:
> +       case V4L2_META_FMT_GENERIC_CSI2_12:
> +       case V4L2_META_FMT_GENERIC_CSI2_14:
> +       case V4L2_META_FMT_GENERIC_CSI2_16:
> +       case V4L2_META_FMT_GENERIC_CSI2_20:
> +       case V4L2_META_FMT_GENERIC_CSI2_24:
> +               return true;
> +       default:
> +               return false;
> +       }

What happens with the non-generic formats ? Or does the 'specific'
nature of those embedded formats mean the sizes are 'known'
specifically?

> +}
> +
>  /**
>   * \brief Insert a text representation of a V4L2PixelFormat into an output
>   * stream
> diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp
> index 14eba0561d6a..87cdbc3edf52 100644
> --- a/src/libcamera/v4l2_videodevice.cpp
> +++ b/src/libcamera/v4l2_videodevice.cpp
> @@ -888,7 +888,7 @@ int V4L2VideoDevice::setFormat(V4L2DeviceFormat *format)
>  int V4L2VideoDevice::getFormatMeta(V4L2DeviceFormat *format)
>  {
>         struct v4l2_format v4l2Format = {};
> -       struct v4l2_meta_format *pix = &v4l2Format.fmt.meta;
> +       struct v4l2_meta_format *meta = &v4l2Format.fmt.meta;
>         int ret;
>  
>         v4l2Format.type = bufferType_;
> @@ -898,25 +898,42 @@ int V4L2VideoDevice::getFormatMeta(V4L2DeviceFormat *format)
>                 return ret;
>         }
>  
> -       format->size.width = 0;
> -       format->size.height = 0;
> -       format->fourcc = V4L2PixelFormat(pix->dataformat);
> +       format->fourcc = V4L2PixelFormat(meta->dataformat);
> +       format->planes[0].size = meta->buffersize;
>         format->planesCount = 1;
> -       format->planes[0].bpl = pix->buffersize;
> -       format->planes[0].size = pix->buffersize;
> +
> +       bool genericLineBased = caps_.isMetaCapture() &&
> +                               format->fourcc.isGenericLineBasedMetadata();
> +
> +       if (genericLineBased) {
> +               format->size.width = meta->width;
> +               format->size.height = meta->height;
> +               format->planes[0].bpl = meta->bytesperline;
> +       } else {
> +               format->size.width = 0;
> +               format->size.height = 0;
> +               format->planes[0].bpl = meta->buffersize;

I guess perhaps it's here that it's just a full buffer size.

Anyway, I can see that could all be extended later when we /have/
specific formats to deal with.


Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>

> +       }
>  
>         return 0;
>  }
>  
>  int V4L2VideoDevice::trySetFormatMeta(V4L2DeviceFormat *format, bool set)
>  {
> +       bool genericLineBased = caps_.isMetaCapture() &&
> +                               format->fourcc.isGenericLineBasedMetadata();
>         struct v4l2_format v4l2Format = {};
> -       struct v4l2_meta_format *pix = &v4l2Format.fmt.meta;
> +       struct v4l2_meta_format *meta = &v4l2Format.fmt.meta;
>         int ret;
>  
>         v4l2Format.type = bufferType_;
> -       pix->dataformat = format->fourcc;
> -       pix->buffersize = format->planes[0].size;
> +       meta->dataformat = format->fourcc;
> +       meta->buffersize = format->planes[0].size;
> +       if (genericLineBased) {
> +               meta->width = format->size.width;
> +               meta->height = format->size.height;
> +               meta->bytesperline = format->planes[0].bpl;
> +       }
>         ret = ioctl(set ? VIDIOC_S_FMT : VIDIOC_TRY_FMT, &v4l2Format);
>         if (ret) {
>                 LOG(V4L2, Error)
> @@ -929,12 +946,18 @@ int V4L2VideoDevice::trySetFormatMeta(V4L2DeviceFormat *format, bool set)
>          * Return to caller the format actually applied on the video device,
>          * which might differ from the requested one.
>          */
> -       format->size.width = 0;
> -       format->size.height = 0;
> -       format->fourcc = V4L2PixelFormat(pix->dataformat);
> +       format->fourcc = V4L2PixelFormat(meta->dataformat);
>         format->planesCount = 1;
> -       format->planes[0].bpl = pix->buffersize;
> -       format->planes[0].size = pix->buffersize;
> +       format->planes[0].size = meta->buffersize;
> +       if (genericLineBased) {
> +               format->size.width = meta->width;
> +               format->size.height = meta->height;
> +               format->planes[0].bpl = meta->bytesperline;
> +       } else {
> +               format->size.width = 0;
> +               format->size.height = 0;
> +               format->planes[0].bpl = meta->buffersize;
> +       }
>  
>         return 0;
>  }
> -- 
> 2.47.0
>


More information about the libcamera-devel mailing list