[libcamera-devel] [RFC PATCH v2] pipeline: rkisp1: Query the driver for formats

Paul Elder paul.elder at ideasonboard.com
Wed Jul 20 18:40:04 CEST 2022


Query the driver for the output formats that it supports, instead of
hardcoding it. While at it, cache the framesizes as well.

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 at ideasonboard.com>

---
Changes in v2:
- 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 | 50 +++++++++++++++++--
 src/libcamera/pipeline/rkisp1/rkisp1_path.h   |  3 ++
 2 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
index 6f175758..cf5feebe 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(video_);
+
 	link_ = media->link("rkisp1_isp", 2, resizer, 0);
 	if (!link_)
 		return false;
@@ -48,15 +50,44 @@ bool RkISP1Path::init(MediaDevice *media)
 	return true;
 }
 
+void RkISP1Path::populateFormats(std::unique_ptr<V4L2VideoDevice> &video)
+{
+	V4L2VideoDevice::Formats v4l2Formats = video->formats();
+	if (v4l2Formats.empty()) {
+		LOG(RkISP1, Warning)
+			<< "Failed to enumerate framesizes. Loading default framesizes";
+
+		for (const PixelFormat &format : formats_)
+			streamFormats_[format] = { { minResolution_, maxResolution_ } };
+		return;
+	}
+
+	std::vector<PixelFormat> formats;
+	for (auto pair : v4l2Formats) {
+		const PixelFormat pixelFormat = pair.first.toPixelFormat();
+		const PixelFormatInfo &info = PixelFormatInfo::info(pixelFormat);
+
+		/* \todo Add support for RAW formats. */
+		if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW)
+			continue;
+
+		streamFormats_[pixelFormat] = pair.second;
+	}
+}
+
 StreamConfiguration RkISP1Path::generateConfiguration(const Size &resolution)
 {
 	Size maxResolution = maxResolution_.boundedToAspectRatio(resolution)
 					   .boundedTo(resolution);
 	Size minResolution = minResolution_.expandedToAspectRatio(resolution);
 
+	/*
+	 * Can we use the global min/max resolutions here or does it need to be
+	 * resized to the same aspect ratio as the requested resolution?
+	 */
 	std::map<PixelFormat, std::vector<SizeRange>> streamFormats;
-	for (const PixelFormat &format : formats_)
-		streamFormats[format] = { { minResolution, maxResolution } };
+	for (auto pair : streamFormats_)
+		streamFormats[pair.first] = { { minResolution, maxResolution } };
 
 	StreamFormats formats(streamFormats);
 	StreamConfiguration cfg(formats);
@@ -72,8 +103,14 @@ 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 (std::find_if(streamFormats_.begin(), streamFormats_.end(),
+			 [cfg](auto pair) { return pair.first == cfg->pixelFormat; }) ==
+	    streamFormats_.end())
 		cfg->pixelFormat = formats::NV12;
 
 	cfg->size.boundTo(maxResolution_);
@@ -207,6 +244,8 @@ void RkISP1Path::stop()
 namespace {
 constexpr Size RKISP1_RSZ_MP_SRC_MIN{ 32, 16 };
 constexpr Size RKISP1_RSZ_MP_SRC_MAX{ 4416, 3312 };
+
+/* \todo Remove this eventually. */
 constexpr std::array<PixelFormat, 6> RKISP1_RSZ_MP_FORMATS{
 	formats::YUYV,
 	formats::NV16,
@@ -214,11 +253,12 @@ constexpr std::array<PixelFormat, 6> RKISP1_RSZ_MP_FORMATS{
 	formats::NV21,
 	formats::NV12,
 	formats::R8,
-	/* \todo Add support for RAW formats. */
 };
 
 constexpr Size RKISP1_RSZ_SP_SRC_MIN{ 32, 16 };
 constexpr Size RKISP1_RSZ_SP_SRC_MAX{ 1920, 1920 };
+
+/* \todo Remove this eventually. */
 constexpr std::array<PixelFormat, 8> RKISP1_RSZ_SP_FORMATS{
 	formats::YUYV,
 	formats::NV16,
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
index f3f1ae39..42db158f 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1_path.h
+++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
@@ -57,11 +57,14 @@ public:
 	Signal<FrameBuffer *> &bufferReady() { return video_->bufferReady; }
 
 private:
+	void populateFormats(std::unique_ptr<V4L2VideoDevice> &video);
+
 	static constexpr unsigned int RKISP1_BUFFER_COUNT = 4;
 
 	const char *name_;
 	bool running_;
 
+	std::map<PixelFormat, std::vector<SizeRange>> streamFormats_;
 	const Span<const PixelFormat> formats_;
 	const Size minResolution_;
 	const Size maxResolution_;
-- 
2.30.2



More information about the libcamera-devel mailing list