From patchwork Fri Nov 6 15:13:38 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 28792 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 71A7DC335C for ; Fri, 6 Nov 2026 15:14:00 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1BD6E690F7; Fri, 6 Nov 2026 16:14:00 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=qualcomm.com header.i=@qualcomm.com header.b="PrxQ4j76"; dkim=pass (2048-bit key; unprotected) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="AeegwllL"; dkim-atps=neutral Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D3CC86A7DA for ; Fri, 6 Nov 2026 16:13:56 +0100 (CET) Received: from pps.filterd (m0279872.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 6A6F09bk3185114 for ; Fri, 6 Nov 2026 15:13:55 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=qcppdkim1; bh=dGInKJs5zRn AaSa5XlI2F3kU4oNkZp3bZ/XQfvSamD8=; b=PrxQ4j76/mBskLFsZiH0m8+AD1z fNcA1qJutfkTBpU0lmOZc2rsyauz0KWz4yCDTb5IByxlOoEl0v2JV7o8ffeSc48V jSSMAlyvn0blWDE/CSLzJ0XgFtIauJeMBVM8xTbaMUVew2szHMsRtIrZziOSAXGN /JXyIm/o3LMyzLP50tSE9nOtHu9Aw4bBNAXuDkF9/L5GSo58PANVZAXSBVG6dlbN f5Z5NmHteKt9NqPRN9KVp+u7W5kvjsdcfbLWTxqTDhLq5ZFvhDDs+S7ilr56O4e7 lz1hXn6+vHDlyJalRZ/2TunRekhUWIvW29edXo9bTRxm0CIpMnHF8uxewnw== Received: from mail-qk1-f197.google.com (mail-qk1-f197.google.com [209.85.222.197]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4hs3pab8u8-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Fri, 06 Nov 2026 15:13:55 +0000 (GMT) Received: by mail-qk1-f197.google.com with SMTP id af79cd13be357-943e8ff02d0so83739185a.2 for ; Fri, 06 Nov 2026 07:13:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1793978034; x=1794582834; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=dGInKJs5zRnAaSa5XlI2F3kU4oNkZp3bZ/XQfvSamD8=; b=AeegwllLe3Ak2f1jYCTHR9bCGgBQfXTsENNACniEWwk3ckyqZ2asOvTxEGGTilx7vR vkz0rCLTqKbcOooBBC9X32SXzamC+7h9sng2mxjVahq4+f7xk7zCwZzRRxS9C98KcuH5 rho6JzAVBAqK4+5933QZkwlQBEF5TPiEiQiG1FfKKhZ4gQYQz8BoYLSyrdg5Q3my8xdJ J2XhvjpTdAw1jtpXApAe3qMzrtOhLEIkM4WR55Ve4+cSbnbFxFFU/RydXSkJoWTAKcD5 QIjQIBDDYWZshFXxDc/qzAdwLu8zZ2D9TfLEYhqWyqFW/KY1BtBn03GhUNacU7DQUVuG G9wA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1793978034; x=1794582834; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=dGInKJs5zRnAaSa5XlI2F3kU4oNkZp3bZ/XQfvSamD8=; b=B9a9mJ3mfgdzHTLWXZHg9PpAzrG/szbEVsbupoRZfSlbVA2/8pSoEzrx+s/fdwuOb/ 5sfLeODp9mjE+2DPAD9C3kOGdCn80wqTQZSTY3ayWRKeMsICy9wYk3FPEPj4aDRcnkij mUPNjKwLKo+GQC5cJmgYmU0oNtF1GKM92ZCxT0Nxg2bYrnpAWPixRS1y/63ktFyb7611 Qy3lE9XDi+2kSDBf1e3XNGLz4VwOJRNW9UM9fCKgtIXiE13upzInvcijiZDwydZDiaJG E15WL2CIxU+vbdi0muE7WN+oaemNzPIiXJ5l7N/6rqJJhFPQjMggKhM1l+WoRFraub9L VGUA== X-Gm-Message-State: APuU4Z/4MYMApt579a2VovaZmULbpODM2iafhm6ehD6VgnfrjiivALfw E/Pw1ehh5SHADHUiJWPwmh7vemkaLsThFPIZxcnoWjJFSoVLwLWcD2HMa5UOXycfp6OC7g6fwZ7 qKXq5wpjD6RavcGuEnt0vTaSCf/DZS+ySokT/OKgQj9bqQuFUml2upT1/AfPa32rmyjr7Pfa/Qz YX+9MuimbJ X-Gm-Gg: AYBFou2sJh7sFOPU0++jWssmtdUAVprBSe7bXfxVvkpbt0qJd5XpSprzyGs27VzP88N mGEhC517Uuq2ciPRNx9uWirkFtCgU4B8Y4DjUPb3iTvvu+RUyc1+KKr0nTfAzYqaZnMIyHZniD1 tiI3wk7Jk0Xyhzc1g7TxhfM4HQvRKUKRFX4Wpkkmbocbbmg72SXaQFdxmduQp1U5r3r7gJDsTlJ tkvlA1uCRv5DEjIoCbDXxZsgJBcd7+rcDD3E3hm8lbNVLtCidEEcLE7lhoxnwCvWqPYzoEITpEO jFAM7N0o/bu0E6SyVk5mLFgpWA6MCL7lynJwMMY9/mexg6Io4GqiM4WYUJ+OpML6CfE6BtBdwNS fbC2SmgZqT3qo3eY4rjGpi3PW1pPrtr+kBDbtL3JhRrBwBS0JvW+bufOhadveZ0oBPmYnO0XfEA OttCp/MfhEMG+0J49vS9633wvonRYX0heYg1pnqSk3VjW+MCeT7YgWrpjUXPBn7hIO X-Received: by 2002:a05:620a:3704:b0:93f:571b:c72e with SMTP id af79cd13be357-945f34b1170mr429962085a.14.1793978034223; Fri, 06 Nov 2026 07:13:54 -0800 (PST) X-Received: by 2002:a05:620a:3704:b0:93f:571b:c72e with SMTP id af79cd13be357-945f34b1170mr429953585a.14.1793978033329; Fri, 06 Nov 2026 07:13:53 -0800 (PST) Received: from shalem (2001-1c00-0c32-7800-5bfa-a036-83f0-f9ec.cable.dynamic.v6.ziggo.nl. [2001:1c00:c32:7800:5bfa:a036:83f0:f9ec]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-c4d3569b856sm86042466b.46.2026.11.06.07.13.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 06 Nov 2026 07:13:52 -0800 (PST) From: Hans de Goede To: libcamera-devel@lists.libcamera.org Cc: Gjorgji Rosikopulos , Loic Poulain , Hans de Goede Subject: [PATCH v3 4/7] camss: Add dummy ISP class for raw only image capture Date: Fri, 6 Nov 2026 16:13:38 +0100 Message-ID: <20261106151345.32491-5-johannes.goede@oss.qualcomm.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261106151345.32491-1-johannes.goede@oss.qualcomm.com> References: <20261106151345.32491-1-johannes.goede@oss.qualcomm.com> MIME-Version: 1.0 X-Proofpoint-GUID: gA2axqNpCnEAKckNqoky3WDzYhD-bSHa X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYxMTA2MDA1OSBTYWx0ZWRfX6XP534vQMEsr LTTA0YrWqVIKZt5Hs19xt1nF7miqi+9Dr6uRvD3TfxvM+STdnfS7feAT6Fy/ZsiETBOa/Sb/CqX K917KJH8RI1/Pjxc/MNo/8wYF6eGW8lQAmyQQl39IH4Z3aaJm9AVDkYZ9o21uapP9fPfC1np9DE 42tlugEKuAHSBPFCVnaKMrrcAFyWtdtf59a7MvsI6UE9xTLDkf5OlKiGUAZTjflpyPpd+AE53uE ymb7fT0ZVJvXSX0OJlt5T1A5MHaPRX/7fYVAPFXnJ+Qow+pRWjXngj0YgX4KzFJGVHefd7pmmNZ lqexyrGFCxdFoK+fSoqcJC/j0/48ert21wCf1k3TRAFRVMbnsyioH1+q3WtplR3s7XniupNkcaK o8t2VKkkaaZRmr8PwBheFk/tp9h5rTRzRPbhixcbxdloqew/snqCBp4eLB7PhtykOTaTbwHrfFj rnQF9zNcn+2k5A6DCZQ== X-Proofpoint-ORIG-GUID: gA2axqNpCnEAKckNqoky3WDzYhD-bSHa X-Authority-Analysis: v=2.4 cv=X7rHu2Te c=1 sm=1 tr=0 ts=6aedeeb3 cx=c_pps a=50t2pK5VMbmlHzFWWp8p/g==:117 a=xqWC_Br6kY4A:10 a=zJRp6_cAMcgA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=yx91gb_oNiZeI1HMLzn7:22 a=EUspDBNiAAAA:8 a=T6x4K98W11HLE5YqqdAA:9 a=IoWCM6iH3mJn3m4BftBB:22 X-Proofpoint-Spam-Info: AW1haW4tMjYxMTA2MDA1OSBTYWx0ZWRfX6nHhYkB26IYB rVMjjYUwfOZv8hnAigHNfvSaszlFLyeGjz4Jx8mCzzEy0j2c+cA/hsixQxkGV4ikpCaH+OWZe75 v6aC2EPCIyyW+CGNaRYaT9MbmVqvmb0= X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293, Aquarius:18.0.1176, Hydra:6.1.138, FMLib:17.12.100.49 definitions=2026-11-06_05,2026-11-06_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 clxscore=1015 impostorscore=0 phishscore=0 malwarescore=0 bulkscore=0 spamscore=0 priorityscore=1501 lowpriorityscore=0 adultscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2611040001 definitions=main-2611060059 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 still get gain / exposure metadata added for raw image capture the code still needs to call into the IPA, this also enables autogain / exposure support for raw capture. This implements a new CamssIspRaw class which uses software-statistics + the software ISP IPA for this, while simply passing the raw buffers directly to the application after running the software-statistics. Signed-off-by: Hans de Goede --- src/libcamera/pipeline/camss/camss.cpp | 70 +++--- .../pipeline/camss/camss_isp_raw.cpp | 228 ++++++++++++++++++ src/libcamera/pipeline/camss/camss_isp_raw.h | 72 ++++++ src/libcamera/pipeline/camss/meson.build | 1 + 4 files changed, 342 insertions(+), 29 deletions(-) create mode 100644 src/libcamera/pipeline/camss/camss_isp_raw.cpp create mode 100644 src/libcamera/pipeline/camss/camss_isp_raw.h diff --git a/src/libcamera/pipeline/camss/camss.cpp b/src/libcamera/pipeline/camss/camss.cpp index bcb372601..20b64ea49 100644 --- a/src/libcamera/pipeline/camss/camss.cpp +++ b/src/libcamera/pipeline/camss/camss.cpp @@ -38,6 +38,7 @@ #include "camss_csi.h" #include "camss_frames.h" #include "camss_isp.h" +#include "camss_isp_raw.h" #include "camss_isp_soft.h" namespace libcamera { @@ -61,7 +62,10 @@ public: void cancelPendingRequests(); std::unique_ptr csi_; - std::unique_ptr isp_; + std::unique_ptr processedIsp_; + std::unique_ptr rawIsp_; + /* Points to either processedIsp_ or rawIsp_ */ + CamssIsp *isp_; std::unique_ptr delayedCtrls_; CamssFrames frameInfos_; @@ -172,23 +176,16 @@ CameraConfiguration::Status CamssCameraConfiguration::validate() } } - if (!processedCount) { - /* - * \todo allow this, add dummyISP ISP class which only - * calls CPU stats on ready raw output buffers + runs the result - * through the softIPA to get sensor-control + metadata-info - */ - LOG(Camss, Debug) - << "Camera configuration cannot support raw-only streams"; + if (!rawCount && !processedCount) return Invalid; - } if (!rawCount) { rawConfig.size = processedConfig.size; rawConfig.bufferCount = processedConfig.bufferCount; } - csiConfig_ = data_->csi_->validate(rawConfig, data_->isp_.get()); + CamssIsp *isp = processedCount ? data_->processedIsp_.get() : data_->rawIsp_.get(); + csiConfig_ = data_->csi_->validate(rawConfig, isp); if (!csiConfig_.pixelFormat.isValid()) return Invalid; @@ -196,7 +193,7 @@ CameraConfiguration::Status CamssCameraConfiguration::validate() << " stride " << csiConfig_.stride << " frameSize " << csiConfig_.frameSize; - ispConfig_ = data_->isp_->validate(csiConfig_, processedConfig); + ispConfig_ = isp->validate(csiConfig_, processedConfig); if (!ispConfig_.pixelFormat.isValid()) return Invalid; @@ -216,7 +213,7 @@ CameraConfiguration::Status CamssCameraConfiguration::validate() stream = &data_->csi_->rawStream_; } else { hwCfg = &ispConfig_; - stream = &data_->isp_->outStream_; + stream = &isp->outStream_; } StreamConfiguration &cfg = config_[i]; @@ -321,7 +318,7 @@ PipelineHandlerCamss::generateConfiguration(Camera *camera, std::spanaddConfiguration(csiConfig); if (processedRequested) { - cfg = data->isp_->generateConfiguration(csiConfig); + cfg = data->processedIsp_->generateConfiguration(csiConfig); if (!cfg.pixelFormat.isValid()) return nullptr; @@ -346,6 +343,11 @@ int PipelineHandlerCamss::configure(Camera *camera, CameraConfiguration *c) if (ret) return ret; + if (config->ispConfig_.pixelFormat == config->csiConfig_.pixelFormat) + data->isp_ = data->rawIsp_.get(); + else + data->isp_ = data->processedIsp_.get(); + return data->isp_->configure(config->csiConfig_, config->ispConfig_, &data->controlInfo_); } @@ -426,7 +428,7 @@ void PipelineHandlerCamss::stopDevice(Camera *camera) } CamssCameraData::CamssCameraData(PipelineHandler *pipe) - : Camera::Private(pipe) + : Camera::Private(pipe), isp_(nullptr) { frameInfos_.bufferAvailable.connect(this, &CamssCameraData::queuePendingRequests); } @@ -523,27 +525,37 @@ bool PipelineHandlerCamss::match(DeviceEnumerator *enumerator) data->delayedCtrls_ = std::make_unique(sensor->device(), params); - data->isp_ = std::make_unique(this, sensor, - &data->frameInfos_, - &data->controlInfo_); - if (!data->isp_->isValid()) { + data->processedIsp_ = std::make_unique(this, sensor, + &data->frameInfos_, + &data->controlInfo_); + if (!data->processedIsp_->isValid()) { LOG(Camss, Error) << "Failed to create software ISP"; continue; } - data->isp_->inputBufferReady.connect(data->csi_.get(), - &CamssCsiCamera::tryReturnBuffer); - data->isp_->outputBufferReady.connect(data.get(), - &CamssCameraData::ispOutputBufferReady); - data->isp_->paramBufferReady.connect(data.get(), - &CamssCameraData::ispParameterBufferReady); - data->isp_->statsReady.connect(data.get(), &CamssCameraData::statsReady); - data->isp_->metadataReady.connect(data.get(), &CamssCameraData::metadataReady); - data->isp_->setSensorControls.connect(data.get(), &CamssCameraData::setSensorControls); + data->rawIsp_ = std::make_unique(this, sensor, + &data->frameInfos_, + &data->controlInfo_); + if (!data->rawIsp_->isValid()) { + LOG(Camss, Error) << "Failed to create raw ISP"; + continue; + } + + for (auto isp : { data->processedIsp_.get(), data->rawIsp_.get() }) { + isp->inputBufferReady.connect(data->csi_.get(), + &CamssCsiCamera::tryReturnBuffer); + isp->outputBufferReady.connect(data.get(), + &CamssCameraData::ispOutputBufferReady); + isp->paramBufferReady.connect(data.get(), + &CamssCameraData::ispParameterBufferReady); + isp->statsReady.connect(data.get(), &CamssCameraData::statsReady); + isp->metadataReady.connect(data.get(), &CamssCameraData::metadataReady); + isp->setSensorControls.connect(data.get(), &CamssCameraData::setSensorControls); + } /* Create and register the Camera instance. */ std::set streams = { - &data->isp_->outStream_, + &data->processedIsp_->outStream_, &data->csi_->rawStream_, }; std::shared_ptr camera = diff --git a/src/libcamera/pipeline/camss/camss_isp_raw.cpp b/src/libcamera/pipeline/camss/camss_isp_raw.cpp new file mode 100644 index 000000000..cd9226d7b --- /dev/null +++ b/src/libcamera/pipeline/camss/camss_isp_raw.cpp @@ -0,0 +1,228 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Qualcomm CAMSS dummy ISP class for raw only image capture. + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include "camss_isp_raw.h" + +#include + +#include + +#include +#include +#include +#include +#include + +#include "libcamera/internal/camera_manager.h" +#include "libcamera/internal/camera_sensor.h" +#include "libcamera/internal/dma_buf_allocator.h" +#include "libcamera/internal/ipa_manager.h" +#include "libcamera/internal/media_device.h" +#include "libcamera/internal/pipeline_handler.h" +#include "libcamera/internal/software_isp/debayer_params.h" +#include "libcamera/internal/software_isp/swstats_cpu.h" +#include "libcamera/internal/v4l2_subdevice.h" +#include "libcamera/internal/v4l2_videodevice.h" + +#include "camss_frames.h" + +namespace libcamera { + +LOG_DECLARE_CATEGORY(Camss) + +/** + * \class CamssIspRaw + * \brief CAMSS dummy ISP class for raw only image capture + */ + +/** + * \brief Constructs CamssIspRaw object + * \param[in] pipe The pipeline handler in use + * \param[in] sensor Pointer to the CameraSensor instance owned by the pipeline + * \param[in] frameInfos Pointer to CamssFrames instance owned by the pipeline + * \param[out] ControlInfoMap to which to add ISP provided controls + */ +CamssIspRaw::CamssIspRaw(PipelineHandler *pipe, const CameraSensor *sensor, + CamssFrames *frameInfos, ControlInfoMap *ispControls) + : sensor_(sensor), frameInfos_(frameInfos) +{ + sharedParams_ = SharedMemObject("softIsp_params"); + if (!sharedParams_) { + LOG(Camss, Error) << "Failed to create shared memory for parameters"; + return; + } + + const CameraManager &cm = *pipe->cameraManager(); + + stats_ = std::make_unique(cm); + if (!stats_->isValid()) { + LOG(Camss, Error) << "Failed to create SwStatsCpu object"; + return; + } + + stats_->statsReady.connect(this, + [&](uint32_t frame, uint32_t statsBufferId) { + statsReady.emit(frame, statsBufferId); + }); + + ipa_ = pipe->createIPA(0, 0); + if (!ipa_) { + LOG(Camss, Error) << "Creating IPA failed"; + return; + } + + /* + * The API tuning file is made from the sensor name. If the tuning file + * isn't found, fall back to the 'uncalibrated' file. + */ + std::string ipaTuningFile = + ipa_->configurationFile(sensor->model() + ".yaml", "uncalibrated.yaml"); + + IPACameraSensorInfo sensorInfo{}; + int ret = sensor->sensorInfo(&sensorInfo); + if (ret) { + LOG(Camss, Error) << "Camera sensor information not available"; + ipa_.reset(); + return; + } + + bool ccmEnabled; + bool lscEnabled; + ret = ipa_->init(IPASettings{ ipaTuningFile, sensor->model() }, + stats_->getStatsFD(), + sharedParams_.fd(), + sensorInfo, + sensor->controls(), + ispControls, + &ccmEnabled, + &lscEnabled); + if (ret) { + LOG(Camss, Error) << "IPA init failed"; + ipa_.reset(); + return; + } + + ipa_->metadataReady.connect(this, + [&](uint32_t frame, const ControlList &metadata) { + metadataReady.emit(frame, metadata); + }); + ipa_->setSensorControls.connect(this, + [&](const ControlList &sensorControls) { + setSensorControls.emit(sensorControls); + }); +} + +CamssIspRaw::~CamssIspRaw() = default; + +bool CamssIspRaw::isValid() +{ + return !!ipa_; +} + +Size CamssIspRaw::getMargins([[maybe_unused]] PixelFormat inputFormat) +{ + return Size(); +} + +StreamConfiguration CamssIspRaw::generateConfiguration(const StreamConfiguration &raw) const +{ + return raw; +} + +StreamConfiguration CamssIspRaw::validate(const StreamConfiguration &raw, + [[maybe_unused]] const StreamConfiguration &req) const +{ + return raw; +} + +int CamssIspRaw::configure(const StreamConfiguration &inputCfg, + const StreamConfiguration &outputCfg, + ControlInfoMap *ispControls) +{ + ipa::softisp::IPAConfigInfo configInfo; + configInfo.sensorControls = sensor_->controls(); + + if (inputCfg.pixelFormat != outputCfg.pixelFormat || + inputCfg.size != outputCfg.size) + return -EINVAL; + + int ret = ipa_->configure(configInfo, ispControls); + if (ret < 0) + return ret; + + ret = stats_->configure(inputCfg); + if (ret < 0) + return ret; + + /* Use 2/3 center of image to reduce CPU load */ + Rectangle statsWindow; + statsWindow.width = inputCfg.size.width * 2 / 3; + statsWindow.height = inputCfg.size.height * 2 / 3; + statsWindow.x = (inputCfg.size.width - statsWindow.width) / 2; + statsWindow.y = (inputCfg.size.height - statsWindow.height) / 2; + /* stats_->setWindow() takes care of necessary alignment itself */ + stats_->setWindow(statsWindow); + + return 0; +} + +int CamssIspRaw::allocateBuffers([[maybe_unused]] unsigned int bufferCount) +{ + frameInfos_->init({}, {}); + return 0; +} + +void CamssIspRaw::freeBuffers() +{ + frameInfos_->clear(); +} + +int CamssIspRaw::exportOutputBuffers([[maybe_unused]] const Stream *stream, + [[maybe_unused]] unsigned int count, + [[maybe_unused]] std::vector> *buffers) +{ + /* Must never be called when there only is a raw stream */ + return -EINVAL; +} + +void CamssIspRaw::queueBuffers(Request *request, FrameBuffer *inputBuffer) +{ + uint32_t frame = request->sequence(); + + DmaSyncer inputDmaSync(inputBuffer->planes()[0].fd, DmaSyncer::SyncType::Read); + + MappedFrameBuffer input(inputBuffer, MappedFrameBuffer::MapFlag::Read); + if (!input.isValid()) { + LOG(Camss, Error) << "mmap-ing buffer(s) failed"; + return; + } + + ipa_->queueRequest(frame, request->controls()); + /* + * This emits statsReady which calls ipa_->processStats(), which emits + * metadataReady which makes camss.cpp mark the request as completed. + */ + stats_->processFrame(frame, 0, input); +} + +void CamssIspRaw::processStats(const uint32_t frame, const uint32_t statsBufferId, + const ControlList &sensorControls) +{ + ipa_->processStats(frame, statsBufferId, sensorControls); +} + +int CamssIspRaw::start() +{ + return ipa_->start(); +} + +void CamssIspRaw::stop() +{ + ipa_->stop(); +} + +} /* namespace libcamera */ diff --git a/src/libcamera/pipeline/camss/camss_isp_raw.h b/src/libcamera/pipeline/camss/camss_isp_raw.h new file mode 100644 index 000000000..76b9d1af8 --- /dev/null +++ b/src/libcamera/pipeline/camss/camss_isp_raw.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Qualcomm CAMSS dummy ISP class for raw only image capture. + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#pragma once + +#include +#include + +#include +#include + +/* FIXME drop once using own camss IPA, which will map on IPA side */ +#include "libcamera/internal/mapped_framebuffer.h" +#include "libcamera/internal/shared_mem_object.h" +#include "libcamera/internal/software_isp/debayer_params.h" +#include "libcamera/internal/v4l2_subdevice.h" + +#include "camss_isp.h" + +namespace libcamera { + +class CameraSensor; +class CamssFrames; +class ControlInfoMap; +class DeviceEnumerator; +class MediaDevice; +class PipelineHandler; +class Stream; +class SwStatsCpu; +class V4L2VideoDevice; + +class CamssIspRaw : public CamssIsp +{ +public: + CamssIspRaw(PipelineHandler *pipe, const CameraSensor *sensor, + CamssFrames *frameInfos, ControlInfoMap *ispControls); + ~CamssIspRaw() override; + + bool isValid() override; + Size getMargins(PixelFormat inputFormat) override; + + StreamConfiguration generateConfiguration(const StreamConfiguration &raw) const override; + StreamConfiguration validate(const StreamConfiguration &raw, const StreamConfiguration &req) const override; + int configure(const StreamConfiguration &inputCfg, + const StreamConfiguration &outputCfg, + ControlInfoMap *ispControls) override; + + int allocateBuffers(unsigned int bufferCount) override; + void freeBuffers() override; + int exportOutputBuffers(const Stream *stream, unsigned int count, + std::vector> *buffers) override; + void queueBuffers(Request *request, FrameBuffer *input) override; + + void processStats(const uint32_t frame, const uint32_t statsBufferId, + const ControlList &sensorControls) override; + + int start() override; + void stop() override; + +private: + const CameraSensor *sensor_; + class CamssFrames *frameInfos_; + SharedMemObject sharedParams_; + std::unique_ptr stats_; + std::unique_ptr ipa_; +}; + +} /* namespace libcamera */ diff --git a/src/libcamera/pipeline/camss/meson.build b/src/libcamera/pipeline/camss/meson.build index 2f3931dd1..518d85478 100644 --- a/src/libcamera/pipeline/camss/meson.build +++ b/src/libcamera/pipeline/camss/meson.build @@ -5,6 +5,7 @@ libcamera_internal_sources += files([ 'camss_csi.cpp', 'camss_frames.cpp', 'camss_isp.cpp', + 'camss_isp_raw.cpp', 'camss_isp_soft.cpp', 'camss_util.cpp', ])