summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libcamera/internal/v4l2_videodevice.h7
-rw-r--r--src/libcamera/v4l2_videodevice.cpp50
2 files changed, 42 insertions, 15 deletions
diff --git a/include/libcamera/internal/v4l2_videodevice.h b/include/libcamera/internal/v4l2_videodevice.h
index 4d21f5a0..fb4c0aab 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,13 +218,13 @@ protected:
private:
int getFormatMeta(V4L2DeviceFormat *format);
- int setFormatMeta(V4L2DeviceFormat *format);
+ int trySetFormatMeta(V4L2DeviceFormat *format, bool set);
int getFormatMultiplane(V4L2DeviceFormat *format);
- int setFormatMultiplane(V4L2DeviceFormat *format);
+ int trySetFormatMultiplane(V4L2DeviceFormat *format, bool set);
int getFormatSingleplane(V4L2DeviceFormat *format);
- int setFormatSingleplane(V4L2DeviceFormat *format);
+ int trySetFormatSingleplane(V4L2DeviceFormat *format, bool set);
std::vector<V4L2PixelFormat> enumPixelformats(uint32_t code);
std::vector<SizeRange> enumSizes(V4L2PixelFormat pixelFormat);
diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp
index 3614b2ed..e0d22012 100644
--- a/src/libcamera/v4l2_videodevice.cpp
+++ b/src/libcamera/v4l2_videodevice.cpp
@@ -724,6 +724,26 @@ int V4L2VideoDevice::getFormat(V4L2DeviceFormat *format)
}
/**
+ * \brief Try an image format on the V4L2 video device
+ * \param[inout] format The image format to test applicability to the video device
+ *
+ * Try the supplied \a format on the video device without applying it, returning
+ * the format that would be applied. This is equivalent to setFormat(), except
+ * that the device configuration is not changed.
+ *
+ * \return 0 on success or a negative error code otherwise
+ */
+int V4L2VideoDevice::tryFormat(V4L2DeviceFormat *format)
+{
+ if (caps_.isMeta())
+ return trySetFormatMeta(format, false);
+ else if (caps_.isMultiplanar())
+ return trySetFormatMultiplane(format, false);
+ else
+ return trySetFormatSingleplane(format, false);
+}
+
+/**
* \brief Configure an image format on the V4L2 video device
* \param[inout] format The image format to apply to the video device
*
@@ -735,11 +755,11 @@ int V4L2VideoDevice::getFormat(V4L2DeviceFormat *format)
int V4L2VideoDevice::setFormat(V4L2DeviceFormat *format)
{
if (caps_.isMeta())
- return setFormatMeta(format);
+ return trySetFormatMeta(format, true);
else if (caps_.isMultiplanar())
- return setFormatMultiplane(format);
+ return trySetFormatMultiplane(format, true);
else
- return setFormatSingleplane(format);
+ return trySetFormatSingleplane(format, true);
}
int V4L2VideoDevice::getFormatMeta(V4L2DeviceFormat *format)
@@ -765,7 +785,7 @@ int V4L2VideoDevice::getFormatMeta(V4L2DeviceFormat *format)
return 0;
}
-int V4L2VideoDevice::setFormatMeta(V4L2DeviceFormat *format)
+int V4L2VideoDevice::trySetFormatMeta(V4L2DeviceFormat *format, bool set)
{
struct v4l2_format v4l2Format = {};
struct v4l2_meta_format *pix = &v4l2Format.fmt.meta;
@@ -774,9 +794,11 @@ int V4L2VideoDevice::setFormatMeta(V4L2DeviceFormat *format)
v4l2Format.type = bufferType_;
pix->dataformat = format->fourcc;
pix->buffersize = format->planes[0].size;
- ret = ioctl(VIDIOC_S_FMT, &v4l2Format);
+ ret = ioctl(set ? VIDIOC_S_FMT : VIDIOC_TRY_FMT, &v4l2Format);
if (ret) {
- LOG(V4L2, Error) << "Unable to set format: " << strerror(-ret);
+ LOG(V4L2, Error)
+ << "Unable to " << (set ? "set" : "try")
+ << " format: " << strerror(-ret);
return ret;
}
@@ -820,7 +842,7 @@ int V4L2VideoDevice::getFormatMultiplane(V4L2DeviceFormat *format)
return 0;
}
-int V4L2VideoDevice::setFormatMultiplane(V4L2DeviceFormat *format)
+int V4L2VideoDevice::trySetFormatMultiplane(V4L2DeviceFormat *format, bool set)
{
struct v4l2_format v4l2Format = {};
struct v4l2_pix_format_mplane *pix = &v4l2Format.fmt.pix_mp;
@@ -838,9 +860,11 @@ int V4L2VideoDevice::setFormatMultiplane(V4L2DeviceFormat *format)
pix->plane_fmt[i].sizeimage = format->planes[i].size;
}
- ret = ioctl(VIDIOC_S_FMT, &v4l2Format);
+ ret = ioctl(set ? VIDIOC_S_FMT : VIDIOC_TRY_FMT, &v4l2Format);
if (ret) {
- LOG(V4L2, Error) << "Unable to set format: " << strerror(-ret);
+ LOG(V4L2, Error)
+ << "Unable to " << (set ? "set" : "try")
+ << " format: " << strerror(-ret);
return ret;
}
@@ -883,7 +907,7 @@ int V4L2VideoDevice::getFormatSingleplane(V4L2DeviceFormat *format)
return 0;
}
-int V4L2VideoDevice::setFormatSingleplane(V4L2DeviceFormat *format)
+int V4L2VideoDevice::trySetFormatSingleplane(V4L2DeviceFormat *format, bool set)
{
struct v4l2_format v4l2Format = {};
struct v4l2_pix_format *pix = &v4l2Format.fmt.pix;
@@ -895,9 +919,11 @@ int V4L2VideoDevice::setFormatSingleplane(V4L2DeviceFormat *format)
pix->pixelformat = format->fourcc;
pix->bytesperline = format->planes[0].bpl;
pix->field = V4L2_FIELD_NONE;
- ret = ioctl(VIDIOC_S_FMT, &v4l2Format);
+ ret = ioctl(set ? VIDIOC_S_FMT : VIDIOC_TRY_FMT, &v4l2Format);
if (ret) {
- LOG(V4L2, Error) << "Unable to set format: " << strerror(-ret);
+ LOG(V4L2, Error)
+ << "Unable to " << (set ? "set" : "try")
+ << " format: " << strerror(-ret);
return ret;
}