From patchwork Sat Jan 13 14:22:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 19391 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 3CCDCBEFBE for ; Sat, 13 Jan 2024 14:22:36 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id EAA3761D57; Sat, 13 Jan 2024 15:22:35 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1705155755; bh=ohjUIPZffS8k2fkeJ6xh+YuTvwgp5+VpBHdHod0X8Z0=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=VroKVk5uFGfN6TmaJ1/wkfcEW3i193RdOR2LYtb9vca1Lqx75B+XAcsVTHtok3ejt rrQTEiQChKEXRJ6d6virDL/jeDaEcv+94Efokp1T5nM+GCAowrgarSXi06E7eAiYQQ tnKCZED8pcA7ky/s89koUYlQKVwHBitWR+KODvQ89Ujs2kKBVJUB7lh0FZqru3iTzT UIu+Kj4XCKHKIF1HzvZeWtrLT1TOCJrC70cgZUW7ZJsrC0IaqgFMbMRGjeRShr8pZH EjAt+QfAl6IrKUqFemtw/rkLKo6JThShA2Hf0bGSxeH0NvMc5epqLczVQYf5OIfnxf qlLg86DnS4JnQ== 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 9049E61D57 for ; Sat, 13 Jan 2024 15:22:34 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="UkJFMPhn"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705155753; 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=MhV+7e5PwAfY//Qg+OcERhnWF5/MkXCggJzq1QGqDc4=; b=UkJFMPhnINJEbJCihUMJEgU5q6AHPHcXRKOsaXKjHbWh4AAQQj6N+nibEo0vg0siWdvygg 898h+TdlC/aWVRlOdb1kIokUW5ITY3VezVYGegdlx3mYxL38FiP0KmKO4jtML3QFZwLF+R fMTEIeNNYVghkPVzg52IrMvYWJzm088= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-59-efFDu9GxMzi1wI7Qls1YIg-1; Sat, 13 Jan 2024 09:22:29 -0500 X-MC-Unique: efFDu9GxMzi1wI7Qls1YIg-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id A1C8F38041FA; Sat, 13 Jan 2024 14:22:28 +0000 (UTC) Received: from localhost.localdomain (unknown [10.39.192.58]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8B5F63C25; Sat, 13 Jan 2024 14:22:26 +0000 (UTC) To: libcamera-devel@lists.libcamera.org, Andrey Konovalov Date: Sat, 13 Jan 2024 15:22:01 +0100 Message-ID: <20240113142218.28063-2-hdegoede@redhat.com> In-Reply-To: <20240113142218.28063-1-hdegoede@redhat.com> References: <20240113142218.28063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [libcamera-devel] [PATCH v2 01/18] libcamera: pipeline: simple: fix size adjustment in validate() 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: , X-Patchwork-Original-From: Hans de Goede via libcamera-devel From: Hans de Goede Reply-To: Hans de Goede Cc: Maxime Ripard , g.martti@gmail.com, t.langendam@gmail.com, srinivas.kandagatla@linaro.org, Pavel Machek , Bryan O'Donoghue , admin@dennisbonke.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Andrey Konovalov SimpleCameraConfiguration::validate() adjusts the configuration of its streams (if the size is not in the outputSizes) to the captureSize. But the captureSize itself can be not in the outputSizes, and then the adjusted configuration won't be valid resulting in camera configuration failure. Signed-off-by: Andrey Konovalov Signed-off-by: Hans de Goede Tested-by: Bryan O'Donoghue # sc8280xp Lenovo x13s Tested-by: Pavel Machek Reviewed-by: Milan Zamazal --- src/libcamera/pipeline/simple/simple.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 911051b2..4d0e7255 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -997,10 +997,13 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() } if (!pipeConfig_->outputSizes.contains(cfg.size)) { + Size adjustedSize = pipeConfig_->captureSize; + if (!pipeConfig_->outputSizes.contains(adjustedSize)) + adjustedSize = pipeConfig_->outputSizes.max; LOG(SimplePipeline, Debug) << "Adjusting size from " << cfg.size - << " to " << pipeConfig_->captureSize; - cfg.size = pipeConfig_->captureSize; + << " to " << adjustedSize; + cfg.size = adjustedSize; status = Adjusted; } From patchwork Sat Jan 13 14:22:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 19392 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 0A8BDC328C for ; Sat, 13 Jan 2024 14:22:38 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7F654628D7; Sat, 13 Jan 2024 15:22:38 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1705155758; bh=MVH5Mb9n40cAdYJ18kqmacYPT+Is2fHh40jlXj3asio=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=Ie15+HBzdooUvIuu+/IOndAqoU5o1LKqhvuUY+yBAR1a4hc6JnZwtW5TSyCvzGZRa nu8/Biiv1MlsGrHM95MY62m+f7x1ZqJrMOHAFSVrgCKt+WByAPFZ0kCXgBauBTaxex kiloMNCF2bPT8JdKnBAaW3xkodCVV1UpjstjqGbtt7Bq+L5bYjKU2bxsKfyHYMlZic NDk/SKIOaMDE5iUXVehC+3Tg0FCzYQb+zRkGDqrJgA6VZSG6qbfIXYsV40IgaTHuH7 r5H+tZzXBMsMlG6xr9yCzKg0c/fCCRfHbDZ4p20PrW2M5dn0rQZgAKrsQRQ4VJsbsN IFtP4p6XgXUuQ== 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 2796A628D7 for ; Sat, 13 Jan 2024 15:22:36 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="bAQImjdI"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705155755; 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=3Dph6tgUwIMymKaR6vzKDJ5GrjN1cKT7d9ocTwK0xS0=; b=bAQImjdIBhUqQeTh85FbuFCt2P9kUJL2bYBs8qKMsp2fxRnOE1AtjxU7L8FqUc3zjdjEXc 7Aofn+egu5KTd/JC87Io2JgvUjUjfpnH5J16pzHHyOdplrHUbjwCG7uUMC5xoHkCkyUHuW H5vttJkw81cGcg6RKAQhMFE3QSINjCA= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-460-WFeYtAlVNRGHzGX6uekerA-1; Sat, 13 Jan 2024 09:22:31 -0500 X-MC-Unique: WFeYtAlVNRGHzGX6uekerA-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id 094B5811E86; Sat, 13 Jan 2024 14:22:31 +0000 (UTC) Received: from localhost.localdomain (unknown [10.39.192.58]) by smtp.corp.redhat.com (Postfix) with ESMTP id EA0FB3C25; Sat, 13 Jan 2024 14:22:28 +0000 (UTC) To: libcamera-devel@lists.libcamera.org, Andrey Konovalov Date: Sat, 13 Jan 2024 15:22:02 +0100 Message-ID: <20240113142218.28063-3-hdegoede@redhat.com> In-Reply-To: <20240113142218.28063-1-hdegoede@redhat.com> References: <20240113142218.28063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [libcamera-devel] [PATCH v2 02/18] libcamera: internal: Move dma_heaps.[h, cpp] to common directories 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: , X-Patchwork-Original-From: Hans de Goede via libcamera-devel From: Hans de Goede Reply-To: Hans de Goede Cc: Maxime Ripard , g.martti@gmail.com, t.langendam@gmail.com, srinivas.kandagatla@linaro.org, Pavel Machek , Bryan O'Donoghue , admin@dennisbonke.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Andrey Konovalov DmaHeap class is useful outside the RPi pipeline handler too. Move dma_heaps.h and dma_heaps.cpp to common directories. Update the build files and RPi vc4 pipeline handler accordingly. Signed-off-by: Andrey Konovalov Signed-off-by: Hans de Goede Tested-by: Bryan O'Donoghue # sc8280xp Lenovo x13s Tested-by: Pavel Machek Reviewed-by: Kieran Bingham Reviewed-by: Naushir Patuck --- .../libcamera/internal}/dma_heaps.h | 4 ---- include/libcamera/internal/meson.build | 1 + .../{pipeline/rpi/vc4 => }/dma_heaps.cpp | 18 +++++++----------- src/libcamera/meson.build | 1 + src/libcamera/pipeline/rpi/vc4/meson.build | 1 - src/libcamera/pipeline/rpi/vc4/vc4.cpp | 5 ++--- 6 files changed, 11 insertions(+), 19 deletions(-) rename {src/libcamera/pipeline/rpi/vc4 => include/libcamera/internal}/dma_heaps.h (92%) rename src/libcamera/{pipeline/rpi/vc4 => }/dma_heaps.cpp (83%) diff --git a/src/libcamera/pipeline/rpi/vc4/dma_heaps.h b/include/libcamera/internal/dma_heaps.h similarity index 92% rename from src/libcamera/pipeline/rpi/vc4/dma_heaps.h rename to include/libcamera/internal/dma_heaps.h index 0a4a8d86..cff8f140 100644 --- a/src/libcamera/pipeline/rpi/vc4/dma_heaps.h +++ b/include/libcamera/internal/dma_heaps.h @@ -13,8 +13,6 @@ namespace libcamera { -namespace RPi { - class DmaHeap { public: @@ -27,6 +25,4 @@ private: UniqueFD dmaHeapHandle_; }; -} /* namespace RPi */ - } /* namespace libcamera */ diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build index 7f1f3440..33eb0fb3 100644 --- a/include/libcamera/internal/meson.build +++ b/include/libcamera/internal/meson.build @@ -25,6 +25,7 @@ libcamera_internal_headers = files([ 'device_enumerator.h', 'device_enumerator_sysfs.h', 'device_enumerator_udev.h', + 'dma_heaps.h', 'formats.h', 'framebuffer.h', 'ipa_manager.h', diff --git a/src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp b/src/libcamera/dma_heaps.cpp similarity index 83% rename from src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp rename to src/libcamera/dma_heaps.cpp index 317b1fc1..7444d9c2 100644 --- a/src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp +++ b/src/libcamera/dma_heaps.cpp @@ -5,8 +5,6 @@ * dma_heaps.h - Helper class for dma-heap allocations. */ -#include "dma_heaps.h" - #include #include #include @@ -16,6 +14,8 @@ #include +#include "libcamera/internal/dma_heaps.h" + /* * /dev/dma-heap/linux,cma is the dma-heap allocator, which allows dmaheap-cma * to only have to worry about importing. @@ -30,9 +30,7 @@ static constexpr std::array heapNames = { namespace libcamera { -LOG_DECLARE_CATEGORY(RPI) - -namespace RPi { +LOG_DEFINE_CATEGORY(DmaHeap) DmaHeap::DmaHeap() { @@ -40,7 +38,7 @@ DmaHeap::DmaHeap() int ret = ::open(name, O_RDWR | O_CLOEXEC, 0); if (ret < 0) { ret = errno; - LOG(RPI, Debug) << "Failed to open " << name << ": " + LOG(DmaHeap, Debug) << "Failed to open " << name << ": " << strerror(ret); continue; } @@ -50,7 +48,7 @@ DmaHeap::DmaHeap() } if (!dmaHeapHandle_.isValid()) - LOG(RPI, Error) << "Could not open any dmaHeap device"; + LOG(DmaHeap, Error) << "Could not open any dmaHeap device"; } DmaHeap::~DmaHeap() = default; @@ -69,7 +67,7 @@ UniqueFD DmaHeap::alloc(const char *name, std::size_t size) ret = ::ioctl(dmaHeapHandle_.get(), DMA_HEAP_IOCTL_ALLOC, &alloc); if (ret < 0) { - LOG(RPI, Error) << "dmaHeap allocation failure for " + LOG(DmaHeap, Error) << "dmaHeap allocation failure for " << name; return {}; } @@ -77,7 +75,7 @@ UniqueFD DmaHeap::alloc(const char *name, std::size_t size) UniqueFD allocFd(alloc.fd); ret = ::ioctl(allocFd.get(), DMA_BUF_SET_NAME, name); if (ret < 0) { - LOG(RPI, Error) << "dmaHeap naming failure for " + LOG(DmaHeap, Error) << "dmaHeap naming failure for " << name; return {}; } @@ -85,6 +83,4 @@ UniqueFD DmaHeap::alloc(const char *name, std::size_t size) return allocFd; } -} /* namespace RPi */ - } /* namespace libcamera */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 45f63e93..3c5e43df 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -17,6 +17,7 @@ libcamera_sources = files([ 'delayed_controls.cpp', 'device_enumerator.cpp', 'device_enumerator_sysfs.cpp', + 'dma_heaps.cpp', 'fence.cpp', 'formats.cpp', 'framebuffer.cpp', diff --git a/src/libcamera/pipeline/rpi/vc4/meson.build b/src/libcamera/pipeline/rpi/vc4/meson.build index cdb049c5..386e2296 100644 --- a/src/libcamera/pipeline/rpi/vc4/meson.build +++ b/src/libcamera/pipeline/rpi/vc4/meson.build @@ -1,7 +1,6 @@ # SPDX-License-Identifier: CC0-1.0 libcamera_sources += files([ - 'dma_heaps.cpp', 'vc4.cpp', ]) diff --git a/src/libcamera/pipeline/rpi/vc4/vc4.cpp b/src/libcamera/pipeline/rpi/vc4/vc4.cpp index 26102ea7..3a42e75e 100644 --- a/src/libcamera/pipeline/rpi/vc4/vc4.cpp +++ b/src/libcamera/pipeline/rpi/vc4/vc4.cpp @@ -12,12 +12,11 @@ #include #include "libcamera/internal/device_enumerator.h" +#include "libcamera/internal/dma_heaps.h" #include "../common/pipeline_base.h" #include "../common/rpi_stream.h" -#include "dma_heaps.h" - using namespace std::chrono_literals; namespace libcamera { @@ -87,7 +86,7 @@ public: RPi::Device isp_; /* DMAHEAP allocation helper. */ - RPi::DmaHeap dmaHeap_; + DmaHeap dmaHeap_; SharedFD lsTable_; struct Config { From patchwork Sat Jan 13 14:22:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 19395 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 65693C328C for ; Sat, 13 Jan 2024 14:22:45 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 17F72628B7; Sat, 13 Jan 2024 15:22:45 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1705155765; bh=qEK+s2Qrke44/RPeyE0f4TZVE7NY+YtoJdoGhkJlTu4=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=W5uCtlPTVuYEHPNJZi/Dsf7I4fz/OEZ9rm++tmpL2ylZqaB9jasaRp18oFy4OHvmd Irn3yGZBTK6jlHVHrGs14m8WWm2THzDS1LqhDXQbedTr2DGgucAixu528wUAKEstFn kPPxG4UJLnrXwiCSchdHC0SIxwXx1RIyhzzypfb2OUH6aAW21YahCrCbV4/V/I9VY1 Z13QfD18oK13JI67h5mx83TTT2Hi72oh68ycEo/jTEgqFIQNS1S1ubHChH+lYOawKX mjmEms1TU/qrwqJlXsjBLnnJLSfHsoeAECI0OQ4VAJx/yavsmsRpSuqr8z6gtOmoDc ERGHIbx9ZGLng== 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 1D127628B7 for ; Sat, 13 Jan 2024 15:22:42 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="S96MsB0u"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705155761; 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=ZJXgz4PaVpQMdyy9EXG54yJisYoI7RdmKq6n90BOzkk=; b=S96MsB0uaaWSgSTTB4sjCq5dL64HhrpxiQeSeo6VuE75ItGfCEVWytKXNrZuReudtILfKC LBkeUJE/GYvJ8h00Pzim03JKQ6+yzHSm2QZT3OJqnJhFg3K4Q2Eo/yeNXitHpuylo7tWrW Z94YrwRQH/BMtd2TPUI8m8mG5za40mg= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-640-QSHKST5RONi7KCRO2Ec7rw-1; Sat, 13 Jan 2024 09:22:34 -0500 X-MC-Unique: QSHKST5RONi7KCRO2Ec7rw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id 6714982A6C0; Sat, 13 Jan 2024 14:22:33 +0000 (UTC) Received: from localhost.localdomain (unknown [10.39.192.58]) by smtp.corp.redhat.com (Postfix) with ESMTP id 57D823C25; Sat, 13 Jan 2024 14:22:31 +0000 (UTC) To: libcamera-devel@lists.libcamera.org, Andrey Konovalov Date: Sat, 13 Jan 2024 15:22:03 +0100 Message-ID: <20240113142218.28063-4-hdegoede@redhat.com> In-Reply-To: <20240113142218.28063-1-hdegoede@redhat.com> References: <20240113142218.28063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [libcamera-devel] [PATCH v2 03/18] libcamera: dma_heaps: extend DmaHeap class to support system heap 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: , X-Patchwork-Original-From: Hans de Goede via libcamera-devel From: Hans de Goede Reply-To: Hans de Goede Cc: Maxime Ripard , g.martti@gmail.com, t.langendam@gmail.com, srinivas.kandagatla@linaro.org, Pavel Machek , Bryan O'Donoghue , admin@dennisbonke.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Andrey Konovalov Add an argument to the constructor to specify dma heaps type(s) to use. Can be DmaHeapFlag::Cma and/or DmaHeapFlag::System. By default DmaHeapFlag::Cma is used. If both DmaHeapFlag::Cma and DmaHeapFlag::System are set, CMA heap is tried first. Signed-off-by: Andrey Konovalov Signed-off-by: Hans de Goede Tested-by: Bryan O'Donoghue # sc8280xp Lenovo x13s Tested-by: Pavel Machek --- include/libcamera/internal/dma_heaps.h | 12 +++++++- src/libcamera/dma_heaps.cpp | 39 +++++++++++++++----------- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/include/libcamera/internal/dma_heaps.h b/include/libcamera/internal/dma_heaps.h index cff8f140..22aa1007 100644 --- a/include/libcamera/internal/dma_heaps.h +++ b/include/libcamera/internal/dma_heaps.h @@ -9,6 +9,7 @@ #include +#include #include namespace libcamera { @@ -16,7 +17,14 @@ namespace libcamera { class DmaHeap { public: - DmaHeap(); + enum class DmaHeapFlag { + Cma = (1 << 0), + System = (1 << 1), + }; + + using DmaHeapFlags = Flags; + + DmaHeap(DmaHeapFlags flags = DmaHeapFlag::Cma); ~DmaHeap(); bool isValid() const { return dmaHeapHandle_.isValid(); } UniqueFD alloc(const char *name, std::size_t size); @@ -25,4 +33,6 @@ private: UniqueFD dmaHeapHandle_; }; +LIBCAMERA_FLAGS_ENABLE_OPERATORS(DmaHeap::DmaHeapFlag) + } /* namespace libcamera */ diff --git a/src/libcamera/dma_heaps.cpp b/src/libcamera/dma_heaps.cpp index 7444d9c2..177de31b 100644 --- a/src/libcamera/dma_heaps.cpp +++ b/src/libcamera/dma_heaps.cpp @@ -16,6 +16,8 @@ #include "libcamera/internal/dma_heaps.h" +namespace libcamera { + /* * /dev/dma-heap/linux,cma is the dma-heap allocator, which allows dmaheap-cma * to only have to worry about importing. @@ -23,28 +25,33 @@ * Annoyingly, should the cma heap size be specified on the kernel command line * instead of DT, the heap gets named "reserved" instead. */ -static constexpr std::array heapNames = { - "/dev/dma_heap/linux,cma", - "/dev/dma_heap/reserved" +static constexpr std::array, 3> heapNames = { + /* CMA heap names first */ + std::make_pair(DmaHeap::DmaHeapFlag::Cma, "/dev/dma_heap/linux,cma"), + std::make_pair(DmaHeap::DmaHeapFlag::Cma, "/dev/dma_heap/reserved"), + std::make_pair(DmaHeap::DmaHeapFlag::System, "/dev/dma_heap/system") }; -namespace libcamera { - LOG_DEFINE_CATEGORY(DmaHeap) -DmaHeap::DmaHeap() +DmaHeap::DmaHeap(DmaHeapFlags flags) { - for (const char *name : heapNames) { - int ret = ::open(name, O_RDWR | O_CLOEXEC, 0); - if (ret < 0) { - ret = errno; - LOG(DmaHeap, Debug) << "Failed to open " << name << ": " - << strerror(ret); - continue; - } + int ret; - dmaHeapHandle_ = UniqueFD(ret); - break; + for (const auto &name : heapNames) { + if (flags & name.first) { + ret = ::open(name.second, O_RDWR | O_CLOEXEC, 0); + if (ret < 0) { + ret = errno; + LOG(DmaHeap, Debug) << "Failed to open " << name.second << ": " + << strerror(ret); + continue; + } + + LOG(DmaHeap, Debug) << "Using " << name.second; + dmaHeapHandle_ = UniqueFD(ret); + break; + } } if (!dmaHeapHandle_.isValid()) From patchwork Sat Jan 13 14:22:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 19393 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 BD49ABEFBE for ; Sat, 13 Jan 2024 14:22:41 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 05B22628FA; Sat, 13 Jan 2024 15:22:41 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1705155761; bh=G+Vwn3XmlanJ0/3vJS/pf3T0YDoZKDJwb7RWGmooNW4=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=QTFKo8ChpXgfU8L7/L+4M+2leAvMcNbmAGKrOea+OGKOS+e478cKylcbXpa+PXZZF BcU2w/uK0tu2M97D01xtZR8RQB+537VvMZDCcCEgkJlLVhF7RO4bTcsfM5TX7H/uh7 qqTUHF9tsLGd06K0OpXPmWYra9FpsKxgIPXV8AywZL+Y5sZ59u/VAJAi1/0RvVf8Rh fU1+3gNchByjQvVBqA8fw7RZIlvDlm7oqhknM6mYgZYPpNNm10h035I2qpW4DfX98s GT6MBIAxcrmjms+oyrv9q4I3fiA6R2dSCgbfsm+YpW7VQJpMXNWY6OKmvbuJInV1SR 3XA9RZm+y4C8Q== 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 49B54627E7 for ; Sat, 13 Jan 2024 15:22:39 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="I66x1qdc"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705155758; 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=QH+TnvEI1+Kly+mWxq7D447tIgaJDmwwdseg93/lWeI=; b=I66x1qdcCPu5iNSjU8LUULfpy/VGszGrBxEnBgOFaVtrtY2h/iAJXSQFSbR9D1kkeXRJ9H BBqh9XKfxIF/4u/G64g/0CPNAjab3rSkoutGy24KuoXe9wHtzVWE6qhe7YKOnD8ocb/K6G 9pvnAJHJY7z0BChgR74bNpj4gDGJuMU= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-461-XzCLk8cYP3-FMNr-63iqrQ-1; Sat, 13 Jan 2024 09:22:36 -0500 X-MC-Unique: XzCLk8cYP3-FMNr-63iqrQ-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id DE0721C0CCB8; Sat, 13 Jan 2024 14:22:35 +0000 (UTC) Received: from localhost.localdomain (unknown [10.39.192.58]) by smtp.corp.redhat.com (Postfix) with ESMTP id AF6783C25; Sat, 13 Jan 2024 14:22:33 +0000 (UTC) To: libcamera-devel@lists.libcamera.org, Andrey Konovalov Date: Sat, 13 Jan 2024 15:22:04 +0100 Message-ID: <20240113142218.28063-5-hdegoede@redhat.com> In-Reply-To: <20240113142218.28063-1-hdegoede@redhat.com> References: <20240113142218.28063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [libcamera-devel] [PATCH v2 04/18] libcamera: internal: Move SharedMemObject class to a common directory 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: , X-Patchwork-Original-From: Hans de Goede via libcamera-devel From: Hans de Goede Reply-To: Hans de Goede Cc: Maxime Ripard , g.martti@gmail.com, t.langendam@gmail.com, srinivas.kandagatla@linaro.org, Pavel Machek , Bryan O'Donoghue , admin@dennisbonke.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Andrey Konovalov Move SharedMemObject class out of RPi namespace and put it into include/libcamera/internal so that everyone could use it. Signed-off-by: Andrey Konovalov Signed-off-by: Hans de Goede Tested-by: Bryan O'Donoghue # sc8280xp Lenovo x13s Tested-by: Pavel Machek --- include/libcamera/internal/meson.build | 1 + .../common => include/libcamera/internal}/shared_mem_object.h | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) rename {src/libcamera/pipeline/rpi/common => include/libcamera/internal}/shared_mem_object.h (98%) diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build index 33eb0fb3..5807dfd9 100644 --- a/include/libcamera/internal/meson.build +++ b/include/libcamera/internal/meson.build @@ -39,6 +39,7 @@ libcamera_internal_headers = files([ 'process.h', 'pub_key.h', 'request.h', + 'shared_mem_object.h', 'source_paths.h', 'sysfs.h', 'v4l2_device.h', diff --git a/src/libcamera/pipeline/rpi/common/shared_mem_object.h b/include/libcamera/internal/shared_mem_object.h similarity index 98% rename from src/libcamera/pipeline/rpi/common/shared_mem_object.h rename to include/libcamera/internal/shared_mem_object.h index aa56c220..bfb639ee 100644 --- a/src/libcamera/pipeline/rpi/common/shared_mem_object.h +++ b/include/libcamera/internal/shared_mem_object.h @@ -19,8 +19,6 @@ namespace libcamera { -namespace RPi { - template class SharedMemObject { @@ -123,6 +121,4 @@ private: T *obj_; }; -} /* namespace RPi */ - } /* namespace libcamera */ From patchwork Sat Jan 13 14:22:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 19394 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 2074DC32BC for ; Sat, 13 Jan 2024 14:22:45 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 927A5628BF; Sat, 13 Jan 2024 15:22:44 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1705155764; bh=fBzL2s5oxRsGrkzd2/fc8S9Z2CN3n1c7m6lC/Zmfzww=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=P1xx3LySYzNOFBkw65caZTCb4gNCqs7y1IG0u5OGNIXd3q0D+YZ37uz7z6hgDSfoG 1pZthS7ohRZMlL9dtWo3oVaM+XUrUE7AAVwNz8F5K1Y2vPSxeYr0EL2fEpxFjo6RC8 xpI2B5t+fxH0+nFPyje1cFngEqfu3/Z5+laTdKLUrjWDuQ5kyFUBZep8I+swnIF92b BxLCi/wJfbchZKwwSuQXAGpLcbVo+TI21KIaqkzQBZx2uCTfiUmDeVQ5is9/as3Y/p FJkkKMvmL0DZiQBvxiFlO9M1GomhQVdnc2FfiZsX/RRTHX6PAC6wUmGrPUNwuYsi17 5hnthXK8XuVCw== 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 05FD0628B1 for ; Sat, 13 Jan 2024 15:22:41 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="DJObr7HE"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705155760; 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=H1oIVgkw6WX1+fpLPBZklA9UQJyKLouaD0z3IEBI+IY=; b=DJObr7HE0I4kK5KPZeXGsmKVhogf965Adv5z+tuh4wUbr29viWORR9S+Q2QXZIfV7FBtxl pJqIvnJ2XlUS56F3PbixhRu7o5fVn1iOyzH2oSStGAYKXRGOxUSl6aOPdFgvYQtGd0uJsw 6npSForzMak9A8w4fkfr++Se6l/taac= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-601-594lwOrdMayC1xqNKFoBUg-1; Sat, 13 Jan 2024 09:22:38 -0500 X-MC-Unique: 594lwOrdMayC1xqNKFoBUg-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id 1306D85A588; Sat, 13 Jan 2024 14:22:38 +0000 (UTC) Received: from localhost.localdomain (unknown [10.39.192.58]) by smtp.corp.redhat.com (Postfix) with ESMTP id 27DE13C25; Sat, 13 Jan 2024 14:22:36 +0000 (UTC) To: libcamera-devel@lists.libcamera.org, Andrey Konovalov Date: Sat, 13 Jan 2024 15:22:05 +0100 Message-ID: <20240113142218.28063-6-hdegoede@redhat.com> In-Reply-To: <20240113142218.28063-1-hdegoede@redhat.com> References: <20240113142218.28063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [libcamera-devel] [PATCH v2 05/18] libcamera: internal: Document the SharedMemObject class 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: , X-Patchwork-Original-From: Hans de Goede via libcamera-devel From: Hans de Goede Reply-To: Hans de Goede Cc: Maxime Ripard , g.martti@gmail.com, t.langendam@gmail.com, srinivas.kandagatla@linaro.org, Pavel Machek , Bryan O'Donoghue , admin@dennisbonke.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Dennis Bonke Document the SharedMemObject class. Signed-off-by: Dennis Bonke Signed-off-by: Hans de Goede Tested-by: Bryan O'Donoghue # sc8280xp Lenovo x13s Tested-by: Pavel Machek Reviewed-by: Kieran Bingham --- .../libcamera/internal/shared_mem_object.h | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/include/libcamera/internal/shared_mem_object.h b/include/libcamera/internal/shared_mem_object.h index bfb639ee..e862ce48 100644 --- a/include/libcamera/internal/shared_mem_object.h +++ b/include/libcamera/internal/shared_mem_object.h @@ -19,10 +19,20 @@ namespace libcamera { +/** + * \class SharedMemObject + * \brief Helper class for shared memory allocations. + * + * Takes a template T which is used to indicate the + * data type of the object stored. + */ template class SharedMemObject { public: + /** + * \brief The size of the object that is going to be stored here. + */ static constexpr std::size_t SIZE = sizeof(T); SharedMemObject() @@ -30,6 +40,11 @@ public: { } + /** + * \brief Contstructor for the SharedMemObject. + * \param[in] name The requested name. + * \param[in] args Any additional args. + */ template SharedMemObject(const std::string &name, Args &&...args) : name_(name), obj_(nullptr) @@ -57,6 +72,10 @@ public: obj_ = new (mem) T(std::forward(args)...); } + /** + * \brief Move constructor for SharedMemObject. + * \param[in] rhs The object to move. + */ SharedMemObject(SharedMemObject &&rhs) { this->name_ = std::move(rhs.name_); @@ -76,6 +95,10 @@ public: /* Make SharedMemObject non-copyable for now. */ LIBCAMERA_DISABLE_COPY(SharedMemObject) + /** + * \brief Operator= for SharedMemObject. + * \param[in] rhs The SharedMemObject object to take the data from. + */ SharedMemObject &operator=(SharedMemObject &&rhs) { this->name_ = std::move(rhs.name_); @@ -85,31 +108,61 @@ public: return *this; } + /** + * \brief Operator-> for SharedMemObject. + * + * \return the object. + */ T *operator->() { return obj_; } + /** + * \brief Operator-> for SharedMemObject. + * + * \return the object. + */ const T *operator->() const { return obj_; } + /** + * \brief Operator* for SharedMemObject. + * + * \return the object. + */ T &operator*() { return *obj_; } + /** + * \brief Operator* for SharedMemObject. + * + * \return the object. + */ const T &operator*() const { return *obj_; } + /** + * \brief Gets the file descriptor for the underlaying storage file. + * + * \return the file descriptor. + */ const SharedFD &fd() const { return fd_; } + /** + * \brief Operator bool() for SharedMemObject. + * + * \return true if the object is not null, false otherwise. + */ explicit operator bool() const { return !!obj_; From patchwork Sat Jan 13 14:22:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 19396 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 0FADEBEFBE for ; Sat, 13 Jan 2024 14:22:49 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A230862916; Sat, 13 Jan 2024 15:22:48 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1705155768; bh=XVWTF2bafeSJX8cYS3jYzTVWSXfazy4QST85a1l8y2c=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=CZxbIw80EG0GdACQxdf842zWipJ+hUT/7RtCtBHQXxjSVEoPZcxx20VUptRqLSk9U aeOThVqa1S5aDR2q3YM06zdqPjNecW58sGuQN6u/kpL6+KnHGjZ6gAxtc2uCkNLcd2 xSFcGSNsfcHbM2KUH3JwYMhqBXRdysCXaSD24JoNcov7YozYyzKgGLep4Tq34K/5X2 PX6rNy2s2xeqD6BxNI0g+qbXskoy6quGM/yTih1JwN62c4U2EWWF4oAHFSb7fw7met 27ufzshapmp7sdSWe6RbS6dV9eFO7fklZitGN+s2Duh+P/aH8MdLu0RxT/NK/ZtyZG tTSxxu7sRc6Eg== 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 208C6628B7 for ; Sat, 13 Jan 2024 15:22:47 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="VFdnqJ5w"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705155766; 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=bojsjgIBeZItXfqcOq45Tyix7akDejRV5UNJPVRdwiA=; b=VFdnqJ5wl7ni95zpeuSRZNIdKiX+5IB4VO46PguZ8D1ii9cxzdOLrnMS7K9tiH80jPr4RV fYPZ8TpG+ChmHwhuScRYjlK0tYvMlUJf2HjOQpV4I1f38s3vfrgbB9lDxn2ZgonAotniG+ O9HHfdsgte6C/U7cpMz3AMGLjIu+sRI= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-48-7SqzoaRpN-m28jq56Qcz2Q-1; Sat, 13 Jan 2024 09:22:40 -0500 X-MC-Unique: 7SqzoaRpN-m28jq56Qcz2Q-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id 65436185A781; Sat, 13 Jan 2024 14:22:40 +0000 (UTC) Received: from localhost.localdomain (unknown [10.39.192.58]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5AF153C25; Sat, 13 Jan 2024 14:22:38 +0000 (UTC) To: libcamera-devel@lists.libcamera.org, Andrey Konovalov Date: Sat, 13 Jan 2024 15:22:06 +0100 Message-ID: <20240113142218.28063-7-hdegoede@redhat.com> In-Reply-To: <20240113142218.28063-1-hdegoede@redhat.com> References: <20240113142218.28063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [libcamera-devel] [PATCH v2 06/18] libcamera: introduce SoftwareIsp class 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: , X-Patchwork-Original-From: Hans de Goede via libcamera-devel From: Hans de Goede Reply-To: Hans de Goede Cc: Maxime Ripard , g.martti@gmail.com, t.langendam@gmail.com, srinivas.kandagatla@linaro.org, Pavel Machek , Bryan O'Donoghue , admin@dennisbonke.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Andrey Konovalov Doxygen documentation by Dennis Bonke. Co-authored-by: Dennis Bonke Signed-off-by: Dennis Bonke Signed-off-by: Andrey Konovalov Signed-off-by: Hans de Goede Tested-by: Bryan O'Donoghue # sc8280xp Lenovo x13s Tested-by: Pavel Machek --- include/libcamera/internal/meson.build | 1 + include/libcamera/internal/software_isp.h | 231 ++++++++++++++++++++++ src/libcamera/meson.build | 1 + src/libcamera/software_isp.cpp | 62 ++++++ 4 files changed, 295 insertions(+) create mode 100644 include/libcamera/internal/software_isp.h create mode 100644 src/libcamera/software_isp.cpp diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build index 5807dfd9..1325941d 100644 --- a/include/libcamera/internal/meson.build +++ b/include/libcamera/internal/meson.build @@ -40,6 +40,7 @@ libcamera_internal_headers = files([ 'pub_key.h', 'request.h', 'shared_mem_object.h', + 'software_isp.h', 'source_paths.h', 'sysfs.h', 'v4l2_device.h', diff --git a/include/libcamera/internal/software_isp.h b/include/libcamera/internal/software_isp.h new file mode 100644 index 00000000..42ff48ec --- /dev/null +++ b/include/libcamera/internal/software_isp.h @@ -0,0 +1,231 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Linaro Ltd + * + * software_isp.h - Interface for a software implementation of an ISP + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "libcamera/internal/pipeline_handler.h" + +namespace libcamera { + +class FrameBuffer; +class PixelFormat; +struct StreamConfiguration; + +LOG_DECLARE_CATEGORY(SoftwareIsp) + +/** + * \brief Base class for the Software ISP. + * + * Base class of the SoftwareIsp interface. + */ +class SoftwareIsp +{ +public: + /** + * \brief Constructor for the SoftwareIsp object. + * \param[in] pipe The pipeline handler in use. + * \param[in] sensorControls The sensor controls. + */ + SoftwareIsp(PipelineHandler *pipe, const ControlInfoMap &sensorControls); + virtual ~SoftwareIsp(); + + /** + * \brief Load a configuration from a file. + * \param[in] filename The file to load from. + * + * \return 0 on success. + */ + virtual int loadConfiguration(const std::string &filename) = 0; + + /** + * \brief Gets if there is a valid debayer object. + * + * \returns true if there is, false otherwise. + */ + virtual bool isValid() const = 0; + + /** + * \brief Get the supported output formats. + * \param[in] input The input format. + * + * \return all supported output formats or an empty vector if there are none. + */ + virtual std::vector formats(PixelFormat input) = 0; + + /** + * \brief Get the supported output sizes for the given input format and size. + * \param[in] inputFormat The input format. + * \param[in] inputSize The input size. + * + * \return The valid size ranges or an empty range if there are none. + */ + virtual SizeRange sizes(PixelFormat inputFormat, const Size &inputSize) = 0; + + /** + * \brief Get the stride and the frame size. + * \param[in] pixelFormat The output format. + * \param[in] size The output size. + * + * \return a tuple of the stride and the frame size, or a tuple with 0,0 if there is no valid output config. + */ + virtual std::tuple + strideAndFrameSize(const PixelFormat &pixelFormat, const Size &size) = 0; + + /** + * \brief Configure the SwIspSimple object according to the passed in parameters. + * \param[in] inputCfg The input configuration. + * \param[in] outputCfgs The output configurations. + * \param[in] sensorControls The sensor controls. + * + * \return 0 on success, a negative errno on failure. + */ + virtual int configure(const StreamConfiguration &inputCfg, + const std::vector> &outputCfgs, + const ControlInfoMap &sensorControls) = 0; + + /** + * \brief Exports the buffers for use in processing. + * \param[in] output The number of outputs requested. + * \param[in] count The number of planes. + * \param[out] buffers The exported buffers. + * + * \return count when successful, a negative return value if an error occurred. + */ + virtual int exportBuffers(unsigned int output, unsigned int count, + std::vector> *buffers) = 0; + + /** + * \brief Starts the Software ISP worker. + * + * \return 0 on success, any other value indicates an error. + */ + virtual int start() = 0; + + /** + * \brief Stops the Software ISP worker. + */ + virtual void stop() = 0; + + /** + * \brief Queues buffers for processing. + * \param[in] input The input framebuffer. + * \param[in] outputs The output framebuffers. + * + * \return 0 on success, a negative errno on failure + */ + virtual int queueBuffers(FrameBuffer *input, + const std::map &outputs) = 0; + + /** + * \brief Process the statistics gathered. + * \param[in] sensorControls The sensor controls. + */ + virtual void processStats(const ControlList &sensorControls) = 0; // rather merge with queueBuffers()? + + /** + * \brief Get the signal for when the sensor controls are set. + * + * \return The control list of the sensor controls. + */ + virtual Signal &getSignalSetSensorControls() = 0; + + /** + * \brief Signals that the input buffer is ready. + */ + Signal inputBufferReady; + /** + * \brief Signals that the output buffer is ready. + */ + Signal outputBufferReady; + + /** + * \brief Signals that the ISP stats are ready. + * + * The int parameter isn't actually used. + */ + Signal ispStatsReady; +}; + +/** + * \brief Base class for the Software ISP Factory. + * + * Base class of the SoftwareIsp Factory. + */ +class SoftwareIspFactoryBase +{ +public: + SoftwareIspFactoryBase(); + virtual ~SoftwareIspFactoryBase() = default; + + /** + * \brief Creates a SoftwareIsp object. + * \param[in] pipe The pipeline handler in use. + * \param[in] sensorControls The sensor controls. + * + * \return An unique pointer to the created SoftwareIsp object. + */ + static std::unique_ptr create(PipelineHandler *pipe, + const ControlInfoMap &sensorControls); + /** + * \brief Gives back a pointer to the factory. + * + * \return A static pointer to the factory instance. + */ + static SoftwareIspFactoryBase *&factory(); + +private: + LIBCAMERA_DISABLE_COPY_AND_MOVE(SoftwareIspFactoryBase) + + static void registerType(SoftwareIspFactoryBase *factory); + virtual std::unique_ptr createInstance(PipelineHandler *pipe, + const ControlInfoMap &sensorControls) const = 0; +}; + +/** + * \brief Implementation for the Software ISP Factory. + */ +template +class SoftwareIspFactory : public SoftwareIspFactoryBase +{ +public: + SoftwareIspFactory() + : SoftwareIspFactoryBase() + { + } + + /** + * \brief Creates an instance of a SoftwareIsp object. + * \param[in] pipe The pipeline handler in use. + * \param[in] sensorControls The sensor controls. + * + * \return An unique pointer to the created SoftwareIsp object. + */ + std::unique_ptr createInstance(PipelineHandler *pipe, + const ControlInfoMap &sensorControls) const override + { + return std::make_unique<_SoftwareIsp>(pipe, sensorControls); + } +}; + +#define REGISTER_SOFTWAREISP(softwareIsp) \ + static SoftwareIspFactory global_##softwareIsp##Factory; + +} /* namespace libcamera */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 3c5e43df..86494663 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -41,6 +41,7 @@ libcamera_sources = files([ 'process.cpp', 'pub_key.cpp', 'request.cpp', + 'software_isp.cpp', 'source_paths.cpp', 'stream.cpp', 'sysfs.cpp', diff --git a/src/libcamera/software_isp.cpp b/src/libcamera/software_isp.cpp new file mode 100644 index 00000000..2ff97d70 --- /dev/null +++ b/src/libcamera/software_isp.cpp @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Linaro Ltd + * + * software_isp.cpp - Interface for a software implementation of an ISP + */ + +#include "libcamera/internal/software_isp.h" + +#include + +namespace libcamera { + +LOG_DEFINE_CATEGORY(SoftwareIsp) + +SoftwareIsp::SoftwareIsp([[maybe_unused]] PipelineHandler *pipe, + [[maybe_unused]] const ControlInfoMap &sensorControls) +{ +} + +SoftwareIsp::~SoftwareIsp() +{ +} + +/* SoftwareIspFactoryBase */ + +SoftwareIspFactoryBase::SoftwareIspFactoryBase() +{ + registerType(this); +} + +void SoftwareIspFactoryBase::registerType(SoftwareIspFactoryBase *factory) +{ + SoftwareIspFactoryBase *®istered = + SoftwareIspFactoryBase::factory(); + + ASSERT(!registered && factory); + registered = factory; +} + +SoftwareIspFactoryBase *&SoftwareIspFactoryBase::factory() +{ + static SoftwareIspFactoryBase *factory; + return factory; +} + +std::unique_ptr +SoftwareIspFactoryBase::create(PipelineHandler *pipe, + const ControlInfoMap &sensorControls) +{ + SoftwareIspFactoryBase *factory = SoftwareIspFactoryBase::factory(); + if (!factory) + return nullptr; + + std::unique_ptr swIsp = factory->createInstance(pipe, sensorControls); + if (swIsp->isValid()) + return swIsp; + + return nullptr; +} + +} /* namespace libcamera */ From patchwork Sat Jan 13 14:22:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 19397 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 D97FCC32BD for ; Sat, 13 Jan 2024 14:22:49 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4A2DE628D7; Sat, 13 Jan 2024 15:22:49 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1705155769; bh=lObTuBQCrBYAxAFT0s3W3uHT3+9ndjnV+qHHBjDRaxk=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=e8cxydadbqf1+x1VOa57Xl1MUg+AITNxB8nAUMXECHtLwNdWg4byYCl8fEyy7/TuW Qq4bq/TdR+MbaNHDWbYJ2KLMPdSHoNqM+YA5d9ndxVjQnXCxVuAmbn1lTnpWX2NiYg 76MAeAL2TV4JXyZzDveCGDSGFgeK8b5Dpp0SRNSnryynxUPWHVWWciss2Eb9k0EVF6 5VGAOauB1GbglY91TZMvywe8A8X4Ah1p1vlPegI2+sYPpeUe1+OaX2rA0lbSA4UhAs eRUqLhPbA+jLAiq3M2nwmgj6KmCY7pCO6TuWepJbdPfDsEQqQL4FRMU61kufvYF8wY GxprT2RcYi3Zw== 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 1179061D57 for ; Sat, 13 Jan 2024 15:22:47 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="hOTvaqai"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705155767; 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=1dVTJdC2XcSn2yOY5g3dW1cPZNI0Y/weZM4xp5bZgqw=; b=hOTvaqaiVDX7JdfTnmU3VUUjaBevSxUG2WUenezYda8ufIok9+XMsoKKLL06J6IneTdOWl TNBi5xR+ppspsKBWKeWKKSRQO5UnNT1NcD/uxzoDWTVigrTH88S5+idDHmob1FfmajV8Dv Ur9yjOAwYjuN1HKQ+3vNYhfq3x9noFs= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-339-EqBQ_aKLOjqAWpNOs7DCuQ-1; Sat, 13 Jan 2024 09:22:43 -0500 X-MC-Unique: EqBQ_aKLOjqAWpNOs7DCuQ-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id 04E2E1C0CCB8; Sat, 13 Jan 2024 14:22:43 +0000 (UTC) Received: from localhost.localdomain (unknown [10.39.192.58]) by smtp.corp.redhat.com (Postfix) with ESMTP id DA70F3C25; Sat, 13 Jan 2024 14:22:40 +0000 (UTC) To: libcamera-devel@lists.libcamera.org, Andrey Konovalov Date: Sat, 13 Jan 2024 15:22:07 +0100 Message-ID: <20240113142218.28063-8-hdegoede@redhat.com> In-Reply-To: <20240113142218.28063-1-hdegoede@redhat.com> References: <20240113142218.28063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [libcamera-devel] [PATCH v2 07/18] libcamera: software_isp: Add SwStats base class 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: , X-Patchwork-Original-From: Hans de Goede via libcamera-devel From: Hans de Goede Reply-To: Hans de Goede Cc: Maxime Ripard , g.martti@gmail.com, t.langendam@gmail.com, srinivas.kandagatla@linaro.org, Pavel Machek , Bryan O'Donoghue , admin@dennisbonke.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add a virtual base class for CPU based software statistics gathering implementations. The idea is for the implementations to offer a configure function + functions to gather statistics on a line by line basis. This allows CPU based software debayering to call into interlace debayering and statistics gathering on a line by line bases while the input data is still hot in the cache. This base class also allows the user of an implementation to specify a window over which to gather statistics instead of processing the whole frame; and it allows the implementation to choose to only process 1/2, 1/4th, etc. of the lines instead of processing all lines (in the window) by setting y_skip_mask_ from configure(). Skipping columns is left up the line-processing functions provided by the implementation. Doxygen documentation by Dennis Bonke. Co-authored-by: Dennis Bonke Signed-off-by: Dennis Bonke Co-authored-by: Andrey Konovalov Signed-off-by: Andrey Konovalov Signed-off-by: Hans de Goede Tested-by: Bryan O'Donoghue # sc8280xp Lenovo x13s Tested-by: Pavel Machek --- include/libcamera/internal/meson.build | 1 + .../internal/software_isp/meson.build | 6 + .../internal/software_isp/swisp_stats.h | 34 +++ .../libcamera/internal/software_isp/swstats.h | 215 ++++++++++++++++++ src/libcamera/meson.build | 1 + src/libcamera/software_isp/meson.build | 5 + src/libcamera/software_isp/swstats.cpp | 22 ++ 7 files changed, 284 insertions(+) create mode 100644 include/libcamera/internal/software_isp/meson.build create mode 100644 include/libcamera/internal/software_isp/swisp_stats.h create mode 100644 include/libcamera/internal/software_isp/swstats.h create mode 100644 src/libcamera/software_isp/meson.build create mode 100644 src/libcamera/software_isp/swstats.cpp diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build index 1325941d..caa533c4 100644 --- a/include/libcamera/internal/meson.build +++ b/include/libcamera/internal/meson.build @@ -51,3 +51,4 @@ libcamera_internal_headers = files([ ]) subdir('converter') +subdir('software_isp') diff --git a/include/libcamera/internal/software_isp/meson.build b/include/libcamera/internal/software_isp/meson.build new file mode 100644 index 00000000..1c43acc4 --- /dev/null +++ b/include/libcamera/internal/software_isp/meson.build @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: CC0-1.0 + +libcamera_internal_headers += files([ + 'swisp_stats.h', + 'swstats.h', +]) diff --git a/include/libcamera/internal/software_isp/swisp_stats.h b/include/libcamera/internal/software_isp/swisp_stats.h new file mode 100644 index 00000000..07ba7d6a --- /dev/null +++ b/include/libcamera/internal/software_isp/swisp_stats.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Linaro Ltd + * + * swisp_stats.h - Statistics data format used by the software ISP and software IPA + */ + +#pragma once + +namespace libcamera { + +/** + * \brief Struct that holds the statistics for the Software ISP. + */ +struct SwIspStats { + /** + * \brief Holds the sum of all sampled red pixels. + */ + unsigned long sumR_; + /** + * \brief Holds the sum of all sampled green pixels. + */ + unsigned long sumG_; + /** + * \brief Holds the sum of all sampled blue pixels. + */ + unsigned long sumB_; + /** + * \brief A histogram of luminance values. + */ + unsigned int y_histogram[16]; +}; + +} /* namespace libcamera */ diff --git a/include/libcamera/internal/software_isp/swstats.h b/include/libcamera/internal/software_isp/swstats.h new file mode 100644 index 00000000..dcac7064 --- /dev/null +++ b/include/libcamera/internal/software_isp/swstats.h @@ -0,0 +1,215 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Linaro Ltd + * Copyright (C) 2023, Red Hat Inc. + * + * Authors: + * Hans de Goede + * + * swstats.h - software statistics base class + */ + +#pragma once + +#include + +#include +#include + +#include + +namespace libcamera { + +class PixelFormat; +struct SharedFD; +struct StreamConfiguration; + +LOG_DECLARE_CATEGORY(SwStats) + +/** + * \class SwStats + * \brief Base class for the software ISP statistics. + * + * Base class for the software ISP statistics. + */ +class SwStats +{ +public: + virtual ~SwStats() = 0; + + /** + * \brief Gets wether the statistics object is valid. + * + * \return true if it's valid, false otherwise. + */ + virtual bool isValid() const = 0; + + /** + * \brief Configure the statistics object for the passed in input format. + * \param[in] inputCfg The input format + * + * \return 0 on success, a negative errno value on failure. + */ + virtual int configure(const StreamConfiguration &inputCfg) = 0; + + /** + * \brief Get the file descriptor for the statistics. + * + * \return the file descriptor + */ + virtual const SharedFD &getStatsFD() = 0; + +protected: + /** + * \brief Called when there is data to get statistics from. + * \param[in] src The input data + */ + typedef void (SwStats::*statsProcessFn)(const uint8_t *src[]); + /** + * \brief Called when the statistics gathering is done or when a new frame starts. + */ + typedef void (SwStats::*statsVoidFn)(); + + /* Variables set by configure(), used every line */ + /** + * \brief The function called when a line is ready for statistics processing. + * + * Used for line 0 and 1, repeating if there isn't a 3rd and a 4th line in the bayer order. + */ + statsProcessFn stats0_; + /** + * \brief The function called when a line is ready for statistics processing. + * + * Used for line 3 and 4, only needed if the bayer order has 4 different lines. + */ + statsProcessFn stats2_; + + /** + * \brief The memory used per pixel in bits. + */ + unsigned int bpp_; + /** + * \brief Skip lines where this bitmask is set in y. + */ + unsigned int y_skip_mask_; + + /** + * \brief Statistics window, set by setWindow(), used ever line. + */ + Rectangle window_; + + /** + * \brief The function called at the start of a frame. + */ + statsVoidFn startFrame_; + /** + * \brief The function called at the end of a frame. + */ + statsVoidFn finishFrame_; + /** + * \brief The size of the bayer pattern. + */ + Size patternSize_; + /** + * \brief The offset of x, applied to window_.x for bayer variants. + * + * This can either be 0 or 1. + */ + unsigned int x_shift_; + +public: + /** + * \brief Get the pattern size. + * + * For some input-formats, e.g. Bayer data, processing is done multiple lines + * and/or columns at a time. Get width and height at which the (bayer) pattern + * repeats. Window values are rounded down to a multiple of this and the height + * also indicates if processLine2() should be called or not. + * This may only be called after a successful configure() call. + * + * \return the pattern size. + */ + const Size &patternSize() { return patternSize_; } + + /** + * \brief Specify window coordinates over which to gather statistics. + * \param[in] window The window object. + */ + void setWindow(Rectangle window) + { + window_ = window; + + window_.x &= ~(patternSize_.width - 1); + window_.x += x_shift_; + window_.y &= ~(patternSize_.height - 1); + + /* width_ - x_shift_ to make sure the window fits */ + window_.width -= x_shift_; + window_.width &= ~(patternSize_.width - 1); + window_.height &= ~(patternSize_.height - 1); + } + + /** + * \brief Reset state to start statistics gathering for a new frame. + * + * This may only be called after a successful setWindow() call. + */ + void startFrame() + { + (this->*startFrame_)(); + } + + /** + * \brief Process line 0. + * \param[in] y The y coordinate. + * \param[in] src The input data. + * + * This function processes line 0 for input formats with patternSize height == 1. + * It'll process line 0 and 1 for input formats with patternSize height >= 2. + * This function may only be called after a successful setWindow() call. + */ + void processLine0(unsigned int y, const uint8_t *src[]) + { + if ((y & y_skip_mask_) || y < (unsigned int)window_.y || + y >= (window_.y + window_.height)) + return; + + (this->*stats0_)(src); + } + + /** + * \brief Process line 2 and 3. + * \param[in] y The y coordinate. + * \param[in] src The input data. + * + * This function processes line 2 and 3 for input formats with patternSize height == 4. + * This function may only be called after a successful setWindow() call. + */ + void processLine2(unsigned int y, const uint8_t *src[]) + { + if ((y & y_skip_mask_) || y < (unsigned int)window_.y || + y >= (window_.y + window_.height)) + return; + + (this->*stats2_)(src); + } + + /** + * \brief Finish statistics calculation for the current frame. + * + * This may only be called after a successful setWindow() call. + */ + void finishFrame() + { + (this->*finishFrame_)(); + } + + /** + * \brief Signals that the statistics are ready. + * + * The int parameter isn't actually used. + */ + Signal statsReady; +}; + +} /* namespace libcamera */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 86494663..3d63e8a2 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -71,6 +71,7 @@ subdir('converter') subdir('ipa') subdir('pipeline') subdir('proxy') +subdir('software_isp') null_dep = dependency('', required : false) diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build new file mode 100644 index 00000000..9359075d --- /dev/null +++ b/src/libcamera/software_isp/meson.build @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: CC0-1.0 + +libcamera_sources += files([ + 'swstats.cpp', +]) diff --git a/src/libcamera/software_isp/swstats.cpp b/src/libcamera/software_isp/swstats.cpp new file mode 100644 index 00000000..e65a7ada --- /dev/null +++ b/src/libcamera/software_isp/swstats.cpp @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Linaro Ltd + * Copyright (C) 2023, Red Hat Inc. + * + * Authors: + * Hans de Goede + * + * swstats.cpp - software statistics base class + */ + +#include "libcamera/internal/software_isp/swstats.h" + +namespace libcamera { + +LOG_DEFINE_CATEGORY(SwStats) + +SwStats::~SwStats() +{ +} + +} /* namespace libcamera */ From patchwork Sat Jan 13 14:22:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 19398 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 5D664C32BC for ; Sat, 13 Jan 2024 14:22:54 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C0FA2628B7; Sat, 13 Jan 2024 15:22:53 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1705155773; bh=eFI/fdQvCKtqt5YP3BJh4G6bo9P8bDRFhACvmRW8uO0=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=xZ+3KrWF3ByvvBw9LP9J8i3uhvYcJJL97QIDAqfuSDm04N9MCX1BmZub7oqtHAdjh gkj8W/AGl5nsMmb0vah93xPAQu0OBO0zfqia9PgeXguTUCrM52MyQUlZ+gRzpDWxl1 OFWkuoohL9J3VK4hFzQ8drEqLFb78fCkIBxDDHew6oltTrIscy5gtuTRXYQ1dYSiKA fixJrO0fCm0rxI7DS3OupGJ+Ytq4A9wRzEwocqpMkefZfCQThyaAbz3P/JFM5/2lA5 yM/hJ8kGFaQnKIcrAv2ODQr+5BLTjZM+F83unPdyoVULH4JZ1YtbhSAyHPY9bf7ahX BFAvs54J69CNA== 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 79F90628B7 for ; Sat, 13 Jan 2024 15:22:51 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="KXuctxWs"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705155770; 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=iHh0+quNqZweKageHVF3MNHrPbdzsoknlC/B33SLw6s=; b=KXuctxWsYbVtYUfOR4ontnXzGhwW4u+DEqWpSprcs12EdXzeQkSn9vEN92vyYWro1b842x PaUrCcZJAi/P4FvX4HrWhrvQJXsPNmj/Baio6Nv09YXNzIDmUnRlG1SdgGktD8ZGQjpVuL sMncH4YfnDz38yih4VHLpAztgrFTJ58= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-190-dHIwm4UUOnWbkEGIAVSmKA-1; Sat, 13 Jan 2024 09:22:47 -0500 X-MC-Unique: dHIwm4UUOnWbkEGIAVSmKA-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id 871DB3C11C8E; Sat, 13 Jan 2024 14:22:46 +0000 (UTC) Received: from localhost.localdomain (unknown [10.39.192.58]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4DCC13C25; Sat, 13 Jan 2024 14:22:43 +0000 (UTC) To: libcamera-devel@lists.libcamera.org, Andrey Konovalov Date: Sat, 13 Jan 2024 15:22:08 +0100 Message-ID: <20240113142218.28063-9-hdegoede@redhat.com> In-Reply-To: <20240113142218.28063-1-hdegoede@redhat.com> References: <20240113142218.28063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [libcamera-devel] [PATCH v2 08/18] libcamera: software_isp: Add SwStatsCpu class 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: , X-Patchwork-Original-From: Hans de Goede via libcamera-devel From: Hans de Goede Reply-To: Hans de Goede Cc: Maxime Ripard , g.martti@gmail.com, t.langendam@gmail.com, srinivas.kandagatla@linaro.org, Pavel Machek , Bryan O'Donoghue , admin@dennisbonke.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add a CPU based SwStats implementation for SoftwareISP / SoftIPA use. Co-authored-by: Andrey Konovalov Signed-off-by: Andrey Konovalov Co-authored-by: Pavel Machek Signed-off-by: Pavel Machek Co-authored-by: Dennis Bonke Signed-off-by: Dennis Bonke Co-authored-by: Marttico Signed-off-by: Marttico Co-authored-by: Toon Langendam Signed-off-by: Toon Langendam Signed-off-by: Hans de Goede Tested-by: Bryan O'Donoghue # sc8280xp Lenovo x13s Tested-by: Pavel Machek --- .../internal/software_isp/meson.build | 1 + .../internal/software_isp/swstats_cpu.h | 44 +++++ src/libcamera/software_isp/meson.build | 1 + src/libcamera/software_isp/swstats_cpu.cpp | 164 ++++++++++++++++++ 4 files changed, 210 insertions(+) create mode 100644 include/libcamera/internal/software_isp/swstats_cpu.h create mode 100644 src/libcamera/software_isp/swstats_cpu.cpp diff --git a/include/libcamera/internal/software_isp/meson.build b/include/libcamera/internal/software_isp/meson.build index 1c43acc4..1d9e4018 100644 --- a/include/libcamera/internal/software_isp/meson.build +++ b/include/libcamera/internal/software_isp/meson.build @@ -3,4 +3,5 @@ libcamera_internal_headers += files([ 'swisp_stats.h', 'swstats.h', + 'swstats_cpu.h', ]) diff --git a/include/libcamera/internal/software_isp/swstats_cpu.h b/include/libcamera/internal/software_isp/swstats_cpu.h new file mode 100644 index 00000000..8bb86e98 --- /dev/null +++ b/include/libcamera/internal/software_isp/swstats_cpu.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Linaro Ltd + * Copyright (C) 2023, Red Hat Inc. + * + * Authors: + * Hans de Goede + * + * swstats_cpu.h - CPU based software statistics implementation + */ + +#pragma once + +#include "libcamera/internal/shared_mem_object.h" +#include "libcamera/internal/software_isp/swisp_stats.h" +#include "libcamera/internal/software_isp/swstats.h" + +namespace libcamera { + +/** + * \class SwStatsCpu + * \brief Implementation for the Software statistics on the CPU. + */ +class SwStatsCpu : public SwStats +{ +public: + SwStatsCpu(); + ~SwStatsCpu() { } + + bool isValid() const { return sharedStats_.fd().isValid(); } + const SharedFD &getStatsFD() { return sharedStats_.fd(); } + int configure(const StreamConfiguration &inputCfg); +private: + void statsBGGR10PLine0(const uint8_t *src[]); + void statsGBRG10PLine0(const uint8_t *src[]); + void resetStats(void); + void finishStats(void); + + SharedMemObject sharedStats_; + SwIspStats stats_; + bool swap_lines_; +}; + +} /* namespace libcamera */ diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build index 9359075d..d31c6217 100644 --- a/src/libcamera/software_isp/meson.build +++ b/src/libcamera/software_isp/meson.build @@ -2,4 +2,5 @@ libcamera_sources += files([ 'swstats.cpp', + 'swstats_cpu.cpp', ]) diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp new file mode 100644 index 00000000..59453d07 --- /dev/null +++ b/src/libcamera/software_isp/swstats_cpu.cpp @@ -0,0 +1,164 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Linaro Ltd + * Copyright (C) 2023, Red Hat Inc. + * + * Authors: + * Hans de Goede + * + * swstats_cpu.cpp - CPU based software statistics implementation + */ + +#include "libcamera/internal/software_isp/swstats_cpu.h" + +#include + +#include + +#include "libcamera/internal/bayer_format.h" + +namespace libcamera { + +SwStatsCpu::SwStatsCpu() + : SwStats() +{ + sharedStats_ = SharedMemObject("softIsp_stats"); + if (!sharedStats_.fd().isValid()) + LOG(SwStats, Error) + << "Failed to create shared memory for statistics"; +} + +/* for brightness values in the 0 to 255 range: */ +static const unsigned int BRIGHT_LVL = 200U << 8; +static const unsigned int TOO_BRIGHT_LVL = 240U << 8; + +static const unsigned int RED_Y_MUL = 77; /* 0.30 * 256 */ +static const unsigned int GREEN_Y_MUL = 150; /* 0.59 * 256 */ +static const unsigned int BLUE_Y_MUL = 29; /* 0.11 * 256 */ + +#define SWISP_LINARO_START_LINE_STATS(pixel_t) \ + pixel_t r, g, g2, b; \ + unsigned int y_val; \ + \ + unsigned int sumR = 0; \ + unsigned int sumG = 0; \ + unsigned int sumB = 0; + +#define SWISP_LINARO_ACCUMULATE_LINE_STATS(div) \ + sumR += r; \ + sumG += g; \ + sumB += b; \ + \ + y_val = r * RED_Y_MUL; \ + y_val += g * GREEN_Y_MUL; \ + y_val += b * BLUE_Y_MUL; \ + stats_.y_histogram[y_val / (256 * 16 * (div))]++; + +#define SWISP_LINARO_FINISH_LINE_STATS() \ + stats_.sumR_ += sumR; \ + stats_.sumG_ += sumG; \ + stats_.sumB_ += sumB; + +static inline __attribute__((always_inline)) void +statsBayer10P(const int width, const uint8_t *src0, const uint8_t *src1, bool bggr, SwIspStats &stats_) +{ + const int width_in_bytes = width * 5 / 4; + + SWISP_LINARO_START_LINE_STATS(uint8_t) + + for (int x = 0; x < width_in_bytes; x += 5) { + if (bggr) { + /* BGGR */ + b = src0[x]; + g = src0[x + 1]; + g2 = src1[x]; + r = src1[x + 1]; + } else { + /* GBRG */ + g = src0[x]; + b = src0[x + 1]; + r = src1[x]; + g2 = src1[x + 1]; + } + g = (g + g2) / 2; + + SWISP_LINARO_ACCUMULATE_LINE_STATS(1) + } + + SWISP_LINARO_FINISH_LINE_STATS() +} + +void SwStatsCpu::statsBGGR10PLine0(const uint8_t *src[]) +{ + const uint8_t *src0 = src[1] + window_.x * 5 / 4; + const uint8_t *src1 = src[2] + window_.x * 5 / 4; + + if (swap_lines_) + std::swap(src0, src1); + + statsBayer10P(window_.width, src0, src1, true, stats_); +} + +void SwStatsCpu::statsGBRG10PLine0(const uint8_t *src[]) +{ + const uint8_t *src0 = src[1] + window_.x * 5 / 4; + const uint8_t *src1 = src[2] + window_.x * 5 / 4; + + if (swap_lines_) + std::swap(src0, src1); + + statsBayer10P(window_.width, src0, src1, false, stats_); +} + +void SwStatsCpu::resetStats(void) +{ + stats_.sumR_ = 0; + stats_.sumB_ = 0; + stats_.sumG_ = 0; + std::fill_n(stats_.y_histogram, 16, 0); +} + +void SwStatsCpu::finishStats(void) +{ + *sharedStats_ = stats_; + statsReady.emit(0); +} + +int SwStatsCpu::configure(const StreamConfiguration &inputCfg) +{ + BayerFormat bayerFormat = + BayerFormat::fromPixelFormat(inputCfg.pixelFormat); + + startFrame_ = (SwStats::statsVoidFn)&SwStatsCpu::resetStats; + finishFrame_ = (SwStats::statsVoidFn)&SwStatsCpu::finishStats; + + if (bayerFormat.bitDepth == 10 && + bayerFormat.packing == BayerFormat::Packing::CSI2) { + bpp_ = 10; + patternSize_.height = 2; + patternSize_.width = 4; /* 5 bytes per *4* pixels */ + y_skip_mask_ = 0x02; /* Skip every 3th and 4th line */ + x_shift_ = 0; + + switch (bayerFormat.order) { + case BayerFormat::BGGR: + case BayerFormat::GRBG: + stats0_ = (SwStats::statsProcessFn)&SwStatsCpu::statsBGGR10PLine0; + swap_lines_ = bayerFormat.order == BayerFormat::GRBG; + return 0; + case BayerFormat::GBRG: + case BayerFormat::RGGB: + stats0_ = (SwStats::statsProcessFn)&SwStatsCpu::statsGBRG10PLine0; + swap_lines_ = bayerFormat.order == BayerFormat::RGGB; + return 0; + default: + break; + } + } + + LOG(SwStats, Info) + << "Unsupported input format " << inputCfg.pixelFormat.toString(); + return -EINVAL; +} + +} /* namespace libcamera */ From patchwork Sat Jan 13 14:22:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 19399 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 D3FB6C328C for ; Sat, 13 Jan 2024 14:22:54 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 77E16628D7; Sat, 13 Jan 2024 15:22:54 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1705155774; bh=zxRRfYVp9eJ9KMIXtZ28QZbE2JIMf/QEy1NLeeM2zXg=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=jG/yVjOgaoUrNBlaitonEKYDuxWzmoAbg5u9FvcxFjEQ7r03StHg4zN5R4AbMGECu sRQbF1JBdZAtrFpMMS93lWOjKfyJu7yO9PLrcS1/tGBNA5/nJBDsFIBfj9ZlcgnxHn 9zEQ3eecYEXb65SfjCEQ+61Ws0g5ImbC6UAwGnDPxaJY8zTP1k5gXBtryYL7JgODdD tNYRYzeijV0lLYyfzqjJQJcc6NC3aJyTR1j6vboGLDbLTchXZRTqg0bs/sr6cq8NRT OT/hSrq9d3A8FwbQz6WQpZPBPAIEfZJqDSJbeM7K/IBCoCWaSxCtbhNJaq5hGJnvgB fpvvOrhpL6HTw== 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 8D4E961D57 for ; Sat, 13 Jan 2024 15:22:52 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="CyxNE3KY"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705155771; 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=CB/P6UmIvPqdKb0o8YPwItNIejyIxOOK7VIVMh9mDf4=; b=CyxNE3KYtSISGP2dJVcErw+y8IcJzyi/ypDOK886pOHp5gtiJ7Kc9mwK8s9uGSIFcvTk1L +LXM8FGR+CzPjAGTE2iEt5fAbO3kZP+E3iQ+4OKC6kSBqty1GBPMbsMs7NW0WIQPmlthHg AAC9PYAV9RXUr78kZK9KTpLiKy7LZok= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-266-9a56yyP0MfuUHI76Zb16VQ-1; Sat, 13 Jan 2024 09:22:49 -0500 X-MC-Unique: 9a56yyP0MfuUHI76Zb16VQ-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id E8C9C3C11C8F; Sat, 13 Jan 2024 14:22:48 +0000 (UTC) Received: from localhost.localdomain (unknown [10.39.192.58]) by smtp.corp.redhat.com (Postfix) with ESMTP id D1C503C25; Sat, 13 Jan 2024 14:22:46 +0000 (UTC) To: libcamera-devel@lists.libcamera.org, Andrey Konovalov Date: Sat, 13 Jan 2024 15:22:09 +0100 Message-ID: <20240113142218.28063-10-hdegoede@redhat.com> In-Reply-To: <20240113142218.28063-1-hdegoede@redhat.com> References: <20240113142218.28063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [libcamera-devel] [PATCH v2 09/18] libcamera: software_isp: Add Debayer base class 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: , X-Patchwork-Original-From: Hans de Goede via libcamera-devel From: Hans de Goede Reply-To: Hans de Goede Cc: Maxime Ripard , g.martti@gmail.com, t.langendam@gmail.com, srinivas.kandagatla@linaro.org, Pavel Machek , Bryan O'Donoghue , admin@dennisbonke.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add a base class for debayer implementations. This is intended to be suitable for both GPU (or otherwise) accelerated debayer implementations as well as CPU based debayering. Doxygen documentation by Dennis Bonke. Co-authored-by: Dennis Bonke Signed-off-by: Dennis Bonke Co-authored-by: Andrey Konovalov Signed-off-by: Andrey Konovalov Signed-off-by: Hans de Goede Tested-by: Bryan O'Donoghue # sc8280xp Lenovo x13s Tested-by: Pavel Machek --- .../libcamera/internal/software_isp/debayer.h | 132 ++++++++++++++++++ .../internal/software_isp/debayer_params.h | 43 ++++++ .../internal/software_isp/meson.build | 2 + src/libcamera/software_isp/debayer.cpp | 22 +++ src/libcamera/software_isp/meson.build | 1 + 5 files changed, 200 insertions(+) create mode 100644 include/libcamera/internal/software_isp/debayer.h create mode 100644 include/libcamera/internal/software_isp/debayer_params.h create mode 100644 src/libcamera/software_isp/debayer.cpp diff --git a/include/libcamera/internal/software_isp/debayer.h b/include/libcamera/internal/software_isp/debayer.h new file mode 100644 index 00000000..39e6f393 --- /dev/null +++ b/include/libcamera/internal/software_isp/debayer.h @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Linaro Ltd + * Copyright (C) 2023, Red Hat Inc. + * + * Authors: + * Hans de Goede + * + * debayer.h - debayering base class + */ + +#pragma once + +#include + +#include +#include + +#include +#include + +#include "libcamera/internal/software_isp/debayer_params.h" + +namespace libcamera { + +class FrameBuffer; + +LOG_DECLARE_CATEGORY(Debayer) + +/** + * \class Debayer + * \brief Base debayering class + * + * Base class that provides functions for setting up the debayering process. + */ +class Debayer +{ +public: + virtual ~Debayer() = 0; + + /** + * \brief Configure the debayer object according to the passed in parameters. + * \param[in] inputCfg The input configuration. + * \param[in] outputCfgs The output configurations. + * + * \return 0 on success, a negative errno on failure. + */ + virtual int configure(const StreamConfiguration &inputCfg, + const std::vector> &outputCfgs) = 0; + + /** + * \brief Get the width and height at which the bayer pattern repeats. + * \param[in] inputFormat The input format. + * + * \return pattern size or an empty size for unsupported inputFormats. + */ + virtual Size patternSize(PixelFormat inputFormat) = 0; + + /** + * \brief Get the supported output formats. + * \param[in] inputFormat The input format. + * + * \return all supported output formats or an empty vector if there are none. + */ + virtual std::vector formats(PixelFormat inputFormat) = 0; + + /** + * \brief Get the stride and the frame size. + * \param[in] outputFormat The output format. + * \param[in] size The output size. + * + * \return a tuple of the stride and the frame size, or a tuple with 0,0 if there is no valid output config. + */ + virtual std::tuple + strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) = 0; + + /** + * \brief Process the bayer data into the requested format. + * \param[in] input The input buffer. + * \param[in] output The output buffer. + * \param[in] params The parameters to be used in debayering. + * + * \note DebayerParams is passed by value deliberately so that a copy is passed + * when this is run in another thread by invokeMethod(). + */ + virtual void process(FrameBuffer *input, FrameBuffer *output, DebayerParams params) = 0; + + /** + * \brief Get the supported output sizes for the given input format and size. + * \param[in] inputFormat The input format. + * \param[in] inputSize The input size. + * + * \return The valid size ranges or an empty range if there are none. + */ + SizeRange sizes(PixelFormat inputFormat, const Size &inputSize) + { + Size pattern_size = patternSize(inputFormat); + + if (pattern_size.isNull()) + return {}; + + /* + * For debayer interpolation a border of pattern-height x pattern-width + * is kept around the entire image. Combined with a minimum-size of + * pattern-height x pattern-width this means the input-size needs to be + * at least (3 * pattern-height) x (3 * pattern-width). + */ + if (inputSize.width < (3 * pattern_size.width) || + inputSize.height < (3 * pattern_size.height)) { + LOG(Debayer, Warning) + << "Input format size too small: " << inputSize.toString(); + return {}; + } + + return SizeRange(Size(pattern_size.width, pattern_size.height), + Size((inputSize.width - 2 * pattern_size.width) & ~(pattern_size.width - 1), + (inputSize.height - 2 * pattern_size.height) & ~(pattern_size.height - 1)), + pattern_size.width, pattern_size.height); + } + + /** + * \brief Signals when the input buffer is ready. + */ + Signal inputBufferReady; + + /** + * \brief Signals when the output buffer is ready. + */ + Signal outputBufferReady; +}; + +} /* namespace libcamera */ diff --git a/include/libcamera/internal/software_isp/debayer_params.h b/include/libcamera/internal/software_isp/debayer_params.h new file mode 100644 index 00000000..8f515304 --- /dev/null +++ b/include/libcamera/internal/software_isp/debayer_params.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Red Hat Inc. + * + * Authors: + * Hans de Goede + * + * swstats.h - software statistics base class + */ + +#pragma once + +namespace libcamera { + +/** + * \brief Struct to hold the debayer parameters. + */ +struct DebayerParams { + /** + * \brief Red Gain. + * + * 128 = 0.5, 256 = 1.0, 512 = 2.0, etc. + */ + unsigned int gainR; + /** + * \brief Green Gain. + * + * 128 = 0.5, 256 = 1.0, 512 = 2.0, etc. + */ + unsigned int gainG; + /** + * \brief Blue Gain. + * + * 128 = 0.5, 256 = 1.0, 512 = 2.0, etc. + */ + unsigned int gainB; + /** + * \brief Gamma correction, 1.0 is no correction. + */ + float gamma; +}; + +} /* namespace libcamera */ diff --git a/include/libcamera/internal/software_isp/meson.build b/include/libcamera/internal/software_isp/meson.build index 1d9e4018..7e40925e 100644 --- a/include/libcamera/internal/software_isp/meson.build +++ b/include/libcamera/internal/software_isp/meson.build @@ -1,6 +1,8 @@ # SPDX-License-Identifier: CC0-1.0 libcamera_internal_headers += files([ + 'debayer.h', + 'debayer_params.h', 'swisp_stats.h', 'swstats.h', 'swstats_cpu.h', diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp new file mode 100644 index 00000000..442da1ac --- /dev/null +++ b/src/libcamera/software_isp/debayer.cpp @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Linaro Ltd + * Copyright (C) 2023, Red Hat Inc. + * + * Authors: + * Hans de Goede + * + * debayer.cpp - debayer base class + */ + +#include "libcamera/internal/software_isp/debayer.h" + +namespace libcamera { + +LOG_DEFINE_CATEGORY(Debayer) + +Debayer::~Debayer() +{ +} + +} /* namespace libcamera */ diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build index d31c6217..d4ae5ac7 100644 --- a/src/libcamera/software_isp/meson.build +++ b/src/libcamera/software_isp/meson.build @@ -1,6 +1,7 @@ # SPDX-License-Identifier: CC0-1.0 libcamera_sources += files([ + 'debayer.cpp', 'swstats.cpp', 'swstats_cpu.cpp', ]) From patchwork Sat Jan 13 14:22:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 19401 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 23C23C32BD for ; Sat, 13 Jan 2024 14:23:02 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id BAEBA61D57; Sat, 13 Jan 2024 15:23:01 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1705155781; bh=CY3GiS2AK81nKO39eEE1/6hcpdEkV9KEbpl8i+ITXbQ=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=N9HwK8wKb2z9jAFwsHEbkyVHHOdFRTojuD/zrWU8qZ8qepqt+/raiclc92t3uCeRU arzKRBIe4jYbP9RZYbu+fuFCkEHo6DXKvihaniQUautDsd8af+v4WPq+Fs/XgEkN69 UsbO5IxM7c7gOSlWZMWsSuT6iC35KBdINrGkEsKGaEmgCxwv2EKhVL1xEC2xW72ANk Pphv3r/wKEjuduoZqFp/JBYQVvlAHShGiWcG7uVvDAnlF1u36K/VXEVhDFN1CAAuQO QFMg1MtwoM8i1ooYR1YVyGBv1ID0KpSjr9BzKojsxLuoESBC4rjaV1nXValOxF9c0o TrWwuCv4c44cA== 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 57FE26293E for ; Sat, 13 Jan 2024 15:22:59 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="hj5KYIbt"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705155778; 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=smKNwA+SuPq4ZnFIwXRUUmh9rEFsw4rqtF6BjuXZD6M=; b=hj5KYIbtT5HZJ//eRty7aEJ2HJlcSHwj9sXC/2VTAp8r9/dnzmqP3tF5zfPYAX6/VdRZrD x7K+7nmoUIBdNw7X1GCJ2OCHqIPfDX67TUYZHywfNDDhc1fsDH3o5k80+iyIA+X8hoFd4F 4hrYAgwzYmf54QJwRyoT0ju2S65gH6w= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-625--SmlkuPXMKOlMrYSYoprtw-1; Sat, 13 Jan 2024 09:22:52 -0500 X-MC-Unique: -SmlkuPXMKOlMrYSYoprtw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id 730263C11C8E; Sat, 13 Jan 2024 14:22:51 +0000 (UTC) Received: from localhost.localdomain (unknown [10.39.192.58]) by smtp.corp.redhat.com (Postfix) with ESMTP id 41CD43C25; Sat, 13 Jan 2024 14:22:49 +0000 (UTC) To: libcamera-devel@lists.libcamera.org, Andrey Konovalov Date: Sat, 13 Jan 2024 15:22:10 +0100 Message-ID: <20240113142218.28063-11-hdegoede@redhat.com> In-Reply-To: <20240113142218.28063-1-hdegoede@redhat.com> References: <20240113142218.28063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [libcamera-devel] [PATCH v2 10/18] libcamera: software_isp: Add DebayerCpu class 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: , X-Patchwork-Original-From: Hans de Goede via libcamera-devel From: Hans de Goede Reply-To: Hans de Goede Cc: Maxime Ripard , g.martti@gmail.com, t.langendam@gmail.com, srinivas.kandagatla@linaro.org, Pavel Machek , Bryan O'Donoghue , admin@dennisbonke.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add CPU based debayering implementation. This initial implementation only supports debayering packed 10 bits per pixel bayer data in the 4 standard bayer orders. Doxygen documentation by Dennis Bonke. Co-authored-by: Dennis Bonke Signed-off-by: Dennis Bonke Co-authored-by: Andrey Konovalov Signed-off-by: Andrey Konovalov Co-authored-by: Pavel Machek Signed-off-by: Pavel Machek Signed-off-by: Hans de Goede Tested-by: Bryan O'Donoghue # sc8280xp Lenovo x13s Tested-by: Pavel Machek --- .../internal/software_isp/debayer_cpu.h | 131 +++++ .../internal/software_isp/meson.build | 1 + src/libcamera/software_isp/debayer_cpu.cpp | 528 ++++++++++++++++++ src/libcamera/software_isp/meson.build | 1 + 4 files changed, 661 insertions(+) create mode 100644 include/libcamera/internal/software_isp/debayer_cpu.h create mode 100644 src/libcamera/software_isp/debayer_cpu.cpp diff --git a/include/libcamera/internal/software_isp/debayer_cpu.h b/include/libcamera/internal/software_isp/debayer_cpu.h new file mode 100644 index 00000000..78573f44 --- /dev/null +++ b/include/libcamera/internal/software_isp/debayer_cpu.h @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Linaro Ltd + * Copyright (C) 2023, Red Hat Inc. + * + * Authors: + * Hans de Goede + * + * debayer_cpu.h - CPU based debayering header + */ + +#pragma once + +#include +#include +#include + +#include + +#include "libcamera/internal/software_isp/swstats_cpu.h" +#include "libcamera/internal/software_isp/debayer.h" + +namespace libcamera { + +/** + * \class DebayerCpu + * \brief Class for debayering on the CPU + * + * Implementation for CPU based debayering + */ +class DebayerCpu : public Debayer, public Object +{ +public: + /* + * FIXME this should be a plain (implementation independent) SwStats + * this can be fixed once getStats() is dropped. + */ + /** + * \brief Constructs a DebayerCpu object. + * \param[in] stats Pointer to the stats object to use. + */ + DebayerCpu(std::unique_ptr stats); + ~DebayerCpu(); + + /* + * Setup the Debayer object according to the passed in parameters. + * Return 0 on success, a negative errno value on failure + * (unsupported parameters). + */ + int configure(const StreamConfiguration &inputCfg, + const std::vector> &outputCfgs); + + /* + * Get width and height at which the bayer-pattern repeats. + * Return pattern-size or an empty Size for an unsupported inputFormat. + */ + Size patternSize(PixelFormat inputFormat); + + std::vector formats(PixelFormat input); + std::tuple + strideAndFrameSize(const PixelFormat &outputFormat, const Size &size); + + void process(FrameBuffer *input, FrameBuffer *output, DebayerParams params); + + /** + * \brief Get the file descriptor for the statistics. + * + * \return the file descriptor pointing to the statistics. + */ + const SharedFD &getStatsFD() { return stats_->getStatsFD(); } + + /** + * \brief Get the output frame size. + * + * \return The output frame size. + */ + unsigned int frameSize() { return outputConfig_.frameSize; } +private: + void initLinePointers(const uint8_t *linePointers[], const uint8_t *src); + void shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src); + void process2(const uint8_t *src, uint8_t *dst); + void process4(const uint8_t *src, uint8_t *dst); + /* CSI-2 packed 10-bit raw bayer format (all the 4 orders) */ + void debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]); + void debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]); + void debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[]); + void debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[]); + + typedef void (DebayerCpu::*debayerFn)(uint8_t *dst, const uint8_t *src[]); + + struct DebayerInputConfig { + Size patternSize; + unsigned int bpp; /* Memory used per pixel, not precision */ + unsigned int stride; + std::vector outputFormats; + }; + + struct DebayerOutputConfig { + unsigned int bpp; /* Memory used per pixel, not precision */ + unsigned int stride; + unsigned int frameSize; + }; + + int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config); + int getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config); + int setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat); + + uint8_t gamma_[1024]; + uint8_t red_[256]; + uint8_t green_[256]; + uint8_t blue_[256]; + debayerFn debayer0_; + debayerFn debayer1_; + debayerFn debayer2_; + debayerFn debayer3_; + Rectangle window_; + DebayerInputConfig inputConfig_; + DebayerOutputConfig outputConfig_; + std::unique_ptr stats_; + uint8_t *lineBuffers_[5]; + unsigned int lineBufferIndex_; + bool enableInputMemcpy_; + float gamma_correction_; + int measuredFrames_; + int64_t frameProcessTime_; + /* Skip 30 frames for things to stabilize then measure 30 frames */ + static const int framesToSkip = 30; + static const int framesToMeasure = 60; +}; + +} /* namespace libcamera */ diff --git a/include/libcamera/internal/software_isp/meson.build b/include/libcamera/internal/software_isp/meson.build index 7e40925e..b5a0d737 100644 --- a/include/libcamera/internal/software_isp/meson.build +++ b/include/libcamera/internal/software_isp/meson.build @@ -2,6 +2,7 @@ libcamera_internal_headers += files([ 'debayer.h', + 'debayer_cpu.h', 'debayer_params.h', 'swisp_stats.h', 'swstats.h', diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp new file mode 100644 index 00000000..e0c3c658 --- /dev/null +++ b/src/libcamera/software_isp/debayer_cpu.cpp @@ -0,0 +1,528 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Linaro Ltd + * Copyright (C) 2023, Red Hat Inc. + * + * Authors: + * Hans de Goede + * + * debayer_cpu.cpp - CPU based debayering class + */ + +#include "libcamera/internal/software_isp/debayer_cpu.h" + +#include +#include +#include + +#include + +#include "libcamera/internal/bayer_format.h" +#include "libcamera/internal/framebuffer.h" +#include "libcamera/internal/mapped_framebuffer.h" + +namespace libcamera { + +DebayerCpu::DebayerCpu(std::unique_ptr stats) + : stats_(std::move(stats)), gamma_correction_(1.0) +{ +#ifdef __x86_64__ + enableInputMemcpy_ = false; +#else + enableInputMemcpy_ = true; +#endif + /* Initialize gamma to 1.0 curve */ + for (int i = 0; i < 1024; i++) + gamma_[i] = i / 4; + + for (int i = 0; i < 5; i++) + lineBuffers_[i] = NULL; +} + +DebayerCpu::~DebayerCpu() +{ + for (int i = 0; i < 5; i++) + free(lineBuffers_[i]); +} + +// 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))]; \ + x++; + +// 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))]; \ + x++; + +// 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))]; \ + x++; + +// 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)]; \ + x++; + +void DebayerCpu::debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) +{ + const int width_in_bytes = window_.width * 5 / 4; + const uint8_t *prev = (const uint8_t *)src[0]; + const uint8_t *curr = (const uint8_t *)src[1]; + const uint8_t *next = (const uint8_t *)src[2]; + + /* + * For the first pixel getting a pixel from the previous column uses + * x - 2 to skip the 5th byte with least-significant bits for 4 pixels. + * Same for last pixel (uses x + 2) and looking at the next column. + * x++ in the for-loop skips the 5th byte with 4 x 2 lsb-s for 10bit packed. + */ + for (int x = 0; x < width_in_bytes; x++) { + /* Even pixel */ + BGGR_BGR888(2, 1, 1) + /* Odd pixel BGGR -> GBRG */ + GBRG_BGR888(1, 1, 1) + /* Same thing for next 2 pixels */ + BGGR_BGR888(1, 1, 1) + GBRG_BGR888(1, 2, 1) + } +} + +void DebayerCpu::debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) +{ + const int width_in_bytes = window_.width * 5 / 4; + const uint8_t *prev = (const uint8_t *)src[0]; + const uint8_t *curr = (const uint8_t *)src[1]; + const uint8_t *next = (const uint8_t *)src[2]; + + for (int x = 0; x < width_in_bytes; x++) { + /* Even pixel */ + GRBG_BGR888(2, 1, 1) + /* Odd pixel GRBG -> RGGB */ + RGGB_BGR888(1, 1, 1) + /* Same thing for next 2 pixels */ + GRBG_BGR888(1, 1, 1) + RGGB_BGR888(1, 2, 1) + } +} + +void DebayerCpu::debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[]) +{ + const int width_in_bytes = window_.width * 5 / 4; + const uint8_t *prev = (const uint8_t *)src[0]; + const uint8_t *curr = (const uint8_t *)src[1]; + const uint8_t *next = (const uint8_t *)src[2]; + + for (int x = 0; x < width_in_bytes; x++) { + /* Even pixel */ + GBRG_BGR888(2, 1, 1) + /* Odd pixel GBGR -> BGGR */ + BGGR_BGR888(1, 1, 1) + /* Same thing for next 2 pixels */ + GBRG_BGR888(1, 1, 1) + BGGR_BGR888(1, 2, 1) + } +} + +void DebayerCpu::debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[]) +{ + const int width_in_bytes = window_.width * 5 / 4; + const uint8_t *prev = (const uint8_t *)src[0]; + const uint8_t *curr = (const uint8_t *)src[1]; + const uint8_t *next = (const uint8_t *)src[2]; + + for (int x = 0; x < width_in_bytes; x++) { + /* Even pixel */ + RGGB_BGR888(2, 1, 1) + /* Odd pixel RGGB -> GRBG*/ + GRBG_BGR888(1, 1, 1) + /* Same thing for next 2 pixels */ + RGGB_BGR888(1, 1, 1) + GRBG_BGR888(1, 2, 1) + } +} + +static bool isStandardBayerOrder(BayerFormat::Order order) +{ + return order == BayerFormat::BGGR || order == BayerFormat::GBRG || + order == BayerFormat::GRBG || order == BayerFormat::RGGB; +} + +int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config) +{ + BayerFormat bayerFormat = + BayerFormat::fromPixelFormat(inputFormat); + + if (bayerFormat.bitDepth == 10 && + bayerFormat.packing == BayerFormat::Packing::CSI2 && + isStandardBayerOrder(bayerFormat.order)) { + config.bpp = 10; + config.patternSize.width = 4; /* 5 bytes per *4* pixels */ + config.patternSize.height = 2; + config.outputFormats = std::vector({ formats::RGB888 }); + return 0; + } + + LOG(Debayer, Info) + << "Unsupported input format " << inputFormat.toString(); + return -EINVAL; +} + +int DebayerCpu::getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config) +{ + if (outputFormat == formats::RGB888) { + config.bpp = 24; + return 0; + } + + LOG(Debayer, Info) + << "Unsupported output format " << outputFormat.toString(); + return -EINVAL; +} + +/* TODO: this ignores outputFormat since there is only 1 supported outputFormat for now */ +int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, [[maybe_unused]] PixelFormat outputFormat) +{ + BayerFormat bayerFormat = + BayerFormat::fromPixelFormat(inputFormat); + + if (bayerFormat.bitDepth == 10 && + bayerFormat.packing == BayerFormat::Packing::CSI2) { + switch (bayerFormat.order) { + case BayerFormat::BGGR: + debayer0_ = &DebayerCpu::debayer10P_BGBG_BGR888; + debayer1_ = &DebayerCpu::debayer10P_GRGR_BGR888; + return 0; + case BayerFormat::GBRG: + debayer0_ = &DebayerCpu::debayer10P_GBGB_BGR888; + debayer1_ = &DebayerCpu::debayer10P_RGRG_BGR888; + return 0; + case BayerFormat::GRBG: + debayer0_ = &DebayerCpu::debayer10P_GRGR_BGR888; + debayer1_ = &DebayerCpu::debayer10P_BGBG_BGR888; + return 0; + case BayerFormat::RGGB: + debayer0_ = &DebayerCpu::debayer10P_RGRG_BGR888; + debayer1_ = &DebayerCpu::debayer10P_GBGB_BGR888; + return 0; + default: + break; + } + } + + LOG(Debayer, Error) << "Unsupported input output format combination"; + return -EINVAL; +} + +int DebayerCpu::configure(const StreamConfiguration &inputCfg, + const std::vector> &outputCfgs) +{ + if (getInputConfig(inputCfg.pixelFormat, inputConfig_) != 0) + return -EINVAL; + + if (stats_->configure(inputCfg) != 0) + return -EINVAL; + + const Size &stats_pattern_size = stats_->patternSize(); + if (inputConfig_.patternSize.width != stats_pattern_size.width || + inputConfig_.patternSize.height != stats_pattern_size.height) { + LOG(Debayer, Error) + << "mismatching stats and debayer pattern sizes for " + << inputCfg.pixelFormat.toString(); + return -EINVAL; + } + + inputConfig_.stride = inputCfg.stride; + + if (outputCfgs.size() != 1) { + LOG(Debayer, Error) + << "Unsupported number of output streams: " + << outputCfgs.size(); + return -EINVAL; + } + + const StreamConfiguration &outputCfg = outputCfgs[0]; + SizeRange outSizeRange = sizes(inputCfg.pixelFormat, inputCfg.size); + std::tie(outputConfig_.stride, outputConfig_.frameSize) = + strideAndFrameSize(outputCfg.pixelFormat, outputCfg.size); + + if (!outSizeRange.contains(outputCfg.size) || outputConfig_.stride != outputCfg.stride) { + LOG(Debayer, Error) + << "Invalid output size/stride: " + << "\n " << outputCfg.size << " (" << outSizeRange << ")" + << "\n " << outputCfg.stride << " (" << outputConfig_.stride << ")"; + return -EINVAL; + } + + if (setDebayerFunctions(inputCfg.pixelFormat, outputCfg.pixelFormat) != 0) + return -EINVAL; + + window_.x = ((inputCfg.size.width - outputCfg.size.width) / 2) & + ~(inputConfig_.patternSize.width - 1); + window_.y = ((inputCfg.size.height - outputCfg.size.height) / 2) & + ~(inputConfig_.patternSize.height - 1); + window_.width = outputCfg.size.width; + window_.height = outputCfg.size.height; + + /* Don't pass x,y since process() already adjusts src before passing it */ + stats_->setWindow(Rectangle(window_.size())); + + for (unsigned int i = 0; + i < (inputConfig_.patternSize.height + 1) && enableInputMemcpy_; + i++) { + /* pad with patternSize.Width on both left and right side */ + size_t lineLength = (window_.width + 2 * inputConfig_.patternSize.width) * + inputConfig_.bpp / 8; + + free(lineBuffers_[i]); + lineBuffers_[i] = (uint8_t *)malloc(lineLength); + if (!lineBuffers_[i]) + return -ENOMEM; + } + + measuredFrames_ = 0; + frameProcessTime_ = 0; + + return 0; +} + +Size DebayerCpu::patternSize(PixelFormat inputFormat) +{ + DebayerCpu::DebayerInputConfig config; + + if (getInputConfig(inputFormat, config) != 0) + return {}; + + return config.patternSize; +} + +std::vector DebayerCpu::formats(PixelFormat inputFormat) +{ + DebayerCpu::DebayerInputConfig config; + + if (getInputConfig(inputFormat, config) != 0) + return std::vector(); + + return config.outputFormats; +} + +std::tuple +DebayerCpu::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) +{ + DebayerCpu::DebayerOutputConfig config; + + if (getOutputConfig(outputFormat, config) != 0) + return std::make_tuple(0, 0); + + /* round up to multiple of 8 for 64 bits alignment */ + unsigned int stride = (size.width * config.bpp / 8 + 7) & ~7; + + return std::make_tuple(stride, stride * size.height); +} + +void DebayerCpu::initLinePointers(const uint8_t *linePointers[], const uint8_t *src) +{ + const int patternHeight = inputConfig_.patternSize.height; + + for (int i = 0; i < patternHeight; i++) + linePointers[i + 1] = src + + (-patternHeight / 2 + i) * (int)inputConfig_.stride; + + if (!enableInputMemcpy_) + return; + + for (int i = 0; i < patternHeight; i++) { + /* pad with patternSize.Width on both left and right side */ + size_t lineLength = (window_.width + 2 * inputConfig_.patternSize.width) * + inputConfig_.bpp / 8; + int padding = inputConfig_.patternSize.width * inputConfig_.bpp / 8; + + memcpy(lineBuffers_[i], linePointers[i + 1] - padding, lineLength); + linePointers[i + 1] = lineBuffers_[i] + padding; + } + + /* Point lineBufferIndex_ to first unused lineBuffer */ + lineBufferIndex_ = patternHeight; +} + +void DebayerCpu::shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src) +{ + const int patternHeight = inputConfig_.patternSize.height; + + for (int i = 0; i < patternHeight; i++) + linePointers[i] = linePointers[i + 1]; + + linePointers[patternHeight] = src + + (patternHeight / 2) * (int)inputConfig_.stride; + + if (!enableInputMemcpy_) + return; + + size_t lineLength = (window_.width + 2 * inputConfig_.patternSize.width) * + inputConfig_.bpp / 8; + int padding = inputConfig_.patternSize.width * inputConfig_.bpp / 8; + memcpy(lineBuffers_[lineBufferIndex_], linePointers[patternHeight] - padding, lineLength); + linePointers[patternHeight] = lineBuffers_[lineBufferIndex_] + padding; + + lineBufferIndex_ = (lineBufferIndex_ + 1) % (patternHeight + 1); +} + +void DebayerCpu::process2(const uint8_t *src, uint8_t *dst) +{ + const unsigned int y_end = window_.y + window_.height; + const uint8_t *linePointers[3]; + + /* Adjust src to top left corner of the window */ + src += window_.y * inputConfig_.stride + window_.x * inputConfig_.bpp / 8; + + initLinePointers(linePointers, src); + + for (unsigned int y = window_.y; y < y_end; y += 2) { + shiftLinePointers(linePointers, src); + stats_->processLine0(y, linePointers); + (this->*debayer0_)(dst, linePointers); + src += inputConfig_.stride; + dst += outputConfig_.stride; + + shiftLinePointers(linePointers, src); + (this->*debayer1_)(dst, linePointers); + src += inputConfig_.stride; + dst += outputConfig_.stride; + } +} + +void DebayerCpu::process4(const uint8_t *src, uint8_t *dst) +{ + const unsigned int y_end = window_.y + window_.height; + const uint8_t *linePointers[5]; + + /* Adjust src to top left corner of the window */ + src += window_.y * inputConfig_.stride + window_.x * inputConfig_.bpp / 8; + + initLinePointers(linePointers, src); + + for (unsigned int y = window_.y; y < y_end; y += 4) { + shiftLinePointers(linePointers, src); + stats_->processLine0(y, linePointers); + (this->*debayer0_)(dst, linePointers); + src += inputConfig_.stride; + dst += outputConfig_.stride; + + shiftLinePointers(linePointers, src); + (this->*debayer1_)(dst, linePointers); + src += inputConfig_.stride; + dst += outputConfig_.stride; + + shiftLinePointers(linePointers, src); + stats_->processLine2(y, linePointers); + (this->*debayer2_)(dst, linePointers); + src += inputConfig_.stride; + dst += outputConfig_.stride; + + shiftLinePointers(linePointers, src); + (this->*debayer3_)(dst, linePointers); + src += inputConfig_.stride; + dst += outputConfig_.stride; + } +} + +static inline int64_t timeDiff(timespec &after, timespec &before) +{ + return (after.tv_sec - before.tv_sec) * 1000000000LL + + (int64_t)after.tv_nsec - (int64_t)before.tv_nsec; +} + +void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams params) +{ + timespec frameStartTime; + + if (measuredFrames_ < DebayerCpu::framesToMeasure) { + frameStartTime = {}; + clock_gettime(CLOCK_MONOTONIC_RAW, &frameStartTime); + } + + /* Apply DebayerParams */ + if (params.gamma != gamma_correction_) { + for (int i = 0; i < 1024; i++) + gamma_[i] = 255 * powf(i / 1023.0, params.gamma); + + gamma_correction_ = params.gamma; + } + + for (int i = 0; i < 256; i++) { + int idx; + + /* Apply gamma after gain! */ + idx = std::min({ i * params.gainR / 64U, 1023U }); + red_[i] = gamma_[idx]; + + idx = std::min({ i * params.gainG / 64U, 1023U }); + green_[i] = gamma_[idx]; + + idx = std::min({ i * params.gainB / 64U, 1023U }); + blue_[i] = gamma_[idx]; + } + + /* Copy metadata from the input buffer */ + FrameMetadata &metadata = output->_d()->metadata(); + metadata.status = input->metadata().status; + metadata.sequence = input->metadata().sequence; + metadata.timestamp = input->metadata().timestamp; + + MappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read); + MappedFrameBuffer out(output, MappedFrameBuffer::MapFlag::Write); + if (!in.isValid() || !out.isValid()) { + LOG(Debayer, Error) << "mmap-ing buffer(s) failed"; + metadata.status = FrameMetadata::FrameError; + return; + } + + stats_->startFrame(); + + if (inputConfig_.patternSize.height == 2) + process2(in.planes()[0].data(), out.planes()[0].data()); + else + process4(in.planes()[0].data(), out.planes()[0].data()); + + metadata.planes()[0].bytesused = out.planes()[0].size(); + + /* Measure before emitting signals */ + if (measuredFrames_ < DebayerCpu::framesToMeasure && + ++measuredFrames_ > DebayerCpu::framesToSkip) { + timespec frameEndTime = {}; + clock_gettime(CLOCK_MONOTONIC_RAW, &frameEndTime); + frameProcessTime_ += timeDiff(frameEndTime, frameStartTime); + if (measuredFrames_ == DebayerCpu::framesToMeasure) { + const int measuredFrames = DebayerCpu::framesToMeasure - + DebayerCpu::framesToSkip; + LOG(Debayer, Info) + << "Processed " << measuredFrames + << " frames in " << frameProcessTime_ / 1000 << "us, " + << frameProcessTime_ / (1000 * measuredFrames) + << " us/frame"; + } + } + + stats_->finishFrame(); + outputBufferReady.emit(output); + inputBufferReady.emit(input); +} + +} /* namespace libcamera */ diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build index d4ae5ac7..6d7a44d7 100644 --- a/src/libcamera/software_isp/meson.build +++ b/src/libcamera/software_isp/meson.build @@ -2,6 +2,7 @@ libcamera_sources += files([ 'debayer.cpp', + 'debayer_cpu.cpp', 'swstats.cpp', 'swstats_cpu.cpp', ]) From patchwork Sat Jan 13 14:22:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 19400 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 A6005BEFBE for ; Sat, 13 Jan 2024 14:22:59 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 40A72628BF; Sat, 13 Jan 2024 15:22:59 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1705155779; bh=rg1TgeCZZLMFboNcsBL7nH2K3Xn8d2ogeSG1Md/KNuU=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=PlnCqddoLZdsCS46jr1t4hydqpUlxTvR1eNAYO6fIl+Mw/BapBsRHUVjq81y9LRaL TOL0TGNBcHQVX9af/9DS/hst4wrHg3AufjRdvNURkULDqmE6c9m4mfzytNLMnqAuji nss4V1s3AS30cOIuKimVFQhAs0DB4L5Rf7yk4ALn67gRfjhBP23ZrzSuGh8Wk5UCQa B5g0+vfQ4PczKiKHWRX5HHmQFQCMTVpmuTMjm2Xy1rnbq9gQQ2BwSE8NU5CpB25oU6 PjLTwO0ubaOZN51ZYD8OKikBisV7NaRc3eqi70RaKhzlaNg0JOliHf7z4mKIbgupHq xxNbGmfogpYpQ== 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 75BB461D57 for ; Sat, 13 Jan 2024 15:22:58 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="A1hNZrRX"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705155777; 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=EGaKKv6I9Xr1v9RAPLt99roTMQxTe+c7/mEGsJKjiHU=; b=A1hNZrRX7g7pJb2CnA6wwIEcdkt/9xqPl9s106oQ1xZVDNKnYFsnCjibbLfwabCKktML0U 2mixEu6Kn1PP0n2p53qLwzEZ0C4zLJYGfF6fAhdPGn1iKhXRM+TCG0PyVNpR0j8TGNZ6if WMnShuXcoxOsqt2nv4x0VshgBxJTDJY= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-122-hfXCtJllNQibY1NGF6IR1w-1; Sat, 13 Jan 2024 09:22:54 -0500 X-MC-Unique: hfXCtJllNQibY1NGF6IR1w-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id D22CD101A52A; Sat, 13 Jan 2024 14:22:53 +0000 (UTC) Received: from localhost.localdomain (unknown [10.39.192.58]) by smtp.corp.redhat.com (Postfix) with ESMTP id BD58B3C25; Sat, 13 Jan 2024 14:22:51 +0000 (UTC) To: libcamera-devel@lists.libcamera.org, Andrey Konovalov Date: Sat, 13 Jan 2024 15:22:11 +0100 Message-ID: <20240113142218.28063-12-hdegoede@redhat.com> In-Reply-To: <20240113142218.28063-1-hdegoede@redhat.com> References: <20240113142218.28063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [libcamera-devel] [PATCH v2 11/18] libcamera: ipa: add Soft IPA common files 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: , X-Patchwork-Original-From: Hans de Goede via libcamera-devel From: Hans de Goede Reply-To: Hans de Goede Cc: Maxime Ripard , g.martti@gmail.com, t.langendam@gmail.com, srinivas.kandagatla@linaro.org, Pavel Machek , Bryan O'Donoghue , admin@dennisbonke.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Andrey Konovalov Define the Soft IPA main and event interfaces, add IPASoftBase class the Soft IPA implementation inherit from. Signed-off-by: Andrey Konovalov Signed-off-by: Hans de Goede Tested-by: Bryan O'Donoghue # sc8280xp Lenovo x13s Tested-by: Pavel Machek --- Documentation/Doxyfile.in | 1 + include/libcamera/ipa/meson.build | 1 + include/libcamera/ipa/soft.mojom | 29 ++++++++++++ src/ipa/simple/common/meson.build | 17 +++++++ src/ipa/simple/common/soft_base.cpp | 73 +++++++++++++++++++++++++++++ src/ipa/simple/common/soft_base.h | 50 ++++++++++++++++++++ src/ipa/simple/meson.build | 3 ++ 7 files changed, 174 insertions(+) create mode 100644 include/libcamera/ipa/soft.mojom create mode 100644 src/ipa/simple/common/meson.build create mode 100644 src/ipa/simple/common/soft_base.cpp create mode 100644 src/ipa/simple/common/soft_base.h create mode 100644 src/ipa/simple/meson.build diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in index a86ea6c1..2be8d47b 100644 --- a/Documentation/Doxyfile.in +++ b/Documentation/Doxyfile.in @@ -44,6 +44,7 @@ EXCLUDE = @TOP_SRCDIR@/include/libcamera/base/span.h \ @TOP_SRCDIR@/src/libcamera/pipeline/ \ @TOP_SRCDIR@/src/libcamera/tracepoints.cpp \ @TOP_BUILDDIR@/include/libcamera/internal/tracepoints.h \ + @TOP_BUILDDIR@/include/libcamera/ipa/soft_ipa_interface.h \ @TOP_BUILDDIR@/src/libcamera/proxy/ EXCLUDE_PATTERNS = @TOP_BUILDDIR@/include/libcamera/ipa/*_serializer.h \ diff --git a/include/libcamera/ipa/meson.build b/include/libcamera/ipa/meson.build index f3b4881c..894e38a6 100644 --- a/include/libcamera/ipa/meson.build +++ b/include/libcamera/ipa/meson.build @@ -65,6 +65,7 @@ pipeline_ipa_mojom_mapping = { 'ipu3': 'ipu3.mojom', 'rkisp1': 'rkisp1.mojom', 'rpi/vc4': 'raspberrypi.mojom', + 'simple/simple': 'soft.mojom', 'vimc': 'vimc.mojom', } diff --git a/include/libcamera/ipa/soft.mojom b/include/libcamera/ipa/soft.mojom new file mode 100644 index 00000000..2dae652b --- /dev/null +++ b/include/libcamera/ipa/soft.mojom @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +/* + * \todo Document the interface and remove the related EXCLUDE_PATTERNS entry. + * \todo Add a way to tell SoftIPA the list of params SoftISP accepts? + */ + +module ipa.soft; + +import "include/libcamera/ipa/core.mojom"; + +interface IPASoftInterface { + init(libcamera.IPASettings settings, + libcamera.SharedFD fdStats, + libcamera.SharedFD fdParams, + libcamera.ControlInfoMap sensorCtrlInfoMap) + => (int32 ret); + start() => (int32 ret); + stop(); + configure(libcamera.ControlInfoMap sensorCtrlInfoMap) + => (int32 ret); + + [async] processStats(libcamera.ControlList sensorControls); +}; + +interface IPASoftEventInterface { + setSensorControls(libcamera.ControlList sensorControls); + setIspParams(int32 dummy); +}; diff --git a/src/ipa/simple/common/meson.build b/src/ipa/simple/common/meson.build new file mode 100644 index 00000000..023e617b --- /dev/null +++ b/src/ipa/simple/common/meson.build @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: CC0-1.0 + +soft_ipa_common_sources = files([ + 'soft_base.cpp', +]) + +soft_ipa_common_includes = [ + include_directories('..'), +] + +soft_ipa_common_deps = [ + libcamera_private, +] + +soft_ipa_common_lib = static_library('soft_ipa_common', soft_ipa_common_sources, + include_directories : soft_ipa_common_includes, + dependencies : soft_ipa_common_deps) diff --git a/src/ipa/simple/common/soft_base.cpp b/src/ipa/simple/common/soft_base.cpp new file mode 100644 index 00000000..b4ed9023 --- /dev/null +++ b/src/ipa/simple/common/soft_base.cpp @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Linaro Ltd + * + * soft-base.cpp - Software IPA base class + */ + +#include "soft_base.h" + +#include + +#include +#include + +#include + +namespace libcamera { + +LOG_DEFINE_CATEGORY(IPASoft) + +namespace ipa::soft { + +IPASoftBase::IPASoftBase() +{ +} + +IPASoftBase::~IPASoftBase() +{ +} + +int IPASoftBase::init([[maybe_unused]] const IPASettings &settings, + const SharedFD &fdStats, + const SharedFD &fdParams, + const ControlInfoMap &sensorInfoMap) +{ + fdStats_ = std::move(fdStats); + if (!fdStats_.isValid()) { + LOG(IPASoft, Error) << "Invalid Statistics handle"; + return -ENODEV; + } + + fdParams_ = std::move(fdParams); + if (!fdParams_.isValid()) { + LOG(IPASoft, Error) << "Invalid Parameters handle"; + return -ENODEV; + } + + return platformInit(sensorInfoMap); +} + +int IPASoftBase::configure(const ControlInfoMap &sensorInfoMap) +{ + return platformConfigure(sensorInfoMap); +} + +int IPASoftBase::start() +{ + return platformStart(); +} + +void IPASoftBase::stop() +{ + return platformStop(); +} + +void IPASoftBase::processStats(const ControlList &sensorControls) +{ + return platformProcessStats(sensorControls); +} + +} /* namespace ipa::soft */ + +} /* namespace libcamera */ diff --git a/src/ipa/simple/common/soft_base.h b/src/ipa/simple/common/soft_base.h new file mode 100644 index 00000000..85c98702 --- /dev/null +++ b/src/ipa/simple/common/soft_base.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Linaro Ltd + * + * soft-base.h - Software IPA base class + */ +#pragma once + +#include + +#include + +#include + +namespace libcamera { + +namespace ipa::soft { + +class IPASoftBase : public ipa::soft::IPASoftInterface +{ +public: + IPASoftBase(); + ~IPASoftBase(); + + int init(const IPASettings &settings, + const SharedFD &fdStats, + const SharedFD &fdParams, + const ControlInfoMap &sensorInfoMap) override; + int configure(const ControlInfoMap &sensorInfoMap) override; + + int start() override; + void stop() override; + + void processStats(const ControlList &sensorControls) override; + +protected: + SharedFD fdStats_; + SharedFD fdParams_; + +private: + virtual int platformInit(const ControlInfoMap &sensorInfoMap) = 0; + virtual int platformConfigure(const ControlInfoMap &sensorInfoMap) = 0; + virtual int platformStart() = 0; + virtual void platformStop() = 0; + virtual void platformProcessStats(const ControlList &sensorControls) = 0; +}; + +} /* namespace ipa::soft */ + +} /* namespace libcamera */ diff --git a/src/ipa/simple/meson.build b/src/ipa/simple/meson.build new file mode 100644 index 00000000..9688bbdb --- /dev/null +++ b/src/ipa/simple/meson.build @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: CC0-1.0 + +subdir('common') From patchwork Sat Jan 13 14:22:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 19402 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 34BA8C32BE for ; Sat, 13 Jan 2024 14:23:04 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B16D4628BF; Sat, 13 Jan 2024 15:23:03 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1705155783; bh=qYHImG/8hkP2dGeHdAFzhWMnVGByl02Gb/Et/BSOEOM=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=DSmpBCxkuUgUwwkI1xpR/hmibFiKgDs3DaBtGa+XMNsc4U/ePy6eD/1vWkTUpPJo9 nBWpO6f8VcFp4CvH5n7BQF1k/LvrMn+t+r9NsVFfX/T4j458jN8XvaBg5Kbhl8gYk8 iiTj/ojyWXTftq3bnpO5xzhvDnvngjK09KgaeAmZ+cUg0lcYm5bBs8I3HX1fd+YE+N OBAUB2IbyBaq+zVnP3T6ZwUOW+xDSayPjWa4cq7W38PvyPuL9caAZedDndgQdjVbF7 wC786C8rD2sWFYr7/TKlG9Ke9EqxI1CQrQe/+zOG9i36pgv9YtJhMtbvpzqJl+Fimm v0wOsLL4B2fkA== 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 2190E61D57 for ; Sat, 13 Jan 2024 15:23:01 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="G5r1nZuo"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705155780; 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=32ULhuHZBgqbGMDZ9lo/6o9mYPPrfHjbHiasMs4eVXs=; b=G5r1nZuoPFvU8RXMueJM8i3e9hM/60O5RzIXT7RhqlHicebP+nhkNef9DD7xbyQkqdm3QD YzbYOgYQ8ZKdIzrNCiFAdinQZWU5XMOwflp6njg3Ho6GGIihSmYs/RlaMoQH/YR10inqXj F/00kRvciaaJCnTLO2Tizc5ubyPw33A= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-597-oe9j5ER5NHyQyi8cg6ZK4Q-1; Sat, 13 Jan 2024 09:22:56 -0500 X-MC-Unique: oe9j5ER5NHyQyi8cg6ZK4Q-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id 172EC85A589; Sat, 13 Jan 2024 14:22:56 +0000 (UTC) Received: from localhost.localdomain (unknown [10.39.192.58]) by smtp.corp.redhat.com (Postfix) with ESMTP id 258313C27; Sat, 13 Jan 2024 14:22:54 +0000 (UTC) To: libcamera-devel@lists.libcamera.org, Andrey Konovalov Date: Sat, 13 Jan 2024 15:22:12 +0100 Message-ID: <20240113142218.28063-13-hdegoede@redhat.com> In-Reply-To: <20240113142218.28063-1-hdegoede@redhat.com> References: <20240113142218.28063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [libcamera-devel] [PATCH v2 12/18] libcamera: ipa: Soft IPA: add a Simple Soft IPA implementation 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: , X-Patchwork-Original-From: Hans de Goede via libcamera-devel From: Hans de Goede Reply-To: Hans de Goede Cc: Maxime Ripard , g.martti@gmail.com, t.langendam@gmail.com, srinivas.kandagatla@linaro.org, Pavel Machek , Bryan O'Donoghue , admin@dennisbonke.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Andrey Konovalov Auto exposure/gain and AWB implementation by Dennis, Toon and Martti. Co-authored-by: Dennis Bonke Signed-off-by: Dennis Bonke Co-authored-by: Marttico Signed-off-by: Marttico Co-authored-by: Toon Langendam Signed-off-by: Toon Langendam Signed-off-by: Andrey Konovalov Signed-off-by: Hans de Goede Tested-by: Bryan O'Donoghue # sc8280xp Lenovo x13s Tested-by: Pavel Machek --- meson_options.txt | 3 +- src/ipa/simple/meson.build | 9 + src/ipa/simple/simple/data/meson.build | 9 + src/ipa/simple/simple/data/soft.conf | 3 + src/ipa/simple/simple/meson.build | 26 +++ src/ipa/simple/simple/soft_simple.cpp | 273 +++++++++++++++++++++++++ 6 files changed, 322 insertions(+), 1 deletion(-) create mode 100644 src/ipa/simple/simple/data/meson.build create mode 100644 src/ipa/simple/simple/data/soft.conf create mode 100644 src/ipa/simple/simple/meson.build create mode 100644 src/ipa/simple/simple/soft_simple.cpp diff --git a/meson_options.txt b/meson_options.txt index 5fdc7be8..8ec08658 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -27,7 +27,7 @@ option('gstreamer', option('ipas', type : 'array', - choices : ['ipu3', 'rkisp1', 'rpi/vc4', 'vimc'], + choices : ['ipu3', 'rkisp1', 'rpi/vc4', 'simple/simple', 'vimc'], description : 'Select which IPA modules to build') option('lc-compliance', @@ -46,6 +46,7 @@ option('pipelines', 'rkisp1', 'rpi/vc4', 'simple', + 'simple/simple', 'uvcvideo', 'vimc' ], diff --git a/src/ipa/simple/meson.build b/src/ipa/simple/meson.build index 9688bbdb..14be5dc2 100644 --- a/src/ipa/simple/meson.build +++ b/src/ipa/simple/meson.build @@ -1,3 +1,12 @@ # SPDX-License-Identifier: CC0-1.0 subdir('common') + +foreach pipeline : pipelines + pipeline = pipeline.split('/') + if pipeline.length() < 2 or pipeline[0] != 'simple' + continue + endif + + subdir(pipeline[1]) +endforeach diff --git a/src/ipa/simple/simple/data/meson.build b/src/ipa/simple/simple/data/meson.build new file mode 100644 index 00000000..33548cc6 --- /dev/null +++ b/src/ipa/simple/simple/data/meson.build @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: CC0-1.0 + +conf_files = files([ + 'soft.conf', +]) + +install_data(conf_files, + install_dir : ipa_data_dir / 'soft', + install_tag : 'runtime') diff --git a/src/ipa/simple/simple/data/soft.conf b/src/ipa/simple/simple/data/soft.conf new file mode 100644 index 00000000..0c70e7c0 --- /dev/null +++ b/src/ipa/simple/simple/data/soft.conf @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Dummy configuration file for the soft IPA. diff --git a/src/ipa/simple/simple/meson.build b/src/ipa/simple/simple/meson.build new file mode 100644 index 00000000..8b5d76b5 --- /dev/null +++ b/src/ipa/simple/simple/meson.build @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: CC0-1.0 + +ipa_name = 'ipa_soft_simple' + +mod = shared_module(ipa_name, + ['soft_simple.cpp', libcamera_generated_ipa_headers], + name_prefix : '', + include_directories : [ipa_includes, libipa_includes, '..'], + dependencies : libcamera_private, + link_with : libipa, + link_whole : soft_ipa_common_lib, + install : true, + install_dir : ipa_install_dir) + +if ipa_sign_module + custom_target(ipa_name + '.so.sign', + input : mod, + output : ipa_name + '.so.sign', + command : [ipa_sign, ipa_priv_key, '@INPUT@', '@OUTPUT@'], + install : false, + build_by_default : true) +endif + +subdir('data') + +ipa_names += ipa_name diff --git a/src/ipa/simple/simple/soft_simple.cpp b/src/ipa/simple/simple/soft_simple.cpp new file mode 100644 index 00000000..93fc1545 --- /dev/null +++ b/src/ipa/simple/simple/soft_simple.cpp @@ -0,0 +1,273 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Linaro Ltd + * + * soft_simple.cpp - Simple Software Image Processing Algorithm module + */ + +#include + +#include +#include + +#include + +#include +#include + +#include "libcamera/internal/camera_sensor.h" +#include "libcamera/internal/software_isp/debayer_params.h" +#include "libcamera/internal/software_isp/swisp_stats.h" + +#include "common/soft_base.h" + +#define EXPOSURE_OPTIMAL_VALUE 2.5 +#define EXPOSURE_SATISFACTORY_OFFSET 0.2 + +namespace libcamera { + +LOG_DECLARE_CATEGORY(IPASoft) + +namespace ipa::soft { + +class IPASoftSimple final : public IPASoftBase +{ +public: + IPASoftSimple() + : IPASoftBase(), ignore_updates_(0) + { + } + + ~IPASoftSimple() + { + if (stats_) + munmap(stats_, sizeof(SwIspStats)); + if (params_) + munmap(params_, sizeof(DebayerParams)); + } + + int platformInit(const ControlInfoMap &sensorInfoMap) override; + int platformConfigure(const ControlInfoMap &sensorInfoMap) override; + int platformStart() override; + void platformStop() override; + void platformProcessStats(const ControlList &sensorControls) override; + +private: + void update_exposure(double exposuremsv); + + DebayerParams *params_; + SwIspStats *stats_; + int exposure_min_, exposure_max_; + int again_min_, again_max_; + int again_, exposure_; + int ignore_updates_; +}; + +int IPASoftSimple::platformInit(const ControlInfoMap &sensorInfoMap) +{ + params_ = static_cast(mmap(nullptr, sizeof(DebayerParams), + PROT_WRITE, MAP_SHARED, + fdParams_.get(), 0)); + if (!params_) { + LOG(IPASoft, Error) << "Unable to map Parameters"; + return -ENODEV; + } + + stats_ = static_cast(mmap(nullptr, sizeof(SwIspStats), + PROT_READ, MAP_SHARED, + fdStats_.get(), 0)); + if (!stats_) { + LOG(IPASoft, Error) << "Unable to map Statistics"; + return -ENODEV; + } + + if (sensorInfoMap.find(V4L2_CID_EXPOSURE) == sensorInfoMap.end()) { + LOG(IPASoft, Error) << "Don't have exposure control"; + return -EINVAL; + } + + if (sensorInfoMap.find(V4L2_CID_ANALOGUE_GAIN) == sensorInfoMap.end()) { + LOG(IPASoft, Error) << "Don't have gain control"; + return -EINVAL; + } + + return 0; +} + +int IPASoftSimple::platformConfigure(const ControlInfoMap &sensorInfoMap) +{ + const ControlInfo &exposure_info = sensorInfoMap.find(V4L2_CID_EXPOSURE)->second; + const ControlInfo &gain_info = sensorInfoMap.find(V4L2_CID_ANALOGUE_GAIN)->second; + + exposure_min_ = exposure_info.min().get(); + if (!exposure_min_) { + LOG(IPASoft, Warning) << "Minimum exposure is zero, that can't be linear"; + exposure_min_ = 1; + } + exposure_max_ = exposure_info.max().get(); + again_min_ = gain_info.min().get(); + if (!again_min_) { + LOG(IPASoft, Warning) << "Minimum gain is zero, that can't be linear"; + again_min_ = 100; + } + again_max_ = gain_info.max().get(); + + LOG(IPASoft, Info) << "Exposure " << exposure_min_ << "-" << exposure_max_ + << ", gain " << again_min_ << "-" << again_max_; + + return 0; +} + +int IPASoftSimple::platformStart() +{ + return 0; +} + +void IPASoftSimple::platformStop() +{ +} + +void IPASoftSimple::platformProcessStats(const ControlList &sensorControls) +{ + /* + * Calculate red and blue gains for AWB. + * Clamp max gain at 4.0, this also avoids 0 division. + */ + if (stats_->sumR_ <= stats_->sumG_ / 4) + params_->gainR = 1024; + else + params_->gainR = 256 * stats_->sumG_ / stats_->sumR_; + + if (stats_->sumB_ <= stats_->sumG_ / 4) + params_->gainB = 1024; + else + params_->gainB = 256 * stats_->sumG_ / stats_->sumB_; + + /* Green gain and gamma values are fixed */ + params_->gainG = 256; + params_->gamma = 0.5; + + setIspParams.emit(0); + + /* + * AE / AGC, use 2 frames delay to make sure that the exposure and + * the gain set have applied to the camera sensor. + */ + if (ignore_updates_ > 0) { + --ignore_updates_; + return; + } + + unsigned int denom = 0; + unsigned int num = 0; + unsigned int y_histogramSmall[5] = {}; + + for (int i = 0; i < 16; i++) + y_histogramSmall[(i - i / 8) / 3] += stats_->y_histogram[i]; + + for (int i = 0; i < 5; i++) { + LOG(IPASoft, Debug) << i << ": " << y_histogramSmall[i]; + denom += y_histogramSmall[i]; + num += y_histogramSmall[i] * (i + 1); + } + + float exposuremsv = (float)num / denom; + + /* sanity check */ + if (!sensorControls.contains(V4L2_CID_EXPOSURE) || + !sensorControls.contains(V4L2_CID_ANALOGUE_GAIN)) { + LOG(IPASoft, Error) << "Control(s) missing"; + return; + } + + ControlList ctrls(sensorControls); + + exposure_ = ctrls.get(V4L2_CID_EXPOSURE).get(); + again_ = ctrls.get(V4L2_CID_ANALOGUE_GAIN).get(); + + update_exposure(exposuremsv); + + ctrls.set(V4L2_CID_EXPOSURE, exposure_); + ctrls.set(V4L2_CID_ANALOGUE_GAIN, again_); + + ignore_updates_ = 2; + + setSensorControls.emit(ctrls); + + LOG(IPASoft, Debug) << "exposuremsv " << exposuremsv + << " exp " << exposure_ << " again " << again_ + << " gain R/B " << params_->gainR << "/" << params_->gainB; +} + +/* DENOMINATOR of 10 gives ~10% increment/decrement; DENOMINATOR of 5 - about ~20% */ +#define DENOMINATOR 10 +#define UP_NUMERATOR (DENOMINATOR + 1) +#define DOWN_NUMERATOR (DENOMINATOR - 1) + +void IPASoftSimple::update_exposure(double exposuremsv) +{ + int next; + + if (exposuremsv < EXPOSURE_OPTIMAL_VALUE - EXPOSURE_SATISFACTORY_OFFSET) { + next = exposure_ * UP_NUMERATOR / DENOMINATOR; + if (next - exposure_ < 1) + exposure_ += 1; + else + exposure_ = next; + if (exposure_ >= exposure_max_) { + next = again_ * UP_NUMERATOR / DENOMINATOR; + if (next - again_ < 1) + again_ += 1; + else + again_ = next; + } + } + + if (exposuremsv > EXPOSURE_OPTIMAL_VALUE + EXPOSURE_SATISFACTORY_OFFSET) { + if (exposure_ == exposure_max_ && again_ != again_min_) { + next = again_ * DOWN_NUMERATOR / DENOMINATOR; + if (again_ - next < 1) + again_ -= 1; + else + again_ = next; + } else { + next = exposure_ * DOWN_NUMERATOR / DENOMINATOR; + if (exposure_ - next < 1) + exposure_ -= 1; + else + exposure_ = next; + } + } + + if (exposure_ > exposure_max_) + exposure_ = exposure_max_; + else if (exposure_ < exposure_min_) + exposure_ = exposure_min_; + + if (again_ > again_max_) + again_ = again_max_; + else if (again_ < again_min_) + again_ = again_min_; +} + +} /* namespace ipa::soft */ + +/* + * External IPA module interface + */ +extern "C" { +const struct IPAModuleInfo ipaModuleInfo = { + IPA_MODULE_API_VERSION, + 0, + "SimplePipelineHandler", + "soft/simple", +}; + +IPAInterface *ipaCreate() +{ + return new ipa::soft::IPASoftSimple(); +} + +} /* extern "C" */ + +} /* namespace libcamera */ From patchwork Sat Jan 13 14:22:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 19403 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 EB177C32BF for ; Sat, 13 Jan 2024 14:23:05 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6B48D6293F; Sat, 13 Jan 2024 15:23:05 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1705155785; bh=BfJ5Q9Abhzz6JEp7fS1+QoCoBqrqe1324HyjxPDD+bw=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=rC68iBokerstVOkyLRtdvJwQ8Xu0J++2nT0/Gef4F9mVeLUQzvFHQyjt8X6PGlqzv XA+SU0tU844JmBCv8y+GSdolxuD74IHZhWzoatd5SZQBdauAwgLoJpi+YpcqI+r/RW HkNTNfQ3e+H44fbRHwX0agdd0gSvu6+rXIGibzNDpExeAe8JCPrq+DvdeGFRfzzf5P thwVRBe46d4kzs+NQbEXT8BirQrTJsltGKFcoF5LdaqFj6Yle2P+irmrBVhN8shqyO g3lS/U/JIFz64cKIVA2eonp+01jaSwoV823yl4M7ETNKrv1c+Ejyg2ITPlm7c2N5wX dHRfR+tCo1HTQ== 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 DDACA6293E for ; Sat, 13 Jan 2024 15:23:03 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="iwhK1vGH"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705155783; 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=sQaXLJ5xMtn4atOohd1+oTGyXpXD11nrK5SpNOQcEJU=; b=iwhK1vGHjntjkCFGj+5veOFwkofd/INM+D+P5zH+n9t/FORVyOiu2mYNsMbledRygk+Tbb ASWD1wjUYmkSQuNe/r8dMnWHeTiaTBV4mbfZ8IU1tA2xxCGrbF9yxQYbF70lT2Z+S5gplm Bo1wbs5dGitdyJns2JIAkPmbh1cHq30= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-582-75DdyCoGPv2GTZxhoWEFDA-1; Sat, 13 Jan 2024 09:22:58 -0500 X-MC-Unique: 75DdyCoGPv2GTZxhoWEFDA-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id 4A6AF82A6C3; Sat, 13 Jan 2024 14:22:58 +0000 (UTC) Received: from localhost.localdomain (unknown [10.39.192.58]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5715A3C25; Sat, 13 Jan 2024 14:22:56 +0000 (UTC) To: libcamera-devel@lists.libcamera.org, Andrey Konovalov Date: Sat, 13 Jan 2024 15:22:13 +0100 Message-ID: <20240113142218.28063-14-hdegoede@redhat.com> In-Reply-To: <20240113142218.28063-1-hdegoede@redhat.com> References: <20240113142218.28063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [libcamera-devel] [PATCH v2 13/18] libcamera: software_isp: add Simple SoftwareIsp implementation 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: , X-Patchwork-Original-From: Hans de Goede via libcamera-devel From: Hans de Goede Reply-To: Hans de Goede Cc: Maxime Ripard , g.martti@gmail.com, t.langendam@gmail.com, srinivas.kandagatla@linaro.org, Pavel Machek , Bryan O'Donoghue , admin@dennisbonke.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Andrey Konovalov The implementation of SoftwareIsp handles creation of Soft IPA and interactions with it, so that the pipeline handler wouldn't need to care about the Soft IPA. Doxygen documentation by Dennis Bonke. Signed-off-by: Andrey Konovalov Co-authored-by: Dennis Bonke Signed-off-by: Dennis Bonke Co-authored-by: Hans de Goede Signed-off-by: Hans de Goede Tested-by: Bryan O'Donoghue # sc8280xp Lenovo x13s Tested-by: Pavel Machek --- .../internal/software_isp/meson.build | 1 + .../internal/software_isp/swisp_simple.h | 163 ++++++++++++ src/libcamera/software_isp/meson.build | 19 ++ src/libcamera/software_isp/swisp_simple.cpp | 238 ++++++++++++++++++ 4 files changed, 421 insertions(+) create mode 100644 include/libcamera/internal/software_isp/swisp_simple.h create mode 100644 src/libcamera/software_isp/swisp_simple.cpp diff --git a/include/libcamera/internal/software_isp/meson.build b/include/libcamera/internal/software_isp/meson.build index b5a0d737..cf21ace5 100644 --- a/include/libcamera/internal/software_isp/meson.build +++ b/include/libcamera/internal/software_isp/meson.build @@ -4,6 +4,7 @@ libcamera_internal_headers += files([ 'debayer.h', 'debayer_cpu.h', 'debayer_params.h', + 'swisp_simple.h', 'swisp_stats.h', 'swstats.h', 'swstats_cpu.h', diff --git a/include/libcamera/internal/software_isp/swisp_simple.h b/include/libcamera/internal/software_isp/swisp_simple.h new file mode 100644 index 00000000..87613c23 --- /dev/null +++ b/include/libcamera/internal/software_isp/swisp_simple.h @@ -0,0 +1,163 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Linaro Ltd + * + * swisp_simple.h - Simple software ISP implementation + */ + +#pragma once + +#include +#include + +#include + +#include +#include + +#include "libcamera/internal/dma_heaps.h" +#include "libcamera/internal/software_isp.h" +#include "libcamera/internal/software_isp/debayer_cpu.h" + +namespace libcamera { + +/** + * \brief Class for the Simple Software ISP. + * + * Implementation of the SoftwareIsp interface. + */ +class SwIspSimple : public SoftwareIsp +{ +public: + /** + * \brief Constructor for the SwIspSimple object. + * + * \param[in] pipe The pipeline handler in use. + * \param[in] sensorControls The sensor controls. + */ + SwIspSimple(PipelineHandler *pipe, const ControlInfoMap &sensorControls); + ~SwIspSimple() {} + + /** + * \brief Load a configuration from a file. + * \param[in] filename The file to load from. + * + * \return 0 on success. + */ + int loadConfiguration([[maybe_unused]] const std::string &filename) { return 0; } + + /** + * \brief Gets if there is a valid debayer object. + * + * \returns true if there is, false otherwise. + */ + bool isValid() const; + + /** + * \brief Get the supported output formats. + * \param[in] input The input format. + * + * \return all supported output formats or an empty vector if there are none. + */ + std::vector formats(PixelFormat input); + + /** + * \brief Get the supported output sizes for the given input format and size. + * \param[in] inputFormat The input format. + * \param[in] inputSize The input size. + * + * \return The valid size ranges or an empty range if there are none. + */ + SizeRange sizes(PixelFormat inputFormat, const Size &inputSize); + + /** + * \brief Get the stride and the frame size. + * \param[in] outputFormat The output format. + * \param[in] size The output size. + * + * \return a tuple of the stride and the frame size, or a tuple with 0,0 if there is no valid output config. + */ + std::tuple + strideAndFrameSize(const PixelFormat &outputFormat, const Size &size); + + /** + * \brief Configure the SwIspSimple object according to the passed in parameters. + * \param[in] inputCfg The input configuration. + * \param[in] outputCfgs The output configurations. + * \param[in] sensorControls The sensor controls. + * + * \return 0 on success, a negative errno on failure. + */ + int configure(const StreamConfiguration &inputCfg, + const std::vector> &outputCfgs, + const ControlInfoMap &sensorControls); + + /** + * \brief Exports the buffers for use in processing. + * \param[in] output The number of outputs requested. + * \param[in] count The number of planes. + * \param[out] buffers The exported buffers. + * + * \return count when successful, a negative return value if an error occurred. + */ + int exportBuffers(unsigned int output, unsigned int count, + std::vector> *buffers); + + /** + * \brief Process the statistics gathered. + * \param[in] sensorControls The sensor controls. + */ + void processStats(const ControlList &sensorControls); + + /** + * \brief Starts the Software ISP worker. + * + * \return 0 on success, any other value indicates an error. + */ + int start(); + + /** + * \brief Stops the Software ISP worker. + */ + void stop(); + + /** + * \brief Queues buffers for processing. + * \param[in] input The input framebuffer. + * \param[in] outputs The output framebuffers. + * + * \return 0 on success, a negative errno on failure + */ + int queueBuffers(FrameBuffer *input, + const std::map &outputs); + + /** + * \brief Get the signal for when the sensor controls are set. + * + * \return The control list of the sensor controls. + */ + Signal &getSignalSetSensorControls(); + + /** + * \brief Process the input framebuffer. + * \param[in] input The input framebuffer. + * \param[out] output The output framebuffer. + */ + void process(FrameBuffer *input, FrameBuffer *output); + +private: + void saveIspParams(int dummy); + void statsReady(int dummy); + void inputReady(FrameBuffer *input); + void outputReady(FrameBuffer *output); + + std::unique_ptr debayer_; + Thread ispWorkerThread_; + SharedMemObject sharedParams_; + DebayerParams debayerParams_; + DmaHeap dmaHeap_; + + std::unique_ptr ipa_; +}; + +} /* namespace libcamera */ diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build index 6d7a44d7..9464f2fd 100644 --- a/src/libcamera/software_isp/meson.build +++ b/src/libcamera/software_isp/meson.build @@ -6,3 +6,22 @@ libcamera_sources += files([ 'swstats.cpp', 'swstats_cpu.cpp', ]) + +# Software ISP is enabled for 'simple' pipeline handler. +# The 'pipelines' option value should be +# 'simple/' e.g.: +# -Dpipelines=simple/simple +# The source file should be named swisp_.cpp, +# e.g. 'swisp_simple.cpp'. + +foreach pipeline : pipelines + pipeline = pipeline.split('/') + if pipeline.length() == 2 and pipeline[0] == 'simple' + libcamera_sources += files([ + 'swisp_' + pipeline[1] + '.cpp', + ]) + # the 'break' below can be removed if/when multiple + # Software ISP implementations are allowed in single build + break + endif +endforeach diff --git a/src/libcamera/software_isp/swisp_simple.cpp b/src/libcamera/software_isp/swisp_simple.cpp new file mode 100644 index 00000000..0884166e --- /dev/null +++ b/src/libcamera/software_isp/swisp_simple.cpp @@ -0,0 +1,238 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Linaro Ltd + * + * swisp_simple.cpp - Simple software ISP implementation + */ + +#include "libcamera/internal/software_isp/swisp_simple.h" + +#include +#include +#include + +#include +#include + +#include "libcamera/internal/bayer_format.h" +#include "libcamera/internal/framebuffer.h" +#include "libcamera/internal/ipa_manager.h" +#include "libcamera/internal/mapped_framebuffer.h" + +namespace libcamera { + +SwIspSimple::SwIspSimple(PipelineHandler *pipe, const ControlInfoMap &sensorControls) + : SoftwareIsp(pipe, sensorControls), debayer_(nullptr), debayerParams_{ 256, 256, 256, 0.5f }, + dmaHeap_(DmaHeap::DmaHeapFlag::Cma | DmaHeap::DmaHeapFlag::System) +{ + if (!dmaHeap_.isValid()) { + LOG(SoftwareIsp, Error) << "Failed to create DmaHeap object"; + return; + } + + sharedParams_ = SharedMemObject("softIsp_params"); + if (!sharedParams_.fd().isValid()) { + LOG(SoftwareIsp, Error) << "Failed to create shared memory for parameters"; + return; + } + + std::unique_ptr stats; + + stats = std::make_unique(); + if (!stats) { + LOG(SoftwareIsp, Error) << "Failed to create SwStatsCpu object"; + return; + } + + stats->statsReady.connect(this, &SwIspSimple::statsReady); + + debayer_ = std::make_unique(std::move(stats)); + if (!debayer_) { + LOG(SoftwareIsp, Error) << "Failed to create DebayerCpu object"; + return; + } + + debayer_->inputBufferReady.connect(this, &SwIspSimple::inputReady); + debayer_->outputBufferReady.connect(this, &SwIspSimple::outputReady); + + ipa_ = IPAManager::createIPA(pipe, 0, 0); + if (!ipa_) { + LOG(SoftwareIsp, Error) + << "Creating IPA for software ISP failed"; + debayer_.reset(); + return; + } + + int ret = ipa_->init(IPASettings{ "No cfg file", "No sensor model" }, + debayer_->getStatsFD(), + sharedParams_.fd(), + sensorControls); + if (ret) { + LOG(SoftwareIsp, Error) << "IPA init failed"; + debayer_.reset(); + return; + } + + ipa_->setIspParams.connect(this, &SwIspSimple::saveIspParams); + + debayer_->moveToThread(&ispWorkerThread_); +} + +void SwIspSimple::processStats(const ControlList &sensorControls) +{ + ASSERT(ipa_); + ipa_->processStats(sensorControls); +} + +Signal &SwIspSimple::getSignalSetSensorControls() +{ + ASSERT(ipa_); + return ipa_->setSensorControls; +} + +bool SwIspSimple::isValid() const +{ + return !!debayer_; +} + +std::vector SwIspSimple::formats(PixelFormat inputFormat) +{ + ASSERT(debayer_ != nullptr); + + return debayer_->formats(inputFormat); +} + +SizeRange SwIspSimple::sizes(PixelFormat inputFormat, const Size &inputSize) +{ + ASSERT(debayer_ != nullptr); + + return debayer_->sizes(inputFormat, inputSize); +} + +std::tuple +SwIspSimple::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) +{ + ASSERT(debayer_ != nullptr); + + return debayer_->strideAndFrameSize(outputFormat, size); +} + +int SwIspSimple::configure(const StreamConfiguration &inputCfg, + const std::vector> &outputCfgs, + const ControlInfoMap &sensorControls) +{ + ASSERT(ipa_ != nullptr && debayer_ != nullptr); + + int ret = ipa_->configure(sensorControls); + if (ret < 0) + return ret; + + return debayer_->configure(inputCfg, outputCfgs); +} + +int SwIspSimple::exportBuffers(unsigned int output, unsigned int count, + std::vector> *buffers) +{ + ASSERT(debayer_ != nullptr); + + /* single output for now */ + if (output >= 1) + return -EINVAL; + + for (unsigned int i = 0; i < count; i++) { + const std::string name = "frame-" + std::to_string(i); + const size_t frameSize = debayer_->frameSize(); + + FrameBuffer::Plane outPlane; + outPlane.fd = SharedFD(dmaHeap_.alloc(name.c_str(), frameSize)); + if (!outPlane.fd.isValid()) { + LOG(SoftwareIsp, Error) + << "failed to allocate a dma_buf"; + return -ENOMEM; + } + outPlane.offset = 0; + outPlane.length = frameSize; + + std::vector planes{ outPlane }; + buffers->emplace_back(std::make_unique(std::move(planes))); + } + + return count; +} + +int SwIspSimple::queueBuffers(FrameBuffer *input, + const std::map &outputs) +{ + unsigned int mask = 0; + + /* + * Validate the outputs as a sanity check: at least one output is + * required, all outputs must reference a valid stream and no two + * outputs can reference the same stream. + */ + if (outputs.empty()) + return -EINVAL; + + for (auto [index, buffer] : outputs) { + if (!buffer) + return -EINVAL; + if (index >= 1) /* only single stream atm */ + return -EINVAL; + if (mask & (1 << index)) + return -EINVAL; + + mask |= 1 << index; + } + + process(input, outputs.at(0)); + + return 0; +} + +int SwIspSimple::start() +{ + int ret = ipa_->start(); + if (ret) + return ret; + + ispWorkerThread_.start(); + return 0; +} + +void SwIspSimple::stop() +{ + ispWorkerThread_.exit(); + ispWorkerThread_.wait(); + + ipa_->stop(); +} + +void SwIspSimple::process(FrameBuffer *input, FrameBuffer *output) +{ + debayer_->invokeMethod(&DebayerCpu::process, + ConnectionTypeQueued, input, output, debayerParams_); +} + +void SwIspSimple::saveIspParams([[maybe_unused]] int dummy) +{ + debayerParams_ = *sharedParams_; +} + +void SwIspSimple::statsReady(int dummy) +{ + ispStatsReady.emit(dummy); +} + +void SwIspSimple::inputReady(FrameBuffer *input) +{ + inputBufferReady.emit(input); +} + +void SwIspSimple::outputReady(FrameBuffer *output) +{ + outputBufferReady.emit(output); +} + +REGISTER_SOFTWAREISP(SwIspSimple) + +} /* namespace libcamera */ From patchwork Sat Jan 13 14:22:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 19404 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 86E91C32BC for ; Sat, 13 Jan 2024 14:23:08 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1E747628D8; Sat, 13 Jan 2024 15:23:08 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1705155788; bh=RcnatGuep0KaEgXuxt7iV4wxbfm31boF7Mvv5BGJd94=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=yHyHzrNAXZVQThQztMRbVuNZLlnWqb0QxBq/UfhH+vZQrAzqAdakLt5TT3h6AR54D TyynkOnsReoU+V4HscIIG2dY+P9F7gwgio8nJyJAy8insgIAu7MC2QW1aTHZV9NAS+ pebyg8xpITzP0Ani2Ny/eVkb/yobbL+vVyb2L1EBz2QtYMQzEco0jMNb3q1rOmy6l1 N/9iiLiGF3aX3YCRvdfec+MGV2J4ResIhYHj9cvP/naWBjN6FuR92yXGwO1dNWSJTR eAcUtFVHEsm0VA7TBNIUrLN++oWVZiRJtN3aO7Efk1FMGtAmlrc+oWuuyvm35brLBf ctpuKF56CdLkg== 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 B94E362945 for ; Sat, 13 Jan 2024 15:23:05 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="bOB5OJ8Q"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705155784; 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=soM/A070UM2ujggKFrjYBygbGnH6AS5EDCo3Jn7Fmwk=; b=bOB5OJ8QlM5gkzRLbur5EPAGgiQ/cF0/wlmbZ4wsr/tp5vmQ4J27n67Y9XkXp6Z8Gc4eez Qy5NCnWwyTo5KkTHnr7MDlHo9WU4uYraeeCeffG20OCbTbrhNVB0MsUkYcr1j4KJxw/U3P 7SjWDaTeMVkBx1QFLdqoPPHvbH4PGm4= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-272-Qy-qza2yMU20LrG0hoDpxA-1; Sat, 13 Jan 2024 09:23:01 -0500 X-MC-Unique: Qy-qza2yMU20LrG0hoDpxA-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id ABD8E380409B; Sat, 13 Jan 2024 14:23:00 +0000 (UTC) Received: from localhost.localdomain (unknown [10.39.192.58]) by smtp.corp.redhat.com (Postfix) with ESMTP id 906863C25; Sat, 13 Jan 2024 14:22:58 +0000 (UTC) To: libcamera-devel@lists.libcamera.org, Andrey Konovalov Date: Sat, 13 Jan 2024 15:22:14 +0100 Message-ID: <20240113142218.28063-15-hdegoede@redhat.com> In-Reply-To: <20240113142218.28063-1-hdegoede@redhat.com> References: <20240113142218.28063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [libcamera-devel] [PATCH v2 14/18] libcamera: pipeline: simple: rename converterBuffers_ and related vars 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: , X-Patchwork-Original-From: Hans de Goede via libcamera-devel From: Hans de Goede Reply-To: Hans de Goede Cc: Maxime Ripard , g.martti@gmail.com, t.langendam@gmail.com, srinivas.kandagatla@linaro.org, Pavel Machek , Bryan O'Donoghue , admin@dennisbonke.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Andrey Konovalov The converterBuffers_ and the converterQueue_ are not that specific to the Converter, and could be used by another entity doing the format conversion. Rename converterBuffers_, converterQueue_, and useConverter_ to conversionBuffers_, conversionQueue_ and useConversion_ to disassociate them from the Converter. Signed-off-by: Andrey Konovalov Signed-off-by: Hans de Goede Tested-by: Bryan O'Donoghue # sc8280xp Lenovo x13s Tested-by: Pavel Machek Reviewed-by: Kieran Bingham --- src/libcamera/pipeline/simple/simple.cpp | 63 ++++++++++++------------ 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 4d0e7255..fa298746 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -269,17 +269,18 @@ public: std::vector configs_; std::map> formats_; + std::vector> conversionBuffers_; + std::queue> conversionQueue_; + bool useConversion_; + std::unique_ptr converter_; - std::vector> converterBuffers_; - bool useConverter_; - std::queue> converterQueue_; private: void tryPipeline(unsigned int code, const Size &size); static std::vector routedSourcePads(MediaPad *sink); - void converterInputDone(FrameBuffer *buffer); - void converterOutputDone(FrameBuffer *buffer); + void conversionInputDone(FrameBuffer *buffer); + void conversionOutputDone(FrameBuffer *buffer); }; class SimpleCameraConfiguration : public CameraConfiguration @@ -503,8 +504,8 @@ int SimpleCameraData::init() << "Failed to create converter, disabling format conversion"; converter_.reset(); } else { - converter_->inputBufferReady.connect(this, &SimpleCameraData::converterInputDone); - converter_->outputBufferReady.connect(this, &SimpleCameraData::converterOutputDone); + converter_->inputBufferReady.connect(this, &SimpleCameraData::conversionInputDone); + converter_->outputBufferReady.connect(this, &SimpleCameraData::conversionOutputDone); } } @@ -740,7 +741,7 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer) * point converting an erroneous buffer. */ if (buffer->metadata().status != FrameMetadata::FrameSuccess) { - if (!useConverter_) { + if (!useConversion_) { /* No conversion, just complete the request. */ Request *request = buffer->request(); pipe->completeBuffer(request, buffer); @@ -756,16 +757,16 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer) if (buffer->metadata().status != FrameMetadata::FrameCancelled) video_->queueBuffer(buffer); - if (converterQueue_.empty()) + if (conversionQueue_.empty()) return; Request *request = nullptr; - for (auto &item : converterQueue_.front()) { + for (auto &item : conversionQueue_.front()) { FrameBuffer *outputBuffer = item.second; request = outputBuffer->request(); pipe->completeBuffer(request, outputBuffer); } - converterQueue_.pop(); + conversionQueue_.pop(); if (request) pipe->completeRequest(request); @@ -782,9 +783,9 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer) */ Request *request = buffer->request(); - if (useConverter_ && !converterQueue_.empty()) { + if (useConversion_ && !conversionQueue_.empty()) { const std::map &outputs = - converterQueue_.front(); + conversionQueue_.front(); if (!outputs.empty()) { FrameBuffer *outputBuffer = outputs.begin()->second; if (outputBuffer) @@ -801,14 +802,14 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer) * conversion is needed. If there's no queued request, just requeue the * captured buffer for capture. */ - if (useConverter_) { - if (converterQueue_.empty()) { + if (useConversion_) { + if (conversionQueue_.empty()) { video_->queueBuffer(buffer); return; } - converter_->queueBuffers(buffer, converterQueue_.front()); - converterQueue_.pop(); + converter_->queueBuffers(buffer, conversionQueue_.front()); + conversionQueue_.pop(); return; } @@ -817,13 +818,13 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer) pipe->completeRequest(request); } -void SimpleCameraData::converterInputDone(FrameBuffer *buffer) +void SimpleCameraData::conversionInputDone(FrameBuffer *buffer) { /* Queue the input buffer back for capture. */ video_->queueBuffer(buffer); } -void SimpleCameraData::converterOutputDone(FrameBuffer *buffer) +void SimpleCameraData::conversionOutputDone(FrameBuffer *buffer) { SimplePipelineHandler *pipe = SimpleCameraData::pipe(); @@ -1159,14 +1160,14 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) /* Configure the converter if needed. */ std::vector> outputCfgs; - data->useConverter_ = config->needConversion(); + data->useConversion_ = config->needConversion(); for (unsigned int i = 0; i < config->size(); ++i) { StreamConfiguration &cfg = config->at(i); cfg.setStream(&data->streams_[i]); - if (data->useConverter_) + if (data->useConversion_) outputCfgs.push_back(cfg); } @@ -1192,7 +1193,7 @@ int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream, * Export buffers on the converter or capture video node, depending on * whether the converter is used or not. */ - if (data->useConverter_) + if (data->useConversion_) return data->converter_->exportBuffers(data->streamIndex(stream), count, buffers); else @@ -1213,13 +1214,13 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL return -EBUSY; } - if (data->useConverter_) { + if (data->useConversion_) { /* * When using the converter allocate a fixed number of internal * buffers. */ ret = video->allocateBuffers(kNumInternalBuffers, - &data->converterBuffers_); + &data->conversionBuffers_); } else { /* Otherwise, prepare for using buffers from the only stream. */ Stream *stream = &data->streams_[0]; @@ -1238,7 +1239,7 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL return ret; } - if (data->useConverter_) { + if (data->useConversion_) { ret = data->converter_->start(); if (ret < 0) { stop(camera); @@ -1246,7 +1247,7 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL } /* Queue all internal buffers for capture. */ - for (std::unique_ptr &buffer : data->converterBuffers_) + for (std::unique_ptr &buffer : data->conversionBuffers_) video->queueBuffer(buffer.get()); } @@ -1258,7 +1259,7 @@ void SimplePipelineHandler::stopDevice(Camera *camera) SimpleCameraData *data = cameraData(camera); V4L2VideoDevice *video = data->video_; - if (data->useConverter_) + if (data->useConversion_) data->converter_->stop(); video->streamOff(); @@ -1266,7 +1267,7 @@ void SimplePipelineHandler::stopDevice(Camera *camera) video->bufferReady.disconnect(data, &SimpleCameraData::bufferReady); - data->converterBuffers_.clear(); + data->conversionBuffers_.clear(); releasePipeline(data); } @@ -1284,7 +1285,7 @@ int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request) * queue, it will be handed to the converter in the capture * completion handler. */ - if (data->useConverter_) { + if (data->useConversion_) { buffers.emplace(data->streamIndex(stream), buffer); } else { ret = data->video_->queueBuffer(buffer); @@ -1293,8 +1294,8 @@ int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request) } } - if (data->useConverter_) - data->converterQueue_.push(std::move(buffers)); + if (data->useConversion_) + data->conversionQueue_.push(std::move(buffers)); return 0; } From patchwork Sat Jan 13 14:22:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 19405 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 9EB6CC32C0 for ; Sat, 13 Jan 2024 14:23:09 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 0108562916; Sat, 13 Jan 2024 15:23:08 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1705155789; bh=N+Fjz8FwbnlKfIqZ/ZRioDBkVZRrI6AGTRp91gDofNw=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=EhA7Kn3Lm1vjP793dru8U7SOQT+dj52X5z6Nes5Qp80p9ee9dltFvartFvvx3pw6L +yh3hS5F+BVCfPlQ+DxDyCzJG+uewRA+cwG3S5NjiTTNB+q2UfYx9bz0L8dKJITTE1 T4PUlcwK/uUNw4BhcO28Qrq2hv7ucOikqU8VxHgePbdxTEqXvynU+8a7j4I+hb5DAg V7zf0RTLSjCWMugYN9RzgZAGkwvYA35TL/X+jkaVcp2MQLBW+s88EruOtjpqStMAyD j2+HvtX84iWzxk8OSgulQtjXiV6WQTxKDfCIHXiZAVcfrcQK0YyQC1wSl48UgBzys3 phKzEN4KBfCLA== 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 58F34628BA for ; Sat, 13 Jan 2024 15:23:07 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="ZGUu5dL/"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705155786; 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=p7sk4ygNJ1Kp3Chu8iXvFUxQRGjEV5sSXhNgOViZ9Cw=; b=ZGUu5dL/cv9vZ1cNiQXXmcwus452efYyn4Uqa7UJz/oXPBBtrSUVQ6AKKOHIFgvpNEKtNb klgxmlvt8VKGO09VCBd5Gk2RzsvOH04BE1pi+J/FFC/V08CTIIuLCZuEL7W6G539PKovVp DOSudlOMqpTfoLqUJz4mil8KjM4Wxao= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-665-HK_Syl4ONiW-4GkyWTY6sA-1; Sat, 13 Jan 2024 09:23:03 -0500 X-MC-Unique: HK_Syl4ONiW-4GkyWTY6sA-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id DF41682A6C0; Sat, 13 Jan 2024 14:23:02 +0000 (UTC) Received: from localhost.localdomain (unknown [10.39.192.58]) by smtp.corp.redhat.com (Postfix) with ESMTP id E4B823C25; Sat, 13 Jan 2024 14:23:00 +0000 (UTC) To: libcamera-devel@lists.libcamera.org, Andrey Konovalov Date: Sat, 13 Jan 2024 15:22:15 +0100 Message-ID: <20240113142218.28063-16-hdegoede@redhat.com> In-Reply-To: <20240113142218.28063-1-hdegoede@redhat.com> References: <20240113142218.28063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [libcamera-devel] [PATCH v2 15/18] libcamera: pipeline: simple: enable use of Soft ISP and Soft IPA 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: , X-Patchwork-Original-From: Hans de Goede via libcamera-devel From: Hans de Goede Reply-To: Hans de Goede Cc: Maxime Ripard , g.martti@gmail.com, t.langendam@gmail.com, srinivas.kandagatla@linaro.org, Pavel Machek , Bryan O'Donoghue , admin@dennisbonke.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Andrey Konovalov To enable the Simple Soft ISP and Soft IPA for simple pipeline handler configure the build with: -Dpipelines=simple/simple -Dipas=simple/simple If the pipeline uses Converter, Soft ISP and Soft IPA aren't available. Configuring the build with just: -Dpipelines=simple makes it to work like before - Soft ISP and Soft IPA aren't used. Signed-off-by: Andrey Konovalov Signed-off-by: Hans de Goede Tested-by: Bryan O'Donoghue # sc8280xp Lenovo x13s Tested-by: Pavel Machek --- src/libcamera/pipeline/simple/simple.cpp | 111 ++++++++++++++++++----- 1 file changed, 89 insertions(+), 22 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index fa298746..c76510c2 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -34,6 +34,7 @@ #include "libcamera/internal/device_enumerator.h" #include "libcamera/internal/media_device.h" #include "libcamera/internal/pipeline_handler.h" +#include "libcamera/internal/software_isp.h" #include "libcamera/internal/v4l2_subdevice.h" #include "libcamera/internal/v4l2_videodevice.h" @@ -274,6 +275,7 @@ public: bool useConversion_; std::unique_ptr converter_; + std::unique_ptr swIsp_; private: void tryPipeline(unsigned int code, const Size &size); @@ -281,6 +283,9 @@ private: void conversionInputDone(FrameBuffer *buffer); void conversionOutputDone(FrameBuffer *buffer); + + void ispStatsReady(int dummy); + void setSensorControls(const ControlList &sensorControls); }; class SimpleCameraConfiguration : public CameraConfiguration @@ -509,6 +514,25 @@ int SimpleCameraData::init() } } + /* + * Create SoftwareIsp unconditionally if no converter is used + * - to be revisited + */ + if (!converter_) { + swIsp_ = SoftwareIspFactoryBase::create(pipe, sensor_->controls()); + if (!swIsp_) { + LOG(SimplePipeline, Warning) + << "Failed to create software ISP, disabling software debayering"; + swIsp_.reset(); + } else { + swIsp_->inputBufferReady.connect(this, &SimpleCameraData::conversionInputDone); + swIsp_->outputBufferReady.connect(this, &SimpleCameraData::conversionOutputDone); + swIsp_->ispStatsReady.connect(this, &SimpleCameraData::ispStatsReady); + + swIsp_->getSignalSetSensorControls().connect(this, &SimpleCameraData::setSensorControls); + } + } + video_ = pipe->video(entities_.back().entity); ASSERT(video_); @@ -599,12 +623,20 @@ void SimpleCameraData::tryPipeline(unsigned int code, const Size &size) config.captureFormat = pixelFormat; config.captureSize = format.size; - if (!converter_) { - config.outputFormats = { pixelFormat }; - config.outputSizes = config.captureSize; - } else { + if (converter_) { config.outputFormats = converter_->formats(pixelFormat); config.outputSizes = converter_->sizes(format.size); + } else if (swIsp_) { + config.outputFormats = swIsp_->formats(pixelFormat); + config.outputSizes = swIsp_->sizes(pixelFormat, format.size); + if (config.outputFormats.empty()) { + /* Do not use swIsp for unsupported pixelFormat's */ + config.outputFormats = { pixelFormat }; + config.outputSizes = config.captureSize; + } + } else { + config.outputFormats = { pixelFormat }; + config.outputSizes = config.captureSize; } configs_.push_back(config); @@ -750,9 +782,9 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer) } /* - * The converter is in use. Requeue the internal buffer for - * capture (unless the stream is being stopped), and complete - * the request with all the user-facing buffers. + * The converter or Software ISP is in use. Requeue the internal + * buffer for capture (unless the stream is being stopped), and + * complete the request with all the user-facing buffers. */ if (buffer->metadata().status != FrameMetadata::FrameCancelled) video_->queueBuffer(buffer); @@ -798,9 +830,9 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer) buffer->metadata().timestamp); /* - * Queue the captured and the request buffer to the converter if format - * conversion is needed. If there's no queued request, just requeue the - * captured buffer for capture. + * Queue the captured and the request buffer to the converter or Software + * ISP if format conversion is needed. If there's no queued request, just + * requeue the captured buffer for capture. */ if (useConversion_) { if (conversionQueue_.empty()) { @@ -808,7 +840,11 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer) return; } - converter_->queueBuffers(buffer, conversionQueue_.front()); + if (converter_) + converter_->queueBuffers(buffer, conversionQueue_.front()); + else + swIsp_->queueBuffers(buffer, conversionQueue_.front()); + conversionQueue_.pop(); return; } @@ -834,6 +870,18 @@ void SimpleCameraData::conversionOutputDone(FrameBuffer *buffer) pipe->completeRequest(request); } +void SimpleCameraData::ispStatsReady([[maybe_unused]] int dummy) +{ + swIsp_->processStats(sensor_->getControls({ V4L2_CID_ANALOGUE_GAIN, + V4L2_CID_EXPOSURE })); +} + +void SimpleCameraData::setSensorControls(const ControlList &sensorControls) +{ + ControlList ctrls(sensorControls); + sensor_->setControls(&ctrls); +} + /* Retrieve all source pads connected to a sink pad through active routes. */ std::vector SimpleCameraData::routedSourcePads(MediaPad *sink) { @@ -1016,8 +1064,10 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() /* Set the stride, frameSize and bufferCount. */ if (needConversion_) { std::tie(cfg.stride, cfg.frameSize) = - data_->converter_->strideAndFrameSize(cfg.pixelFormat, - cfg.size); + (data_->converter_) ? data_->converter_->strideAndFrameSize(cfg.pixelFormat, + cfg.size) + : data_->swIsp_->strideAndFrameSize(cfg.pixelFormat, + cfg.size); if (cfg.stride == 0) return Invalid; } else { @@ -1180,7 +1230,9 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) inputCfg.stride = captureFormat.planes[0].bpl; inputCfg.bufferCount = kNumInternalBuffers; - return data->converter_->configure(inputCfg, outputCfgs); + return (data->converter_) ? data->converter_->configure(inputCfg, outputCfgs) + : data->swIsp_->configure(inputCfg, outputCfgs, + data->sensor_->controls()); } int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream, @@ -1194,8 +1246,10 @@ int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream, * whether the converter is used or not. */ if (data->useConversion_) - return data->converter_->exportBuffers(data->streamIndex(stream), - count, buffers); + return (data->converter_) ? data->converter_->exportBuffers(data->streamIndex(stream), + count, buffers) + : data->swIsp_->exportBuffers(data->streamIndex(stream), + count, buffers); else return data->video_->exportBuffers(count, buffers); } @@ -1240,10 +1294,18 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL } if (data->useConversion_) { - ret = data->converter_->start(); - if (ret < 0) { - stop(camera); - return ret; + if (data->converter_) { + ret = data->converter_->start(); + if (ret < 0) { + stop(camera); + return ret; + } + } else if (data->swIsp_) { + ret = data->swIsp_->start(); + if (ret < 0) { + stop(camera); + return ret; + } } /* Queue all internal buffers for capture. */ @@ -1259,8 +1321,13 @@ void SimplePipelineHandler::stopDevice(Camera *camera) SimpleCameraData *data = cameraData(camera); V4L2VideoDevice *video = data->video_; - if (data->useConversion_) - data->converter_->stop(); + if (data->useConversion_) { + if (data->converter_) + data->converter_->stop(); + else if (data->swIsp_) { + data->swIsp_->stop(); + } + } video->streamOff(); video->releaseBuffers(); From patchwork Sat Jan 13 14:22:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 19406 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 E994EBEFBE for ; Sat, 13 Jan 2024 14:23:12 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8E07662949; Sat, 13 Jan 2024 15:23:12 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1705155792; bh=hsBYVdTBrAZWsxlE2UOT1Y8nzt9N04UWvFwDF/G04sU=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=QE77ijKTTPmgAnLKlrDHnzMCZUNHAVmGBwGlGgF8MFDPaMMETZHo2HwrttBO2OQaQ VLoDve78ZvwT6pmMBYGx+/2VGCpjaNBekgL/RWRfZW/eVH/6xmbp7UhsA6mbM7ee8R zXkJ03uBvl8pwVCnKOaSwfeHB/QYqGfuAfswNxf3KdSWntRU5ZbR50zt4FPGh7WBVT QqpaOvgwmLiHijyvrFmGWxbZiGAbZU7n2NX0yfvWqSKwzym7FQKE5Y5Yhy/yWiLCPK TfoyXr14pyUYgmg9Z7xEKaTccXNl6Hv3/4BSuCaFDhb8H9WPF/OLrdH/nfeAEWAkn6 y9PeT+S/06FDA== 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 15816628BA for ; Sat, 13 Jan 2024 15:23:11 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="DMNkBKtc"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705155790; 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=diAP1U/Qgri4qaPRP+DrtDR3hQ8y1Pz2h6tNa7MEXtQ=; b=DMNkBKtcAsXVEaqvgd2IwRAMQtOQljnBtE9KoLhyqhr75OS9+kSO/Ytx9bmsqEb5xwvvQo kqGLEVrLsgVLp7AAL/Nedh78jSi5oi/kvvZ1nGYKteV/0NUJbWAOkJ99Uy/F5TfGDqU798 AekdSkEmpaplyQWN2DY2hXk+uQi6Zfc= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-671-t3V_O6aiNAeHRJBkdj3UqQ-1; Sat, 13 Jan 2024 09:23:05 -0500 X-MC-Unique: t3V_O6aiNAeHRJBkdj3UqQ-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id 01AE429AA389; Sat, 13 Jan 2024 14:23:05 +0000 (UTC) Received: from localhost.localdomain (unknown [10.39.192.58]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2DB8A3C25; Sat, 13 Jan 2024 14:23:03 +0000 (UTC) To: libcamera-devel@lists.libcamera.org, Andrey Konovalov Date: Sat, 13 Jan 2024 15:22:16 +0100 Message-ID: <20240113142218.28063-17-hdegoede@redhat.com> In-Reply-To: <20240113142218.28063-1-hdegoede@redhat.com> References: <20240113142218.28063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [libcamera-devel] [PATCH v2 16/18] libcamera: swstats_cpu: Add support for 8 and 10 bpp unpacked bayer input 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: , X-Patchwork-Original-From: Hans de Goede via libcamera-devel From: Hans de Goede Reply-To: Hans de Goede Cc: Maxime Ripard , g.martti@gmail.com, t.langendam@gmail.com, srinivas.kandagatla@linaro.org, Pavel Machek , Bryan O'Donoghue , admin@dennisbonke.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add support for 8 and 10 bpp unpacked bayer input for all 4 standard bayer orders. Signed-off-by: Hans de Goede Tested-by: Bryan O'Donoghue # sc8280xp Lenovo x13s Tested-by: Pavel Machek --- .../internal/software_isp/swstats_cpu.h | 7 ++ src/libcamera/software_isp/swstats_cpu.cpp | 97 +++++++++++++++++++ 2 files changed, 104 insertions(+) diff --git a/include/libcamera/internal/software_isp/swstats_cpu.h b/include/libcamera/internal/software_isp/swstats_cpu.h index 8bb86e98..3410753c 100644 --- a/include/libcamera/internal/software_isp/swstats_cpu.h +++ b/include/libcamera/internal/software_isp/swstats_cpu.h @@ -11,6 +11,7 @@ #pragma once +#include "libcamera/internal/bayer_format.h" #include "libcamera/internal/shared_mem_object.h" #include "libcamera/internal/software_isp/swisp_stats.h" #include "libcamera/internal/software_isp/swstats.h" @@ -31,6 +32,12 @@ public: const SharedFD &getStatsFD() { return sharedStats_.fd(); } int configure(const StreamConfiguration &inputCfg); private: + int setupStandardBayerOrder(BayerFormat::Order order); + /* Bayer 8 bpp unpacked */ + void statsBGGR8Line0(const uint8_t *src[]); + /* Bayer 10 bpp unpacked */ + void statsBGGR10Line0(const uint8_t *src[]); + /* Bayer 10 bpp packed */ void statsBGGR10PLine0(const uint8_t *src[]); void statsGBRG10PLine0(const uint8_t *src[]); void resetStats(void); diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp index 59453d07..6bd78860 100644 --- a/src/libcamera/software_isp/swstats_cpu.cpp +++ b/src/libcamera/software_isp/swstats_cpu.cpp @@ -59,6 +59,57 @@ static const unsigned int BLUE_Y_MUL = 29; /* 0.11 * 256 */ stats_.sumG_ += sumG; \ stats_.sumB_ += sumB; +void SwStatsCpu::statsBGGR8Line0(const uint8_t *src[]) +{ + const uint8_t *src0 = src[1] + window_.x; + const uint8_t *src1 = src[2] + window_.x; + + SWISP_LINARO_START_LINE_STATS(uint8_t) + + if (swap_lines_) + std::swap(src0, src1); + + /* x += 4 sample every other 2x2 block */ + for (int x = 0; x < (int)window_.width; x += 4) { + b = src0[x]; + g = src0[x + 1]; + g2 = src1[x]; + r = src1[x + 1]; + + g = (g + g2) / 2; + + SWISP_LINARO_ACCUMULATE_LINE_STATS(1) + } + + SWISP_LINARO_FINISH_LINE_STATS() +} + +void SwStatsCpu::statsBGGR10Line0(const uint8_t *src[]) +{ + const uint16_t *src0 = (const uint16_t *)src[1] + window_.x; + const uint16_t *src1 = (const uint16_t *)src[2] + window_.x; + + SWISP_LINARO_START_LINE_STATS(uint16_t) + + if (swap_lines_) + std::swap(src0, src1); + + /* x += 4 sample every other 2x2 block */ + for (int x = 0; x < (int)window_.width; x += 4) { + b = src0[x]; + g = src0[x + 1]; + g2 = src1[x]; + r = src1[x + 1]; + + g = (g + g2) / 2; + + /* divide Y by 4 for 10 -> 8 bpp value */ + SWISP_LINARO_ACCUMULATE_LINE_STATS(4) + } + + SWISP_LINARO_FINISH_LINE_STATS() +} + static inline __attribute__((always_inline)) void statsBayer10P(const int width, const uint8_t *src0, const uint8_t *src1, bool bggr, SwIspStats &stats_) { @@ -124,6 +175,39 @@ void SwStatsCpu::finishStats(void) statsReady.emit(0); } +/* + * Check if order is a standard Bayer order and setup x_shift_ and swap_lines_ + * so that a single BGGR stats function can be used for all 4 standard orders. + */ +int SwStatsCpu::setupStandardBayerOrder(BayerFormat::Order order) +{ + switch (order) { + case BayerFormat::BGGR: + x_shift_ = 0; + swap_lines_ = false; + break; + case BayerFormat::GBRG: + x_shift_ = 1; /* BGGR -> GBRG */ + swap_lines_ = false; + break; + case BayerFormat::GRBG: + x_shift_ = 0; + swap_lines_ = true; /* BGGR -> GRBG */ + break; + case BayerFormat::RGGB: + x_shift_ = 1; /* BGGR -> GBRG */ + swap_lines_ = true; /* GBRG -> RGGB */ + break; + default: + return -EINVAL; + } + + patternSize_.height = 2; + patternSize_.width = 2; + y_skip_mask_ = 0x02; /* Skip every 3th and 4th line */ + return 0; +} + int SwStatsCpu::configure(const StreamConfiguration &inputCfg) { BayerFormat bayerFormat = @@ -132,6 +216,19 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg) startFrame_ = (SwStats::statsVoidFn)&SwStatsCpu::resetStats; finishFrame_ = (SwStats::statsVoidFn)&SwStatsCpu::finishStats; + if (bayerFormat.packing == BayerFormat::Packing::None && + setupStandardBayerOrder(bayerFormat.order) == 0) { + bpp_ = (bayerFormat.bitDepth + 7) & ~7; + switch (bayerFormat.bitDepth) { + case 8: + stats0_ = (SwStats::statsProcessFn)&SwStatsCpu::statsBGGR8Line0; + return 0; + case 10: + stats0_ = (SwStats::statsProcessFn)&SwStatsCpu::statsBGGR10Line0; + return 0; + } + } + if (bayerFormat.bitDepth == 10 && bayerFormat.packing == BayerFormat::Packing::CSI2) { bpp_ = 10; From patchwork Sat Jan 13 14:22:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 19407 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 F2CE3C328C for ; Sat, 13 Jan 2024 14:23:13 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 96BFE628D8; Sat, 13 Jan 2024 15:23:13 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1705155793; bh=SDHhaQ6+Ym6KOnX6DRinkpCo6BVpc5mSXiCTgqa1lL8=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=b4YXJVHn/m0fFhLfRYyS6Ly8ClRh988dm2RPqmGPb6ypcaoSeOtga7oZ6YeH+oc1G pSgLZEtpu0zPiC8+BoQx2yyJjN0IkhAuBN0lMXZmyWUyNdYTHXMztX7RVcJLgsLg1D gOeMsASh8/TzgQpAa8fM1i+wk8bfKuFbjNQr6dJ0U0WsMc8G3RmHBYUCsw0BJTs+Jd QGOEPtOo2h/KQMPKUgvAY4ZejgQIRGC9sS42yNbeOL3UOhPtMvDVyfUj0p470af9gC 5jUu1D8BUIR49qfxfl+1vvAxTPqEDnSe6Y3QGXDpDXeFsGz7zLhkaVPpckw70kzwqg BFQZSchz3Bf3A== 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 B660E628BA for ; Sat, 13 Jan 2024 15:23:11 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="MMvARURB"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705155790; 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=i+hhMJI4JwhF6806NjP/595IzSd4eALvqtFpD2YFpZ4=; b=MMvARURBUmvZF4fP376FMApMnzT/gdns3iplBZFaWIFDCa7v85axxEYg6RZKPeKIZfZuOU ac1S4xpFT8sUXg7rUZcJ/VoMinPG3cQCHAQD5eyD1IEU1FDdUfYq15Y9hZ3er1ZJJyw2Ob bk0EnPEFJ9mahcJFvQiB3AUmkIhYCSc= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-454-FfISoMptMAKqHZhugg4pOw-1; Sat, 13 Jan 2024 09:23:07 -0500 X-MC-Unique: FfISoMptMAKqHZhugg4pOw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id 3628B85A589; Sat, 13 Jan 2024 14:23:07 +0000 (UTC) Received: from localhost.localdomain (unknown [10.39.192.58]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3EB053C25; Sat, 13 Jan 2024 14:23:05 +0000 (UTC) To: libcamera-devel@lists.libcamera.org, Andrey Konovalov Date: Sat, 13 Jan 2024 15:22:17 +0100 Message-ID: <20240113142218.28063-18-hdegoede@redhat.com> In-Reply-To: <20240113142218.28063-1-hdegoede@redhat.com> References: <20240113142218.28063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [libcamera-devel] [PATCH v2 17/18] libcamera: debayer_cpu: Add support for 8 and 10 bpp unpacked bayer input 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: , X-Patchwork-Original-From: Hans de Goede via libcamera-devel From: Hans de Goede Reply-To: Hans de Goede Cc: Maxime Ripard , g.martti@gmail.com, t.langendam@gmail.com, srinivas.kandagatla@linaro.org, Pavel Machek , Bryan O'Donoghue , admin@dennisbonke.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add support for 8 and 10 bpp unpacked bayer input for all 4 standard bayer orders. Signed-off-by: Hans de Goede Tested-by: Bryan O'Donoghue # sc8280xp Lenovo x13s Tested-by: Pavel Machek --- .../internal/software_isp/debayer_cpu.h | 9 ++ src/libcamera/software_isp/debayer_cpu.cpp | 100 ++++++++++++++++++ 2 files changed, 109 insertions(+) diff --git a/include/libcamera/internal/software_isp/debayer_cpu.h b/include/libcamera/internal/software_isp/debayer_cpu.h index 78573f44..99914e2a 100644 --- a/include/libcamera/internal/software_isp/debayer_cpu.h +++ b/include/libcamera/internal/software_isp/debayer_cpu.h @@ -17,6 +17,7 @@ #include +#include "libcamera/internal/bayer_format.h" #include "libcamera/internal/software_isp/swstats_cpu.h" #include "libcamera/internal/software_isp/debayer.h" @@ -80,6 +81,12 @@ private: void shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src); void process2(const uint8_t *src, uint8_t *dst); void process4(const uint8_t *src, uint8_t *dst); + /* 8-bit raw bayer format */ + void debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]); + void debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]); + /* unpacked 10-bit raw bayer format */ + void debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]); + void debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]); /* CSI-2 packed 10-bit raw bayer format (all the 4 orders) */ void debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]); void debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]); @@ -103,6 +110,7 @@ private: int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config); int getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config); + int setupStandardBayerOrder(BayerFormat::Order order); int setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat); uint8_t gamma_[1024]; @@ -119,6 +127,7 @@ private: std::unique_ptr stats_; uint8_t *lineBuffers_[5]; unsigned int lineBufferIndex_; + unsigned int x_shift_; /* Offset of 0/1 applied to window_.x */ bool enableInputMemcpy_; float gamma_correction_; int measuredFrames_; diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp index e0c3c658..d1f8fa15 100644 --- a/src/libcamera/software_isp/debayer_cpu.cpp +++ b/src/libcamera/software_isp/debayer_cpu.cpp @@ -45,6 +45,11 @@ DebayerCpu::~DebayerCpu() free(lineBuffers_[i]); } +#define DECLARE_SRC_POINTERS(pixel_t) \ + const pixel_t *prev = (const pixel_t *)src[0] + x_shift_; \ + const pixel_t *curr = (const pixel_t *)src[1] + x_shift_; \ + const pixel_t *next = (const pixel_t *)src[2] + x_shift_; + // RGR // GBG // RGR @@ -81,6 +86,46 @@ DebayerCpu::~DebayerCpu() *dst++ = red_[curr[x] / (div)]; \ x++; +void DebayerCpu::debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) +{ + DECLARE_SRC_POINTERS(uint8_t) + + for (int x = 0; x < (int)window_.width;) { + BGGR_BGR888(1, 1, 1) + GBRG_BGR888(1, 1, 1) + } +} + +void DebayerCpu::debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) +{ + DECLARE_SRC_POINTERS(uint8_t) + + for (int x = 0; x < (int)window_.width;) { + GRBG_BGR888(1, 1, 1) + RGGB_BGR888(1, 1, 1) + } +} + +void DebayerCpu::debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) +{ + DECLARE_SRC_POINTERS(uint16_t) + + for (int x = 0; x < (int)window_.width;) { + BGGR_BGR888(1, 1, 4) + GBRG_BGR888(1, 1, 4) + } +} + +void DebayerCpu::debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) +{ + DECLARE_SRC_POINTERS(uint16_t) + + for (int x = 0; x < (int)window_.width;) { + GRBG_BGR888(1, 1, 4) + RGGB_BGR888(1, 1, 4) + } +} + void DebayerCpu::debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) { const int width_in_bytes = window_.width * 5 / 4; @@ -170,6 +215,16 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf BayerFormat bayerFormat = BayerFormat::fromPixelFormat(inputFormat); + if ((bayerFormat.bitDepth == 8 || bayerFormat.bitDepth == 10) && + bayerFormat.packing == BayerFormat::Packing::None && + isStandardBayerOrder(bayerFormat.order)) { + config.bpp = (bayerFormat.bitDepth + 7) & ~7; + config.patternSize.width = 2; + config.patternSize.height = 2; + config.outputFormats = std::vector({ formats::RGB888 }); + return 0; + } + if (bayerFormat.bitDepth == 10 && bayerFormat.packing == BayerFormat::Packing::CSI2 && isStandardBayerOrder(bayerFormat.order)) { @@ -197,12 +252,57 @@ int DebayerCpu::getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &c return -EINVAL; } +/* + * Check for standard Bayer orders and set x_shift_ and swap debayer0/1, so that + * a single pair of BGGR debayer functions can be used for all 4 standard orders. + */ +int DebayerCpu::setupStandardBayerOrder(BayerFormat::Order order) +{ + switch (order) { + case BayerFormat::BGGR: + break; + case BayerFormat::GBRG: + x_shift_ = 1; /* BGGR -> GBRG */ + break; + case BayerFormat::GRBG: + std::swap(debayer0_, debayer1_); /* BGGR -> GRBG */ + break; + case BayerFormat::RGGB: + x_shift_ = 1; /* BGGR -> GBRG */ + std::swap(debayer0_, debayer1_); /* GBRG -> RGGB */ + break; + default: + return -EINVAL; + } + + return 0; +} + /* TODO: this ignores outputFormat since there is only 1 supported outputFormat for now */ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, [[maybe_unused]] PixelFormat outputFormat) { BayerFormat bayerFormat = BayerFormat::fromPixelFormat(inputFormat); + x_shift_ = 0; + + if ((bayerFormat.bitDepth == 8 || bayerFormat.bitDepth == 10) && + bayerFormat.packing == BayerFormat::Packing::None && + isStandardBayerOrder(bayerFormat.order)) { + switch (bayerFormat.bitDepth) { + case 8: + debayer0_ = &DebayerCpu::debayer8_BGBG_BGR888; + debayer1_ = &DebayerCpu::debayer8_GRGR_BGR888; + break; + case 10: + debayer0_ = &DebayerCpu::debayer10_BGBG_BGR888; + debayer1_ = &DebayerCpu::debayer10_GRGR_BGR888; + break; + } + setupStandardBayerOrder(bayerFormat.order); + return 0; + } + if (bayerFormat.bitDepth == 10 && bayerFormat.packing == BayerFormat::Packing::CSI2) { switch (bayerFormat.order) { From patchwork Sat Jan 13 14:22:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 19408 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 7AE02C32BD for ; Sat, 13 Jan 2024 14:23:19 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2354F62945; Sat, 13 Jan 2024 15:23:19 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1705155799; bh=yKqOHb0PaVLFqvzK2FMtDNXbnF8zJTMer4bge0eZ5Ew=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=uT9ASNzeJ2Q+rEQY1V4JhaIjVgbPLZdBkd5AH9Gl4Esr05q2a9YEzTgjtL6Ywx1df XNFVbUzIBt8DrnNc2X6ReBkiA4CGkXj8qUlNF5A/npR5cUllWIxMEWQQ4StiApoW4n /ncnHi8srDqEyAd4L2+si/Yc4GQB3GjcZb64WL8EK+E+9JQ0Iedh39CnYp8OiFStSg 7aKtsZJ9zBf6r6rbXUXBBiiUNr+M0nNTe0Z9fVxgL0r+2F7pewA4vJR+dQ5ecfV/zy S5mH4QpiSc8s/Tts70AKeQDAlyczb3pBKkp07T/vTTmEppdeVe0hIToOCkVDUVhy7y Lx/KPf85JHa5A== 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 0203A628B1 for ; Sat, 13 Jan 2024 15:23:16 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="a+NXN8C0"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1705155796; 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=Pa0Fyd790cew1kOWIPhZ75+OEi+zOdG8ysc+f1wvhRY=; b=a+NXN8C04SU9q5WtItm7Z1ojwj33y080Xz6AQPWKiafuWpCQy4UXwDXenOiP+vt3oB5nvg +S8Ex4Jx7aK9/TnCwQ0fwsCaYIwpUDkuMUqxCQzvKUYWt4X8pxYJqQnrdtoCMsLQqXtT24 tiB5CqQOMRfInbYkk62aYtB6R89ZcMM= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-687-oaE6KQq3Mpytou6fgjIV_g-1; Sat, 13 Jan 2024 09:23:09 -0500 X-MC-Unique: oaE6KQq3Mpytou6fgjIV_g-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id 71B0F29AA38D; Sat, 13 Jan 2024 14:23:09 +0000 (UTC) Received: from localhost.localdomain (unknown [10.39.192.58]) by smtp.corp.redhat.com (Postfix) with ESMTP id 758AF3C25; Sat, 13 Jan 2024 14:23:07 +0000 (UTC) To: libcamera-devel@lists.libcamera.org, Andrey Konovalov Date: Sat, 13 Jan 2024 15:22:18 +0100 Message-ID: <20240113142218.28063-19-hdegoede@redhat.com> In-Reply-To: <20240113142218.28063-1-hdegoede@redhat.com> References: <20240113142218.28063-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [libcamera-devel] [PATCH v2 18/18] libcamera: debayer_cpu: Add BGR888 output support 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: , X-Patchwork-Original-From: Hans de Goede via libcamera-devel From: Hans de Goede Reply-To: Hans de Goede Cc: Maxime Ripard , g.martti@gmail.com, t.langendam@gmail.com, srinivas.kandagatla@linaro.org, Pavel Machek , Bryan O'Donoghue , admin@dennisbonke.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" BGR888 is RGB888 with the red and blue pixels swapped, adjust the debayering to swap the red and blue pixels in the bayer pattern to add support for writing formats::BGR888. Signed-off-by: Hans de Goede Tested-by: Bryan O'Donoghue # sc8280xp Lenovo x13s Tested-by: Pavel Machek --- .../internal/software_isp/debayer_cpu.h | 1 + src/libcamera/software_isp/debayer_cpu.cpp | 43 ++++++++++++++++--- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/include/libcamera/internal/software_isp/debayer_cpu.h b/include/libcamera/internal/software_isp/debayer_cpu.h index 99914e2a..4ad4ba8f 100644 --- a/include/libcamera/internal/software_isp/debayer_cpu.h +++ b/include/libcamera/internal/software_isp/debayer_cpu.h @@ -129,6 +129,7 @@ private: unsigned int lineBufferIndex_; unsigned int x_shift_; /* Offset of 0/1 applied to window_.x */ bool enableInputMemcpy_; + bool swapRedBlueGains_; float gamma_correction_; int measuredFrames_; int64_t frameProcessTime_; diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp index d1f8fa15..6c794735 100644 --- a/src/libcamera/software_isp/debayer_cpu.cpp +++ b/src/libcamera/software_isp/debayer_cpu.cpp @@ -221,7 +221,7 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf config.bpp = (bayerFormat.bitDepth + 7) & ~7; config.patternSize.width = 2; config.patternSize.height = 2; - config.outputFormats = std::vector({ formats::RGB888 }); + config.outputFormats = std::vector({ formats::RGB888, formats::BGR888 }); return 0; } @@ -231,7 +231,7 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf config.bpp = 10; config.patternSize.width = 4; /* 5 bytes per *4* pixels */ config.patternSize.height = 2; - config.outputFormats = std::vector({ formats::RGB888 }); + config.outputFormats = std::vector({ formats::RGB888, formats::BGR888 }); return 0; } @@ -242,7 +242,7 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf int DebayerCpu::getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config) { - if (outputFormat == formats::RGB888) { + if (outputFormat == formats::RGB888 || outputFormat == formats::BGR888) { config.bpp = 24; return 0; } @@ -278,12 +278,41 @@ int DebayerCpu::setupStandardBayerOrder(BayerFormat::Order order) return 0; } -/* TODO: this ignores outputFormat since there is only 1 supported outputFormat for now */ -int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, [[maybe_unused]] PixelFormat outputFormat) +int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat) { BayerFormat bayerFormat = BayerFormat::fromPixelFormat(inputFormat); + swapRedBlueGains_ = false; + + switch (outputFormat) { + case formats::RGB888: + break; + case formats::BGR888: + /* Swap R and B in bayer order to generate BGR888 instead of RGB888 */ + swapRedBlueGains_ = true; + + switch (bayerFormat.order) { + case BayerFormat::BGGR: + bayerFormat.order = BayerFormat::RGGB; + break; + case BayerFormat::GBRG: + bayerFormat.order = BayerFormat::GRBG; + break; + case BayerFormat::GRBG: + bayerFormat.order = BayerFormat::GBRG; + break; + case BayerFormat::RGGB: + bayerFormat.order = BayerFormat::BGGR; + break; + default: + goto invalid_fmt; + } + break; + default: + goto invalid_fmt; + } + x_shift_ = 0; if ((bayerFormat.bitDepth == 8 || bayerFormat.bitDepth == 10) && @@ -327,6 +356,7 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, [[maybe_unused]] Pi } } +invalid_fmt: LOG(Debayer, Error) << "Unsupported input output format combination"; return -EINVAL; } @@ -566,6 +596,9 @@ void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams gamma_correction_ = params.gamma; } + if (swapRedBlueGains_) + std::swap(params.gainR, params.gainB); + for (int i = 0; i < 256; i++) { int idx;