[libcamera-devel] [PATCH v2 09/16] libcamera: v4l2_device: Add enumeration of pixelformats and frame sizes
Jacopo Mondi
jacopo at jmondi.org
Thu Jun 13 17:59:14 CEST 2019
Hi Niklas,
On Wed, Jun 12, 2019 at 02:43:52AM +0200, Niklas Söderlund wrote:
> 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 <niklas.soderlund at ragnatech.se>
> ---
> src/libcamera/include/v4l2_device.h | 5 ++
> src/libcamera/v4l2_device.cpp | 110 ++++++++++++++++++++++++++++
> 2 files changed, 115 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 <libcamera/geometry.h>
> #include <libcamera/signal.h>
>
> +#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<unsigned int> enumPixelformats();
> + std::vector<SizeRange> 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..202680d8632a4dd1 100644
> --- a/src/libcamera/v4l2_device.cpp
> +++ b/src/libcamera/v4l2_device.cpp
> @@ -634,6 +634,29 @@ int V4L2Device::setFormatSingleplane(V4L2DeviceFormat *format)
> return 0;
> }
>
> +/**
> + * \brief Enumerate all pixelformats and frame sizes
> + *
> + * Enumerate all pixelformats and frame sizes supported by the video device.
pixel formats
> + *
> + * \return A list of the supported device formats
> + */
> +ImageFormats V4L2Device::formats()
> +{
> + ImageFormats formats;
> +
> + for (unsigned int pixelformat : enumPixelformats()) {
> + if (formats.addFormat(pixelformat, enumSizes(pixelformat))) {
> + 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 +786,93 @@ int V4L2Device::createPlane(Buffer *buffer, unsigned int planeIndex,
> return 0;
> }
>
> +std::vector<unsigned int> V4L2Device::enumPixelformats()
> +{
> + std::vector<unsigned int> 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 pixelformats: "
> + << strerror(-ret);
> + return {};
> + }
> +
> + return formats;
> +}
> +
> +std::vector<SizeRange> V4L2Device::enumSizes(unsigned int pixelFormat)
> +{
> + std::vector<SizeRange> 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 {};
> + }
This happens if the driver is out of specification, and as you know
this NEVER EVER happens. Joking aside, I would drop this check, true
it doesn't hurt though...
> +
> + 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 "
"type: "
Minors apart
Reviewed-by: Jacopo Mondi <jacopo at jmondi.org>
Thanks
j
> + << 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
> --
> 2.21.0
>
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel at lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://lists.libcamera.org/pipermail/libcamera-devel/attachments/20190613/713ecfaa/attachment.sig>
More information about the libcamera-devel
mailing list