summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNiklas Söderlund <niklas.soderlund@ragnatech.se>2019-05-01 01:36:36 +0200
committerNiklas Söderlund <niklas.soderlund@ragnatech.se>2019-06-19 11:54:30 +0200
commit87e46f7f594ec9e1e4873df43807e66fc407c6a9 (patch)
treed81c801553662926e0b05637a599bd905c52f993 /src
parentce02ea29cda94f065d857ae00101e2fef5467a40 (diff)
libcamera: v4l2_device: Add enumeration of pixelformats and frame sizes
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@ragnatech.se> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'src')
-rw-r--r--src/libcamera/include/v4l2_device.h5
-rw-r--r--src/libcamera/v4l2_device.cpp114
2 files changed, 119 insertions, 0 deletions
diff --git a/src/libcamera/include/v4l2_device.h b/src/libcamera/include/v4l2_device.h
index bdecc087..1a67850a 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 0821bd75..e14fc610 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<SizeRange> 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<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 pixel formats: "
+ << 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 {};
+ }
+
+ 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