[libcamera-devel] [RFC 2/3] libcamera: v4l2_device: Add methods to get/set format
Jacopo Mondi
jacopo at jmondi.org
Sat Jan 26 16:13:17 CET 2019
Add methods to set and get the image format programmed on a V4L2Device
for both the single and multi planar use case.
Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
---
src/libcamera/include/v4l2_device.h | 13 +++
src/libcamera/v4l2_device.cpp | 131 ++++++++++++++++++++++++++++
2 files changed, 144 insertions(+)
diff --git a/src/libcamera/include/v4l2_device.h b/src/libcamera/include/v4l2_device.h
index ee0c4eb..01dbf45 100644
--- a/src/libcamera/include/v4l2_device.h
+++ b/src/libcamera/include/v4l2_device.h
@@ -14,6 +14,7 @@
#include <libcamera/buffer.h>
#include <libcamera/event_notifier.h>
+#include <libcamera/stream.h>
namespace libcamera {
@@ -81,6 +82,9 @@ public:
int requestBuffers(unsigned int qty = 8);
int requestBuffers(unsigned int qty, std::vector<FrameBuffer *> &buffers);
+ int format(StreamConfiguration *config);
+ int setFormat(StreamConfiguration *config);
+
int queueBuffer(FrameBuffer *frame);
FrameBuffer *dequeueBuffer();
@@ -93,6 +97,7 @@ private:
std::string deviceNode_;
int fd_;
V4L2Capability caps_;
+ unsigned int buftype_;
enum v4l2_memory memoryType_;
enum v4l2_buf_type bufferType_;
@@ -101,6 +106,14 @@ private:
void bufferAvailable(EventNotifier *notifier);
EventNotifier *fdEvent_;
+
+ unsigned int getPlanesFromFormat(unsigned int pixfmt);
+ unsigned int getBppFromFormat(unsigned int pixfmt);
+ int getFormatSingleplane(StreamConfiguration *config);
+ int setFormatSingleplane(StreamConfiguration *config);
+
+ int getFormatMultiplane(StreamConfiguration *config);
+ int setFormatMultiplane(StreamConfiguration *config);
};
} /* namespace libcamera */
diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp
index 4d39c85..d16691d 100644
--- a/src/libcamera/v4l2_device.cpp
+++ b/src/libcamera/v4l2_device.cpp
@@ -203,6 +203,15 @@ int V4L2Device::open()
return -EINVAL;
}
+ if (caps_.isCapture())
+ buftype_ = caps_.isMultiplanar() ?
+ V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
+ V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ else
+ buftype_ = caps_.isMultiplanar() ?
+ V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
+ V4L2_BUF_TYPE_VIDEO_OUTPUT;
+
return 0;
}
@@ -314,6 +323,26 @@ int V4L2Device::requestBuffers(unsigned int qty, std::vector<FrameBuffer *> &buf
return 0;
}
+/**
+ * \brief Retrieve the image format set on the V4L2 device
+ * \return 0 for success, a negative error code otherwise
+ */
+int V4L2Device::format(StreamConfiguration *config)
+{
+ return caps_.isMultiplanar() ? getFormatMultiplane(config) :
+ getFormatSingleplane(config);
+}
+
+/**
+ * \brief Program an image format on the V4L2 device
+ * \return 0 for success, a negative error code otherwise
+ */
+int V4L2Device::setFormat(StreamConfiguration *config)
+{
+ return caps_.isMultiplanar() ? setFormatMultiplane(config) :
+ setFormatSingleplane(config);
+}
+
int V4L2Device::queueBuffer(FrameBuffer *frame)
{
struct v4l2_buffer buf = {};
@@ -422,6 +451,108 @@ int V4L2Device::streamOff()
}
delete fdEvent_;
+}
+
+/* TODO: this is a simple stub at the moment. */
+unsigned int V4L2Device::getPlanesFromFormat(unsigned int pixfmt)
+{
+ return 1;
+}
+
+/* TODO: this is a simple stub at the moment. */
+unsigned int V4L2Device::getBppFromFormat(unsigned int pixfmt)
+{
+ return 16;
+}
+
+int V4L2Device::getFormatSingleplane(StreamConfiguration *config)
+{
+ struct v4l2_format v4l2Fmt;
+ struct v4l2_pix_format *pix = &v4l2Fmt.fmt.pix;
+ int ret;
+
+ ret = ioctl(fd_, VIDIOC_S_FMT, &v4l2Fmt);
+ if (ret) {
+ ret = -errno;
+ LOG(Error) << "Unable to get format: " << strerror(-ret);
+ return ret;
+ }
+
+ config->setWidth(pix->width);
+ config->setHeight(pix->height);
+ config->setPixelFormat(pix->pixelformat);
+
+ return 0;
+}
+
+int V4L2Device::setFormatSingleplane(StreamConfiguration *config)
+{
+ struct v4l2_format v4l2Fmt;
+ struct v4l2_pix_format *pix = &v4l2Fmt.fmt.pix;
+ int ret;
+
+ v4l2Fmt.type = buftype_;
+ pix->width = config->width();
+ pix->height = config->height();
+
+ pix->width = config->width();
+ pix->height = config->height();
+ pix->pixelformat = config->pixelformat();
+
+ ret = ioctl(fd_, VIDIOC_S_FMT, &v4l2Fmt);
+ if (ret) {
+ ret = -errno;
+ LOG(Error) << "Unable to set format: " << strerror(-ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+int V4L2Device::getFormatMultiplane(StreamConfiguration *config)
+{
+ struct v4l2_format v4l2Fmt;
+ struct v4l2_pix_format_mplane *pix = &v4l2Fmt.fmt.pix_mp;
+ int ret;
+
+ ret = ioctl(fd_, VIDIOC_G_FMT, &v4l2Fmt);
+ if (ret) {
+ ret = -errno;
+ LOG(Error) << "Unable to get format: " << strerror(-ret);
+ return ret;
+ }
+
+ config->setWidth(pix->width);
+ config->setHeight(pix->height);
+ config->setPixelFormat(pix->pixelformat);
+
+ return 0;
+}
+
+int V4L2Device::setFormatMultiplane(StreamConfiguration *config)
+{
+ struct v4l2_format v4l2Fmt;
+ struct v4l2_pix_format_mplane *pix = &v4l2Fmt.fmt.pix_mp;
+ int ret;
+
+ v4l2Fmt.type = buftype_;
+ pix->width = config->width();
+ pix->height = config->height();
+ pix->pixelformat = config->pixelformat();
+
+ unsigned int numPlanes = getPlanesFromFormat(pix->pixelformat);
+ unsigned int bpp = getBppFromFormat(pix->pixelformat);
+ for (unsigned int i = 0; i < numPlanes; ++i) {
+ pix->plane_fmt[i].bytesperline = bpp * pix->width;
+ pix->plane_fmt[i].sizeimage = bpp * pix->width * pix->height;
+ }
+
+ ret = ioctl(fd_, VIDIOC_S_FMT, &v4l2Fmt);
+ if (ret) {
+ ret = -errno;
+ LOG(Error) << "Unable to set format: " << strerror(-ret);
+ return ret;
+ }
return 0;
}
--
2.20.1
More information about the libcamera-devel
mailing list