[libcamera-devel,4/8] libcamera: v4l2_videodevice: Support filtering formats by media bus code

Message ID 20200313233856.25202-5-laurent.pinchart@ideasonboard.com
State Superseded
Headers show
Series
  • Simple pipeline handler
Related show

Commit Message

Laurent Pinchart March 13, 2020, 11:38 p.m. UTC
Add support for the recent V4L2 extension to VIDIOC_ENUM_FMT that allows
filtering pixel formats by media bus codes.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 src/libcamera/include/v4l2_videodevice.h |  4 ++--
 src/libcamera/v4l2_videodevice.cpp       | 16 +++++++++++++---
 2 files changed, 15 insertions(+), 5 deletions(-)

Patch

diff --git a/src/libcamera/include/v4l2_videodevice.h b/src/libcamera/include/v4l2_videodevice.h
index d051c9060f09..72e7a50e6c3d 100644
--- a/src/libcamera/include/v4l2_videodevice.h
+++ b/src/libcamera/include/v4l2_videodevice.h
@@ -184,7 +184,7 @@  public:
 
 	int getFormat(V4L2DeviceFormat *format);
 	int setFormat(V4L2DeviceFormat *format);
-	ImageFormats formats();
+	ImageFormats formats(uint32_t code = 0);
 
 	int setCrop(Rectangle *rect);
 	int setCompose(Rectangle *rect);
@@ -220,7 +220,7 @@  private:
 	int getFormatSingleplane(V4L2DeviceFormat *format);
 	int setFormatSingleplane(V4L2DeviceFormat *format);
 
-	std::vector<unsigned int> enumPixelformats();
+	std::vector<unsigned int> enumPixelformats(uint32_t code);
 	std::vector<SizeRange> enumSizes(unsigned int pixelFormat);
 
 	int setSelection(unsigned int target, Rectangle *rect);
diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp
index ca0d147f5fc1..ccc5faba3c27 100644
--- a/src/libcamera/v4l2_videodevice.cpp
+++ b/src/libcamera/v4l2_videodevice.cpp
@@ -839,16 +839,19 @@  int V4L2VideoDevice::setFormatSingleplane(V4L2DeviceFormat *format)
 
 /**
  * \brief Enumerate all pixel formats and frame sizes
+ * \param[in] code Restrict formats to this media bus code.
  *
  * Enumerate all pixel formats and frame sizes supported by the video device.
+ * If the \a code argument is not zero, only formats compatible with that media
+ * bus code will be enumerated.
  *
  * \return A list of the supported video device formats
  */
-ImageFormats V4L2VideoDevice::formats()
+ImageFormats V4L2VideoDevice::formats(uint32_t code)
 {
 	ImageFormats formats;
 
-	for (unsigned int pixelformat : enumPixelformats()) {
+	for (unsigned int pixelformat : enumPixelformats(code)) {
 		std::vector<SizeRange> sizes = enumSizes(pixelformat);
 		if (sizes.empty())
 			return {};
@@ -864,7 +867,7 @@  ImageFormats V4L2VideoDevice::formats()
 	return formats;
 }
 
-std::vector<unsigned int> V4L2VideoDevice::enumPixelformats()
+std::vector<unsigned int> V4L2VideoDevice::enumPixelformats(uint32_t code)
 {
 	std::vector<unsigned int> formats;
 	int ret;
@@ -873,11 +876,18 @@  std::vector<unsigned int> V4L2VideoDevice::enumPixelformats()
 		struct v4l2_fmtdesc pixelformatEnum = {};
 		pixelformatEnum.index = index;
 		pixelformatEnum.type = bufferType_;
+		pixelformatEnum.mbus_code = code;
 
 		ret = ioctl(VIDIOC_ENUM_FMT, &pixelformatEnum);
 		if (ret)
 			break;
 
+		if (code && !(pixelformatEnum.flags & V4L2_FMT_FLAG_MBUS_CODE)) {
+			LOG(V4L2, Error)
+				<< "Media bus code filtering not supported by the device";
+			return {};
+		}
+
 		formats.push_back(pixelformatEnum.pixelformat);
 	}