@@ -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);
@@ -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
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.