[WIP,RFC,16/26] libcamera: v4l2_pixelformat: Add toNonGeneric() helper
diff mbox series

Message ID 20261023-b4-raw-model-v1-16-eadb9948901b@ideasonboard.com
State New
Headers show
Series
  • Support the new common raw sensor model
Related show

Commit Message

Jai Luthra Oct. 23, 2026, 10:58 a.m. UTC
Many pipelines may not support the generic RAW format fourccs
immediately. Add a toNonGeneric() helper that gives the bayer-order
specific fourcc value given a PixelFormat and a ColorFilterArray.

Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
---
 include/libcamera/internal/v4l2_pixelformat.h |   3 +
 src/libcamera/v4l2_pixelformat.cpp            | 127 ++++++++++++++++++++++++++
 2 files changed, 130 insertions(+)

Patch
diff mbox series

diff --git a/include/libcamera/internal/v4l2_pixelformat.h b/include/libcamera/internal/v4l2_pixelformat.h
index 543eb21b3c07..2e0991a59a6d 100644
--- a/include/libcamera/internal/v4l2_pixelformat.h
+++ b/include/libcamera/internal/v4l2_pixelformat.h
@@ -20,6 +20,8 @@ 
 
 namespace libcamera {
 
+class ColorFilterArray;
+
 class V4L2PixelFormat
 {
 public:
@@ -48,6 +50,7 @@  public:
 	PixelFormat toPixelFormat(bool warn = true) const;
 	static const std::vector<V4L2PixelFormat> &
 	fromPixelFormat(const PixelFormat &pixelFormat);
+	bool toNonGeneric(const ColorFilterArray cfa);
 
 	bool isGenericLineBasedMetadata() const;
 
diff --git a/src/libcamera/v4l2_pixelformat.cpp b/src/libcamera/v4l2_pixelformat.cpp
index d51987c5ad8a..ca479edb49c2 100644
--- a/src/libcamera/v4l2_pixelformat.cpp
+++ b/src/libcamera/v4l2_pixelformat.cpp
@@ -14,6 +14,7 @@ 
 
 #include <libcamera/base/log.h>
 
+#include <libcamera/color_filter_array.h>
 #include <libcamera/formats.h>
 #include <libcamera/pixel_format.h>
 
@@ -245,6 +246,111 @@  const std::map<V4L2PixelFormat, V4L2PixelFormat::Info> vpf2pf{
 		{ formats::MJPEG, "JPEG JFIF" } },
 };
 
+struct FormatWithCfa {
+	V4L2PixelFormat pixfmt;
+	ColorFilterArray cfa;
+
+	bool operator<(const FormatWithCfa &other) const
+	{
+		return std::tie(pixfmt, cfa.order) <
+		       std::tie(other.pixfmt, other.cfa.order);
+	}
+};
+
+const std::map<FormatWithCfa, V4L2PixelFormat> generic2specific {
+	/* 8-bit */
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_8), ColorFilterArray::BGGR },
+		V4L2PixelFormat(V4L2_PIX_FMT_SBGGR8) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_8), ColorFilterArray::GBRG },
+		V4L2PixelFormat(V4L2_PIX_FMT_SGBRG8) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_8), ColorFilterArray::GRBG },
+		V4L2PixelFormat(V4L2_PIX_FMT_SGRBG8) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_8), ColorFilterArray::RGGB },
+		V4L2PixelFormat(V4L2_PIX_FMT_SRGGB8) },
+	/* 10-bit */
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_10), ColorFilterArray::BGGR },
+		V4L2PixelFormat(V4L2_PIX_FMT_SBGGR10) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_10), ColorFilterArray::GBRG },
+		V4L2PixelFormat(V4L2_PIX_FMT_SGBRG10) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_10), ColorFilterArray::GRBG },
+		V4L2PixelFormat(V4L2_PIX_FMT_SGRBG10) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_10), ColorFilterArray::RGGB },
+		V4L2PixelFormat(V4L2_PIX_FMT_SRGGB10) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_CSI2_10), ColorFilterArray::BGGR },
+		V4L2PixelFormat(V4L2_PIX_FMT_SBGGR10P) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_CSI2_10), ColorFilterArray::GBRG },
+		V4L2PixelFormat(V4L2_PIX_FMT_SGBRG10P) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_CSI2_10), ColorFilterArray::GRBG },
+		V4L2PixelFormat(V4L2_PIX_FMT_SGRBG10P) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_CSI2_10), ColorFilterArray::RGGB },
+		V4L2PixelFormat(V4L2_PIX_FMT_SRGGB10P) },
+	/* 12-bit */
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_12), ColorFilterArray::BGGR },
+		V4L2PixelFormat(V4L2_PIX_FMT_SBGGR12) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_12), ColorFilterArray::GBRG },
+		V4L2PixelFormat(V4L2_PIX_FMT_SGBRG12) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_12), ColorFilterArray::GRBG },
+		V4L2PixelFormat(V4L2_PIX_FMT_SGRBG12) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_12), ColorFilterArray::RGGB },
+		V4L2PixelFormat(V4L2_PIX_FMT_SRGGB12) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_CSI2_12), ColorFilterArray::BGGR },
+		V4L2PixelFormat(V4L2_PIX_FMT_SBGGR12P) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_CSI2_12), ColorFilterArray::GBRG },
+		V4L2PixelFormat(V4L2_PIX_FMT_SGBRG12P) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_CSI2_12), ColorFilterArray::GRBG },
+		V4L2PixelFormat(V4L2_PIX_FMT_SGRBG12P) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_CSI2_12), ColorFilterArray::RGGB },
+		V4L2PixelFormat(V4L2_PIX_FMT_SRGGB12P) },
+	/* 14-bit */
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_14), ColorFilterArray::BGGR },
+		V4L2PixelFormat(V4L2_PIX_FMT_SBGGR14) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_14), ColorFilterArray::GBRG },
+		V4L2PixelFormat(V4L2_PIX_FMT_SGBRG14) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_14), ColorFilterArray::GRBG },
+		V4L2PixelFormat(V4L2_PIX_FMT_SGRBG14) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_14), ColorFilterArray::RGGB },
+		V4L2PixelFormat(V4L2_PIX_FMT_SRGGB14) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_CSI2_14), ColorFilterArray::BGGR },
+		V4L2PixelFormat(V4L2_PIX_FMT_SBGGR14P) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_CSI2_14), ColorFilterArray::GBRG },
+		V4L2PixelFormat(V4L2_PIX_FMT_SGBRG14P) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_CSI2_14), ColorFilterArray::GRBG },
+		V4L2PixelFormat(V4L2_PIX_FMT_SGRBG14P) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_CSI2_14), ColorFilterArray::RGGB },
+		V4L2PixelFormat(V4L2_PIX_FMT_SRGGB14P) },
+	/* 16-bit */
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_16), ColorFilterArray::BGGR },
+		V4L2PixelFormat(V4L2_PIX_FMT_SBGGR16) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_16), ColorFilterArray::GBRG },
+		V4L2PixelFormat(V4L2_PIX_FMT_SGBRG16) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_16), ColorFilterArray::GRBG },
+		V4L2PixelFormat(V4L2_PIX_FMT_SGRBG16) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_16), ColorFilterArray::RGGB },
+		V4L2PixelFormat(V4L2_PIX_FMT_SRGGB16) },
+	/* Monochrome */
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_8), ColorFilterArray::MONO },
+		V4L2PixelFormat(V4L2_PIX_FMT_GREY) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_10), ColorFilterArray::MONO },
+		V4L2PixelFormat(V4L2_PIX_FMT_Y10) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_CSI2_10), ColorFilterArray::MONO },
+		V4L2PixelFormat(V4L2_PIX_FMT_Y10P) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_12), ColorFilterArray::MONO },
+		V4L2PixelFormat(V4L2_PIX_FMT_Y12) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_CSI2_12), ColorFilterArray::MONO },
+		V4L2PixelFormat(V4L2_PIX_FMT_Y12P) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_RAW_16), ColorFilterArray::MONO },
+		V4L2PixelFormat(V4L2_PIX_FMT_Y16) },
+	/* IPU3 */
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_IPU3_RAW10), ColorFilterArray::BGGR },
+		V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SBGGR10) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_IPU3_RAW10), ColorFilterArray::GBRG },
+		V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SGBRG10) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_IPU3_RAW10), ColorFilterArray::GRBG },
+		V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SGRBG10) },
+	{ { V4L2PixelFormat(V4L2_PIX_FMT_IPU3_RAW10), ColorFilterArray::RGGB },
+		V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SRGGB10) },
+};
+
 } /* namespace */
 
 /**
@@ -390,6 +496,27 @@  V4L2PixelFormat::fromPixelFormat(const PixelFormat &pixelFormat)
 	return info.v4l2Formats;
 }
 
+/**
+ * \brief Convert a generic V4L2PixelFormat to a specific one given a color
+ * filter array pattern.
+ * \param[in] cfa Color filter array pattern
+ *
+ * If no specific variant is known for the combination, the format is left
+ * unmodified and false is returned.
+ *
+ * \return True if the format is converted, false otherwise
+ */
+bool V4L2PixelFormat::toNonGeneric(const ColorFilterArray cfa)
+{
+	const auto it = generic2specific.find({*this, cfa});
+	if (it != generic2specific.end()) {
+		*this = it->second;
+		return true;
+	}
+
+	return false;
+}
+
 /**
  * \brief Test if a V4L2PixelFormat is one of the line based generic metadata
  * formats