From patchwork Thu Nov 27 21:19:22 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 25266 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 27282C32DE for ; Thu, 27 Nov 2025 21:19:53 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8D21860AA1; Thu, 27 Nov 2025 22:19:52 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="R39ksAz1"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 317A0609DE for ; Thu, 27 Nov 2025 22:19:51 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764278390; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=m0TWLmMioXl3HUUExaR3N5JO/5+SuggwSZ1P2x+UZPQ=; b=R39ksAz1Mqvd6gmbatLDK3NbwVzcwBSrU6mjVtdcH4tPCTqBsALAdCVAEPkk9KZD3cc3zg CYOoUyVUVkTjrfBSq7GpfDapDKrRRNRxCq5hEdPmPsnxTslM0MdrCac8yXOhM+WZm/1Mz9 1HbDIvNwWqv4CqqbF3vYyWcu6o+d6ds= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-308-0VR6ifEZOR2Ote8_zT7zGQ-1; Thu, 27 Nov 2025 16:19:47 -0500 X-MC-Unique: 0VR6ifEZOR2Ote8_zT7zGQ-1 X-Mimecast-MFC-AGG-ID: 0VR6ifEZOR2Ote8_zT7zGQ_1764278385 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 5271D195608A; Thu, 27 Nov 2025 21:19:45 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.45.224.67]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 2976719560B0; Thu, 27 Nov 2025 21:19:41 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Laurent Pinchart , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Paul Elder , Umang Jain Subject: [PATCH v16 1/9] libcamera: simple: Exclude raw configurations from output conversions Date: Thu, 27 Nov 2025 22:19:22 +0100 Message-ID: <20251127211932.122463-2-mzamazal@redhat.com> In-Reply-To: <20251127211932.122463-1-mzamazal@redhat.com> References: <20251127211932.122463-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: EYtEkwCwuS7kqdBpyWZ5r5HUHeeGOpDYirrVMIdzwns_1764278385 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" In order to support raw streams, we need to add raw formats to software ISP configurations. In this preparatory patch, the raw formats are excluded from output configurations for conversions. Reviewed-by: Umang Jain Signed-off-by: Milan Zamazal --- src/libcamera/pipeline/simple/simple.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index a06a52926..ee65cd181 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -264,6 +265,12 @@ static const SimplePipelineInfo supportedDevices[] = { { "sun6i-csi", {}, false }, }; +bool isRaw(const StreamConfiguration &cfg) +{ + return libcamera::PixelFormatInfo::info(cfg.pixelFormat).colourEncoding == + libcamera::PixelFormatInfo::ColourEncodingRAW; +} + } /* namespace */ class SimpleCameraData : public Camera::Private @@ -1471,7 +1478,7 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) cfg.setStream(&data->streams_[i]); - if (data->useConversion_) + if (data->useConversion_ && !isRaw(cfg)) outputCfgs.push_back(cfg); } From patchwork Thu Nov 27 21:19:23 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 25267 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id EB6A8C3260 for ; Thu, 27 Nov 2025 21:19:58 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 563B360AA4; Thu, 27 Nov 2025 22:19:58 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="MCNlJfR5"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5C391609DE for ; Thu, 27 Nov 2025 22:19:57 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764278396; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=y5qBdTBBPKvXA9RA30kBUsV6KPe1Q8Z9DBFaJbqaSDU=; b=MCNlJfR5iEgWTudzS2Ab9d6RNX/cJ74YCAbqZ3QDd0WUA+Gw+fFXortCcYmIn1T3uP8lrT LWJ/3UrNybcv6vs6qzPrHYduB+fmijvwlxNs5lnJMXgHOk8+pfIC0ahx/6/xeEwBHXduoa bc3TZAI6svvncAKSq0emaTqybdC6edg= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-63-MpVTFqzeMmKkJ0nK9ageVw-1; Thu, 27 Nov 2025 16:19:50 -0500 X-MC-Unique: MpVTFqzeMmKkJ0nK9ageVw-1 X-Mimecast-MFC-AGG-ID: MpVTFqzeMmKkJ0nK9ageVw_1764278389 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E443919560A7; Thu, 27 Nov 2025 21:19:48 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.45.224.67]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id E15F519560B0; Thu, 27 Nov 2025 21:19:45 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Laurent Pinchart , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Paul Elder , Umang Jain Subject: [PATCH v16 2/9] libcamera: simple: Handle processed and raw formats separately Date: Thu, 27 Nov 2025 22:19:23 +0100 Message-ID: <20251127211932.122463-3-mzamazal@redhat.com> In-Reply-To: <20251127211932.122463-1-mzamazal@redhat.com> References: <20251127211932.122463-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: a19muWdCXXaiQl-rdZ5vWJ-v6BzkeigFHjUi_lnvqrw_1764278389 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" 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 --- src/libcamera/pipeline/simple/simple.cpp | 79 +++++++++++++++++------- 1 file changed, 56 insertions(+), 23 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index ee65cd181..6b83254fb 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; + 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; + } + + /* 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) - formats[format].push_back(cfg.outputSizes); + processedFormats[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; - } - - sizes.erase(++cur, sizes.end()); + 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; From patchwork Thu Nov 27 21:19:24 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 25268 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id CBF57C32E0 for ; Thu, 27 Nov 2025 21:20:02 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4850A60AA6; Thu, 27 Nov 2025 22:20:01 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="Qnjzw6k3"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C0E1860A80 for ; Thu, 27 Nov 2025 22:19:57 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764278396; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=tYjGNeAKolNnShfvX4B5M441HrRVezJkFQBiiZ8flSs=; b=Qnjzw6k3exBxI6EUgvUFJOdYXaYYtcW6QnGM6ox8HSAAJj4PzQTpSsPa/0QmfFtcPYJHNZ 4VDAsqV4GrkUFeyfEyMdK+P8sT3hTZVocm9PyEk241TFgbRLUFmt4RFrhBcLdDUEdywQBp fLlpzhWFXoTEtrZg6dKHJhdG3MCVi7g= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-669-0X8_2yl7Ody1P_ZxiMfSMw-1; Thu, 27 Nov 2025 16:19:53 -0500 X-MC-Unique: 0X8_2yl7Ody1P_ZxiMfSMw-1 X-Mimecast-MFC-AGG-ID: 0X8_2yl7Ody1P_ZxiMfSMw_1764278392 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 110CF1956050; Thu, 27 Nov 2025 21:19:52 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.45.224.67]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 5199119560B6; Thu, 27 Nov 2025 21:19:49 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Laurent Pinchart , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Paul Elder , Umang Jain Subject: [PATCH v16 3/9] libcamera: simple: Validate raw stream configurations Date: Thu, 27 Nov 2025 22:19:24 +0100 Message-ID: <20251127211932.122463-4-mzamazal@redhat.com> In-Reply-To: <20251127211932.122463-1-mzamazal@redhat.com> References: <20251127211932.122463-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: PHafrvcPpI_YqzXqMeys7WMyEoFqAhs5EqFthfU2abM_1764278392 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" 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. Co-developed-by: Umang Jain Signed-off-by: Milan Zamazal --- src/libcamera/pipeline/simple/simple.cpp | 91 +++++++++++++++++------- 1 file changed, 64 insertions(+), 27 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 6b83254fb..e631bd613 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 @@ -1146,21 +1148,42 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() LOG(SimplePipeline, Debug) << "Largest stream size is " << maxStreamSize; + /* 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; + } } } @@ -1220,21 +1243,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; + } } /* @@ -1245,7 +1282,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; @@ -1265,9 +1302,9 @@ 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); } 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 +1312,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 +1335,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, From patchwork Thu Nov 27 21:19:25 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 25269 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id AE01DC32DE for ; Thu, 27 Nov 2025 21:20:04 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3212C60AAC; Thu, 27 Nov 2025 22:20:04 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="EwgKDJxu"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 695ED609DE for ; Thu, 27 Nov 2025 22:20:02 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764278401; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WdwfhrJv2BlCiuiF/TeoUq4DiaAo2epnr77mYjt21tU=; b=EwgKDJxukNw979u2w69jQmhnEpEqBBGryBDxD0lcnULGlLR7+wTWQL8O2e6MMcNy7eXfqQ q6uRdaneMRv267wvt22z9DKNH6N5xxA153M+TUjxjkSY3bBHVtyURsFAjJiu6k9rDYvKLD xChJ8aHpdKX+f+Tb+/ez1JLB49L+0Xc= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-144-LUrJpy5sMgaAVg4vqxQuvw-1; Thu, 27 Nov 2025 16:19:57 -0500 X-MC-Unique: LUrJpy5sMgaAVg4vqxQuvw-1 X-Mimecast-MFC-AGG-ID: LUrJpy5sMgaAVg4vqxQuvw_1764278395 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 536F01956053; Thu, 27 Nov 2025 21:19:55 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.45.224.67]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id AE83119560B0; Thu, 27 Nov 2025 21:19:52 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Laurent Pinchart , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Paul Elder , Umang Jain Subject: [PATCH v16 4/9] libcamera: simple: Don't enforce conversion with an added raw stream Date: Thu, 27 Nov 2025 22:19:25 +0100 Message-ID: <20251127211932.122463-5-mzamazal@redhat.com> In-Reply-To: <20251127211932.122463-1-mzamazal@redhat.com> References: <20251127211932.122463-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: XFKdvhpGge2GR7h4bkcgK3xKysUbW_I-4QCXtf7Afns_1764278395 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" When a raw stream is requested, either alone or together with a processed stream, it can be produced without conversion. Let's amend the corresponding check on the number of configurations, so that the mere presence of a raw stream doesn't enforce conversion. Reviewed-by: Umang Jain Signed-off-by: Milan Zamazal --- src/libcamera/pipeline/simple/simple.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index e631bd613..143d0f596 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -1239,7 +1239,7 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() * require any conversion, similar to raw capture use cases). This is * left as a future improvement. */ - needConversion_ = config_.size() > 1; + needConversion_ = config_.size() > 1 + rawCount; for (unsigned int i = 0; i < config_.size(); ++i) { StreamConfiguration &cfg = config_[i]; From patchwork Thu Nov 27 21:19:26 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 25270 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 9ADC6C32E7 for ; Thu, 27 Nov 2025 21:20:06 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 28DCE60AAA; Thu, 27 Nov 2025 22:20:06 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="BkTkih6Q"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id CD7A760A85 for ; Thu, 27 Nov 2025 22:20:02 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764278401; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hoQ+n9CN5YSxMb1VydhqZEFi7QT8LXvomfkNUL9XkaE=; b=BkTkih6QwOZjRu8gnY85ckXB1/I0dV6OxgC0P3kxhozPbIzQOaddzgrJQ9I241CM4B2ovC SBnmZcIXp1Ij9eDTMKO0jRSIsqFhJ88EQyOz+hLWst2O3De+prfIEe54mhVhHsEUPTOHkL eio81nF35TaFRcGVCONy3Jv/FNfI9iE= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-683-6Gj5zLGjNIqcEHBjsBX2cg-1; Thu, 27 Nov 2025 16:19:59 -0500 X-MC-Unique: 6Gj5zLGjNIqcEHBjsBX2cg-1 X-Mimecast-MFC-AGG-ID: 6Gj5zLGjNIqcEHBjsBX2cg_1764278398 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 9DE7D1800561; Thu, 27 Nov 2025 21:19:58 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.45.224.67]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id F1FD119560B0; Thu, 27 Nov 2025 21:19:55 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Laurent Pinchart , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Paul Elder , Umang Jain Subject: [PATCH v16 5/9] libcamera: simple: Set the number of software ISP streams to 2 Date: Thu, 27 Nov 2025 22:19:26 +0100 Message-ID: <20251127211932.122463-6-mzamazal@redhat.com> In-Reply-To: <20251127211932.122463-1-mzamazal@redhat.com> References: <20251127211932.122463-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: 9tK_sHdW8BmPxffhuX3VqfEm2d9la3VEfpj9vJeDSkQ_1764278398 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" When software ISP is enabled, we want to be able to provide a raw stream in addition to the processed stream. For this purpose, we need two streams. If only the processed stream is requested, it doesn't harm to allocate two. The number of streams is determined as a camera property in the pipeline matching. To be able to produce both raw and processed output, two streams must be provided. The actual number of streams needed (one or two) is determined only in SimplePipelineHandler::validate(). In theory, software ISP could produce multiple processed streams but this is out of scope of this patch series. Hence two streams are sufficient at the moment. When software ISP is not enabled, the camera won't be able to produce multiple streams (assuming there's no hardware converter) and only single stream should be allocated as before. The simple pipeline handler assumes there's a linear pipeline from the camera sensor to a video capture device, and only supports a single stream. Branches in the hardware pipeline that would allow capturing multiple streams from the same camera sensor are not supported. We have no plan to change that, as a device that can produce multiple streams will likely be better supported by a dedicated pipeline handler. Reviewed-by: Umang Jain Signed-off-by: Milan Zamazal --- src/libcamera/pipeline/simple/simple.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 143d0f596..3b9122342 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -1835,6 +1835,16 @@ bool SimplePipelineHandler::matchDevice(std::shared_ptr media, } } + if (info.swIspEnabled) { + /* + * When the software ISP is enabled, the simple pipeline handler + * exposes the raw stream, giving a total of two streams. This + * is mutually exclusive with the presence of a converter. + */ + ASSERT(!converter_); + numStreams = 2; + } + swIspEnabled_ = info.swIspEnabled; const GlobalConfiguration &configuration = cameraManager()->_d()->configuration(); for (GlobalConfiguration::Configuration entry : From patchwork Thu Nov 27 21:19:27 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 25271 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id AD099C32EF for ; Thu, 27 Nov 2025 21:20:09 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2FC9C60A8B; Thu, 27 Nov 2025 22:20:09 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="Hnd/8AGT"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8E8EE609DE for ; Thu, 27 Nov 2025 22:20:07 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764278406; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=M2ruzuZ/Wrhj/vuQSKZ4qf8/2Qg3IjNXjpRKa6rerzc=; b=Hnd/8AGT4JtzAC+vGmvdpBbW5nGPLzPmhLXCjfPZO8+kFN7I+8dDmTUbosSWpolHqdre3X FeoEHNjH+1LGJGgnpJVjchi5uK72ABGOvm7mkKYDLi1RDkvz7nQpOTBiaQFY9uH31p669B J3wGZsr0tjcU211D50Fy65h3I0F47II= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-175-QmJIby6fMUqk47dWuDetfw-1; Thu, 27 Nov 2025 16:20:03 -0500 X-MC-Unique: QmJIby6fMUqk47dWuDetfw-1 X-Mimecast-MFC-AGG-ID: QmJIby6fMUqk47dWuDetfw_1764278401 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D0F271800343; Thu, 27 Nov 2025 21:20:01 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.45.224.67]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 399F119560B0; Thu, 27 Nov 2025 21:19:58 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Laurent Pinchart , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Paul Elder , Umang Jain Subject: [PATCH v16 6/9] libcamera: simple: Require metadata only when software ISP is used Date: Thu, 27 Nov 2025 22:19:27 +0100 Message-ID: <20251127211932.122463-7-mzamazal@redhat.com> In-Reply-To: <20251127211932.122463-1-mzamazal@redhat.com> References: <20251127211932.122463-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: tg5WyI4pQMD5HYcMduhcHmshSoakrdB6iQaaENUmrRk_1764278401 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" If software ISP is enabled then metadata is required in the simple pipeline. But this doesn't apply if the software ISP is not actually used, for example when only a raw stream is produced. Then the pipeline waits for metadata that never comes. This patch fixes the problem by requiring metadata only when software ISP is used. Reviewed-by: Umang Jain Signed-off-by: Milan Zamazal --- src/libcamera/pipeline/simple/simple.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 3b9122342..927875586 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -1697,6 +1697,7 @@ int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request) int ret; std::map buffers; + bool metadataRequired = false; for (auto &[stream, buffer] : request->buffers()) { /* @@ -1706,6 +1707,7 @@ int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request) */ if (data->useConversion_) { buffers.emplace(stream, buffer); + metadataRequired = !!data->swIsp_; } else { ret = data->video_->queueBuffer(buffer); if (ret < 0) @@ -1713,7 +1715,7 @@ int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request) } } - data->frameInfo_.create(request, !!data->swIsp_); + data->frameInfo_.create(request, metadataRequired); if (data->useConversion_) { data->conversionQueue_.push({ request, std::move(buffers) }); if (data->swIsp_) From patchwork Thu Nov 27 21:19:28 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 25273 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 88773C32F0 for ; Thu, 27 Nov 2025 21:20:15 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 0D0B360A8B; Thu, 27 Nov 2025 22:20:15 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="iat50/3X"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8AC7A609DE for ; Thu, 27 Nov 2025 22:20:12 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764278411; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WRLKlNFbldXB5OZCzkHmr6NrJPBMSvNxykQ/+XDOMOE=; b=iat50/3XdNRTBL845ddX8jloJM2rYsrMOKTLkuYTHYFbNNS9+Q/7BYjbBNkCxnu/NwI25Z Cmgl2pL+5/MemsZUnXKhdZMkDjP5qmPuA9820uILX91JGi3rhDTU7RwiNQUlZ1TtWEtTCY 86JZWUw4jPdMG74LkF4rcyOfDunfYY8= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-345-hkaaA-nBMTemM_ZgM3IiBg-1; Thu, 27 Nov 2025 16:20:06 -0500 X-MC-Unique: hkaaA-nBMTemM_ZgM3IiBg-1 X-Mimecast-MFC-AGG-ID: hkaaA-nBMTemM_ZgM3IiBg_1764278405 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id DA7EE1800447; Thu, 27 Nov 2025 21:20:04 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.45.224.67]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 6400F19560B7; Thu, 27 Nov 2025 21:20:02 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Laurent Pinchart , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Paul Elder , Umang Jain Subject: [PATCH v16 7/9] libcamera: simple: Make raw streams working Date: Thu, 27 Nov 2025 22:19:28 +0100 Message-ID: <20251127211932.122463-8-mzamazal@redhat.com> In-Reply-To: <20251127211932.122463-1-mzamazal@redhat.com> References: <20251127211932.122463-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: mYKuDPIyq6Po87nrXt2dWo_ywlkSnnpKfqABrj2rUMM_1764278405 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" When a raw stream is requested, whether alone or together with a processed stream, its buffers must be handled outside the software ISP machinery. They serve as output buffers, even when a processed stream is produced. But when both processed and raw streams are requested, the buffer can be completed only after the processing is finished, to make sure it's untouched by the application as long as the processing runs. At most one raw stream and at most one processed stream are supported and can be combined. An example of producing both raw and processed files using `cam' application: cam -c1 -C100 -Ffile# \ -s role=viewfinder,width=1920,height=1080,pixelformat=RGB888 \ -s role=raw,width=3280,height=2464,pixelformat=SRGGB8 Note the difference in viewfinder and raw stream sizes due to the fact that debayering requires enlarging the image width, which enforces selecting a larger sensor resolution in this case. In order to track whether a raw stream is requested and which one it is, SimpleCameraData::rawStream_ member variable is introduced. This is the final step to make raw streams working. Signed-off-by: Milan Zamazal --- src/libcamera/pipeline/simple/simple.cpp | 47 +++++++++++++++++------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 927875586..cbfc06fb6 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -333,6 +333,7 @@ public: }; std::vector streams_; + Stream *rawStream_; /* * All entities in the pipeline, from the camera sensor to the video @@ -468,7 +469,7 @@ private: SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe, unsigned int numStreams, MediaEntity *sensor) - : Camera::Private(pipe), streams_(numStreams) + : Camera::Private(pipe), streams_(numStreams), rawStream_(nullptr) { /* * Find the shortest path from the camera sensor to a video capture @@ -884,10 +885,13 @@ void SimpleCameraData::imageBufferReady(FrameBuffer *buffer) * point converting an erroneous buffer. */ if (buffer->metadata().status != FrameMetadata::FrameSuccess) { - if (!useConversion_) { + if (!useConversion_ || rawStream_) { /* No conversion, just complete the request. */ Request *request = buffer->request(); pipe->completeBuffer(request, buffer); + SimpleFrameInfo *info = frameInfo_.find(request->sequence()); + if (info) + info->metadataRequired = false; tryCompleteRequest(request); return; } @@ -946,7 +950,8 @@ void SimpleCameraData::imageBufferReady(FrameBuffer *buffer) */ if (useConversion_) { if (conversionQueue_.empty()) { - video_->queueBuffer(buffer); + if (!rawStream_) + video_->queueBuffer(buffer); return; } @@ -998,8 +1003,15 @@ void SimpleCameraData::tryCompleteRequest(Request *request) void SimpleCameraData::conversionInputDone(FrameBuffer *buffer) { - /* Queue the input buffer back for capture. */ - video_->queueBuffer(buffer); + if (rawStream_) { + /* Complete the input buffer as with raw-only processing. */ + Request *request = buffer->request(); + if (pipe()->completeBuffer(request, buffer)) + tryCompleteRequest(request); + } else { + /* Queue the input buffer back for capture. */ + video_->queueBuffer(buffer); + } } void SimpleCameraData::conversionOutputDone(FrameBuffer *buffer) @@ -1543,13 +1555,18 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) std::vector> outputCfgs; data->useConversion_ = config->needConversion(); + data->rawStream_ = nullptr; for (unsigned int i = 0; i < config->size(); ++i) { StreamConfiguration &cfg = config->at(i); + bool rawStream = isRaw(cfg); cfg.setStream(&data->streams_[i]); - if (data->useConversion_ && !isRaw(cfg)) + if (data->useConversion_ && !rawStream) outputCfgs.push_back(cfg); + + if (rawStream) + data->rawStream_ = &data->streams_[i]; } if (outputCfgs.empty()) @@ -1580,7 +1597,7 @@ int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream, * Export buffers on the converter or capture video node, depending on * whether the converter is used or not. */ - if (data->useConversion_) + if (data->useConversion_ && stream != data->rawStream_) return data->converter_ ? data->converter_->exportBuffers(stream, count, buffers) : data->swIsp_->exportBuffers(stream, count, buffers); @@ -1603,7 +1620,7 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL return -EBUSY; } - if (data->useConversion_) { + if (data->useConversion_ && !data->rawStream_) { /* * When using the converter allocate a fixed number of internal * buffers. @@ -1611,8 +1628,11 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL ret = video->allocateBuffers(kNumInternalBuffers, &data->conversionBuffers_); } else { - /* Otherwise, prepare for using buffers from the only stream. */ - Stream *stream = &data->streams_[0]; + /* + * Otherwise, prepare for using buffers from either the raw stream, if + * requested, or the only stream configured. + */ + Stream *stream = (data->rawStream_ ? data->rawStream_ : &data->streams_[0]); ret = video->importBuffers(stream->configuration().bufferCount); } if (ret < 0) { @@ -1653,8 +1673,9 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL } /* Queue all internal buffers for capture. */ - for (std::unique_ptr &buffer : data->conversionBuffers_) - video->queueBuffer(buffer.get()); + if (!data->rawStream_) + for (std::unique_ptr &buffer : data->conversionBuffers_) + video->queueBuffer(buffer.get()); } return 0; @@ -1705,7 +1726,7 @@ int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request) * queue, it will be handed to the converter in the capture * completion handler. */ - if (data->useConversion_) { + if (data->useConversion_ && stream != data->rawStream_) { buffers.emplace(stream, buffer); metadataRequired = !!data->swIsp_; } else { From patchwork Thu Nov 27 21:19:29 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 25272 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id C9C30C3260 for ; Thu, 27 Nov 2025 21:20:14 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1FC3D60A9E; Thu, 27 Nov 2025 22:20:14 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="ZZFMjDgs"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DA0F3609DE for ; Thu, 27 Nov 2025 22:20:11 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764278410; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=tA3FvcMGKlKLFd7ZIG/lffo3qpOGGb9svNtHOKpTi4U=; b=ZZFMjDgsUbjHV6Qt38N0v3W/xKy2XCzeytf2nEo2n/fapjP9T81dTpHUD5bRmlb5p7YZz0 T7K+msniNJlkkg32YdRCXUtNl8y9AOCtZe3ah1ZB9xecWuEO3ugGts/jgpLaq1kv9u4zau 75LULwFP57m2agxDSkcqhmnDXQQFMKE= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-80-l1zWlIGcNaGbUjdHABa4-A-1; Thu, 27 Nov 2025 16:20:09 -0500 X-MC-Unique: l1zWlIGcNaGbUjdHABa4-A-1 X-Mimecast-MFC-AGG-ID: l1zWlIGcNaGbUjdHABa4-A_1764278408 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 2C3D419560AD; Thu, 27 Nov 2025 21:20:08 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.45.224.67]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 75A0D19560B0; Thu, 27 Nov 2025 21:20:05 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Laurent Pinchart , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Paul Elder , Umang Jain Subject: [PATCH v16 8/9] libcamera: simple: Move colour space logging after adjustment Date: Thu, 27 Nov 2025 22:19:29 +0100 Message-ID: <20251127211932.122463-9-mzamazal@redhat.com> In-Reply-To: <20251127211932.122463-1-mzamazal@redhat.com> References: <20251127211932.122463-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: q9BnkPKqSGtM84-RVEWKGj08infKsHzXdQwz5mQTwzk_1764278408 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The log message about adjusting an unspecified colour space should log the value after, not before, the adjustment. Signed-off-by: Milan Zamazal --- src/libcamera/pipeline/simple/simple.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index cbfc06fb6..2820d1254 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -1305,9 +1305,6 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() default: cfg.colorSpace = ColorSpace::Raw; } - LOG(SimplePipeline, Debug) - << "Unspecified color space set to " - << cfg.colorSpace.value().toString(); /* * Adjust the assigned color space to make sure everything is OK. * Since this is assigning an unspecified color space rather than @@ -1315,6 +1312,9 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() * to Adjusted. */ cfg.colorSpace->adjust(cfg.pixelFormat); + LOG(SimplePipeline, Debug) + << "Unspecified color space set to " + << cfg.colorSpace.value().toString(); } else { if (cfg.colorSpace->adjust(cfg.pixelFormat)) { LOG(SimplePipeline, Debug) From patchwork Thu Nov 27 21:19:30 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 25274 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 8365AC32E0 for ; Thu, 27 Nov 2025 21:20:19 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2074860A9D; Thu, 27 Nov 2025 22:20:19 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="KhGqy1B/"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 71AF6609DE for ; Thu, 27 Nov 2025 22:20:17 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764278416; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=azn2d01FldaHRnitYFUL5IBBXfP/igEXGo+xMnUcl8w=; b=KhGqy1B/1w7ZLukyJrx9h/FVY5acm8hlPDszKQnoNBVCqYh9HO/ST+x4+inuCBkk+MDnGp bSI2Nhwgez8S05iII1Suasc5vDpucrUme5spX1c3L17QdZuXMM8i1lSJtcZ8fRyXqscCHX fkktrQtLbh7KtjrTVV3hNhujXvC6CeU= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-252-IUtRDHsAMOiou0Eus6Kz6g-1; Thu, 27 Nov 2025 16:20:12 -0500 X-MC-Unique: IUtRDHsAMOiou0Eus6Kz6g-1 X-Mimecast-MFC-AGG-ID: IUtRDHsAMOiou0Eus6Kz6g_1764278411 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 4303919560B0; Thu, 27 Nov 2025 21:20:11 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.45.224.67]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 9FC2C19560B0; Thu, 27 Nov 2025 21:20:08 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Laurent Pinchart , Kieran Bingham , =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= , Paul Elder , Umang Jain Subject: [PATCH v16 9/9] libcamera: simple: Compute separate max stream sizes Date: Thu, 27 Nov 2025 22:19:30 +0100 Message-ID: <20251127211932.122463-10-mzamazal@redhat.com> In-Reply-To: <20251127211932.122463-1-mzamazal@redhat.com> References: <20251127211932.122463-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: 8TqbDDVnHtUTxFOQiORIQ-8Bd4SvsRKRYUmyUCOpz5A_1764278411 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Configuration validation computes the maximum size of all the requested streams and compares it to the output sizes. When e.g. only a raw stream is requested then this may result in an invalid adjustment of its size. This is because the output sizes are computed for processed streams and may be smaller than capture sizes. If a raw stream with the capture size is requested, it may then be wrongly adjusted to a larger size because the output sizes, which are irrelevant for raw streams anyway, are smaller than the requested capture size. Let's fix the problem by tracking raw and processed streams maximum sizes separately and comparing raw stream sizes against capture rather than output sizes. Signed-off-by: Milan Zamazal --- src/libcamera/pipeline/simple/simple.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 2820d1254..bb67000e2 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -1153,12 +1153,18 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() } /* Find the largest stream size. */ - Size maxStreamSize; - for (const StreamConfiguration &cfg : config_) - maxStreamSize.expandTo(cfg.size); + 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 stream size is " + << maxProcessedStreamSize << "/" << maxRawStreamSize; /* Cap the number of raw stream configurations */ unsigned int rawCount = 0; @@ -1217,8 +1223,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; } @@ -1236,7 +1244,8 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() << V4L2SubdeviceFormat{ pipeConfig_->code, pipeConfig_->sensorSize, {} } << " -> " << pipeConfig_->captureSize << "-" << pipeConfig_->captureFormat - << " for max stream size " << maxStreamSize; + << " for max stream size " + << maxProcessedStreamSize << "/" << maxRawStreamSize; /* * Adjust the requested streams.