@@ -265,6 +265,7 @@ public:
Size captureSize;
std::vector<PixelFormat> outputFormats;
SizeRange outputSizes;
+ bool swisp;
};
std::vector<Stream> streams_;
@@ -289,6 +290,7 @@ public:
};
std::queue<RequestOutputs> conversionQueue_;
bool useConversion_;
+ bool isRaw_;
std::unique_ptr<Converter> converter_;
std::unique_ptr<SoftwareIsp> swIsp_;
@@ -646,19 +648,24 @@ void SimpleCameraData::tryPipeline(unsigned int code, const Size &size)
config.sensorSize = size;
config.captureFormat = pixelFormat;
config.captureSize = format.size;
+ config.swisp = false;
if (converter_) {
config.outputFormats = converter_->formats(pixelFormat);
config.outputSizes = converter_->sizes(format.size);
- } else if (swIsp_) {
- config.outputFormats = swIsp_->formats(pixelFormat);
- config.outputSizes = swIsp_->sizes(pixelFormat, format.size);
- if (config.outputFormats.empty()) {
- /* Do not use swIsp for unsupported pixelFormat's. */
- config.outputFormats = { pixelFormat };
- config.outputSizes = config.captureSize;
- }
} else {
+ if (swIsp_) {
+ Configuration swispConfig = config;
+ swispConfig.outputFormats = swIsp_->formats(pixelFormat);
+ swispConfig.outputSizes = swIsp_->sizes(pixelFormat, format.size);
+ if (swispConfig.outputFormats.empty()) {
+ /* Do not use swIsp for unsupported pixelFormat's. */
+ swispConfig.outputFormats = { pixelFormat };
+ swispConfig.outputSizes = swispConfig.captureSize;
+ }
+ swispConfig.swisp = true;
+ configs_.push_back(swispConfig);
+ }
config.outputFormats = { pixelFormat };
config.outputSizes = config.captureSize;
}
@@ -859,7 +866,7 @@ void SimpleCameraData::imageBufferReady(FrameBuffer *buffer)
if (converter_)
converter_->queueBuffers(buffer, conversionQueue_.front().outputs);
- else
+ else if (!isRaw_) {
/*
* request->sequence() cannot be retrieved from `buffer' inside
* queueBuffers because unique_ptr's make buffer->request() invalid
@@ -867,6 +874,7 @@ void SimpleCameraData::imageBufferReady(FrameBuffer *buffer)
*/
swIsp_->queueBuffers(request->sequence(), buffer,
conversionQueue_.front().outputs);
+ }
conversionQueue_.pop();
return;
@@ -1049,6 +1057,8 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()
pipeConfig_ = nullptr;
for (const SimpleCameraData::Configuration *pipeConfig : *configs) {
+ if (pipeConfig->swisp == data_->isRaw_)
+ continue;
const Size &size = pipeConfig->captureSize;
if (size.width >= maxStreamSize.width &&
@@ -1099,6 +1109,13 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()
PixelFormat pixelFormat = *it;
if (cfg.pixelFormat != pixelFormat) {
+ if (data_->isRaw_) {
+ LOG(SimplePipeline, Error)
+ << "Cannot convert pixel format with raw output (from "
+ << cfg.pixelFormat << " to "
+ << pixelFormat << ")";
+ return Invalid;
+ }
LOG(SimplePipeline, Debug) << "Adjusting pixel format";
cfg.pixelFormat = pixelFormat;
status = Adjusted;
@@ -1112,8 +1129,16 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()
* not guaranteed to be a valid output size. In such cases, use
* the smaller valid output size closest to the requested.
*/
- if (!pipeConfig_->outputSizes.contains(adjustedSize))
+ if (!pipeConfig_->outputSizes.contains(adjustedSize)) {
+ if (data_->isRaw_) {
+ LOG(SimplePipeline, Error)
+ << "Cannot adjust output size with raw output (from "
+ << cfg.pixelFormat << " to "
+ << pixelFormat << ")";
+ return Invalid;
+ }
adjustedSize = adjustSize(cfg.size, pipeConfig_->outputSizes);
+ }
LOG(SimplePipeline, Debug)
<< "Adjusting size from " << cfg.size
<< " to " << adjustedSize;
@@ -1174,12 +1199,29 @@ SimplePipelineHandler::generateConfiguration(Camera *camera, Span<const StreamRo
if (roles.empty())
return config;
+ bool raw = false;
+ for (auto &role : roles) {
+ if (role == StreamRole::Raw) {
+ raw = true;
+ break;
+ }
+ }
+ if (raw && roles.size() > 1) {
+ LOG(SimplePipeline, Error)
+ << "Can't capture multiple streams with a raw stream";
+ return nullptr;
+ }
+ data->isRaw_ = raw;
+ LOG(SimplePipeline, Debug) << "Raw stream requested: " << raw;
+
/* Create the formats map. */
std::map<PixelFormat, std::vector<SizeRange>> formats;
for (const SimpleCameraData::Configuration &cfg : data->configs_) {
- for (PixelFormat format : cfg.outputFormats)
- formats[format].push_back(cfg.outputSizes);
+ if (raw != cfg.swisp) {
+ for (PixelFormat format : cfg.outputFormats)
+ formats[format].push_back(cfg.outputSizes);
+ }
}
/* Sort the sizes and merge any consecutive overlapping ranges. */
Simple pipeline was used to introduce software ISP. If software ISP is enabled, the pipeline always debayers the input and doesn't produce raw output anymore, even when requested. This patch fixes the problem and allows producing raw output if it is requested, by specifying raw stream role. When raw output is requested, only single stream (raw or processed) is allowed. This is not necessarily an inherent property, it just simplifies the implementation and is sufficient for the current needs. If raw stream is requested, it means raw as it is and no pixel format or size conversions are permitted. This is not only logical but also simplifying the changes because we don't have to check for raw when conversion is used. The patch must deal with the fact that software ISP and its output configurations are arranged before we know whether a raw or a processed stream will be requested. This means that if software ISP is enabled then it is always initialized and we store raw output configurations together with software ISP ones. We filter output configurations later as needed. The raw output may not be useful without exposure and gain adjustments, it can be all black (or just noisy). This will be handled in a separate patch introducing manual gain and exposure controls. Signed-off-by: Milan Zamazal <mzamazal@redhat.com> --- src/libcamera/pipeline/simple/simple.cpp | 66 +++++++++++++++++++----- 1 file changed, 54 insertions(+), 12 deletions(-)