[libcamera-devel] [PATCH v3 04/22] libcamera: V4L2VideoDevice: Add tryFormat
Paul Elder
paul.elder at ideasonboard.com
Sat Jul 4 15:31:22 CEST 2020
Add tryFormat and its variations (meta, single-plane, multi-plane) to
V4L2VideoDevice.
Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
---
New in v3
---
include/libcamera/internal/v4l2_videodevice.h | 4 +
src/libcamera/v4l2_videodevice.cpp | 121 ++++++++++++++++++
2 files changed, 125 insertions(+)
diff --git a/include/libcamera/internal/v4l2_videodevice.h b/include/libcamera/internal/v4l2_videodevice.h
index 4d21f5a..56c3aee 100644
--- a/include/libcamera/internal/v4l2_videodevice.h
+++ b/include/libcamera/internal/v4l2_videodevice.h
@@ -186,6 +186,7 @@ public:
const V4L2Capability &caps() const { return caps_; }
int getFormat(V4L2DeviceFormat *format);
+ int tryFormat(V4L2DeviceFormat *format);
int setFormat(V4L2DeviceFormat *format);
std::map<V4L2PixelFormat, std::vector<SizeRange>> formats(uint32_t code = 0);
@@ -217,12 +218,15 @@ protected:
private:
int getFormatMeta(V4L2DeviceFormat *format);
+ int tryFormatMeta(V4L2DeviceFormat *format);
int setFormatMeta(V4L2DeviceFormat *format);
int getFormatMultiplane(V4L2DeviceFormat *format);
+ int tryFormatMultiplane(V4L2DeviceFormat *format);
int setFormatMultiplane(V4L2DeviceFormat *format);
int getFormatSingleplane(V4L2DeviceFormat *format);
+ int tryFormatSingleplane(V4L2DeviceFormat *format);
int setFormatSingleplane(V4L2DeviceFormat *format);
std::vector<V4L2PixelFormat> enumPixelformats(uint32_t code);
diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp
index 3614b2e..f25914c 100644
--- a/src/libcamera/v4l2_videodevice.cpp
+++ b/src/libcamera/v4l2_videodevice.cpp
@@ -723,6 +723,26 @@ int V4L2VideoDevice::getFormat(V4L2DeviceFormat *format)
return getFormatSingleplane(format);
}
+/**
+ * \brief Try an image format on the V4L2 video device
+ * \param[inout] format The image format to test applicablity to the video device
+ *
+ * Test if the supplied \a format to the video device is acceptable, and return
+ * the actually applied format parameters, as \ref V4L2VideoDevice::tryFormat
+ * would do.
+ *
+ * \return 0 on success or a negative error code otherwise
+ */
+int V4L2VideoDevice::tryFormat(V4L2DeviceFormat *format)
+{
+ if (caps_.isMeta())
+ return tryFormatMeta(format);
+ else if (caps_.isMultiplanar())
+ return tryFormatMultiplane(format);
+ else
+ return tryFormatSingleplane(format);
+}
+
/**
* \brief Configure an image format on the V4L2 video device
* \param[inout] format The image format to apply to the video device
@@ -765,6 +785,35 @@ int V4L2VideoDevice::getFormatMeta(V4L2DeviceFormat *format)
return 0;
}
+int V4L2VideoDevice::tryFormatMeta(V4L2DeviceFormat *format)
+{
+ struct v4l2_format v4l2Format = {};
+ struct v4l2_meta_format *pix = &v4l2Format.fmt.meta;
+ int ret;
+
+ v4l2Format.type = bufferType_;
+ pix->dataformat = format->fourcc;
+ pix->buffersize = format->planes[0].size;
+ ret = ioctl(VIDIOC_TRY_FMT, &v4l2Format);
+ if (ret) {
+ LOG(V4L2, Error) << "Unable to try format: " << strerror(-ret);
+ return ret;
+ }
+
+ /*
+ * Return to caller the format actually applied on the video device,
+ * which might differ from the requested one.
+ */
+ format->size.width = 0;
+ format->size.height = 0;
+ format->fourcc = V4L2PixelFormat(pix->dataformat);
+ format->planesCount = 1;
+ format->planes[0].bpl = pix->buffersize;
+ format->planes[0].size = pix->buffersize;
+
+ return 0;
+}
+
int V4L2VideoDevice::setFormatMeta(V4L2DeviceFormat *format)
{
struct v4l2_format v4l2Format = {};
@@ -820,6 +869,46 @@ int V4L2VideoDevice::getFormatMultiplane(V4L2DeviceFormat *format)
return 0;
}
+int V4L2VideoDevice::tryFormatMultiplane(V4L2DeviceFormat *format)
+{
+ struct v4l2_format v4l2Format = {};
+ struct v4l2_pix_format_mplane *pix = &v4l2Format.fmt.pix_mp;
+ int ret;
+
+ v4l2Format.type = bufferType_;
+ pix->width = format->size.width;
+ pix->height = format->size.height;
+ pix->pixelformat = format->fourcc;
+ pix->num_planes = format->planesCount;
+ pix->field = V4L2_FIELD_NONE;
+
+ for (unsigned int i = 0; i < pix->num_planes; ++i) {
+ pix->plane_fmt[i].bytesperline = format->planes[i].bpl;
+ pix->plane_fmt[i].sizeimage = format->planes[i].size;
+ }
+
+ ret = ioctl(VIDIOC_TRY_FMT, &v4l2Format);
+ if (ret) {
+ LOG(V4L2, Error) << "Unable to try format: " << strerror(-ret);
+ return ret;
+ }
+
+ /*
+ * Return to caller the format actually applied on the video device,
+ * which might differ from the requested one.
+ */
+ format->size.width = pix->width;
+ format->size.height = pix->height;
+ format->fourcc = V4L2PixelFormat(pix->pixelformat);
+ format->planesCount = pix->num_planes;
+ for (unsigned int i = 0; i < format->planesCount; ++i) {
+ format->planes[i].bpl = pix->plane_fmt[i].bytesperline;
+ format->planes[i].size = pix->plane_fmt[i].sizeimage;
+ }
+
+ return 0;
+}
+
int V4L2VideoDevice::setFormatMultiplane(V4L2DeviceFormat *format)
{
struct v4l2_format v4l2Format = {};
@@ -883,6 +972,38 @@ int V4L2VideoDevice::getFormatSingleplane(V4L2DeviceFormat *format)
return 0;
}
+int V4L2VideoDevice::tryFormatSingleplane(V4L2DeviceFormat *format)
+{
+ struct v4l2_format v4l2Format = {};
+ struct v4l2_pix_format *pix = &v4l2Format.fmt.pix;
+ int ret;
+
+ v4l2Format.type = bufferType_;
+ pix->width = format->size.width;
+ pix->height = format->size.height;
+ pix->pixelformat = format->fourcc;
+ pix->bytesperline = format->planes[0].bpl;
+ pix->field = V4L2_FIELD_NONE;
+ ret = ioctl(VIDIOC_TRY_FMT, &v4l2Format);
+ if (ret) {
+ LOG(V4L2, Error) << "Unable to try format: " << strerror(-ret);
+ return ret;
+ }
+
+ /*
+ * Return to caller the format actually applied on the device,
+ * which might differ from the requested one.
+ */
+ format->size.width = pix->width;
+ format->size.height = pix->height;
+ format->fourcc = V4L2PixelFormat(pix->pixelformat);
+ format->planesCount = 1;
+ format->planes[0].bpl = pix->bytesperline;
+ format->planes[0].size = pix->sizeimage;
+
+ return 0;
+}
+
int V4L2VideoDevice::setFormatSingleplane(V4L2DeviceFormat *format)
{
struct v4l2_format v4l2Format = {};
--
2.27.0
More information about the libcamera-devel
mailing list