[v14,4/8] libcamera: simple: Validate raw stream configurations
diff mbox series

Message ID 20251101193558.38279-5-mzamazal@redhat.com
State New
Headers show
Series
  • Enable raw streams with software ISP
Related show

Commit Message

Milan Zamazal Nov. 1, 2025, 7:35 p.m. UTC
SimpleCameraConfiguration::validate() looks for the best configuration.
As part of enabling raw stream support, the method must consider raw
streams in addition to the processed streams.

Raw streams are adjusted from the capture format and size.

Note that with both processed and raw streams, the requested sizes must
be mutually matching, including resizing due to debayer requirements.
For example, the following `cam' setup is valid for imx219

  cam -s role=viewfinder,width=1920,height=1080 \
      -s role=raw,width=3280,height=2464

rather than

  cam -s role=viewfinder,width=1920,height=1080 \
      -s role=raw,width=1920,height=1080

due to the resolution of 1924x1080 actually selected for debayering to
1920x1080.  If the resolutions don't match mutually or don't match the
available sizes, validation adjusts them.

Setting up the right configurations is still not enough to make the raw
streams working.  Buffer handling must be changed in the simple
pipeline, which is addressed in followup patches.

Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
Co-developed-by: Umang Jain <uajain@igalia.com>
Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
---
 src/libcamera/pipeline/simple/simple.cpp | 89 +++++++++++++++++-------
 1 file changed, 63 insertions(+), 26 deletions(-)

Patch
diff mbox series

diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
index 5d6b9c5e9..c4b22c311 100644
--- a/src/libcamera/pipeline/simple/simple.cpp
+++ b/src/libcamera/pipeline/simple/simple.cpp
@@ -11,6 +11,7 @@ 
 #include <list>
 #include <map>
 #include <memory>
+#include <optional>
 #include <queue>
 #include <set>
 #include <stdint.h>
@@ -27,6 +28,7 @@ 
 #include <libcamera/camera.h>
 #include <libcamera/color_space.h>
 #include <libcamera/control_ids.h>
+#include <libcamera/geometry.h>
 #include <libcamera/pixel_format.h>
 #include <libcamera/request.h>
 #include <libcamera/stream.h>
@@ -1140,21 +1142,42 @@  CameraConfiguration::Status SimpleCameraConfiguration::validate()
 	LOG(SimplePipeline, Debug)
 		<< "Largest stream size is " << maxStreamSize;
 
+	/* Cap the number of raw stream configuration */
+	unsigned int rawCount = 0;
+	PixelFormat requestedRawFormat;
+	for (const StreamConfiguration &cfg : config_) {
+		if (!isRaw(cfg))
+			continue;
+		requestedRawFormat = cfg.pixelFormat;
+		rawCount++;
+	}
+
+	if (rawCount > 1) {
+		LOG(SimplePipeline, Error)
+			<< "Camera configuration with multiple raw streams not supported";
+		return Invalid;
+	}
+
 	/*
 	 * Find the best configuration for the pipeline using a heuristic.
-	 * First select the pixel format based on the streams (which are
-	 * considered ordered from highest to lowest priority). Default to the
-	 * first pipeline configuration if no streams request a supported pixel
-	 * format.
+	 * First select the pixel format based on the raw streams followed by
+	 * non-raw streams (which are considered ordered from highest to lowest
+	 * priority). Default to the first pipeline configuration if no streams
+	 * request a supported pixel format.
 	 */
 	const std::vector<const SimpleCameraData::Configuration *> *configs =
 		&data_->formats_.begin()->second;
 
-	for (const StreamConfiguration &cfg : config_) {
-		auto it = data_->formats_.find(cfg.pixelFormat);
-		if (it != data_->formats_.end()) {
-			configs = &it->second;
-			break;
+	auto rawIter = data_->formats_.find(requestedRawFormat);
+	if (rawIter != data_->formats_.end()) {
+		configs = &rawIter->second;
+	} else {
+		for (const StreamConfiguration &cfg : config_) {
+			auto it = data_->formats_.find(cfg.pixelFormat);
+			if (it != data_->formats_.end()) {
+				configs = &it->second;
+				break;
+			}
 		}
 	}
 
@@ -1213,21 +1236,35 @@  CameraConfiguration::Status SimpleCameraConfiguration::validate()
 
 	for (unsigned int i = 0; i < config_.size(); ++i) {
 		StreamConfiguration &cfg = config_[i];
+		const bool raw = isRaw(cfg);
 
 		/* Adjust the pixel format and size. */
-		auto it = std::find(pipeConfig_->outputFormats.begin(),
-				    pipeConfig_->outputFormats.end(),
-				    cfg.pixelFormat);
-		if (it == pipeConfig_->outputFormats.end())
-			it = pipeConfig_->outputFormats.begin();
-
-		PixelFormat pixelFormat = *it;
-		if (cfg.pixelFormat != pixelFormat) {
-			LOG(SimplePipeline, Debug)
-				<< "Adjusting pixel format from "
-				<< cfg.pixelFormat << " to " << pixelFormat;
-			cfg.pixelFormat = pixelFormat;
-			status = Adjusted;
+		if (raw) {
+			if (cfg.pixelFormat != pipeConfig_->captureFormat ||
+			    cfg.size != pipeConfig_->captureSize) {
+				cfg.pixelFormat = pipeConfig_->captureFormat;
+				cfg.size = pipeConfig_->captureSize;
+
+				LOG(SimplePipeline, Debug)
+					<< "Adjusting raw stream to "
+					<< cfg.toString();
+				status = Adjusted;
+			}
+		} else {
+			auto it = std::find(pipeConfig_->outputFormats.begin(),
+					    pipeConfig_->outputFormats.end(),
+					    cfg.pixelFormat);
+			if (it == pipeConfig_->outputFormats.end())
+				it = pipeConfig_->outputFormats.begin();
+
+			PixelFormat pixelFormat = *it;
+			if (cfg.pixelFormat != pixelFormat) {
+				LOG(SimplePipeline, Debug)
+					<< "Adjusting processed pixel format from "
+					<< cfg.pixelFormat << " to " << pixelFormat;
+				cfg.pixelFormat = pixelFormat;
+				status = Adjusted;
+			}
 		}
 
 		/*
@@ -1238,7 +1275,7 @@  CameraConfiguration::Status SimpleCameraConfiguration::validate()
 		 * case, perform the standard pixel format based color space adjustment.
 		 */
 		if (!cfg.colorSpace) {
-			const PixelFormatInfo &info = PixelFormatInfo::info(pixelFormat);
+			const PixelFormatInfo &info = PixelFormatInfo::info(cfg.pixelFormat);
 			switch (info.colourEncoding) {
 			case PixelFormatInfo::ColourEncodingRGB:
 				cfg.colorSpace = ColorSpace::Srgb;
@@ -1254,14 +1291,14 @@  CameraConfiguration::Status SimpleCameraConfiguration::validate()
 				<< cfg.colorSpace.value().toString();
 			status = Adjusted;
 		}
-		if (cfg.colorSpace->adjust(pixelFormat)) {
+		if (cfg.colorSpace->adjust(cfg.pixelFormat)) {
 			LOG(SimplePipeline, Debug)
 				<< "Color space adjusted to "
 				<< cfg.colorSpace.value().toString();
 			status = Adjusted;
 		}
 
-		if (!pipeConfig_->outputSizes.contains(cfg.size)) {
+		if (!raw && !pipeConfig_->outputSizes.contains(cfg.size)) {
 			Size adjustedSize = pipeConfig_->captureSize;
 			/*
 			 * The converter (when present) may not be able to output
@@ -1284,7 +1321,7 @@  CameraConfiguration::Status SimpleCameraConfiguration::validate()
 			needConversion_ = true;
 
 		/* Set the stride and frameSize. */
-		if (needConversion_) {
+		if (needConversion_ && !raw) {
 			std::tie(cfg.stride, cfg.frameSize) =
 				data_->converter_
 					? data_->converter_->strideAndFrameSize(cfg.pixelFormat,