From patchwork Sat Jul 4 13:31:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 8625 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id A4F12BD792 for ; Sat, 4 Jul 2020 13:32:04 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7341860E3F; Sat, 4 Jul 2020 15:32:04 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="qwN9Vw+w"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0391560C50 for ; Sat, 4 Jul 2020 15:32:03 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 85F55296; Sat, 4 Jul 2020 15:32:01 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1593869522; bh=aKCQ4dp/ptdqUv1bvCyZGuoDg4r4Ml4ik9kjQPlnovA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qwN9Vw+wR41q+iOUQR5W3Zlkz991jFFJ0uuaR83QqM4Q3DBuJUaJWu1rFcm3yrsd2 BRWv3KZkpvw6MXOW5ehbPM5vIbR3hJ8hM5f/BMZYXU39MaJsWJJqFX9tUgnIlqBtUP SKC7OI7Je6210sxed7Ufj0VZB7wIyGC886czqHoc= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Sat, 4 Jul 2020 22:31:22 +0900 Message-Id: <20200704133140.1738660-5-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200704133140.1738660-1-paul.elder@ideasonboard.com> References: <20200704133140.1738660-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 04/22] libcamera: V4L2VideoDevice: Add tryFormat 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add tryFormat and its variations (meta, single-plane, multi-plane) to V4L2VideoDevice. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- New in v3 --- include/libcamera/internal/v4l2_videodevice.h | 4 + src/libcamera/v4l2_videodevice.cpp | 121 ++++++++++++++++++ 2 files changed, 125 insertions(+) diff --git a/include/libcamera/internal/v4l2_videodevice.h b/include/libcamera/internal/v4l2_videodevice.h index 4d21f5a..56c3aee 100644 --- a/include/libcamera/internal/v4l2_videodevice.h +++ b/include/libcamera/internal/v4l2_videodevice.h @@ -186,6 +186,7 @@ public: const V4L2Capability &caps() const { return caps_; } int getFormat(V4L2DeviceFormat *format); + int tryFormat(V4L2DeviceFormat *format); int setFormat(V4L2DeviceFormat *format); std::map> formats(uint32_t code = 0); @@ -217,12 +218,15 @@ protected: private: int getFormatMeta(V4L2DeviceFormat *format); + int tryFormatMeta(V4L2DeviceFormat *format); int setFormatMeta(V4L2DeviceFormat *format); int getFormatMultiplane(V4L2DeviceFormat *format); + int tryFormatMultiplane(V4L2DeviceFormat *format); int setFormatMultiplane(V4L2DeviceFormat *format); int getFormatSingleplane(V4L2DeviceFormat *format); + int tryFormatSingleplane(V4L2DeviceFormat *format); int setFormatSingleplane(V4L2DeviceFormat *format); std::vector enumPixelformats(uint32_t code); diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp index 3614b2e..f25914c 100644 --- a/src/libcamera/v4l2_videodevice.cpp +++ b/src/libcamera/v4l2_videodevice.cpp @@ -723,6 +723,26 @@ int V4L2VideoDevice::getFormat(V4L2DeviceFormat *format) return getFormatSingleplane(format); } +/** + * \brief Try an image format on the V4L2 video device + * \param[inout] format The image format to test applicablity to the video device + * + * Test if the supplied \a format to the video device is acceptable, and return + * the actually applied format parameters, as \ref V4L2VideoDevice::tryFormat + * would do. + * + * \return 0 on success or a negative error code otherwise + */ +int V4L2VideoDevice::tryFormat(V4L2DeviceFormat *format) +{ + if (caps_.isMeta()) + return tryFormatMeta(format); + else if (caps_.isMultiplanar()) + return tryFormatMultiplane(format); + else + return tryFormatSingleplane(format); +} + /** * \brief Configure an image format on the V4L2 video device * \param[inout] format The image format to apply to the video device @@ -765,6 +785,35 @@ int V4L2VideoDevice::getFormatMeta(V4L2DeviceFormat *format) return 0; } +int V4L2VideoDevice::tryFormatMeta(V4L2DeviceFormat *format) +{ + struct v4l2_format v4l2Format = {}; + struct v4l2_meta_format *pix = &v4l2Format.fmt.meta; + int ret; + + v4l2Format.type = bufferType_; + pix->dataformat = format->fourcc; + pix->buffersize = format->planes[0].size; + ret = ioctl(VIDIOC_TRY_FMT, &v4l2Format); + if (ret) { + LOG(V4L2, Error) << "Unable to try format: " << strerror(-ret); + return ret; + } + + /* + * Return to caller the format actually applied on the video device, + * which might differ from the requested one. + */ + format->size.width = 0; + format->size.height = 0; + format->fourcc = V4L2PixelFormat(pix->dataformat); + format->planesCount = 1; + format->planes[0].bpl = pix->buffersize; + format->planes[0].size = pix->buffersize; + + return 0; +} + int V4L2VideoDevice::setFormatMeta(V4L2DeviceFormat *format) { struct v4l2_format v4l2Format = {}; @@ -820,6 +869,46 @@ int V4L2VideoDevice::getFormatMultiplane(V4L2DeviceFormat *format) return 0; } +int V4L2VideoDevice::tryFormatMultiplane(V4L2DeviceFormat *format) +{ + struct v4l2_format v4l2Format = {}; + struct v4l2_pix_format_mplane *pix = &v4l2Format.fmt.pix_mp; + int ret; + + v4l2Format.type = bufferType_; + pix->width = format->size.width; + pix->height = format->size.height; + pix->pixelformat = format->fourcc; + pix->num_planes = format->planesCount; + pix->field = V4L2_FIELD_NONE; + + for (unsigned int i = 0; i < pix->num_planes; ++i) { + pix->plane_fmt[i].bytesperline = format->planes[i].bpl; + pix->plane_fmt[i].sizeimage = format->planes[i].size; + } + + ret = ioctl(VIDIOC_TRY_FMT, &v4l2Format); + if (ret) { + LOG(V4L2, Error) << "Unable to try format: " << strerror(-ret); + return ret; + } + + /* + * Return to caller the format actually applied on the video device, + * which might differ from the requested one. + */ + format->size.width = pix->width; + format->size.height = pix->height; + format->fourcc = V4L2PixelFormat(pix->pixelformat); + format->planesCount = pix->num_planes; + for (unsigned int i = 0; i < format->planesCount; ++i) { + format->planes[i].bpl = pix->plane_fmt[i].bytesperline; + format->planes[i].size = pix->plane_fmt[i].sizeimage; + } + + return 0; +} + int V4L2VideoDevice::setFormatMultiplane(V4L2DeviceFormat *format) { struct v4l2_format v4l2Format = {}; @@ -883,6 +972,38 @@ int V4L2VideoDevice::getFormatSingleplane(V4L2DeviceFormat *format) return 0; } +int V4L2VideoDevice::tryFormatSingleplane(V4L2DeviceFormat *format) +{ + struct v4l2_format v4l2Format = {}; + struct v4l2_pix_format *pix = &v4l2Format.fmt.pix; + int ret; + + v4l2Format.type = bufferType_; + pix->width = format->size.width; + pix->height = format->size.height; + pix->pixelformat = format->fourcc; + pix->bytesperline = format->planes[0].bpl; + pix->field = V4L2_FIELD_NONE; + ret = ioctl(VIDIOC_TRY_FMT, &v4l2Format); + if (ret) { + LOG(V4L2, Error) << "Unable to try format: " << strerror(-ret); + return ret; + } + + /* + * Return to caller the format actually applied on the device, + * which might differ from the requested one. + */ + format->size.width = pix->width; + format->size.height = pix->height; + format->fourcc = V4L2PixelFormat(pix->pixelformat); + format->planesCount = 1; + format->planes[0].bpl = pix->bytesperline; + format->planes[0].size = pix->sizeimage; + + return 0; +} + int V4L2VideoDevice::setFormatSingleplane(V4L2DeviceFormat *format) { struct v4l2_format v4l2Format = {};