From patchwork Sun Oct 27 23:43:09 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2245 Return-Path: Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B6FFD61517 for ; Mon, 28 Oct 2019 00:41:28 +0100 (CET) X-Originating-IP: 93.2.121.143 Received: from uno.localdomain (143.121.2.93.rev.sfr.net [93.2.121.143]) (Authenticated sender: jacopo@jmondi.org) by relay7-d.mail.gandi.net (Postfix) with ESMTPSA id 6B07920003; Sun, 27 Oct 2019 23:41:28 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 28 Oct 2019 00:43:09 +0100 Message-Id: <20191027234312.35284-8-jacopo@jmondi.org> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191027234312.35284-1-jacopo@jmondi.org> References: <20191027234312.35284-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 07/10] libcamera: v4l2_videodevice: Add PixelFormat conversion X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 27 Oct 2019 23:41:29 -0000 Add support for the newly introduced PixelFormat type in the V4L2VideoDevice class by providing helper operations to translate a PixelFormat to the corresponding V4L2-defined fourcc code and vice versa. More work is needed to properly suppor the V4L2 multi-planar (*M) formats. Signed-off-by: Jacopo Mondi --- 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 #include +#include #include #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..89370698bcf1 100644 --- a/src/libcamera/v4l2_videodevice.cpp +++ b/src/libcamera/v4l2_videodevice.cpp @@ -17,6 +17,8 @@ #include #include +#include + #include #include @@ -1234,6 +1236,145 @@ V4L2VideoDevice *V4L2VideoDevice::fromEntityName(const MediaDevice *media, return new V4L2VideoDevice(mediaEntity); } +/** + * \brief Convert a \a v4l2Fourcc code to its corresponding PixelFormat + * \param[in] v4l2Fourcc A V4L2_PIX_FORMAT_* pixel code + * \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 code + * \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 code + * \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