[libcamera-devel] [PATCH 09/17] libcamera: v4l2_device: Add enumeration of pixelformats and frame sizes

Niklas Söderlund niklas.soderlund at ragnatech.se
Mon May 27 02:15:35 CEST 2019


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       | 104 ++++++++++++++++++++++++++++
 2 files changed, 109 insertions(+)

diff --git a/src/libcamera/include/v4l2_device.h b/src/libcamera/include/v4l2_device.h
index 2e7bd1e7f4cce276..db2d12757c6f564a 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 {
@@ -126,6 +127,7 @@ public:
 
 	int getFormat(V4L2DeviceFormat *format);
 	int setFormat(V4L2DeviceFormat *format);
+	V4L2DeviceFormats formats();
 
 	int exportBuffers(BufferPool *pool);
 	int importBuffers(BufferPool *pool);
@@ -154,6 +156,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 8366ffc4db559520..a9667092a20505d9 100644
--- a/src/libcamera/v4l2_device.cpp
+++ b/src/libcamera/v4l2_device.cpp
@@ -564,6 +564,23 @@ int V4L2Device::setFormatMultiplane(V4L2DeviceFormat *format)
 	return 0;
 }
 
+/**
+ * \brief Enumerate all pixelformats and frame sizes
+ *
+ * Enumerate all pixelformats and frame sizes reported by the video device.
+ *
+ * \return All pixelformats and frame sizes
+ */
+V4L2DeviceFormats V4L2Device::formats()
+{
+	std::map<unsigned int, std::vector<SizeRange>> formatMap = {};
+
+	for (unsigned int pixelformat : enumPixelformats())
+		formatMap[pixelformat] = enumSizes(pixelformat);
+
+	return V4L2DeviceFormats(formatMap);
+}
+
 int V4L2Device::requestBuffers(unsigned int count)
 {
 	struct v4l2_requestbuffers rb = {};
@@ -692,6 +709,93 @@ int V4L2Device::createPlane(Buffer *buffer, unsigned int planeIndex,
 
 	return 0;
 }
+std::vector<unsigned int> V4L2Device::enumPixelformats()
+{
+	std::vector<unsigned int> pixelformats;
+	int ret;
+
+	for (unsigned int index = 0;; index++) {
+		struct v4l2_fmtdesc pixelformatEnum = {
+			.index = index,
+			.type = bufferType_,
+		};
+
+		ret = ioctl(fd_, VIDIOC_ENUM_FMT, &pixelformatEnum);
+		if (ret)
+			break;
+
+		pixelformats.push_back(pixelformatEnum.pixelformat);
+	}
+
+	if (ret && errno != EINVAL) {
+		ret = errno;
+		LOG(V4L2, Error)
+			<< "Unable to enumerate pixelformats: "
+			<< strerror(ret);
+		return {};
+	}
+
+	return pixelformats;
+}
+
+std::vector<SizeRange> V4L2Device::enumSizes(unsigned int pixelformat)
+{
+	std::vector<SizeRange> sizes;
+	int ret;
+
+	for (unsigned int index = 0;; index++) {
+		struct v4l2_frmsizeenum frameSize = {
+			.index = index,
+			.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)
+				<< "None 0 index for none 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)
+				<< "Unkown 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
-- 
2.21.0



More information about the libcamera-devel mailing list