[libcamera-devel] libcamera: v4l2_device: Enumerate Formats

Message ID 20190503175158.15035-1-kieran.bingham@ideasonboard.com
State Superseded
Delegated to: Kieran Bingham
Headers show
Series
  • [libcamera-devel] libcamera: v4l2_device: Enumerate Formats
Related show

Commit Message

Kieran Bingham May 3, 2019, 5:51 p.m. UTC
Provide a means to enumerate the supported formats on a device and
return a FormatEnum of the results.

Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
---
 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.

Patch

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 <libcamera/geometry.h>
 #include <libcamera/signal.h>
 
+#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<SizeRange> *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<SizeRange> *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