From patchwork Fri May 3 17:51:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 1158 X-Patchwork-Delegate: kieran.bingham@ideasonboard.com Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 72C0B60003 for ; Fri, 3 May 2019 19:52:02 +0200 (CEST) Received: from Q.Home (unknown [IPv6:2a02:c7f:1887:5d00:c990:5ff4:193b:c9b8]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id CFB4731E; Fri, 3 May 2019 19:52:01 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1556905921; bh=zNJGJxpOWEj23Mp7+tRn/mmxD3ZLAnp2Zg70dVwcNLs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=pxMOZf1Z22rch6DSGk5u4wkxpYKMZpociZ/9zeG63n31ziityP5VHHvBvWf0mwvzP Ly85hT+agSvDXkrtmzJkNCC+ocF0YczIR/xKSJAQoKThQACnbgl1jjs9gaiH0LutKh GP/AnH+Yd6VNoQZxpj4vy9Mvtv9SGK5bULztNYsE= From: Kieran Bingham To: LibCamera Devel Date: Fri, 3 May 2019 18:51:58 +0100 Message-Id: <20190503175158.15035-1-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190503171319.GD4903@pendragon.ideasonboard.com> References: <20190503171319.GD4903@pendragon.ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH] libcamera: v4l2_device: Enumerate Formats 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: Fri, 03 May 2019 17:52:02 -0000 Provide a means to enumerate the supported formats on a device and return a FormatEnum of the results. Signed-off-by: Kieran Bingham --- src/libcamera/include/v4l2_device.h | 5 ++ src/libcamera/v4l2_device.cpp | 93 +++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) This is an untested method for enumerating frame sizes from a V4L2Device. It might warrant some updates to use the new Size type. diff --git a/src/libcamera/include/v4l2_device.h b/src/libcamera/include/v4l2_device.h index 2e7bd1e7f4cc..87c2aa35bd5c 100644 --- a/src/libcamera/include/v4l2_device.h +++ b/src/libcamera/include/v4l2_device.h @@ -16,6 +16,7 @@ #include #include +#include "formats.h" #include "log.h" namespace libcamera { @@ -124,6 +125,7 @@ public: const char *busName() const { return caps_.bus_info(); } const std::string &deviceNode() const { return deviceNode_; } + FormatEnum formats(void); int getFormat(V4L2DeviceFormat *format); int setFormat(V4L2DeviceFormat *format); @@ -144,6 +146,9 @@ protected: std::string logPrefix() const; private: + int enumerateFrameSizes(unsigned int pixelFormat, + std::vector *sizes); + int getFormatSingleplane(V4L2DeviceFormat *format); int setFormatSingleplane(V4L2DeviceFormat *format); diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 8366ffc4db55..12b622ba8db5 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -412,6 +412,99 @@ std::string V4L2Device::logPrefix() const return deviceNode_ + (V4L2_TYPE_IS_OUTPUT(bufferType_) ? "[out]" : "[cap]"); } +int V4L2Device::enumerateFrameSizes(unsigned int pixelFormat, + std::vector *sizes) +{ + struct v4l2_frmsizeenum sizeEnum = {}; + int ret; + + sizeEnum.index = 0; + sizeEnum.pixel_format = pixelFormat; + + while (true) { + ret = ioctl(fd_, VIDIOC_ENUM_FRAMESIZES, &sizeEnum); + if (ret) + break; + + switch (sizeEnum.type) { + case V4L2_FRMSIZE_TYPE_DISCRETE: + sizes->emplace_back(sizeEnum.discrete.width, sizeEnum.discrete.height, + sizeEnum.discrete.width, sizeEnum.discrete.height); + break; + + case V4L2_FRMSIZE_TYPE_CONTINUOUS: + case V4L2_FRMSIZE_TYPE_STEPWISE: + sizes->emplace_back(sizeEnum.stepwise.min_width, sizeEnum.stepwise.min_height, + sizeEnum.stepwise.max_width, sizeEnum.stepwise.max_height); + /* + * TODO: How do we handle the {step_width,step_height} + * parameters here + */ + break; + default: + break; + } + + sizeEnum.index++; + } + + if (ret && (errno != EINVAL && errno != ENOTTY)) { + ret = -errno; + LOG(V4L2, Error) + << "Unable to enumerate frame sizes" + << ": " << strerror(-ret); + sizes->clear(); + + return ret; + } + + return 0; +} + +/** + * \brief List the device image resolutions and formats on \a pad + * + * Retrieve a list of image formats and sizes available on the video device. + * + * Each image size list is associated with a pixel format code for which + * the reported resolutions are supported. + * + * \return A map of image formats associated with a list of image sizes, or + * an empty map on error. + */ +FormatEnum V4L2Device::formats(void) +{ + FormatEnum formatMap = {}; + struct v4l2_fmtdesc v4l2FormatDesc = {}; + int ret; + + v4l2FormatDesc.index = 0; + v4l2FormatDesc.type = bufferType_; + + while (true) { + ret = ioctl(fd_, VIDIOC_ENUM_FMT, &v4l2FormatDesc); + if (ret) + break; + + ret = enumerateFrameSizes(v4l2FormatDesc.pixelformat, + &formatMap[v4l2FormatDesc.pixelformat]); + if (ret) + break; + + v4l2FormatDesc.index++; + } + + if (ret && (errno != EINVAL && errno != ENOTTY)) { + ret = -errno; + LOG(V4L2, Error) + << "Unable to enumerate device formats" + << ": " << strerror(-ret); + formatMap.clear(); + } + + return formatMap; +} + /** * \brief Retrieve the image format set on the V4L2 device * \param[out] format The image format applied on the device