From patchwork Thu Dec 14 12:13:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 19319 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 F1249BD87C for ; Thu, 14 Dec 2023 12:14:06 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 936DA62B58; Thu, 14 Dec 2023 13:14:06 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1702556046; bh=wzZtq87pwIp4bkDwv99FE+gohvDyk6GlJxITW4iDdh8=; 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=HbZvufE3ug2Dtga1XoTJJJyl1ISAE6DAKMRRHPuGIyDmo4nA1MLOOHC0i6damns1d DTpUdjHMA28v6+cF0lHobPvysPJ7FO9E97dZFiQjXR/4AQ1RK3VwRAHWmga2T9WVGz wuhhOT2nsg2Z74RyIVEDrq0NtCjZwDCXxZLOyNVhyJG2Es3aqtRHET19cMsDf9EQXp kjkDHe29zkhvsBWmpVwwasKHy9TLiecXTIDJTVMyrVfHIBD8sxARFedlRAHwXXKCCl pJaGzsyU6B9Qz5v6xsJFYRgRU/PUyctRsKmwOcQA7jERvjFOp2TUREVq0K0j5U0WuR YawlV1mQVK2qQ== 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 20E1C62B52 for ; Thu, 14 Dec 2023 13:14:04 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="T/k+kqD9"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702556043; 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=dWnOKmi+sc5buSYcLiTXGs4X2NRo61ufepPWcmP87vM=; b=T/k+kqD9sfmgJ6Jfv9Yd2XAVUIHpJmnuNmJRlrf6c3mlXlxceqSTQ1mkEefGWaPzxbl9RD wjp87iTU5iftQTi9UGHUUeOCavIFKPC+nvnJSuqnXqX5rQbrRQht+XgvPxZkt5nYk5SKBc qcX79EsSeVEiOsFl24KLKKomIJLDpEs= 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-561-ubUzBS2MNyar7QWjPNJQIg-1; Thu, 14 Dec 2023 07:13:58 -0500 X-MC-Unique: ubUzBS2MNyar7QWjPNJQIg-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (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 5DD4E848C07; Thu, 14 Dec 2023 12:13:58 +0000 (UTC) Received: from shalem.redhat.com (unknown [10.39.194.72]) by smtp.corp.redhat.com (Postfix) with ESMTP id ECD581121306; Thu, 14 Dec 2023 12:13:56 +0000 (UTC) To: libcamera-devel@lists.libcamera.org, Andrey Konovalov Date: Thu, 14 Dec 2023 13:13:42 +0100 Message-ID: <20231214121350.206015-5-hdegoede@redhat.com> In-Reply-To: <20231214121350.206015-1-hdegoede@redhat.com> References: <20231214121350.206015-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.3 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [libcamera-devel] [PATCH 04/11] 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 Suggested-by: Pavel Machek Signed-off-by: Pavel Machek Signed-off-by: Hans de Goede --- .../internal/software_isp/meson.build | 1 + .../internal/software_isp/swstats_cpu.h | 46 +++++ src/libcamera/software_isp/meson.build | 1 + src/libcamera/software_isp/swstats_cpu.cpp | 169 ++++++++++++++++++ 4 files changed, 217 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..0ceb995f --- /dev/null +++ b/include/libcamera/internal/software_isp/swstats_cpu.h @@ -0,0 +1,46 @@ +/* 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 : public SwStats +{ +public: + SwStatsCpu(); + ~SwStatsCpu() { } + + bool isValid() const { return sharedStats_.fd().isValid(); } + const SharedFD &getStatsFD() { return sharedStats_.fd(); } + int configure(const StreamConfiguration &inputCfg); + /* FIXME this should be dropped once AWB has moved to the IPA */ + SwIspStats getStats() { return *sharedStats_; } +private: + void statsBGGR10PLine0(const uint8_t *src, unsigned int stride); + void statsGBRG10PLine0(const uint8_t *src, unsigned int stride); + void statsGRBG10PLine0(const uint8_t *src, unsigned int stride); + void statsRGGB10PLine0(const uint8_t *src, unsigned int stride); + void resetStats(void); + void finishStats(void); + + SharedMemObject sharedStats_; + SwIspStats stats_; + + unsigned int bright_sum_; + unsigned int too_bright_sum_; +}; + +} /* 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..15f23953 --- /dev/null +++ b/src/libcamera/software_isp/swstats_cpu.cpp @@ -0,0 +1,169 @@ +/* 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 = 170U << 8; +static const unsigned int TOO_BRIGHT_LVL = 210U << 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 */ + +static inline __attribute__((always_inline)) void +statsBayer10P(const int width, const uint8_t *src0, const uint8_t *src1, bool bggr, unsigned int &bright_sum_, unsigned int &too_bright_sum_, SwIspStats &stats_) +{ + const int width_in_bytes = width * 5 / 4; + uint8_t r, g, b, g2; + unsigned int y_val; + unsigned int sumR = 0; + unsigned int sumG = 0; + unsigned int sumB = 0; + + unsigned int bright_sum = 0; + unsigned int too_bright_sum = 0; + + 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; + + sumR += r; + sumG += g; + sumB += b; + + y_val = r * RED_Y_MUL; + y_val += g * GREEN_Y_MUL; + y_val += b * BLUE_Y_MUL; + if (y_val > BRIGHT_LVL) ++bright_sum; + if (y_val > TOO_BRIGHT_LVL) ++too_bright_sum; + } + + stats_.sumR_ += sumR; + stats_.sumG_ += sumG; + stats_.sumB_ += sumB; + + bright_sum_ += bright_sum; + too_bright_sum_ += too_bright_sum; +} + +void SwStatsCpu::statsBGGR10PLine0(const uint8_t *src, unsigned int stride) +{ + statsBayer10P(window_.width, src, src + stride, true, bright_sum_, too_bright_sum_, stats_); +} + +void SwStatsCpu::statsGBRG10PLine0(const uint8_t *src, unsigned int stride) +{ + statsBayer10P(window_.width, src, src + stride, false, bright_sum_, too_bright_sum_, stats_); +} + +void SwStatsCpu::statsGRBG10PLine0(const uint8_t *src, unsigned int stride) +{ + /* GRBG is BGGR with the lines swapped */ + statsBayer10P(window_.width, src + stride, src, true, bright_sum_, too_bright_sum_, stats_); +} + +void SwStatsCpu::statsRGGB10PLine0(const uint8_t *src, unsigned int stride) +{ + /* RGGB is GBRG with the lines swapped */ + statsBayer10P(window_.width, src + stride, src, false, bright_sum_, too_bright_sum_, stats_); +} + +void SwStatsCpu::resetStats(void) +{ + stats_.sumR_ = 0; + stats_.sumB_ = 0; + stats_.sumG_ = 0; + + bright_sum_ = 0; + too_bright_sum_ = 0; +} + +void SwStatsCpu::finishStats(void) +{ + /* calculate the fractions of "bright" and "too bright" pixels */ + stats_.bright_ratio = (float)bright_sum_ / (window_.height * window_.width / 16); + stats_.too_bright_ratio = (float)too_bright_sum_ / (window_.height * window_.width / 16); + + *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_ = 0x0c; /* Skip every 3th and 4th line */ + x_shift_ = 0; + + switch (bayerFormat.order) { + case BayerFormat::BGGR: + stats0_ = (SwStats::statsProcessFn)&SwStatsCpu::statsBGGR10PLine0; + return 0; + case BayerFormat::GBRG: + stats0_ = (SwStats::statsProcessFn)&SwStatsCpu::statsGBRG10PLine0; + return 0; + case BayerFormat::GRBG: + stats0_ = (SwStats::statsProcessFn)&SwStatsCpu::statsGRBG10PLine0; + return 0; + case BayerFormat::RGGB: + stats0_ = (SwStats::statsProcessFn)&SwStatsCpu::statsRGGB10PLine0; + return 0; + default: + break; + } + /* } else if (future supported fmts) { ... */ + } + + LOG(SwStats, Info) + << "Unsupported input format " << inputCfg.pixelFormat.toString(); + return -EINVAL; +} + +} /* namespace libcamera */