From patchwork Mon Jan 28 15:11:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 431 Return-Path: Received: from relay10.mail.gandi.net (relay10.mail.gandi.net [217.70.178.230]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AA43460DB7 for ; Mon, 28 Jan 2019 16:11:30 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay10.mail.gandi.net (Postfix) with ESMTPSA id 3F2C8240013; Mon, 28 Jan 2019 15:11:30 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 28 Jan 2019 16:11:36 +0100 Message-Id: <20190128151137.31075-2-jacopo@jmondi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190128151137.31075-1-jacopo@jmondi.org> References: <20190128151137.31075-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 1/2] libcamera: v4l2-format: Add V4L2DeviceFormat X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 28 Jan 2019 15:11:30 -0000 Add a V4L2DeviceFormat class aimed to be used to provide format configuration requests to a V4L2Device. Signed-off-by: Jacopo Mondi Reviewed-by: Kieran Bingham --- src/libcamera/include/v4l2_device.h | 14 ++++++++ src/libcamera/v4l2_device.cpp | 56 +++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/src/libcamera/include/v4l2_device.h b/src/libcamera/include/v4l2_device.h index c67ebbf..c70959e 100644 --- a/src/libcamera/include/v4l2_device.h +++ b/src/libcamera/include/v4l2_device.h @@ -53,6 +53,20 @@ struct V4L2Capability final : v4l2_capability { } }; +class V4L2DeviceFormat +{ +public: + uint32_t width; + uint32_t height; + uint32_t fourcc; + + struct { + uint32_t size; + uint32_t bpl; + } planesFmt[3]; + unsigned int planes; +}; + class MediaEntity; class V4L2Device { diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 408f9b9..d6143f2 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -80,6 +80,62 @@ LOG_DEFINE_CATEGORY(V4L2) * \return True if the device provides Streaming I/O IOCTLs */ +/** + * \class V4L2DeviceFormat + * \brief The V4L2 device image format and sizes + * + * Describes the image format and image sizes to be programmed on a V4L2 + * video device. The image format is defined by fourcc code as defined by + * the V4L2 APIs with the V4L2_PIX_FMT_ macros, a visible width and height + * and a variable number of planes (1 to 3) with variable sizes and line + * strides. + * + * Formats defined as 'single planar' by the V4L2 APIs are represented with + * V4L2DeviceFormat instances with a single plane + * (V4L2DeviceFormat::planes = 1). Semi-planar and multiplanar formats use + * 2 and 3 planes respectively. + * + * V4L2DeviceFormat defines the exchange format between components that + * receive image configuration requests from applications and a V4L2Device. + * The V4L2Device validates and applies the requested size and format to + * the device driver. + */ + +/** + * \var V4L2DeviceFormat::width + * \brief The image width + */ + +/** + * \var V4L2DeviceFormat::height + * \brief The image height + */ + +/** + * \var V4L2DeviceFormat::fourcc + * \brief The pixel encoding scheme + * + * The fourcc code, as defined by the V4L2 APIs with the V4L2_PIX_FMT_ macros, + * that identifies the image format pixel encoding scheme. + */ + +/** + * \var V4L2DeviceFormat::planesFmt + * \brief The per-plane size information + * + * Images are stored in memory in one or more data planes. Each data plane + * has a specific size and line length, which could differ from the image + * visible sizes to accommodate line or plane padding data. + * + * Only the first V4L2DeviceFormat::planes entries are considered valid. + * + */ + +/** + * \var V4L2DeviceFormat::planes + * \brief The number of valid data planes + */ + /** * \class V4L2Device * \brief V4L2Device object and API From patchwork Mon Jan 28 15:11:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 432 Return-Path: Received: from relay10.mail.gandi.net (relay10.mail.gandi.net [217.70.178.230]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7361560DB8 for ; Mon, 28 Jan 2019 16:11:31 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay10.mail.gandi.net (Postfix) with ESMTPSA id E3FD5240010; Mon, 28 Jan 2019 15:11:30 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 28 Jan 2019 16:11:37 +0100 Message-Id: <20190128151137.31075-3-jacopo@jmondi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190128151137.31075-1-jacopo@jmondi.org> References: <20190128151137.31075-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 2/2] libcamera: v4l2_device: Add methods to get/set format X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 28 Jan 2019 15:11:31 -0000 Add methods to set and get the image format programmed on a V4L2Device for both the single and multi planar use case. Signed-off-by: Jacopo Mondi Reviewed-by: Kieran Bingham --- src/libcamera/include/v4l2_device.h | 10 +++ src/libcamera/v4l2_device.cpp | 128 ++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+) diff --git a/src/libcamera/include/v4l2_device.h b/src/libcamera/include/v4l2_device.h index c70959e..fe54220 100644 --- a/src/libcamera/include/v4l2_device.h +++ b/src/libcamera/include/v4l2_device.h @@ -86,10 +86,20 @@ public: const char *deviceName() const { return caps_.card(); } const char *busName() const { return caps_.bus_info(); } + int format(V4L2DeviceFormat *fmt); + int setFormat(V4L2DeviceFormat *fmt); + private: std::string deviceNode_; int fd_; V4L2Capability caps_; + enum v4l2_buf_type bufferType_; + + int getFormatSingleplane(V4L2DeviceFormat *fmt); + int setFormatSingleplane(V4L2DeviceFormat *fmt); + + int getFormatMultiplane(V4L2DeviceFormat *fmt); + int setFormatMultiplane(V4L2DeviceFormat *fmt); }; } /* namespace libcamera */ diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index d6143f2..5c415d0 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -227,6 +227,15 @@ int V4L2Device::open() return -EINVAL; } + if (caps_.isCapture()) + bufferType_ = caps_.isMultiplanar() + ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE + : V4L2_BUF_TYPE_VIDEO_CAPTURE; + else + bufferType_ = caps_.isMultiplanar() + ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE + : V4L2_BUF_TYPE_VIDEO_OUTPUT; + return 0; } @@ -269,4 +278,123 @@ void V4L2Device::close() * \return The string containing the device location */ +/** + * \brief Retrieve the image format set on the V4L2 device + * \return 0 for success, a negative error code otherwise + */ +int V4L2Device::format(V4L2DeviceFormat *fmt) +{ + return caps_.isMultiplanar() ? getFormatMultiplane(fmt) : + getFormatSingleplane(fmt); +} + +/** + * \brief Configure an image format on the V4L2 device + * \return 0 for success, a negative error code otherwise + */ +int V4L2Device::setFormat(V4L2DeviceFormat *fmt) +{ + return caps_.isMultiplanar() ? setFormatMultiplane(fmt) : + setFormatSingleplane(fmt); +} + +int V4L2Device::getFormatSingleplane(V4L2DeviceFormat *fmt) +{ + struct v4l2_format v4l2Fmt; + struct v4l2_pix_format *pix = &v4l2Fmt.fmt.pix; + int ret; + + v4l2Fmt.type = bufferType_; + ret = ioctl(fd_, VIDIOC_S_FMT, &v4l2Fmt); + if (ret) { + ret = -errno; + LOG(Error) << "Unable to get format: " << strerror(-ret); + return ret; + } + + fmt->width = pix->width; + fmt->height = pix->height; + fmt->fourcc = pix->pixelformat; + fmt->planes = 1; + fmt->planesFmt[0].bpl = pix->bytesperline; + fmt->planesFmt[0].size = pix->sizeimage; + + return 0; +} + +int V4L2Device::setFormatSingleplane(V4L2DeviceFormat *fmt) +{ + struct v4l2_format v4l2Fmt; + struct v4l2_pix_format *pix = &v4l2Fmt.fmt.pix; + int ret; + + v4l2Fmt.type = bufferType_; + pix->width = fmt->width; + pix->height = fmt->height; + pix->pixelformat = fmt->fourcc; + + ret = ioctl(fd_, VIDIOC_S_FMT, &v4l2Fmt); + if (ret) { + ret = -errno; + LOG(Error) << "Unable to set format: " << strerror(-ret); + return ret; + } + + return 0; +} + +int V4L2Device::getFormatMultiplane(V4L2DeviceFormat *fmt) +{ + struct v4l2_format v4l2Fmt; + struct v4l2_pix_format_mplane *pix = &v4l2Fmt.fmt.pix_mp; + int ret; + + v4l2Fmt.type = bufferType_; + ret = ioctl(fd_, VIDIOC_G_FMT, &v4l2Fmt); + if (ret) { + ret = -errno; + LOG(Error) << "Unable to get format: " << strerror(-ret); + return ret; + } + + fmt->width = pix->width; + fmt->height = pix->height; + fmt->fourcc = pix->pixelformat; + fmt->planes = pix->num_planes; + + for (unsigned int i = 0; i < fmt->planes; ++i) { + fmt->planesFmt[i].bpl = pix->plane_fmt[i].bytesperline; + fmt->planesFmt[i].size = pix->plane_fmt[i].sizeimage; + } + + return 0; +} + +int V4L2Device::setFormatMultiplane(V4L2DeviceFormat *fmt) +{ + struct v4l2_format v4l2Fmt; + struct v4l2_pix_format_mplane *pix = &v4l2Fmt.fmt.pix_mp; + int ret; + + v4l2Fmt.type = bufferType_; + pix->width = fmt->width; + pix->height = fmt->height; + pix->pixelformat = fmt->fourcc; + pix->num_planes = fmt->planes; + + for (unsigned int i = 0; i < pix->num_planes; ++i) { + pix->plane_fmt[i].bytesperline = fmt->planesFmt[i].bpl; + pix->plane_fmt[i].sizeimage = fmt->planesFmt[i].size; + } + + ret = ioctl(fd_, VIDIOC_S_FMT, &v4l2Fmt); + if (ret) { + ret = -errno; + LOG(Error) << "Unable to set format: " << strerror(-ret); + return ret; + } + + return 0; +} + } /* namespace libcamera */