From b98f3ee039b516e36a5c7b762f508e02515e1e3a Mon Sep 17 00:00:00 2001 From: Milan Zamazal Date: Thu, 4 Dec 2025 17:49:11 +0100 Subject: [PATCH] libcamera: simple: Handle processed and raw formats separately Let's handle both processed and/or raw output configurations. In addition to the already handled processed formats and sizes, this patch adds handling of raw formats and sizes, which correspond to the capture formats and sizes. When creating stream configurations, raw or processed formats are selected according to the requested stream roles. This is another preparatory patch without making raw outputs working. Reviewed-by: Umang Jain Signed-off-by: Milan Zamazal Signed-off-by: Kieran Bingham --- src/libcamera/pipeline/simple/simple.cpp | 85 ++++++++++++++++-------- 1 file changed, 59 insertions(+), 26 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 17ca9045..3950bb3d 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -1357,42 +1357,75 @@ SimplePipelineHandler::generateConfiguration(Camera *camera, Span> formats; - - for (const SimpleCameraData::Configuration &cfg : data->configs_) { - for (PixelFormat format : cfg.outputFormats) - formats[format].push_back(cfg.outputSizes); - } - - /* Sort the sizes and merge any consecutive overlapping ranges. */ - for (auto &[format, sizes] : formats) { - std::sort(sizes.begin(), sizes.end(), - [](SizeRange &a, SizeRange &b) { - return a.min < b.min; - }); - - auto cur = sizes.begin(); - auto next = cur; - - while (++next != sizes.end()) { - if (cur->max.width >= next->min.width && - cur->max.height >= next->min.height) - cur->max = next->max; - else if (++cur != next) - *cur = *next; + bool processedRequested = false; + bool rawRequested = false; + for (const auto &role : roles) + if (role == StreamRole::Raw) { + if (rawRequested) { + LOG(SimplePipeline, Error) + << "Can't capture multiple raw streams"; + return nullptr; + } + rawRequested = true; + } else { + processedRequested = true; } - sizes.erase(++cur, sizes.end()); + /* Create the formats maps. */ + std::map> processedFormats; + std::map> rawFormats; + + for (const SimpleCameraData::Configuration &cfg : data->configs_) { + rawFormats[cfg.captureFormat].push_back(cfg.captureSize); + for (PixelFormat format : cfg.outputFormats) + processedFormats[format].push_back(cfg.outputSizes); } + if (processedRequested && processedFormats.empty()) { + LOG(SimplePipeline, Error) + << "Processed stream requested but no corresponding output configuration found"; + return nullptr; + } + if (rawRequested && rawFormats.empty()) { + LOG(SimplePipeline, Error) + << "Raw stream requested but no corresponding output configuration found"; + return nullptr; + } + + auto setUpFormatSizes = [](std::map> &formats) { + /* Sort the sizes and merge any consecutive overlapping ranges. */ + + for (auto &[format, sizes] : formats) { + std::sort(sizes.begin(), sizes.end(), + [](SizeRange &a, SizeRange &b) { + return a.min < b.min; + }); + + auto cur = sizes.begin(); + auto next = cur; + + while (++next != sizes.end()) { + if (cur->max.width >= next->min.width && + cur->max.height >= next->min.height) + cur->max = next->max; + else if (++cur != next) + *cur = *next; + } + + sizes.erase(++cur, sizes.end()); + } + }; + setUpFormatSizes(processedFormats); + setUpFormatSizes(rawFormats); + /* * Create the stream configurations. Take the first entry in the formats * map as the default, for lack of a better option. * * \todo Implement a better way to pick the default format */ - for ([[maybe_unused]] StreamRole role : roles) { + for (StreamRole role : roles) { + const auto &formats = (role == StreamRole::Raw ? rawFormats : processedFormats); StreamConfiguration cfg{ StreamFormats{ formats } }; cfg.pixelFormat = formats.begin()->first; cfg.size = formats.begin()->second[0].max;