From patchwork Fri Jan 24 21:57:59 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 22647 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 ECC64BD78E for ; Fri, 24 Jan 2025 21:58:51 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 14C0A6856E; Fri, 24 Jan 2025 22:58:51 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="O+i1cG0/"; 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 26E576856D for ; Fri, 24 Jan 2025 22:58:44 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1737755923; 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=QzXrvRvq0gETsT/aE6TGKpFDvf1zyuilwiuvEJuWHJY=; b=O+i1cG0/l1n+TSACAJORz3XV79WpAPe0GqyRaI9ogK7gYxpQJ+FHiKHqBzayB8+vYOyVgC vrU4oA3uT61etbVoMI+GDZuJ8LKoworNpd7YUI9DRvUj17zHGmd0uvc46f5mwhYJmEWvBo FfKtpbks83JSMgcc8buHIikMs2mlNdc= 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-55--_4ILZHBNQuxKSt4NA0W_Q-1; Fri, 24 Jan 2025 16:58:41 -0500 X-MC-Unique: -_4ILZHBNQuxKSt4NA0W_Q-1 X-Mimecast-MFC-AGG-ID: -_4ILZHBNQuxKSt4NA0W_Q Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 9452F18009D9 for ; Fri, 24 Jan 2025 21:58:40 +0000 (UTC) Received: from mzamazal-thinkpadp1gen3.tpbc.com (unknown [10.39.192.49]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id E7EC11800358; Fri, 24 Jan 2025 21:58:38 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal Subject: [RFC PATCH v2 08/13] libcamera: simple: Handle adjusted and raw configurations separately Date: Fri, 24 Jan 2025 22:57:59 +0100 Message-ID: <20250124215806.158024-9-mzamazal@redhat.com> In-Reply-To: <20250124215806.158024-1-mzamazal@redhat.com> References: <20250124215806.158024-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: dwzFz4kU25h9FciPU8ds-yigCD8_lBN5iOuUiDBmxG4_1737755920 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 using software ISP to produce both a processed and a raw stream at the same time, we have to deal with two different output formats. When generating stream configurations, consider only raw formats for raw streams. Also, mark raw configurations using StreamConfiguration::colorSpace value, which is the only available place in StreamConfiguration for the purpose. When validating stream configurations, use separate check for sizes to produce raw and processed pipe configurations. Later, use the corresponding pipe configurations for raw and processed stream configurations. Signed-off-by: Milan Zamazal --- src/libcamera/pipeline/simple/simple.cpp | 90 ++++++++++++++++++++---- 1 file changed, 77 insertions(+), 13 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 87a2043f..beb11069 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -1062,7 +1063,9 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() * without upscaling. */ const SimpleCameraData::Configuration *maxPipeConfig = nullptr; + const SimpleCameraData::Configuration *maxPipeConfigRaw = nullptr; pipeConfig_ = nullptr; + const SimpleCameraData::Configuration *pipeConfigRaw = nullptr; for (const SimpleCameraData::Configuration *pipeConfig : *configs) { const Size &size = pipeConfig->captureSize; @@ -1075,6 +1078,17 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() if (!maxPipeConfig || maxPipeConfig->captureSize < size) maxPipeConfig = pipeConfig; + + if (!pipeConfig->swisp) { + if (size.width >= maxStreamSize.width && + size.height >= maxStreamSize.height) { + if (!pipeConfigRaw || size < pipeConfigRaw->captureSize) + pipeConfigRaw = pipeConfig; + } + + if (!maxPipeConfigRaw || maxPipeConfigRaw->captureSize < size) + maxPipeConfigRaw = pipeConfig; + } } /* If no configuration was large enough, select the largest one. */ @@ -1085,6 +1099,13 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() } pipeConfig_ = maxPipeConfig; } + if (data_->rawRequested_ && !pipeConfigRaw) { + if (!maxPipeConfigRaw) { + LOG(SimplePipeline, Error) << "No valid configuration for raw found"; + return Invalid; + } + pipeConfigRaw = maxPipeConfigRaw; + } LOG(SimplePipeline, Debug) << "Picked " @@ -1092,6 +1113,14 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() << " -> " << pipeConfig_->captureSize << "-" << pipeConfig_->captureFormat << " for max stream size " << maxStreamSize; + if (pipeConfigRaw) { + LOG(SimplePipeline, Info) + << "Picked raw " + << V4L2SubdeviceFormat{ pipeConfigRaw->code, pipeConfigRaw->sensorSize, {} } + << " -> " << pipeConfigRaw->captureSize + << "-" << pipeConfigRaw->captureFormat + << " for max stream size " << maxStreamSize; + } /* * Adjust the requested streams. @@ -1110,31 +1139,50 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() for (unsigned int i = 0; i < config_.size(); ++i) { StreamConfiguration &cfg = config_[i]; + const SimpleCameraData::Configuration *pipeConfig = + (cfg.colorSpace == ColorSpace::Raw ? pipeConfigRaw : pipeConfig_); + if (!pipeConfig) + continue; /* Adjust the pixel format and size. */ - auto it = std::find(pipeConfig_->outputFormats.begin(), - pipeConfig_->outputFormats.end(), + auto it = std::find(pipeConfig->outputFormats.begin(), + pipeConfig->outputFormats.end(), cfg.pixelFormat); - if (it == pipeConfig_->outputFormats.end()) - it = pipeConfig_->outputFormats.begin(); + if (it == pipeConfig->outputFormats.end()) + it = pipeConfig->outputFormats.begin(); PixelFormat pixelFormat = *it; if (cfg.pixelFormat != pixelFormat) { + if (isRawFormat(pixelFormat)) { + 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; } - if (!pipeConfig_->outputSizes.contains(cfg.size)) { - Size adjustedSize = pipeConfig_->captureSize; + if (!pipeConfig->outputSizes.contains(cfg.size)) { + Size adjustedSize = pipeConfig->captureSize; /* * The converter (when present) may not be able to output * a size identical to its input size. The capture size is thus * 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)) - adjustedSize = adjustSize(cfg.size, pipeConfig_->outputSizes); + if (!pipeConfig->outputSizes.contains(adjustedSize)) { + if (isRawFormat(pixelFormat)) { + 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; @@ -1143,8 +1191,8 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() } /* \todo Create a libcamera core class to group format and size */ - if (cfg.pixelFormat != pipeConfig_->captureFormat || - cfg.size != pipeConfig_->captureSize) + if (cfg.pixelFormat != pipeConfig->captureFormat || + cfg.size != pipeConfig->captureSize) needConversion_ = true; /* Set the stride, frameSize and bufferCount. */ @@ -1246,10 +1294,26 @@ SimplePipelineHandler::generateConfiguration(Camera *camera, Spanfirst; - cfg.size = formats.begin()->second[0].max; + if (role == StreamRole::Raw) { + bool found = false; + for (auto &[format, sizes] : formats) + if (isRawFormat(format)) { + cfg.pixelFormat = format; + cfg.size = sizes[0].max; + found = true; + break; + } + if (!found) { + LOG(SimplePipeline, Error) << "Raw stream requested but no raw format found "; + return nullptr; + } + cfg.colorSpace = ColorSpace::Raw; + } else { + cfg.pixelFormat = formats.begin()->first; + cfg.size = formats.begin()->second[0].max; + } config->addConfiguration(cfg); }