diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 3950bb3d..1cce2fd0 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -1138,29 +1140,57 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() status = Adjusted; } - /* Find the largest stream size. */ - Size maxStreamSize; - for (const StreamConfiguration &cfg : config_) - maxStreamSize.expandTo(cfg.size); + /* Find the largest stream sizes. */ + Size maxProcessedStreamSize; + Size maxRawStreamSize; + for (const StreamConfiguration &cfg : config_) { + if (isRaw(cfg)) + maxRawStreamSize.expandTo(cfg.size); + else + maxProcessedStreamSize.expandTo(cfg.size); + } LOG(SimplePipeline, Debug) - << "Largest stream size is " << maxStreamSize; + << "Largest processed stream size is " << maxProcessedStreamSize; + LOG(SimplePipeline, Debug) + << "Largest raw stream size is " << maxRawStreamSize; + + /* Cap the number of raw stream configurations */ + 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 *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; + } } } @@ -1182,8 +1212,10 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() const Size &captureSize = pipeConfig->captureSize; const Size &maxOutputSize = pipeConfig->outputSizes.max; - if (maxOutputSize.width >= maxStreamSize.width && - maxOutputSize.height >= maxStreamSize.height) { + if (maxOutputSize.width >= maxProcessedStreamSize.width && + maxOutputSize.height >= maxProcessedStreamSize.height && + captureSize.width >= maxRawStreamSize.width && + captureSize.height >= maxRawStreamSize.height) { if (!pipeConfig_ || captureSize < pipeConfig_->captureSize) pipeConfig_ = pipeConfig; } @@ -1201,7 +1233,8 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() << V4L2SubdeviceFormat{ pipeConfig_->code, pipeConfig_->sensorSize, {} } << " -> " << pipeConfig_->captureSize << "-" << pipeConfig_->captureFormat - << " for max stream size " << maxStreamSize; + << " for max processed stream size " << maxProcessedStreamSize + << " and max raw stream size " << maxRawStreamSize; /* * Adjust the requested streams. @@ -1220,21 +1253,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(); + if (raw) { + if (cfg.pixelFormat != pipeConfig_->captureFormat || + cfg.size != pipeConfig_->captureSize) { + cfg.pixelFormat = pipeConfig_->captureFormat; + cfg.size = pipeConfig_->captureSize; - PixelFormat pixelFormat = *it; - if (cfg.pixelFormat != pixelFormat) { - LOG(SimplePipeline, Debug) - << "Adjusting pixel format from " - << cfg.pixelFormat << " to " << pixelFormat; - cfg.pixelFormat = pixelFormat; - status = Adjusted; + 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; + } } /* @@ -1245,7 +1292,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; @@ -1262,12 +1309,12 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() * adjusting a requested one, changes here shouldn't set the status * to Adjusted. */ - cfg.colorSpace->adjust(pixelFormat); + cfg.colorSpace->adjust(cfg.pixelFormat); LOG(SimplePipeline, Debug) << "Unspecified color space set to " << cfg.colorSpace.value().toString(); } else { - if (cfg.colorSpace->adjust(pixelFormat)) { + if (cfg.colorSpace->adjust(cfg.pixelFormat)) { LOG(SimplePipeline, Debug) << "Color space adjusted to " << cfg.colorSpace.value().toString(); @@ -1275,7 +1322,7 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() } } - 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 @@ -1298,7 +1345,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,