[libcamera-devel,v4,6/9] pipeline: rkisp1: Query the driver for formats
diff mbox series

Message ID 20221124025133.17875-7-laurent.pinchart@ideasonboard.com
State Accepted
Headers show
Series
  • Add Bayer format support for RkISP1
Related show

Commit Message

Laurent Pinchart Nov. 24, 2022, 2:51 a.m. UTC
From: Paul Elder <paul.elder@ideasonboard.com>

Query the driver for the output formats and sizes that it supports,
instead of hardcoding them. This allows future-proofing for formats that
are supported by some but not all versions of the driver.

As the rkisp1 driver currently does not support VIDIOC_ENUM_FRAMESIZES,
fallback to the hardcoded list of supported formats and framesizes. This
feature will be added to the driver in parallel, though we cannot
guarantee that users will have a new enough kernel for it.

Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
---
Changes since v3:

- Demote Warning message to Info and rewrite it

Changes since v2:

- Don't pass V4L2VideoDevice to RkISP1Path::populateFormats()
- Use structured binding in for range loop
- Use std::set::count() to replace std::find_if()
- Don't cache sizes, use std::set instead of std::map
- Update min and max resolutions based on enumerated sizes
- Drop comment about aspect ratio

Changes since v1:

- Enumerate and cache framesizes as well
- Massage generateConfiguration accordingly
- This lets us skip modifying V4L2VideoDevice::formats() to support lack
  of ENUM_FRAMESIZES
- Also requires us to keep the list of hardcoded formats for backward
  compatibility
---
 src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 51 +++++++++++++++++--
 src/libcamera/pipeline/rkisp1/rkisp1_path.h   |  8 ++-
 2 files changed, 54 insertions(+), 5 deletions(-)

Patch
diff mbox series

diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
index 2d38f0fb37ab..7a2b0d172d84 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
+++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
@@ -41,6 +41,8 @@  bool RkISP1Path::init(MediaDevice *media)
 	if (video_->open() < 0)
 		return false;
 
+	populateFormats();
+
 	link_ = media->link("rkisp1_isp", 2, resizer, 0);
 	if (!link_)
 		return false;
@@ -48,6 +50,41 @@  bool RkISP1Path::init(MediaDevice *media)
 	return true;
 }
 
+void RkISP1Path::populateFormats()
+{
+	V4L2VideoDevice::Formats v4l2Formats = video_->formats();
+	if (v4l2Formats.empty()) {
+		LOG(RkISP1, Info)
+			<< "Failed to enumerate supported formats and sizes, using defaults";
+
+		for (const PixelFormat &format : formats_)
+			streamFormats_.insert(format);
+		return;
+	}
+
+	minResolution_ = { 65535, 65535 };
+	maxResolution_ = { 0, 0 };
+
+	std::vector<PixelFormat> formats;
+	for (const auto &[format, sizes] : v4l2Formats) {
+		const PixelFormat pixelFormat = format.toPixelFormat();
+		const PixelFormatInfo &info = PixelFormatInfo::info(pixelFormat);
+
+		/* \todo Add support for RAW formats. */
+		if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW)
+			continue;
+
+		streamFormats_.insert(pixelFormat);
+
+		for (const auto &size : sizes) {
+			if (minResolution_ > size.min)
+				minResolution_ = size.min;
+			if (maxResolution_ < size.max)
+				maxResolution_ = size.max;
+		}
+	}
+}
+
 StreamConfiguration RkISP1Path::generateConfiguration(const Size &resolution)
 {
 	Size maxResolution = maxResolution_.boundedToAspectRatio(resolution)
@@ -55,7 +92,7 @@  StreamConfiguration RkISP1Path::generateConfiguration(const Size &resolution)
 	Size minResolution = minResolution_.expandedToAspectRatio(resolution);
 
 	std::map<PixelFormat, std::vector<SizeRange>> streamFormats;
-	for (const PixelFormat &format : formats_)
+	for (const auto &format : streamFormats_)
 		streamFormats[format] = { { minResolution, maxResolution } };
 
 	StreamFormats formats(streamFormats);
@@ -72,8 +109,12 @@  CameraConfiguration::Status RkISP1Path::validate(StreamConfiguration *cfg)
 	const StreamConfiguration reqCfg = *cfg;
 	CameraConfiguration::Status status = CameraConfiguration::Valid;
 
-	if (std::find(formats_.begin(), formats_.end(), cfg->pixelFormat) ==
-	    formats_.end())
+	/*
+	 * Default to NV12 if the requested format is not supported. All
+	 * versions of the ISP are guaranteed to support NV12 on both the main
+	 * and self paths.
+	 */
+	if (!streamFormats_.count(cfg->pixelFormat))
 		cfg->pixelFormat = formats::NV12;
 
 	cfg->size.boundTo(maxResolution_);
@@ -204,6 +245,10 @@  void RkISP1Path::stop()
 	running_ = false;
 }
 
+/*
+ * \todo Remove the hardcoded resolutions and formats once all users will have
+ * migrated to a recent enough kernel.
+ */
 namespace {
 constexpr Size RKISP1_RSZ_MP_SRC_MIN{ 32, 16 };
 constexpr Size RKISP1_RSZ_MP_SRC_MAX{ 4416, 3312 };
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
index f3f1ae391d65..d88effbb6f56 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1_path.h
+++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
@@ -8,6 +8,7 @@ 
 #pragma once
 
 #include <memory>
+#include <set>
 #include <vector>
 
 #include <libcamera/base/signal.h>
@@ -57,14 +58,17 @@  public:
 	Signal<FrameBuffer *> &bufferReady() { return video_->bufferReady; }
 
 private:
+	void populateFormats();
+
 	static constexpr unsigned int RKISP1_BUFFER_COUNT = 4;
 
 	const char *name_;
 	bool running_;
 
 	const Span<const PixelFormat> formats_;
-	const Size minResolution_;
-	const Size maxResolution_;
+	std::set<PixelFormat> streamFormats_;
+	Size minResolution_;
+	Size maxResolution_;
 
 	std::unique_ptr<V4L2Subdevice> resizer_;
 	std::unique_ptr<V4L2VideoDevice> video_;