From patchwork Wed Jun 19 02:51:22 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 1459 Return-Path: Received: from vsp-unauthed02.binero.net (vsp-unauthed02.binero.net [195.74.38.227]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2864861A26 for ; Wed, 19 Jun 2019 04:52:29 +0200 (CEST) X-Halon-ID: 3e849a76-923d-11e9-8ab4-005056917a89 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (unknown [89.233.230.99]) by bin-vsp-out-01.atm.binero.net (Halon) with ESMTPA id 3e849a76-923d-11e9-8ab4-005056917a89; Wed, 19 Jun 2019 04:52:15 +0200 (CEST) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Wed, 19 Jun 2019 04:51:22 +0200 Message-Id: <20190619025129.21164-10-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190619025129.21164-1-niklas.soderlund@ragnatech.se> References: <20190619025129.21164-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 09/16] libcamera: v4l2_device: Add enumeration of pixelformats and frame sizes 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: Wed, 19 Jun 2019 02:52:29 -0000 Add methods to enumerate pixelformats and frame sizes from a v4l2 device. The interface is similar to how V4L2Subdevice enumerates mbus codes and frame sizes. Signed-off-by: Niklas Söderlund Reviewed-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- * Changes since v3 - Catch the error from V4L2Device::enumSizes() in V4L2Device::formats() - s/pixelformats/pixel formats/ --- src/libcamera/include/v4l2_device.h | 5 ++ src/libcamera/v4l2_device.cpp | 114 ++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+) diff --git a/src/libcamera/include/v4l2_device.h b/src/libcamera/include/v4l2_device.h index bdecc087fe5afae0..1a67850ac4c1088f 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 { @@ -132,6 +133,7 @@ public: int getFormat(V4L2DeviceFormat *format); int setFormat(V4L2DeviceFormat *format); + ImageFormats formats(); int exportBuffers(BufferPool *pool); int importBuffers(BufferPool *pool); @@ -163,6 +165,9 @@ private: int createPlane(Buffer *buffer, unsigned int plane, unsigned int length); + std::vector enumPixelformats(); + std::vector enumSizes(unsigned int pixelFormat); + Buffer *dequeueBuffer(); void bufferAvailable(EventNotifier *notifier); diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 0821bd75fb428766..e14fc6109a4db470 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -634,6 +634,33 @@ int V4L2Device::setFormatSingleplane(V4L2DeviceFormat *format) return 0; } +/** + * \brief Enumerate all pixel formats and frame sizes + * + * Enumerate all pixel formats and frame sizes supported by the video device. + * + * \return A list of the supported device formats + */ +ImageFormats V4L2Device::formats() +{ + ImageFormats formats; + + for (unsigned int pixelformat : enumPixelformats()) { + std::vector sizes = enumSizes(pixelformat); + if (sizes.empty()) + return {}; + + if (formats.addFormat(pixelformat, sizes)) { + LOG(V4L2, Error) + << "Could not add sizes for pixel format " + << pixelformat; + return {}; + } + } + + return formats; +} + int V4L2Device::requestBuffers(unsigned int count) { struct v4l2_requestbuffers rb = {}; @@ -763,6 +790,93 @@ int V4L2Device::createPlane(Buffer *buffer, unsigned int planeIndex, return 0; } +std::vector V4L2Device::enumPixelformats() +{ + std::vector formats; + int ret; + + for (unsigned int index = 0; ; index++) { + struct v4l2_fmtdesc pixelformatEnum = {}; + pixelformatEnum.index = index; + pixelformatEnum.type = bufferType_; + + ret = ioctl(fd_, VIDIOC_ENUM_FMT, &pixelformatEnum); + if (ret) + break; + + formats.push_back(pixelformatEnum.pixelformat); + } + + if (ret && errno != EINVAL) { + ret = -errno; + LOG(V4L2, Error) + << "Unable to enumerate pixel formats: " + << strerror(-ret); + return {}; + } + + return formats; +} + +std::vector V4L2Device::enumSizes(unsigned int pixelFormat) +{ + std::vector sizes; + int ret; + + for (unsigned int index = 0;; index++) { + struct v4l2_frmsizeenum frameSize = {}; + frameSize.index = index; + frameSize.pixel_format = pixelFormat; + + ret = ioctl(fd_, VIDIOC_ENUM_FRAMESIZES, &frameSize); + if (ret) + break; + + if (index != 0 && + frameSize.type != V4L2_FRMSIZE_TYPE_DISCRETE) { + LOG(V4L2, Error) + << "Non-zero index for non discrete type"; + return {}; + } + + switch (frameSize.type) { + case V4L2_FRMSIZE_TYPE_DISCRETE: + sizes.emplace_back(frameSize.discrete.width, + frameSize.discrete.height); + break; + case V4L2_FRMSIZE_TYPE_CONTINUOUS: + sizes.emplace_back(frameSize.stepwise.min_width, + frameSize.stepwise.min_height, + frameSize.stepwise.max_width, + frameSize.stepwise.max_height); + break; + case V4L2_FRMSIZE_TYPE_STEPWISE: + sizes.emplace_back(frameSize.stepwise.min_width, + frameSize.stepwise.min_height, + frameSize.stepwise.max_width, + frameSize.stepwise.max_height, + frameSize.stepwise.step_width, + frameSize.stepwise.step_height); + break; + default: + LOG(V4L2, Error) + << "Unknown VIDIOC_ENUM_FRAMESIZES type " + << frameSize.type; + return {}; + } + } + + if (ret && errno != EINVAL) { + ret = -errno; + LOG(V4L2, Error) + << "Unable to enumerate frame sizes: " + << strerror(-ret); + return {}; + } + + return sizes; +} + /** * \brief Import the externally allocated \a pool of buffers * \param[in] pool BufferPool of buffers to import