diff options
author | Jacopo Mondi <jacopo@jmondi.org> | 2019-10-25 13:00:43 +0200 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2019-10-28 17:04:01 +0200 |
commit | 2a8bf04227811b29bc94b942e78f1567afd8874b (patch) | |
tree | 31f3897a6fe2dbf56c5634d8519337166072a20d | |
parent | c53f8fbbab29385c584f9229c9ee57107b954225 (diff) |
libcamera: v4l2_videodevice: Add PixelFormat conversion
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 support the V4L2 multi-planar
(NV[0-9]*M) formats.
Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
-rw-r--r-- | src/libcamera/include/v4l2_videodevice.h | 5 | ||||
-rw-r--r-- | src/libcamera/v4l2_videodevice.cpp | 141 |
2 files changed, 146 insertions, 0 deletions
diff --git a/src/libcamera/include/v4l2_videodevice.h b/src/libcamera/include/v4l2_videodevice.h index 4b8cf939..fdf11b3a 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> #include <libcamera/signal.h> #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 208ab541..3f2dc279 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> @@ -1235,6 +1237,145 @@ V4L2VideoDevice *V4L2VideoDevice::fromEntityName(const MediaDevice *media, } /** + * \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; + } +} + +/** + * \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. + * + * \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 * |