summaryrefslogtreecommitdiff
path: root/src/libcamera/v4l2_videodevice.cpp
diff options
context:
space:
mode:
authorJacopo Mondi <jacopo@jmondi.org>2019-10-25 13:00:43 +0200
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2019-10-28 17:04:01 +0200
commit2a8bf04227811b29bc94b942e78f1567afd8874b (patch)
tree31f3897a6fe2dbf56c5634d8519337166072a20d /src/libcamera/v4l2_videodevice.cpp
parentc53f8fbbab29385c584f9229c9ee57107b954225 (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>
Diffstat (limited to 'src/libcamera/v4l2_videodevice.cpp')
-rw-r--r--src/libcamera/v4l2_videodevice.cpp141
1 files changed, 141 insertions, 0 deletions
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
*