[v11,5/8] libcamera: simple: Validate raw stream configurations
diff mbox series

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

Commit Message

Milan Zamazal July 23, 2025, 6:08 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 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>
---
 src/libcamera/pipeline/simple/simple.cpp | 86 +++++++++++++++++-------
 1 file changed, 62 insertions(+), 24 deletions(-)

Patch
diff mbox series

diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
index 37abaa0e0..89ee699c3 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>
@@ -1131,22 +1133,39 @@  CameraConfiguration::Status SimpleCameraConfiguration::validate()
 		<< "Largest stream size is " << maxStreamSize;
 
 	/*
-	 * 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.
+	 * Find the best configuration for the pipeline using a heuristic. First
+	 * select the pixel format based on the streams. If there is a raw stream,
+	 * its format has precedence. If there is no raw stream, the streams 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;
+	std::optional<PixelFormat> rawFormat;
+	for (const auto &cfg : config_)
+		if (cfg.colorSpace == ColorSpace::Raw) {
+			if (rawFormat) {
+				LOG(SimplePipeline, Error)
+					<< "Can't capture multiple raw streams";
+				return Invalid;
+			}
+			rawFormat = cfg.pixelFormat;
+		}
 
-	for (const StreamConfiguration &cfg : config_) {
-		auto it = data_->formats_.find(cfg.pixelFormat);
-		if (it != data_->formats_.end()) {
+	const std::vector<const SimpleCameraData::Configuration *> *configs = nullptr;
+	if (rawFormat) {
+		auto it = data_->formats_.find(rawFormat.value());
+		if (it != data_->formats_.end())
 			configs = &it->second;
-			break;
-		}
 	}
+	if (!configs)
+		for (const StreamConfiguration &cfg : config_) {
+			auto it = data_->formats_.find(cfg.pixelFormat);
+			if (it != data_->formats_.end()) {
+				configs = &it->second;
+				break;
+			}
+		}
+	if (!configs)
+		configs = &data_->formats_.begin()->second;
 
 	/*
 	 * \todo Pick the best sensor output media bus format when the
@@ -1203,17 +1222,27 @@  CameraConfiguration::Status SimpleCameraConfiguration::validate()
 
 	for (unsigned int i = 0; i < config_.size(); ++i) {
 		StreamConfiguration &cfg = config_[i];
+		const bool raw = cfg.colorSpace == ColorSpace::Raw;
 
-		/* 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();
+		/* Adjust the pixel format, colour space and size. */
 
-		PixelFormat pixelFormat = *it;
+		PixelFormat pixelFormat;
+		if (raw) {
+			pixelFormat = pipeConfig_->captureFormat;
+		} else {
+			auto it = std::find(pipeConfig_->outputFormats.begin(),
+					    pipeConfig_->outputFormats.end(),
+					    cfg.pixelFormat);
+			if (it == pipeConfig_->outputFormats.end())
+				it = pipeConfig_->outputFormats.begin();
+			pixelFormat = *it;
+		}
 		if (cfg.pixelFormat != pixelFormat) {
-			LOG(SimplePipeline, Debug) << "Adjusting pixel format";
+			LOG(SimplePipeline, Debug)
+				<< "Adjusting pixel format of a "
+				<< (raw ? "raw" : "processed")
+				<< " stream from " << cfg.pixelFormat
+				<< " to " << pixelFormat;
 			cfg.pixelFormat = pixelFormat;
 			/*
 			 * Do not touch the colour space for raw requested roles.
@@ -1240,7 +1269,7 @@  CameraConfiguration::Status SimpleCameraConfiguration::validate()
 			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
@@ -1259,11 +1288,20 @@  CameraConfiguration::Status SimpleCameraConfiguration::validate()
 
 		/* \todo Create a libcamera core class to group format and size */
 		if (cfg.pixelFormat != pipeConfig_->captureFormat ||
-		    cfg.size != pipeConfig_->captureSize)
-			needConversion_ = true;
+		    cfg.size != pipeConfig_->captureSize) {
+			if (raw) {
+				cfg.pixelFormat = pipeConfig_->captureFormat;
+				cfg.size = pipeConfig_->captureSize;
+				LOG(SimplePipeline, Debug)
+					<< "Adjusting raw configuration to " << cfg;
+				status = Adjusted;
+			} else {
+				needConversion_ = true;
+			}
+		}
 
 		/* Set the stride, frameSize and bufferCount. */
-		if (needConversion_) {
+		if (needConversion_ && !raw) {
 			std::tie(cfg.stride, cfg.frameSize) =
 				data_->converter_
 					? data_->converter_->strideAndFrameSize(cfg.pixelFormat,