From patchwork Mon Nov 25 18:03:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 22082 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 258C0BD160 for ; Mon, 25 Nov 2024 18:03:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C7BE166027; Mon, 25 Nov 2024 19:03:29 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="VLHd1UrB"; 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 0737B65F68 for ; Mon, 25 Nov 2024 19:03:26 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1732557805; 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=CBtOAfpeXHvxV5wVrC2Z5djaW5B8zis7F33WxJyPahk=; b=VLHd1UrBBwo8lakFMHh27ZNgNfRpv3bH+bc5SpqLC1qQ5WQT7Z5oZ7CiahvoHaYhfpzyiz HjqEXG+SxA+cO5Ugud5Einx8gZNFWYFNKMhc79gtjwZ6u04TzuPRSbSMunoKJnn3w7ZzLT GrpDDpTKKsBy8tv1sGTTMxhchtlu+uA= Received: from mx-prod-mc-04.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-45-KIkzwNVuOPijXmr-FyF9FA-1; Mon, 25 Nov 2024 13:03:24 -0500 X-MC-Unique: KIkzwNVuOPijXmr-FyF9FA-1 X-Mimecast-MFC-AGG-ID: KIkzwNVuOPijXmr-FyF9FA Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (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-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id B93B119560B5; Mon, 25 Nov 2024 18:03:23 +0000 (UTC) Received: from nuthatch.redhat.com (unknown [10.45.224.109]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 2F9631956086; Mon, 25 Nov 2024 18:03:21 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Robert Mader Subject: [PATCH v2 1/9] libcamera: software_isp: Determine color temperature Date: Mon, 25 Nov 2024 19:03:02 +0100 Message-ID: <20241125180310.1254519-2-mzamazal@redhat.com> In-Reply-To: <20241125180310.1254519-1-mzamazal@redhat.com> References: <20241125180310.1254519-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: TgXD4zr9D0uQrEy1hy7w0_QnxgmU-eekRrdwRqYaX2g_1732557803 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 AWB algorithm has data to determine color temperature of the image. Let's compute the temperature from it and store it into the context. This piece of information is currently unused but it will be needed in a followup patch introducing support for color correction matrix. Let's store the white balance related information under `awb' subsection of the active state, as the hardware pipelines do. Signed-off-by: Milan Zamazal --- src/ipa/simple/algorithms/awb.cpp | 12 +++++++++--- src/ipa/simple/algorithms/lut.cpp | 2 +- src/ipa/simple/ipa_context.h | 11 +++++++---- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/ipa/simple/algorithms/awb.cpp b/src/ipa/simple/algorithms/awb.cpp index 195de41dc..db384c3fa 100644 --- a/src/ipa/simple/algorithms/awb.cpp +++ b/src/ipa/simple/algorithms/awb.cpp @@ -12,6 +12,7 @@ #include +#include "libipa/colours.h" #include "simple/ipa_context.h" namespace libcamera { @@ -23,7 +24,7 @@ namespace ipa::soft::algorithms { int Awb::configure(IPAContext &context, [[maybe_unused]] const IPAConfigInfo &configInfo) { - auto &gains = context.activeState.gains; + auto &gains = context.activeState.awb.gains; gains.red = gains.green = gains.blue = 1.0; return 0; @@ -54,12 +55,17 @@ void Awb::process(IPAContext &context, * Calculate red and blue gains for AWB. * Clamp max gain at 4.0, this also avoids 0 division. */ - auto &gains = context.activeState.gains; + auto &gains = context.activeState.awb.gains; gains.red = sumR <= sumG / 4 ? 4.0 : static_cast(sumG) / sumR; gains.blue = sumB <= sumG / 4 ? 4.0 : static_cast(sumG) / sumB; /* Green gain is fixed to 1.0 */ - LOG(IPASoftAwb, Debug) << "gain R/B " << gains.red << "/" << gains.blue; + context.activeState.awb.temperatureK = + estimateCCT(1 / gains.red, 1 / gains.green, 1 / gains.blue); + + LOG(IPASoftAwb, Debug) + << "gain R/B: " << gains.red << "/" << gains.blue + << "; temperature: " << context.activeState.awb.temperatureK; } REGISTER_IPA_ALGORITHM(Awb, "Awb") diff --git a/src/ipa/simple/algorithms/lut.cpp b/src/ipa/simple/algorithms/lut.cpp index 9744e773a..7fc87fc5f 100644 --- a/src/ipa/simple/algorithms/lut.cpp +++ b/src/ipa/simple/algorithms/lut.cpp @@ -58,7 +58,7 @@ void Lut::prepare(IPAContext &context, if (context.activeState.gamma.blackLevel != context.activeState.blc.level) updateGammaTable(context); - auto &gains = context.activeState.gains; + auto &gains = context.activeState.awb.gains; auto &gammaTable = context.activeState.gamma.gammaTable; const unsigned int gammaTableSize = gammaTable.size(); diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h index fd121eebe..268ba9cec 100644 --- a/src/ipa/simple/ipa_context.h +++ b/src/ipa/simple/ipa_context.h @@ -34,10 +34,13 @@ struct IPAActiveState { } blc; struct { - double red; - double green; - double blue; - } gains; + struct { + double red; + double green; + double blue; + } gains; + unsigned int temperatureK; + } awb; struct { int32_t exposure; From patchwork Mon Nov 25 18:03:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 22083 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 16329BD160 for ; Mon, 25 Nov 2024 18:03:33 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C5C6E6603A; Mon, 25 Nov 2024 19:03:32 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="KsyBHa2T"; 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 295DE65F7C for ; Mon, 25 Nov 2024 19:03:31 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1732557810; 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=QNJCpZOST9RzzDb5ZifNelAOmIVM9PCUEa8YDg/JSuU=; b=KsyBHa2TaAMwvv1sgNPjJbTNObc95dreWk5YAEavapgoKJB9IN5wy84rGRI+JeqSxbkbu/ 3PS0GEHrLOTM+FC1A6BJ+sob5Yv8Tjqqh6lWMKLSg8T4oBAYFnexhk77WNMLzluzMjIouV 9+b0a+lwHciBpHgAV8xz8LHolr3l4Pg= 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-661-3Ctdf95PPcqP1hCLdY-AcQ-1; Mon, 25 Nov 2024 13:03:26 -0500 X-MC-Unique: 3Ctdf95PPcqP1hCLdY-AcQ-1 X-Mimecast-MFC-AGG-ID: 3Ctdf95PPcqP1hCLdY-AcQ Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (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 DC901195604F; Mon, 25 Nov 2024 18:03:25 +0000 (UTC) Received: from nuthatch.redhat.com (unknown [10.45.224.109]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 544551956086; Mon, 25 Nov 2024 18:03:24 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Robert Mader Subject: [PATCH v2 2/9] libcamera: software_isp: Store color temperature to metadata Date: Mon, 25 Nov 2024 19:03:03 +0100 Message-ID: <20241125180310.1254519-3-mzamazal@redhat.com> In-Reply-To: <20241125180310.1254519-1-mzamazal@redhat.com> References: <20241125180310.1254519-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: F7ie-uf5Lonkh07CARiSwqLhenozC_U7aTnjoPIlv8U_1732557806 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" Image color temperature is a piece of information that should be reported in metadata, let's put it there. Metadata is currently not reported in simple pipeline but we should make at least newly added information ready to be reported. Signed-off-by: Milan Zamazal --- src/ipa/simple/algorithms/awb.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/ipa/simple/algorithms/awb.cpp b/src/ipa/simple/algorithms/awb.cpp index db384c3fa..eef8277fc 100644 --- a/src/ipa/simple/algorithms/awb.cpp +++ b/src/ipa/simple/algorithms/awb.cpp @@ -12,6 +12,8 @@ #include +#include + #include "libipa/colours.h" #include "simple/ipa_context.h" @@ -34,7 +36,7 @@ void Awb::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, [[maybe_unused]] IPAFrameContext &frameContext, const SwIspStats *stats, - [[maybe_unused]] ControlList &metadata) + ControlList &metadata) { const SwIspStats::Histogram &histogram = stats->yHistogram; const uint8_t blackLevel = context.activeState.blc.level; @@ -60,8 +62,10 @@ void Awb::process(IPAContext &context, gains.blue = sumB <= sumG / 4 ? 4.0 : static_cast(sumG) / sumB; /* Green gain is fixed to 1.0 */ - context.activeState.awb.temperatureK = + uint32_t temperature = estimateCCT(1 / gains.red, 1 / gains.green, 1 / gains.blue); + context.activeState.awb.temperatureK = temperature; + metadata.set(controls::ColourTemperature, temperature); LOG(IPASoftAwb, Debug) << "gain R/B: " << gains.red << "/" << gains.blue From patchwork Mon Nov 25 18:03:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 22084 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 08ECEBD160 for ; Mon, 25 Nov 2024 18:03:35 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9674566045; Mon, 25 Nov 2024 19:03:34 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="VkXPl1xq"; 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 BDFE46602C for ; Mon, 25 Nov 2024 19:03:31 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1732557810; 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=Yzv7kEJFhZfXvvjwXLRiBzZD9Ee9ZnQFx0jmP1YBZEY=; b=VkXPl1xqoKsZGr2slnEvTUqRZa94vHcNpEA5wu51rEHwdjLm/7IPhcaEM+xmt6ytgIpYQW e6LIxJj7WrPk8GafMjfqlrXZYmoKb0d2vMPJS8/guvs06nPUZ+kqWp2iEhgbrauQa/7+HA BqC8rbcojdlLfnXXPQn9oJidzO/jWhA= Received: from mx-prod-mc-04.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-443-AUfYaAEaMY2_gxZ0PVBP-A-1; Mon, 25 Nov 2024 13:03:29 -0500 X-MC-Unique: AUfYaAEaMY2_gxZ0PVBP-A-1 X-Mimecast-MFC-AGG-ID: AUfYaAEaMY2_gxZ0PVBP-A Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (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-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0DCB01955DC3; Mon, 25 Nov 2024 18:03:28 +0000 (UTC) Received: from nuthatch.redhat.com (unknown [10.45.224.109]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 78E491956086; Mon, 25 Nov 2024 18:03:26 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Robert Mader Subject: [PATCH v2 3/9] libcamera: software_isp: lut: Remove maybe_unused on a used argument Date: Mon, 25 Nov 2024 19:03:04 +0100 Message-ID: <20241125180310.1254519-4-mzamazal@redhat.com> In-Reply-To: <20241125180310.1254519-1-mzamazal@redhat.com> References: <20241125180310.1254519-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: oRlZ4nGdOkig0x30NSr0ZY1WzOXGS85Vpd3j_BPgeCI_1732557808 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" `params' argument of Lut::prepare is actually used, let's remove maybe_unused from it. Signed-off-by: Milan Zamazal --- src/ipa/simple/algorithms/lut.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ipa/simple/algorithms/lut.cpp b/src/ipa/simple/algorithms/lut.cpp index 7fc87fc5f..8fca96b0a 100644 --- a/src/ipa/simple/algorithms/lut.cpp +++ b/src/ipa/simple/algorithms/lut.cpp @@ -47,7 +47,7 @@ void Lut::updateGammaTable(IPAContext &context) void Lut::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame, [[maybe_unused]] IPAFrameContext &frameContext, - [[maybe_unused]] DebayerParams *params) + DebayerParams *params) { /* * Update the gamma table if needed. This means if black level changes From patchwork Mon Nov 25 18:03:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 22085 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 32865BD160 for ; Mon, 25 Nov 2024 18:03:37 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id DF5D266045; Mon, 25 Nov 2024 19:03:36 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="KEdQNz3x"; 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 ABCBF66034 for ; Mon, 25 Nov 2024 19:03:33 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1732557812; 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=bjgEtxBJTkMYzwgWAelthFy+SWRZMgoQWEniOHqfmnI=; b=KEdQNz3xk9h5OVwemDWpm4Lr6Pt68xjFlVN76URW1HsBDivPAQv+Wrc1VEi7aGY3tMM5yh KuoRudtcibi7bIbno0d9IrzVHjXreB7y4fModlzwLOS2tkCRtU9K1nnSyokEg3//N0pRBs bPVE0kjwXqK/zdfiFTEs37pMEQ+/fnk= 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-518-bpu2sSnpP9SHGueIWDfTlw-1; Mon, 25 Nov 2024 13:03:31 -0500 X-MC-Unique: bpu2sSnpP9SHGueIWDfTlw-1 X-Mimecast-MFC-AGG-ID: bpu2sSnpP9SHGueIWDfTlw Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (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 31BC719560BD; Mon, 25 Nov 2024 18:03:30 +0000 (UTC) Received: from nuthatch.redhat.com (unknown [10.45.224.109]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 9DC701956086; Mon, 25 Nov 2024 18:03:28 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Robert Mader Subject: [PATCH v2 4/9] libcamera: software_isp: Use common code to store debayered pixels Date: Mon, 25 Nov 2024 19:03:05 +0100 Message-ID: <20241125180310.1254519-5-mzamazal@redhat.com> In-Reply-To: <20241125180310.1254519-1-mzamazal@redhat.com> References: <20241125180310.1254519-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: nQ9R06rP_XyUMJpzDUSPGDeYsK9IuyAKorYBbZyRdVI_1732557810 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 debayering macros use the same pattern, let's extract it to a common macro. This reduces code duplication a bit now and it'll make changes of debayering easier when color correction matrix is introduced. Signed-off-by: Milan Zamazal --- src/libcamera/software_isp/debayer_cpu.cpp | 56 +++++++++++----------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp index cf5ecdf7a..4a21ef361 100644 --- a/src/libcamera/software_isp/debayer_cpu.cpp +++ b/src/libcamera/software_isp/debayer_cpu.cpp @@ -61,57 +61,57 @@ DebayerCpu::~DebayerCpu() = default; const pixel_t *curr = (const pixel_t *)src[1] + xShift_; \ const pixel_t *next = (const pixel_t *)src[2] + xShift_; +#define STORE_PIXEL(b, g, r) \ + *dst++ = blue_[b]; \ + *dst++ = green_[g]; \ + *dst++ = red_[r]; \ + if constexpr (addAlphaByte) \ + *dst++ = 255; \ + x++; + /* * RGR * GBG * RGR */ -#define BGGR_BGR888(p, n, div) \ - *dst++ = blue_[curr[x] / (div)]; \ - *dst++ = green_[(prev[x] + curr[x - p] + curr[x + n] + next[x]) / (4 * (div))]; \ - *dst++ = red_[(prev[x - p] + prev[x + n] + next[x - p] + next[x + n]) / (4 * (div))]; \ - if constexpr (addAlphaByte) \ - *dst++ = 255; \ - x++; +#define BGGR_BGR888(p, n, div) \ + STORE_PIXEL( \ + curr[x] / (div), \ + (prev[x] + curr[x - p] + curr[x + n] + next[x]) / (4 * (div)), \ + (prev[x - p] + prev[x + n] + next[x - p] + next[x + n]) / (4 * (div))) /* * GBG * RGR * GBG */ -#define GRBG_BGR888(p, n, div) \ - *dst++ = blue_[(prev[x] + next[x]) / (2 * (div))]; \ - *dst++ = green_[curr[x] / (div)]; \ - *dst++ = red_[(curr[x - p] + curr[x + n]) / (2 * (div))]; \ - if constexpr (addAlphaByte) \ - *dst++ = 255; \ - x++; +#define GRBG_BGR888(p, n, div) \ + STORE_PIXEL( \ + (prev[x] + next[x]) / (2 * (div)), \ + curr[x] / (div), \ + (curr[x - p] + curr[x + n]) / (2 * (div))) /* * GRG * BGB * GRG */ -#define GBRG_BGR888(p, n, div) \ - *dst++ = blue_[(curr[x - p] + curr[x + n]) / (2 * (div))]; \ - *dst++ = green_[curr[x] / (div)]; \ - *dst++ = red_[(prev[x] + next[x]) / (2 * (div))]; \ - if constexpr (addAlphaByte) \ - *dst++ = 255; \ - x++; +#define GBRG_BGR888(p, n, div) \ + STORE_PIXEL( \ + (curr[x - p] + curr[x + n]) / (2 * (div)), \ + curr[x] / (div), \ + (prev[x] + next[x]) / (2 * (div))) /* * BGB * GRG * BGB */ -#define RGGB_BGR888(p, n, div) \ - *dst++ = blue_[(prev[x - p] + prev[x + n] + next[x - p] + next[x + n]) / (4 * (div))]; \ - *dst++ = green_[(prev[x] + curr[x - p] + curr[x + n] + next[x]) / (4 * (div))]; \ - *dst++ = red_[curr[x] / (div)]; \ - if constexpr (addAlphaByte) \ - *dst++ = 255; \ - x++; +#define RGGB_BGR888(p, n, div) \ + STORE_PIXEL( \ + (prev[x - p] + prev[x + n] + next[x - p] + next[x + n]) / (4 * (div)), \ + (prev[x] + curr[x - p] + curr[x + n] + next[x]) / (4 * (div)), \ + curr[x] / (div)) template void DebayerCpu::debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) From patchwork Mon Nov 25 18:03:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 22086 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 AEFEDBD160 for ; Mon, 25 Nov 2024 18:03:38 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1A60066042; Mon, 25 Nov 2024 19:03:38 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="DFNioxzC"; 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 83ED76602C for ; Mon, 25 Nov 2024 19:03:35 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1732557814; 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=ZKOWq3s9ZvOqCNbq6q2BSbj8sJIJG1y3+XsKjBt3CZo=; b=DFNioxzC+8SWXx2EQwrCVLsmQsDDyzKo5kU5II1aspgKuR68Y1Kz56KhlrMBJ7FtnwQAzX d1lZvhQJtbIfsmsB94BblGaQueO/6Po12sA9e9MXJ8RCk3t/l0nBSGM+wfVdftT+48E49t wNz9iiyxu4v0grQr9vND/qJuIG7FW+M= 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-170-9q832I_FPXSsgIIYfk7kHQ-1; Mon, 25 Nov 2024 13:03:33 -0500 X-MC-Unique: 9q832I_FPXSsgIIYfk7kHQ-1 X-Mimecast-MFC-AGG-ID: 9q832I_FPXSsgIIYfk7kHQ Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (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 46B40195608D; Mon, 25 Nov 2024 18:03:32 +0000 (UTC) Received: from nuthatch.redhat.com (unknown [10.45.224.109]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id C2F7B196BC05; Mon, 25 Nov 2024 18:03:30 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Robert Mader Subject: [PATCH v2 5/9] libcamera: software_isp: Use a macro to assign debayering methods Date: Mon, 25 Nov 2024 19:03:06 +0100 Message-ID: <20241125180310.1254519-6-mzamazal@redhat.com> In-Reply-To: <20241125180310.1254519-1-mzamazal@redhat.com> References: <20241125180310.1254519-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: 9IwPtpHNttm1U4Vrdfv8Ref6XzksXjCvQ8RP70ldOfM_1732557812 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" Assignments of the debayering methods to be used is a repetitive pattern that can be (arguably) better expressed by using a macro. This removes some duplication and also makes easier to introduce more complex assignment patterns. This will be useful once color correction matrix support is added. Signed-off-by: Milan Zamazal --- src/libcamera/software_isp/debayer_cpu.cpp | 25 ++++++++++------------ 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp index 4a21ef361..7d080f00f 100644 --- a/src/libcamera/software_isp/debayer_cpu.cpp +++ b/src/libcamera/software_isp/debayer_cpu.cpp @@ -367,6 +367,10 @@ int DebayerCpu::setupStandardBayerOrder(BayerFormat::Order order) return 0; } +#define SET_DEBAYER_METHODS(method0, method1) \ + debayer0_ = addAlphaByte ? &DebayerCpu::method0 : &DebayerCpu::method0; \ + debayer1_ = addAlphaByte ? &DebayerCpu::method1 : &DebayerCpu::method1; + int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat) { BayerFormat bayerFormat = @@ -422,16 +426,13 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputF isStandardBayerOrder(bayerFormat.order)) { switch (bayerFormat.bitDepth) { case 8: - debayer0_ = addAlphaByte ? &DebayerCpu::debayer8_BGBG_BGR888 : &DebayerCpu::debayer8_BGBG_BGR888; - debayer1_ = addAlphaByte ? &DebayerCpu::debayer8_GRGR_BGR888 : &DebayerCpu::debayer8_GRGR_BGR888; + SET_DEBAYER_METHODS(debayer8_BGBG_BGR888, debayer8_GRGR_BGR888) break; case 10: - debayer0_ = addAlphaByte ? &DebayerCpu::debayer10_BGBG_BGR888 : &DebayerCpu::debayer10_BGBG_BGR888; - debayer1_ = addAlphaByte ? &DebayerCpu::debayer10_GRGR_BGR888 : &DebayerCpu::debayer10_GRGR_BGR888; + SET_DEBAYER_METHODS(debayer10_BGBG_BGR888, debayer10_GRGR_BGR888) break; case 12: - debayer0_ = addAlphaByte ? &DebayerCpu::debayer12_BGBG_BGR888 : &DebayerCpu::debayer12_BGBG_BGR888; - debayer1_ = addAlphaByte ? &DebayerCpu::debayer12_GRGR_BGR888 : &DebayerCpu::debayer12_GRGR_BGR888; + SET_DEBAYER_METHODS(debayer12_BGBG_BGR888, debayer12_GRGR_BGR888) break; } setupStandardBayerOrder(bayerFormat.order); @@ -442,20 +443,16 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputF bayerFormat.packing == BayerFormat::Packing::CSI2) { switch (bayerFormat.order) { case BayerFormat::BGGR: - debayer0_ = addAlphaByte ? &DebayerCpu::debayer10P_BGBG_BGR888 : &DebayerCpu::debayer10P_BGBG_BGR888; - debayer1_ = addAlphaByte ? &DebayerCpu::debayer10P_GRGR_BGR888 : &DebayerCpu::debayer10P_GRGR_BGR888; + SET_DEBAYER_METHODS(debayer10P_BGBG_BGR888, debayer10P_GRGR_BGR888) return 0; case BayerFormat::GBRG: - debayer0_ = addAlphaByte ? &DebayerCpu::debayer10P_GBGB_BGR888 : &DebayerCpu::debayer10P_GBGB_BGR888; - debayer1_ = addAlphaByte ? &DebayerCpu::debayer10P_RGRG_BGR888 : &DebayerCpu::debayer10P_RGRG_BGR888; + SET_DEBAYER_METHODS(debayer10P_GBGB_BGR888, debayer10P_RGRG_BGR888) return 0; case BayerFormat::GRBG: - debayer0_ = addAlphaByte ? &DebayerCpu::debayer10P_GRGR_BGR888 : &DebayerCpu::debayer10P_GRGR_BGR888; - debayer1_ = addAlphaByte ? &DebayerCpu::debayer10P_BGBG_BGR888 : &DebayerCpu::debayer10P_BGBG_BGR888; + SET_DEBAYER_METHODS(debayer10P_GRGR_BGR888, debayer10P_BGBG_BGR888) return 0; case BayerFormat::RGGB: - debayer0_ = addAlphaByte ? &DebayerCpu::debayer10P_RGRG_BGR888 : &DebayerCpu::debayer10P_RGRG_BGR888; - debayer1_ = addAlphaByte ? &DebayerCpu::debayer10P_GBGB_BGR888 : &DebayerCpu::debayer10P_GBGB_BGR888; + SET_DEBAYER_METHODS(debayer10P_RGRG_BGR888, debayer10P_GBGB_BGR888) return 0; default: break; From patchwork Mon Nov 25 18:03:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 22087 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 E8B4DBD160 for ; Mon, 25 Nov 2024 18:03:41 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7E1A76604A; Mon, 25 Nov 2024 19:03:41 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="Cy5CZ3Vi"; 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 6C4CA6604A for ; Mon, 25 Nov 2024 19:03:37 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1732557816; 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=luCyc9hNUm4p3xinuCMxgVCxFZvoHEDYp0tghRm3SaU=; b=Cy5CZ3VikveHSzXG0YxlTLPnLYFDYN3rq+fZD0NvNbfYXaNfrcZWIJfQn+XxKZBbfo8UfY T2NrgVgVLRboCjm0ADSoeokZTYnqQ/atknJDZbLM5oThsQQMPT3DS4SIsHVWEDSk6fMmDA sUHcPF/BVhoyM12M8ArqKu/aYovbi9g= Received: from mx-prod-mc-04.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-467-1QsPlPjkNYOLo8la1IcfvQ-1; Mon, 25 Nov 2024 13:03:35 -0500 X-MC-Unique: 1QsPlPjkNYOLo8la1IcfvQ-1 X-Mimecast-MFC-AGG-ID: 1QsPlPjkNYOLo8la1IcfvQ Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (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-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 6290919560B0; Mon, 25 Nov 2024 18:03:34 +0000 (UTC) Received: from nuthatch.redhat.com (unknown [10.45.224.109]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id CE26A1956086; Mon, 25 Nov 2024 18:03:32 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Robert Mader Subject: [PATCH v2 6/9] libcamera: software_isp: Add CCM algorithm Date: Mon, 25 Nov 2024 19:03:07 +0100 Message-ID: <20241125180310.1254519-7-mzamazal@redhat.com> In-Reply-To: <20241125180310.1254519-1-mzamazal@redhat.com> References: <20241125180310.1254519-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: V4TOLwMUzYtxFtEfOSmelhvbMoyEE5QmTFIBzBJIXAA_1732557814 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" This patch adds color correction matrix (CCM) algorithm to software ISP. It is based on the corresponding algorithm in rkisp1. The primary difference against hardware pipelines is that applying the CCM is optional. Applying CCM causes a significant slowdown, time needed to process a frame raises by 40-90% on tested platforms. If CCM is really needed, it can be applied, if not, it's better to stick without it. This can be configured by presence or omission of Ccm algorithm in the tuning file. CCM is changed only if the determined temperature changes by at least 100 K (an arbitrarily selected value), to avoid recomputing the matrices and lookup tables all the time. Some ugly unsigned->signed int typecasting is needed to compare the temperatures. The outputs of the algorithm are not used yet, they will be enabled in followup patches. Signed-off-by: Milan Zamazal --- src/ipa/simple/algorithms/ccm.cpp | 88 +++++++++++++++++++++++++++ src/ipa/simple/algorithms/ccm.h | 44 ++++++++++++++ src/ipa/simple/algorithms/meson.build | 1 + src/ipa/simple/ipa_context.h | 11 ++++ 4 files changed, 144 insertions(+) create mode 100644 src/ipa/simple/algorithms/ccm.cpp create mode 100644 src/ipa/simple/algorithms/ccm.h diff --git a/src/ipa/simple/algorithms/ccm.cpp b/src/ipa/simple/algorithms/ccm.cpp new file mode 100644 index 000000000..bd2c03fe4 --- /dev/null +++ b/src/ipa/simple/algorithms/ccm.cpp @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Ideas On Board + * Copyright (C) 2024, Red Hat Inc. + * + * Color correction matrix + */ + +#include "ccm.h" + +#include + +#include + +#include + +namespace libcamera { + +namespace ipa::soft::algorithms { + +LOG_DEFINE_CATEGORY(IPASoftCcm) + +unsigned int Ccm::kTemperatureThreshold = 100; + +int Ccm::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData) +{ + int ret = ccm_.readYaml(tuningData["ccms"], "ct", "ccm"); + if (ret < 0) { + LOG(IPASoftCcm, Warning) + << "Failed to parse 'ccm' " + << "parameter from tuning file; falling back to unit matrix"; + ccmEnabled_ = false; + } else { + ccmEnabled_ = true; + } + + return 0; +} + +void Ccm::prepare(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, [[maybe_unused]] DebayerParams *params) +{ + context.activeState.ccm.enabled = ccmEnabled_; + + if (!ccmEnabled_) + return; + + unsigned int ct = context.activeState.awb.temperatureK; + + /* Change CCM only on bigger temperature changes. */ + if (frame > 0 && + abs(static_cast(ct) - static_cast(ct_)) < + static_cast(kTemperatureThreshold)) { + frameContext.ccm.ccm = context.activeState.ccm.ccm; + context.activeState.ccm.changed = false; + return; + } + + ct_ = ct; + Matrix ccm = ccm_.getInterpolated(ct); + + context.activeState.ccm.ccm = ccm; + frameContext.ccm.ccm = ccm; + context.activeState.ccm.changed = true; +} + +void Ccm::process([[maybe_unused]] IPAContext &context, + [[maybe_unused]] const uint32_t frame, + IPAFrameContext &frameContext, + [[maybe_unused]] const SwIspStats *stats, + ControlList &metadata) +{ + if (!ccmEnabled_) + return; + + float m[9]; + for (unsigned int i = 0; i < 3; i++) { + for (unsigned int j = 0; j < 3; j++) + m[i * 3 + j] = frameContext.ccm.ccm[i][j]; + } + metadata.set(controls::ColourCorrectionMatrix, m); +} + +REGISTER_IPA_ALGORITHM(Ccm, "Ccm") + +} /* namespace ipa::soft::algorithms */ + +} /* namespace libcamera */ diff --git a/src/ipa/simple/algorithms/ccm.h b/src/ipa/simple/algorithms/ccm.h new file mode 100644 index 000000000..6b7efbe21 --- /dev/null +++ b/src/ipa/simple/algorithms/ccm.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Red Hat Inc. + * + * Color correction matrix + */ + +#pragma once + +#include "libipa/interpolator.h" +#include "libipa/matrix.h" + +#include "algorithm.h" + +namespace libcamera { + +namespace ipa::soft::algorithms { + +class Ccm : public Algorithm +{ +public: + Ccm() = default; + ~Ccm() = default; + + int init(IPAContext &context, const YamlObject &tuningData) override; + void prepare(IPAContext &context, + const uint32_t frame, + IPAFrameContext &frameContext, + DebayerParams *params) override; + void process(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, + const SwIspStats *stats, + ControlList &metadata) override; + +private: + static unsigned int kTemperatureThreshold; + unsigned int ct_; + bool ccmEnabled_; + Interpolator> ccm_; +}; + +} /* namespace ipa::soft::algorithms */ + +} /* namespace libcamera */ diff --git a/src/ipa/simple/algorithms/meson.build b/src/ipa/simple/algorithms/meson.build index 37a2eb534..2d0adb059 100644 --- a/src/ipa/simple/algorithms/meson.build +++ b/src/ipa/simple/algorithms/meson.build @@ -4,5 +4,6 @@ soft_simple_ipa_algorithms = files([ 'awb.cpp', 'agc.cpp', 'blc.cpp', + 'ccm.cpp', 'lut.cpp', ]) diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h index 268ba9cec..5f9ec0afc 100644 --- a/src/ipa/simple/ipa_context.h +++ b/src/ipa/simple/ipa_context.h @@ -12,6 +12,7 @@ #include #include +#include namespace libcamera { @@ -52,9 +53,19 @@ struct IPAActiveState { std::array gammaTable; uint8_t blackLevel; } gamma; + + struct { + Matrix ccm; + bool enabled; + bool changed; + } ccm; }; struct IPAFrameContext : public FrameContext { + struct { + Matrix ccm; + } ccm; + struct { uint32_t exposure; double gain; From patchwork Mon Nov 25 18:03:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 22088 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 425AFBD160 for ; Mon, 25 Nov 2024 18:03:44 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id F077E6604D; Mon, 25 Nov 2024 19:03:43 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="ENO9UKM/"; 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 B1A516604D for ; Mon, 25 Nov 2024 19:03:41 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1732557820; 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=jUK9sXYG2Tov73+9qZh4YCkNQdSEkQzhRE3IzSrtoFk=; b=ENO9UKM/KiqDF1emRZUAs9KC8O0y4tLVNCNeSgKr4b5RemGTwyEJTChEzjaDP8N7HIOIW0 EYfD3stSg7DroJAmGw7QtQKIzBbPnQvzzjihW+twoiY1ix+EjbfR/bEtUpeBR8OmtnlJiO gsAsvJNe/OCs561eD99aBKihyvE62do= 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-622-xHY9ohz9NcuDRZZzbayJ8g-1; Mon, 25 Nov 2024 13:03:37 -0500 X-MC-Unique: xHY9ohz9NcuDRZZzbayJ8g-1 X-Mimecast-MFC-AGG-ID: xHY9ohz9NcuDRZZzbayJ8g Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (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 898A81956048; Mon, 25 Nov 2024 18:03:36 +0000 (UTC) Received: from nuthatch.redhat.com (unknown [10.45.224.109]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id F36AB1944CC9; Mon, 25 Nov 2024 18:03:34 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Robert Mader Subject: [PATCH v2 7/9] libcamera: software_isp: Add an example CCM to uncalibrated.yaml Date: Mon, 25 Nov 2024 19:03:08 +0100 Message-ID: <20241125180310.1254519-8-mzamazal@redhat.com> In-Reply-To: <20241125180310.1254519-1-mzamazal@redhat.com> References: <20241125180310.1254519-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: lMesFs2I0kp4onN37kWZ3Kp0LKD0BHmPVyk2Hu-gizo_1732557816 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" For performance reasons, color correction matrix (CCM) is not applied by default in software ISP. But let's add a commented out example how to define it to the default tuning file. Signed-off-by: Milan Zamazal --- src/ipa/simple/data/uncalibrated.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ipa/simple/data/uncalibrated.yaml b/src/ipa/simple/data/uncalibrated.yaml index 3f1471121..8df3cd4ea 100644 --- a/src/ipa/simple/data/uncalibrated.yaml +++ b/src/ipa/simple/data/uncalibrated.yaml @@ -5,6 +5,13 @@ version: 1 algorithms: - BlackLevel: - Awb: + # Color correction matrices can be defined here: + # - Ccm: + # ccms: + # - ct: 6500 + # ccm: [ 1, 0, 0, + # 0, 1, 0, + # 0, 0, 1] - Lut: - Agc: ... From patchwork Mon Nov 25 18:03:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 22089 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 D0E9EBD160 for ; Mon, 25 Nov 2024 18:03:46 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8982465F74; Mon, 25 Nov 2024 19:03:46 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="amUSFl41"; 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 E7B8E6604A for ; Mon, 25 Nov 2024 19:03:43 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1732557823; 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=ZZX166gH/KMC6BrPwU8YOasZW6ngozEwlwhOYBHnPPw=; b=amUSFl41D7G1DYQLCg9naQti2NIgQnMyiifJH7jmdJW4w70tssjyqFyeubglLB7QMkDIQ5 d8WNKOIwSK6ghR5UCVq9kbtZrA+ytsVxUnoFoS6TNhqdBj1JyauuOq59V6ylwBu5F18lEL JFxSbCSpwR5Oi+uQKrt4o9TS1M/7KV8= 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-53-eZ65WHAWNrWsIxFFvxsFbw-1; Mon, 25 Nov 2024 13:03:39 -0500 X-MC-Unique: eZ65WHAWNrWsIxFFvxsFbw-1 X-Mimecast-MFC-AGG-ID: eZ65WHAWNrWsIxFFvxsFbw Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (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 97F1A1956077; Mon, 25 Nov 2024 18:03:38 +0000 (UTC) Received: from nuthatch.redhat.com (unknown [10.45.224.109]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 150531956086; Mon, 25 Nov 2024 18:03:36 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Robert Mader Subject: [PATCH v2 8/9] libcamera: software_isp: Track whether CCM is enabled Date: Mon, 25 Nov 2024 19:03:09 +0100 Message-ID: <20241125180310.1254519-9-mzamazal@redhat.com> In-Reply-To: <20241125180310.1254519-1-mzamazal@redhat.com> References: <20241125180310.1254519-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: U3-y4vN9IGhBUAh4DO82l2ecV2kR42zLZZB8GFkD-Mc_1732557818 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" Applying color correction matrix (CCM) in software ISP is optional due to performance reasons. CCM is applied if and only if `Ccm' algorithm is present in the tuning file and it defines some CCM. Software ISP debayering is a performance critical piece of code and we do not want to use dynamic conditionals there. Therefore we pass information about CCM application to debayering configuration and let it select the right versions of debayering functions using templates. This is a similar trick as the previously used one for adding or not adding an alpha channel to the output. Debayering gets this information but it ignores it in this patch. Actual processing with CCM is added in the followup patch. Signed-off-by: Milan Zamazal --- include/libcamera/ipa/soft.mojom | 2 +- src/ipa/simple/algorithms/ccm.cpp | 18 +++++------ src/ipa/simple/algorithms/ccm.h | 1 + src/ipa/simple/soft_simple.cpp | 8 +++-- src/libcamera/software_isp/debayer.h | 3 +- src/libcamera/software_isp/debayer_cpu.cpp | 35 ++++++++++++--------- src/libcamera/software_isp/debayer_cpu.h | 24 +++++++------- src/libcamera/software_isp/software_isp.cpp | 5 +-- 8 files changed, 54 insertions(+), 42 deletions(-) diff --git a/include/libcamera/ipa/soft.mojom b/include/libcamera/ipa/soft.mojom index a6c086f82..2ab67296d 100644 --- a/include/libcamera/ipa/soft.mojom +++ b/include/libcamera/ipa/soft.mojom @@ -21,7 +21,7 @@ interface IPASoftInterface { start() => (int32 ret); stop(); configure(IPAConfigInfo configInfo) - => (int32 ret); + => (int32 ret, bool ccmEnabled); [async] queueRequest(uint32 frame, libcamera.ControlList sensorControls); [async] computeParams(uint32 frame); diff --git a/src/ipa/simple/algorithms/ccm.cpp b/src/ipa/simple/algorithms/ccm.cpp index bd2c03fe4..5d56af588 100644 --- a/src/ipa/simple/algorithms/ccm.cpp +++ b/src/ipa/simple/algorithms/ccm.cpp @@ -25,26 +25,24 @@ unsigned int Ccm::kTemperatureThreshold = 100; int Ccm::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData) { int ret = ccm_.readYaml(tuningData["ccms"], "ct", "ccm"); - if (ret < 0) { + if (ret < 0) LOG(IPASoftCcm, Warning) << "Failed to parse 'ccm' " << "parameter from tuning file; falling back to unit matrix"; - ccmEnabled_ = false; - } else { - ccmEnabled_ = true; - } return 0; } +int Ccm::configure(IPAContext &context, + [[maybe_unused]] const IPAConfigInfo &configInfo) +{ + context.activeState.ccm.enabled = true; + return 0; +} + void Ccm::prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, [[maybe_unused]] DebayerParams *params) { - context.activeState.ccm.enabled = ccmEnabled_; - - if (!ccmEnabled_) - return; - unsigned int ct = context.activeState.awb.temperatureK; /* Change CCM only on bigger temperature changes. */ diff --git a/src/ipa/simple/algorithms/ccm.h b/src/ipa/simple/algorithms/ccm.h index 6b7efbe21..a7f6b6047 100644 --- a/src/ipa/simple/algorithms/ccm.h +++ b/src/ipa/simple/algorithms/ccm.h @@ -23,6 +23,7 @@ public: ~Ccm() = default; int init(IPAContext &context, const YamlObject &tuningData) override; + int configure(IPAContext &context, const IPAConfigInfo &configInfo) override; void prepare(IPAContext &context, const uint32_t frame, IPAFrameContext &frameContext, diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp index ac2a94210..0b51e8b5d 100644 --- a/src/ipa/simple/soft_simple.cpp +++ b/src/ipa/simple/soft_simple.cpp @@ -51,7 +51,7 @@ public: const SharedFD &fdStats, const SharedFD &fdParams, const ControlInfoMap &sensorInfoMap) override; - int configure(const IPAConfigInfo &configInfo) override; + int configure(const IPAConfigInfo &configInfo, bool *ccmEnabled) override; int start() override; void stop() override; @@ -177,7 +177,7 @@ int IPASoftSimple::init(const IPASettings &settings, return 0; } -int IPASoftSimple::configure(const IPAConfigInfo &configInfo) +int IPASoftSimple::configure(const IPAConfigInfo &configInfo, bool *ccmEnabled) { sensorInfoMap_ = configInfo.sensorControls; @@ -238,12 +238,16 @@ int IPASoftSimple::configure(const IPAConfigInfo &configInfo) context_.configuration.agc.againMinStep = 1.0; } + context_.activeState.ccm.enabled = false; + for (auto const &algo : algorithms()) { int ret = algo->configure(context_, configInfo); if (ret) return ret; } + *ccmEnabled = context_.activeState.ccm.enabled; + LOG(IPASoft, Info) << "Exposure " << context_.configuration.agc.exposureMin << "-" << context_.configuration.agc.exposureMax diff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h index d7ca060da..ba033d440 100644 --- a/src/libcamera/software_isp/debayer.h +++ b/src/libcamera/software_isp/debayer.h @@ -33,7 +33,8 @@ public: virtual ~Debayer() = 0; virtual int configure(const StreamConfiguration &inputCfg, - const std::vector> &outputCfgs) = 0; + const std::vector> &outputCfgs, + bool ccmEnabled) = 0; virtual std::vector formats(PixelFormat inputFormat) = 0; diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp index 7d080f00f..92f81baf2 100644 --- a/src/libcamera/software_isp/debayer_cpu.cpp +++ b/src/libcamera/software_isp/debayer_cpu.cpp @@ -113,7 +113,7 @@ DebayerCpu::~DebayerCpu() = default; (prev[x] + curr[x - p] + curr[x + n] + next[x]) / (4 * (div)), \ curr[x] / (div)) -template +template void DebayerCpu::debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) { DECLARE_SRC_POINTERS(uint8_t) @@ -124,7 +124,7 @@ void DebayerCpu::debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) } } -template +template void DebayerCpu::debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) { DECLARE_SRC_POINTERS(uint8_t) @@ -135,7 +135,7 @@ void DebayerCpu::debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) } } -template +template void DebayerCpu::debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) { DECLARE_SRC_POINTERS(uint16_t) @@ -147,7 +147,7 @@ void DebayerCpu::debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) } } -template +template void DebayerCpu::debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) { DECLARE_SRC_POINTERS(uint16_t) @@ -159,7 +159,7 @@ void DebayerCpu::debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) } } -template +template void DebayerCpu::debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) { DECLARE_SRC_POINTERS(uint16_t) @@ -171,7 +171,7 @@ void DebayerCpu::debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) } } -template +template void DebayerCpu::debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) { DECLARE_SRC_POINTERS(uint16_t) @@ -183,7 +183,7 @@ void DebayerCpu::debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) } } -template +template void DebayerCpu::debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) { const int widthInBytes = window_.width * 5 / 4; @@ -209,7 +209,7 @@ void DebayerCpu::debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) } } -template +template void DebayerCpu::debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) { const int widthInBytes = window_.width * 5 / 4; @@ -230,7 +230,7 @@ void DebayerCpu::debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) } } -template +template void DebayerCpu::debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[]) { const int widthInBytes = window_.width * 5 / 4; @@ -251,7 +251,7 @@ void DebayerCpu::debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[]) } } -template +template void DebayerCpu::debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[]) { const int widthInBytes = window_.width * 5 / 4; @@ -367,10 +367,11 @@ int DebayerCpu::setupStandardBayerOrder(BayerFormat::Order order) return 0; } -#define SET_DEBAYER_METHODS(method0, method1) \ - debayer0_ = addAlphaByte ? &DebayerCpu::method0 : &DebayerCpu::method0; \ - debayer1_ = addAlphaByte ? &DebayerCpu::method1 : &DebayerCpu::method1; +#define SET_DEBAYER_METHODS(method0, method1) \ + debayer0_ = addAlphaByte ? &DebayerCpu::method0 : &DebayerCpu::method0; \ + debayer1_ = addAlphaByte ? &DebayerCpu::method1 : &DebayerCpu::method1; +template int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat) { BayerFormat bayerFormat = @@ -463,7 +464,8 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputF } int DebayerCpu::configure(const StreamConfiguration &inputCfg, - const std::vector> &outputCfgs) + const std::vector> &outputCfgs, + bool ccmEnabled) { if (getInputConfig(inputCfg.pixelFormat, inputConfig_) != 0) return -EINVAL; @@ -502,7 +504,10 @@ int DebayerCpu::configure(const StreamConfiguration &inputCfg, return -EINVAL; } - if (setDebayerFunctions(inputCfg.pixelFormat, outputCfg.pixelFormat) != 0) + int ret = ccmEnabled + ? setDebayerFunctions(inputCfg.pixelFormat, outputCfg.pixelFormat) + : setDebayerFunctions(inputCfg.pixelFormat, outputCfg.pixelFormat); + if (ret != 0) return -EINVAL; window_.x = ((inputCfg.size.width - outputCfg.size.width) / 2) & diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h index 2c47e7c6e..b2ec8f1bd 100644 --- a/src/libcamera/software_isp/debayer_cpu.h +++ b/src/libcamera/software_isp/debayer_cpu.h @@ -31,7 +31,8 @@ public: ~DebayerCpu(); int configure(const StreamConfiguration &inputCfg, - const std::vector> &outputCfgs); + const std::vector> &outputCfgs, + bool ccmEnabled); Size patternSize(PixelFormat inputFormat); std::vector formats(PixelFormat input); std::tuple @@ -85,28 +86,28 @@ private: using debayerFn = void (DebayerCpu::*)(uint8_t *dst, const uint8_t *src[]); /* 8-bit raw bayer format */ - template + template void debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]); - template + template void debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]); /* unpacked 10-bit raw bayer format */ - template + template void debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]); - template + template void debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]); /* unpacked 12-bit raw bayer format */ - template + template void debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]); - template + template void debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]); /* CSI-2 packed 10-bit raw bayer format (all the 4 orders) */ - template + template void debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]); - template + template void debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]); - template + template void debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[]); - template + template void debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[]); struct DebayerInputConfig { @@ -125,6 +126,7 @@ private: int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config); int getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config); int setupStandardBayerOrder(BayerFormat::Order order); + template int setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat); void setupInputMemcpy(const uint8_t *linePointers[]); void shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src); diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index 2ccbeacc0..0e1d3a457 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -232,11 +232,12 @@ int SoftwareIsp::configure(const StreamConfiguration &inputCfg, { ASSERT(ipa_ && debayer_); - int ret = ipa_->configure(configInfo); + bool ccmEnabled; + int ret = ipa_->configure(configInfo, &ccmEnabled); if (ret < 0) return ret; - return debayer_->configure(inputCfg, outputCfgs); + return debayer_->configure(inputCfg, outputCfgs, ccmEnabled); } /** From patchwork Mon Nov 25 18:03:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 22090 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 CCFD8BD160 for ; Mon, 25 Nov 2024 18:03:49 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 85C3B6604A; Mon, 25 Nov 2024 19:03:49 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="XIyuCu4p"; 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 87F3466051 for ; Mon, 25 Nov 2024 19:03:45 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1732557824; 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=/L7ndDN9dpi5bM5dDHzLSiUSsLtx2dVlTb9f6z+ClZE=; b=XIyuCu4plGsoFcOMGot7H6haMs5DnOtbqsPkXczooXyjcTqPyUQpTA3IaeOFmLEALjjoty YZQrqvd6QauKybj8yPwt5an5gQZXgWPnulrqWiLkPZouzU9Wl+8jXXGqmbduMGegl5Pb68 /uwidEfJ5Z1gCYxY/ie0kie8q8njUDg= Received: from mx-prod-mc-02.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-581-TMBTDjWsMIOHkId97H8ntg-1; Mon, 25 Nov 2024 13:03:41 -0500 X-MC-Unique: TMBTDjWsMIOHkId97H8ntg-1 X-Mimecast-MFC-AGG-ID: TMBTDjWsMIOHkId97H8ntg Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (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-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 9F4B819541BE; Mon, 25 Nov 2024 18:03:40 +0000 (UTC) Received: from nuthatch.redhat.com (unknown [10.45.224.109]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 162FA1956086; Mon, 25 Nov 2024 18:03:38 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Robert Mader Subject: [PATCH v2 9/9] libcamera: software_isp: Apply CCM in debayering Date: Mon, 25 Nov 2024 19:03:10 +0100 Message-ID: <20241125180310.1254519-10-mzamazal@redhat.com> In-Reply-To: <20241125180310.1254519-1-mzamazal@redhat.com> References: <20241125180310.1254519-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: pgnRz8JOY1d-cV4J9xkj6YFmCq76Tb4H995GbQ9hfK8_1732557820 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" This patch applies color correction matrix (CCM) in debayering if the CCM is specified. Not using CCM must still be supported for performance reasons. The CCM is applied as follows: [r1 r2 r3] [r g b] * [g1 g2 g3] [b1 b2 b3] The CCM matrix (the right side of the multiplication) is constant during single frame processing, while the input pixel (the left side) changes. Because each of the color channels is only 8-bit in software ISP, we can make 9 lookup tables with 256 input values for multiplications of each of the r_i, g_i, b_i values. This way we don't have to multiply each pixel, we can use table lookups and additions instead. Gamma (which is non-linear and thus cannot be a part of the 9 lookup tables values) is applied on the final values rounded to integers using another lookup table. We use int16_t to store the precomputed multiplications. This seems to be noticeably (>10%) faster than `float' for the price of slightly less accuracy and it covers the range of values that sane CCMs produce. The selection and structure of data is performance critical, for example using bytes would add significant (>10%) speedup but would be too short to cover the value range. The color lookup tables are changed to unions to be able to serve as both simple lookup tables or CCM lookup tables. This is arguable but it keeps the code easier to understand if nothing else. It is important to make the unions on the whole lookup tables rather than their values because the latter might cause a noticeable slowdown on simple lookup due to the sheer fact that the table is not compact. Using unions makes the initialization of the tables dubious because it is done before the decision about using CCM is made but the initial values are dubious anyway. The tables are copied (as before), which is not elegant but also not a big problem. There are patches posted that use shared buffers for parameters passing in software ISP (see software ISP TODO #5) and they can be adjusted for the new parameter format. With this patch, the reported per-frame slowdown when applying CCM is about 45% on Debix Model A and about 75% on TI AM69 SK. Signed-off-by: Milan Zamazal --- .../internal/software_isp/debayer_params.h | 20 ++++++- src/ipa/simple/algorithms/lut.cpp | 58 ++++++++++++++----- src/ipa/simple/algorithms/lut.h | 1 + src/libcamera/software_isp/debayer.cpp | 53 ++++++++++++++++- src/libcamera/software_isp/debayer_cpu.cpp | 34 ++++++++--- src/libcamera/software_isp/debayer_cpu.h | 7 ++- src/libcamera/software_isp/software_isp.cpp | 6 +- 7 files changed, 145 insertions(+), 34 deletions(-) diff --git a/include/libcamera/internal/software_isp/debayer_params.h b/include/libcamera/internal/software_isp/debayer_params.h index 7d8fdd481..f8731eaee 100644 --- a/include/libcamera/internal/software_isp/debayer_params.h +++ b/include/libcamera/internal/software_isp/debayer_params.h @@ -18,11 +18,25 @@ namespace libcamera { struct DebayerParams { static constexpr unsigned int kRGBLookupSize = 256; + struct CcmColumn { + int16_t r; + int16_t g; + int16_t b; + }; + using ColorLookupTable = std::array; + using CcmLookupTable = std::array; + using GammaLookupTable = std::array; + + union LookupTable { + ColorLookupTable simple; + CcmLookupTable ccm; + }; - ColorLookupTable red; - ColorLookupTable green; - ColorLookupTable blue; + LookupTable red; + LookupTable green; + LookupTable blue; + GammaLookupTable gammaLut; }; } /* namespace libcamera */ diff --git a/src/ipa/simple/algorithms/lut.cpp b/src/ipa/simple/algorithms/lut.cpp index 8fca96b0a..1d9a607b2 100644 --- a/src/ipa/simple/algorithms/lut.cpp +++ b/src/ipa/simple/algorithms/lut.cpp @@ -44,6 +44,11 @@ void Lut::updateGammaTable(IPAContext &context) context.activeState.gamma.blackLevel = blackLevel; } +int16_t Lut::ccmValue(unsigned int i, float ccm) const +{ + return std::round(i * ccm); +} + void Lut::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame, [[maybe_unused]] IPAFrameContext &frameContext, @@ -55,27 +60,48 @@ void Lut::prepare(IPAContext &context, * observed, it's not permanently prone to minor fluctuations or * rounding errors. */ - if (context.activeState.gamma.blackLevel != context.activeState.blc.level) + const bool gammaUpdateNeeded = + context.activeState.gamma.blackLevel != context.activeState.blc.level; + if (gammaUpdateNeeded) updateGammaTable(context); auto &gains = context.activeState.awb.gains; auto &gammaTable = context.activeState.gamma.gammaTable; const unsigned int gammaTableSize = gammaTable.size(); - - for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) { - const double div = static_cast(DebayerParams::kRGBLookupSize) / - gammaTableSize; - /* Apply gamma after gain! */ - unsigned int idx; - idx = std::min({ static_cast(i * gains.red / div), - gammaTableSize - 1 }); - params->red[i] = gammaTable[idx]; - idx = std::min({ static_cast(i * gains.green / div), - gammaTableSize - 1 }); - params->green[i] = gammaTable[idx]; - idx = std::min({ static_cast(i * gains.blue / div), - gammaTableSize - 1 }); - params->blue[i] = gammaTable[idx]; + const double div = static_cast(DebayerParams::kRGBLookupSize) / + gammaTableSize; + + if (!context.activeState.ccm.enabled) { + for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) { + /* Apply gamma after gain! */ + unsigned int idx; + idx = std::min({ static_cast(i * gains.red / div), + gammaTableSize - 1 }); + params->red.simple[i] = gammaTable[idx]; + idx = std::min({ static_cast(i * gains.green / div), + gammaTableSize - 1 }); + params->green.simple[i] = gammaTable[idx]; + idx = std::min({ static_cast(i * gains.blue / div), + gammaTableSize - 1 }); + params->blue.simple[i] = gammaTable[idx]; + } + } else if (context.activeState.ccm.changed || gammaUpdateNeeded) { + auto &ccm = context.activeState.ccm.ccm; + auto &red = params->red.ccm; + auto &green = params->green.ccm; + auto &blue = params->blue.ccm; + for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) { + red[i].r = ccmValue(i, ccm[0][0]); + red[i].g = ccmValue(i, ccm[1][0]); + red[i].b = ccmValue(i, ccm[2][0]); + green[i].r = ccmValue(i, ccm[0][1]); + green[i].g = ccmValue(i, ccm[1][1]); + green[i].b = ccmValue(i, ccm[2][1]); + blue[i].r = ccmValue(i, ccm[0][2]); + blue[i].g = ccmValue(i, ccm[1][2]); + blue[i].b = ccmValue(i, ccm[2][2]); + params->gammaLut[i] = gammaTable[i / div]; + } } } diff --git a/src/ipa/simple/algorithms/lut.h b/src/ipa/simple/algorithms/lut.h index b635987d0..8d50a23fc 100644 --- a/src/ipa/simple/algorithms/lut.h +++ b/src/ipa/simple/algorithms/lut.h @@ -27,6 +27,7 @@ public: private: void updateGammaTable(IPAContext &context); + int16_t ccmValue(unsigned int i, float ccm) const; }; } /* namespace ipa::soft::algorithms */ diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp index f0b832619..47f9996bb 100644 --- a/src/libcamera/software_isp/debayer.cpp +++ b/src/libcamera/software_isp/debayer.cpp @@ -23,11 +23,56 @@ namespace libcamera { * \brief Size of a color lookup table */ +/** + * \struct DebayerParams::CcmColumn + * \brief Type of a single column of a color correction matrix + */ + +/** + * \var DebayerParams::CcmColumn::r + * \brief Red (first) component of a CCM column + */ + +/** + * \var DebayerParams::CcmColumn::g + * \brief Green (second) component of a CCM column + */ + +/** + * \var DebayerParams::CcmColumn::b + * \brief Blue (third) component of a CCM column + */ + /** * \typedef DebayerParams::ColorLookupTable + * \brief Type of the simple lookup tables for red, green, blue values + */ + +/** + * \typedef DebayerParams::CcmLookupTable + * \brief Type of the CCM lookup tables for red, green, blue values + */ + +/** + * \typedef DebayerParams::GammaLookupTable + * \brief Type of the gamma lookup tables for CCM + */ + +/** + * \union DebayerParams::LookupTable * \brief Type of the lookup tables for red, green, blue values */ +/** + * \var DebayerParams::LookupTable::simple + * \brief Simple lookup table for red, green, blue values + */ + +/** + * \var DebayerParams::LookupTable::ccm + * \brief CCM lookup table for red, green, blue values + */ + /** * \var DebayerParams::red * \brief Lookup table for red color, mapping input values to output values @@ -43,6 +88,11 @@ namespace libcamera { * \brief Lookup table for blue color, mapping input values to output values */ +/** + * \var DebayerParams::gammaLut + * \brief Gamma lookup table used with color correction matrix + */ + /** * \class Debayer * \brief Base debayering class @@ -57,10 +107,11 @@ Debayer::~Debayer() } /** - * \fn int Debayer::configure(const StreamConfiguration &inputCfg, const std::vector> &outputCfgs) + * \fn int Debayer::configure(const StreamConfiguration &inputCfg, const std::vector> &outputCfgs, ccmEnabled) * \brief Configure the debayer object according to the passed in parameters * \param[in] inputCfg The input configuration * \param[in] outputCfgs The output configurations + * \param[in] ccmEnabled Whether a color correction matrix is applied * * \return 0 on success, a negative errno on failure */ diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp index 92f81baf2..30bd1991c 100644 --- a/src/libcamera/software_isp/debayer_cpu.cpp +++ b/src/libcamera/software_isp/debayer_cpu.cpp @@ -11,6 +11,7 @@ #include "debayer_cpu.h" +#include #include #include #include @@ -50,8 +51,12 @@ DebayerCpu::DebayerCpu(std::unique_ptr stats) enableInputMemcpy_ = true; /* Initialize color lookup tables */ - for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) - red_[i] = green_[i] = blue_[i] = i; + for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) { + red_.simple[i] = green_.simple[i] = blue_.simple[i] = i; + red_.ccm[i].r = red_.ccm[i].g = red_.ccm[i].b = 0; + green_.ccm[i].r = green_.ccm[i].g = green_.ccm[i].b = 0; + blue_.ccm[i].r = blue_.ccm[i].g = blue_.ccm[i].b = 0; + } } DebayerCpu::~DebayerCpu() = default; @@ -61,12 +66,24 @@ DebayerCpu::~DebayerCpu() = default; const pixel_t *curr = (const pixel_t *)src[1] + xShift_; \ const pixel_t *next = (const pixel_t *)src[2] + xShift_; -#define STORE_PIXEL(b, g, r) \ - *dst++ = blue_[b]; \ - *dst++ = green_[g]; \ - *dst++ = red_[r]; \ - if constexpr (addAlphaByte) \ - *dst++ = 255; \ +#define GAMMA(value) \ + *dst++ = gammaLut_[std::clamp(value, 0, static_cast(gammaLut_.size()) - 1)] + +#define STORE_PIXEL(b_, g_, r_) \ + if constexpr (ccmEnabled) { \ + DebayerParams::CcmColumn &blue = blue_.ccm[b_]; \ + DebayerParams::CcmColumn &green = green_.ccm[g_]; \ + DebayerParams::CcmColumn &red = red_.ccm[r_]; \ + GAMMA(blue.r + blue.g + blue.b); \ + GAMMA(green.r + green.g + green.b); \ + GAMMA(red.r + red.g + red.b); \ + } else { \ + *dst++ = blue_.simple[b_]; \ + *dst++ = green_.simple[g_]; \ + *dst++ = red_.simple[r_]; \ + } \ + if constexpr (addAlphaByte) \ + *dst++ = 255; \ x++; /* @@ -764,6 +781,7 @@ void DebayerCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output green_ = params.green; red_ = swapRedBlueGains_ ? params.blue : params.red; blue_ = swapRedBlueGains_ ? params.red : params.blue; + gammaLut_ = params.gammaLut; /* Copy metadata from the input buffer */ FrameMetadata &metadata = output->_d()->metadata(); diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h index b2ec8f1bd..35c51e4fd 100644 --- a/src/libcamera/software_isp/debayer_cpu.h +++ b/src/libcamera/software_isp/debayer_cpu.h @@ -137,9 +137,10 @@ private: /* Max. supported Bayer pattern height is 4, debayering this requires 5 lines */ static constexpr unsigned int kMaxLineBuffers = 5; - DebayerParams::ColorLookupTable red_; - DebayerParams::ColorLookupTable green_; - DebayerParams::ColorLookupTable blue_; + DebayerParams::LookupTable red_; + DebayerParams::LookupTable green_; + DebayerParams::LookupTable blue_; + DebayerParams::GammaLookupTable gammaLut_; debayerFn debayer0_; debayerFn debayer1_; debayerFn debayer2_; diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index 0e1d3a457..08eca192e 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -79,9 +79,9 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor) for (unsigned int i = 0; i < 256; i++) gammaTable[i] = UINT8_MAX * std::pow(i / 256.0, 0.5); for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) { - debayerParams_.red[i] = gammaTable[i]; - debayerParams_.green[i] = gammaTable[i]; - debayerParams_.blue[i] = gammaTable[i]; + debayerParams_.red.simple[i] = gammaTable[i]; + debayerParams_.green.simple[i] = gammaTable[i]; + debayerParams_.blue.simple[i] = gammaTable[i]; } if (!dmaHeap_.isValid()) {