[libcamera-devel] [PATCH v2 6/7] libcamera: v4l2_videodevice: Add PixelFormat conversion
Kieran Bingham
kieran.bingham at ideasonboard.com
Mon Oct 28 12:53:08 CET 2019
Hi Jacopo,
On 28/10/2019 11:02, Laurent Pinchart wrote:
> From: Jacopo Mondi <jacopo at jmondi.org>
>
> In preparation for switching PixelFormat to DRM pixel formats, add
> helper methods to the V4L2VideoDevice class to translate between DRM
> pixel formats and V4L2 pixel formats.
>
> More work is needed to properly suppor the V4L2 multi-planar (NV[0-9]*M)
s/suppor/support/
> formats.
>
> Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
> Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
> ---
> src/libcamera/include/v4l2_videodevice.h | 5 +
> src/libcamera/v4l2_videodevice.cpp | 141 +++++++++++++++++++++++
> 2 files changed, 146 insertions(+)
>
> diff --git a/src/libcamera/include/v4l2_videodevice.h b/src/libcamera/include/v4l2_videodevice.h
> index 4b8cf9394eb9..fdf11b3a6ec9 100644
> --- a/src/libcamera/include/v4l2_videodevice.h
> +++ b/src/libcamera/include/v4l2_videodevice.h
> @@ -13,6 +13,7 @@
> #include <linux/videodev2.h>
>
> #include <libcamera/geometry.h>
> +#include <libcamera/pixelformats.h>
Hrm, seeing this makes me think the include file should be
"libcamera/pixelformat.h"
> #include <libcamera/signal.h>
Because we don't call this libcamera/signals.h :D
>
> #include "formats.h"
> @@ -155,6 +156,10 @@ public:
> static V4L2VideoDevice *fromEntityName(const MediaDevice *media,
> const std::string &entity);
>
> + static PixelFormat toPixelFormat(uint32_t v4l2Fourcc);
> + uint32_t toV4L2Fourcc(PixelFormat pixelFormat);
> + static uint32_t toV4L2Fourcc(PixelFormat pixelFormat, bool multiplanar);
> +
> protected:
> std::string logPrefix() const;
>
> diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp
> index 208ab54199b1..3f2dc2799796 100644
> --- a/src/libcamera/v4l2_videodevice.cpp
> +++ b/src/libcamera/v4l2_videodevice.cpp
> @@ -17,6 +17,8 @@
> #include <unistd.h>
> #include <vector>
>
> +#include <linux/drm_fourcc.h>
> +
> #include <libcamera/buffer.h>
> #include <libcamera/event_notifier.h>
>
> @@ -1234,6 +1236,145 @@ V4L2VideoDevice *V4L2VideoDevice::fromEntityName(const MediaDevice *media,
> return new V4L2VideoDevice(mediaEntity);
> }
>
> +/**
> + * \brief Convert a \a v4l2Fourcc to the corresponding PixelFormat
> + * \param[in] v4l2Fourcc The V4L2 pixel format (V4L2_PIX_FORMAT_*)
> + * \return The PixelFormat corresponding to \a v4l2Fourcc
> + */
> +PixelFormat V4L2VideoDevice::toPixelFormat(uint32_t v4l2Fourcc)
> +{
> + switch (v4l2Fourcc) {
> + /* RGB formats. */
> + case V4L2_PIX_FMT_RGB24:
> + return DRM_FORMAT_BGR888;
> + case V4L2_PIX_FMT_BGR24:
> + return DRM_FORMAT_RGB888;
> + case V4L2_PIX_FMT_ARGB32:
> + return DRM_FORMAT_BGRA8888;
> +
> + /* YUV packed formats. */
> + case V4L2_PIX_FMT_YUYV:
> + return DRM_FORMAT_YUYV;
> + case V4L2_PIX_FMT_YVYU:
> + return DRM_FORMAT_YVYU;
> + case V4L2_PIX_FMT_UYVY:
> + return DRM_FORMAT_UYVY;
> + case V4L2_PIX_FMT_VYUY:
> + return DRM_FORMAT_VYUY;
> +
> + /* YUY planar formats. */
> + case V4L2_PIX_FMT_NV16:
> + case V4L2_PIX_FMT_NV16M:
> + return DRM_FORMAT_NV16;
> + case V4L2_PIX_FMT_NV61:
> + case V4L2_PIX_FMT_NV61M:
> + return DRM_FORMAT_NV61;
> + case V4L2_PIX_FMT_NV12:
> + case V4L2_PIX_FMT_NV12M:
> + return DRM_FORMAT_NV12;
> + case V4L2_PIX_FMT_NV21:
> + case V4L2_PIX_FMT_NV21M:
> + return DRM_FORMAT_NV21;
> +
> + /* Compressed formats. */
> + case V4L2_PIX_FMT_MJPEG:
> + return DRM_FORMAT_MJPEG;
> +
> + /* V4L2 formats not yet supported by DRM. */
> + case V4L2_PIX_FMT_GREY:
> + default:
> + /*
> + * \todo We can't use LOG() in a static method of a Loggable
> + * class. Until we fix the logger, work around it.
> + */
> + libcamera::_log(__FILE__, __LINE__, _LOG_CATEGORY(V4L2)(),
> + LogError).stream()
> + << "Unsupported V4L2 pixel format "
> + << utils::hex(v4l2Fourcc);
> + return 0;
> + }
> +}
I wonder if these would be more manageable as a table of entries in a
map, with a lookup - but I bet there's not much performance benefits
either way, and it's only ever going to be a (relatively) small table.
Perhaps a future optimisation maybe ...
> +
> +/**
> + * \brief Convert \a PixelFormat to its corresponding V4L2 FourCC
> + * \param[in] pixelFormat The PixelFormat to convert
> + *
> + * For multiplanar formats, the V4L2 format variant (contiguous or
> + * non-contiguous planes) is selected automatically based on the capabilities
> + * of the video device. If the video device supports the V4L2 multiplanar API,
> + * non-contiguous formats are preferred.
I think that's fine for now.
We might have issues later if a device uses planar formats even though
it supports MPLANE, but I can't think of a reason why that would happen
at the moment, so lets go with this.
> + *
> + * \return The V4L2_PIX_FMT_* pixel format code corresponding to \a pixelFormat
> + */
> +uint32_t V4L2VideoDevice::toV4L2Fourcc(PixelFormat pixelFormat)
> +{
> + return V4L2VideoDevice::toV4L2Fourcc(pixelFormat, caps_.isMultiplanar());
> +}
> +
> +/**
> + * \brief Convert \a pixelFormat to its corresponding V4L2 FourCC
> + * \param[in] pixelFormat The PixelFormat to convert
> + * \param[in] multiplanar V4L2 Multiplanar API support flag
> + *
> + * Multiple V4L2 formats may exist for one PixelFormat when the format uses
> + * multiple planes, as V4L2 defines separate 4CCs for contiguous and separate
> + * planes formats. Set the \a multiplanar parameter to false to select a format
> + * with contiguous planes, or to true to select a format with non-contiguous
> + * planes.
> + *
> + * \return The V4L2_PIX_FMT_* pixel format code corresponding to \a pixelFormat
> + */
> +uint32_t V4L2VideoDevice::toV4L2Fourcc(PixelFormat pixelFormat, bool multiplanar)
> +{
> + switch (pixelFormat) {
> + /* RGB formats. */
> + case DRM_FORMAT_BGR888:
> + return V4L2_PIX_FMT_RGB24;
> + case DRM_FORMAT_RGB888:
> + return V4L2_PIX_FMT_BGR24;
> + case DRM_FORMAT_BGRA8888:
> + return V4L2_PIX_FMT_ARGB32;
> +
> + /* YUV packed formats. */
> + case DRM_FORMAT_YUYV:
> + return V4L2_PIX_FMT_YUYV;
> + case DRM_FORMAT_YVYU:
> + return V4L2_PIX_FMT_YVYU;
> + case DRM_FORMAT_UYVY:
> + return V4L2_PIX_FMT_UYVY;
> + case DRM_FORMAT_VYUY:
> + return V4L2_PIX_FMT_VYUY;
> +
> + /*
> + * YUY planar formats.
> + * \todo Add support for non-contiguous memory planes
> + * \todo Select the format variant not only based on \a multiplanar but
> + * also take into account the formats supported by the device.
> + */
> + case DRM_FORMAT_NV16:
> + return V4L2_PIX_FMT_NV16;
> + case DRM_FORMAT_NV61:
> + return V4L2_PIX_FMT_NV61;
> + case DRM_FORMAT_NV12:
> + return V4L2_PIX_FMT_NV12;
> + case DRM_FORMAT_NV21:
> + return V4L2_PIX_FMT_NV21;
> +
> + /* Compressed formats. */
> + case DRM_FORMAT_MJPEG:
> + return V4L2_PIX_FMT_MJPEG;
> + }
> +
> + /*
> + * \todo We can't use LOG() in a static method of a Loggable
> + * class. Until we fix the logger, work around it.
> + */
> + libcamera::_log(__FILE__, __LINE__, _LOG_CATEGORY(V4L2)(), LogError).stream()
> + << "Unsupported V4L2 pixel format "
> + << utils::hex(pixelFormat);
> + return 0;
> +}
> +
> /**
> * \class V4L2M2MDevice
> * \brief Memory-to-Memory video device
>
--
Regards
--
Kieran
More information about the libcamera-devel
mailing list