diff options
-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 * |