From patchwork Thu Dec 14 21:37:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Machek X-Patchwork-Id: 19328 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 B9001BD87C for ; Thu, 14 Dec 2023 21:37:31 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 02DC962B2A; Thu, 14 Dec 2023 22:37:31 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1702589851; bh=WfxhVSvHfG8lERROEGr9Hv/HVLIBBTEbNF54sDHgem4=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=TSVvmVZi+i4kb8mzYuSevAIQpuehSz86pRrHcalTJr4qjljvJzbqPZaWDhw8hhpY+ lOW/K0Mtv45wUBnmcXAvAdrLTopo/WlrvOQadOJ+Ws7sRYn0Qmlh3hoTMeWKbvA5s5 yN+X9w9O+Kw/5xqmSeIOXFcEGus85Ascr6JePY2Sb/Rl1LZhQ1kGjSA9IO10xfVL27 bZGp8sD4Bw4x40W6g47BH1E0DY5xZyUC0qYxAHzWXMdQeNColJ5B5MAw9+hwv111n4 f1LYFt/2IB36X+c/Bg9XJdJN1gHd60eQ8sb+RrxBL1KzeTOfHvCaQ7a/yDxTO9O2BY oNsMT7YdzybRQ== Received: from jabberwock.ucw.cz (jabberwock.ucw.cz [46.255.230.98]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F0E6661D97 for ; Thu, 14 Dec 2023 22:37:28 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ucw.cz header.i=@ucw.cz header.b="D+AmeXn0"; dkim-atps=neutral Received: by jabberwock.ucw.cz (Postfix, from userid 1017) id AA1A71C006F; Thu, 14 Dec 2023 22:37:28 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ucw.cz; s=gen1; t=1702589848; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type; bh=gWZX1rGZJJWFDz6LHEWoaImjs3+/OLyFKBjcW5Y3GHM=; b=D+AmeXn0Tetp0zObx57NjQBEgpH7mSFCVw8WF252CFWN4Tac+gh6xBcvYxcM+bcJv8lSb/ hfLKecvEozu7p0M5pHd+oWcLa0JvZjKS0IywfimSFZvoaQXaAZyziFI2GF4/z7CJXdCraA znbSseyGHUQVIrXKDrPiNb/BHWCidYM= Date: Thu, 14 Dec 2023 22:37:28 +0100 To: hdegoede@redhat.com, libcamera-devel@lists.libcamera.org Message-ID: MIME-Version: 1.0 Content-Disposition: inline Signed-off-by: Pavel Machek Subject: [libcamera-devel] [RFC] Add 8-bit bayer 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: Pavel Machek via libcamera-devel From: Pavel Machek Reply-To: Pavel Machek Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" --- Did I get it mostly right? I can't test other formats but providing them should not be too hard. Does it make sense to add this to your series or is it better to just wait for v1 to be merged? diff --git a/include/libcamera/internal/software_isp/debayer_cpu.h b/include/libcamera/internal/software_isp/debayer_cpu.h index 7fb5be77..f3bb4321 100644 --- a/include/libcamera/internal/software_isp/debayer_cpu.h +++ b/include/libcamera/internal/software_isp/debayer_cpu.h @@ -67,6 +67,9 @@ private: void debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src); void debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src); + void debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src); + void debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src); + typedef void (DebayerCpu::*debayerFn)(uint8_t *dst, const uint8_t *src); struct DebayerInputConfig { diff --git a/include/libcamera/internal/software_isp/swstats_cpu.h b/include/libcamera/internal/software_isp/swstats_cpu.h index 0ceb995f..3c43e146 100644 --- a/include/libcamera/internal/software_isp/swstats_cpu.h +++ b/include/libcamera/internal/software_isp/swstats_cpu.h @@ -29,6 +29,8 @@ public: /* FIXME this should be dropped once AWB has moved to the IPA */ SwIspStats getStats() { return *sharedStats_; } private: + void statsBGGR8Line0(const uint8_t *src, unsigned int stride); + 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); diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp index 3eacdd5d..52910a03 100644 --- a/src/libcamera/software_isp/debayer_cpu.cpp +++ b/src/libcamera/software_isp/debayer_cpu.cpp @@ -111,6 +111,36 @@ void DebayerCpu::debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src) } } +void DebayerCpu::debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src) +{ + const int width_in_bytes = window_.width; + struct ctxt_8bit_src c = { + src - inputConfig_.stride, src, src + inputConfig_.stride, + red_, green_, blue_ }; + + for (int x = 0; x < width_in_bytes; ) { + /* Even pixel */ + bggr8_bgr888(c, dst, x++, 1, 1); + /* Odd pixel BGGR -> GBRG */ + gbrg8_bgr888(c, dst, x++, 1, 1); + } +} + +void DebayerCpu::debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src) +{ + const int width_in_bytes = window_.width; + struct ctxt_8bit_src c = { + src - inputConfig_.stride, src, src + inputConfig_.stride, + red_, green_, blue_ }; + + for (int x = 0; x < width_in_bytes; ) { + /* Even pixel */ + grbg8_bgr888(c, dst, x++, 1, 1); + /* Odd pixel GRBG -> RGGB */ + rggb8_bgr888(c, dst, x++, 1, 1); + } +} + void DebayerCpu::debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src) { const int width_in_bytes = window_.width * 5 / 4; @@ -152,6 +182,22 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf BayerFormat bayerFormat = BayerFormat::fromPixelFormat(inputFormat); + if (bayerFormat.bitDepth == 8) { + config.bpp = 8; + config.patternSize.height = 2; + config.patternSize.width = 4; + config.x_shift = 0; + config.outputFormats = std::vector({ formats::RGB888 }); + + switch (bayerFormat.order) { + case BayerFormat::BGGR: + return 0; + default: + break; + } + /* } else if (future supported fmts) { ... */ + } + if (bayerFormat.bitDepth == 10 && bayerFormat.packing == BayerFormat::Packing::CSI2) { config.bpp = 10; @@ -195,6 +241,17 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, [[maybe_unused]] Pi BayerFormat bayerFormat = BayerFormat::fromPixelFormat(inputFormat); + if (bayerFormat.bitDepth == 8) { + switch (bayerFormat.order) { + case BayerFormat::BGGR: + debayer0_ = &DebayerCpu::debayer8_BGBG_BGR888; + debayer1_ = &DebayerCpu::debayer8_GRGR_BGR888; + return 0; + default: + break; + } + } + if (bayerFormat.bitDepth == 10 && bayerFormat.packing == BayerFormat::Packing::CSI2) { switch (bayerFormat.order) { diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp index 15f23953..e65b1b65 100644 --- a/src/libcamera/software_isp/swstats_cpu.cpp +++ b/src/libcamera/software_isp/swstats_cpu.cpp @@ -37,9 +37,9 @@ 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_) +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_, bool is10p) { - const int width_in_bytes = width * 5 / 4; + const int width_in_bytes = width * (4 + is10p) / 4; uint8_t r, g, b, g2; unsigned int y_val; unsigned int sumR = 0; @@ -49,7 +49,7 @@ statsBayer10P(const int width, const uint8_t *src0, const uint8_t *src1, bool bg unsigned int bright_sum = 0; unsigned int too_bright_sum = 0; - for (int x = 0; x < width_in_bytes; x += 5) { + for (int x = 0; x < width_in_bytes; x += (4 + is10p)) { if (bggr) { /* BGGR */ b = src0[x]; @@ -84,26 +84,31 @@ statsBayer10P(const int width, const uint8_t *src0, const uint8_t *src1, bool bg too_bright_sum_ += too_bright_sum; } +void SwStatsCpu::statsBGGR8Line0(const uint8_t *src, unsigned int stride) +{ + statsBayer10P(window_.width, src, src + stride, true, bright_sum_, too_bright_sum_, stats_, false); +} + void SwStatsCpu::statsBGGR10PLine0(const uint8_t *src, unsigned int stride) { - statsBayer10P(window_.width, src, src + stride, true, bright_sum_, too_bright_sum_, stats_); + statsBayer10P(window_.width, src, src + stride, true, bright_sum_, too_bright_sum_, stats_, true); } void SwStatsCpu::statsGBRG10PLine0(const uint8_t *src, unsigned int stride) { - statsBayer10P(window_.width, src, src + stride, false, bright_sum_, too_bright_sum_, stats_); + statsBayer10P(window_.width, src, src + stride, false, bright_sum_, too_bright_sum_, stats_, true); } 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_); + statsBayer10P(window_.width, src + stride, src, true, bright_sum_, too_bright_sum_, stats_, true); } 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_); + statsBayer10P(window_.width, src + stride, src, false, bright_sum_, too_bright_sum_, stats_, true); } void SwStatsCpu::resetStats(void) @@ -134,6 +139,24 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg) startFrame_ = (SwStats::statsVoidFn)&SwStatsCpu::resetStats; finishFrame_ = (SwStats::statsVoidFn)&SwStatsCpu::finishStats; + if (bayerFormat.bitDepth == 8) { + bpp_ = 8; + patternSize_.height = 2; + patternSize_.width = 4; + y_skip_mask_ = 0x0c; /* Skip every 3th and 4th line */ + x_shift_ = 0; + + switch (bayerFormat.order) { + case BayerFormat::BGGR: + stats0_ = (SwStats::statsProcessFn)&SwStatsCpu::statsBGGR8Line0; + return 0; + default: + break; + } + /* } else if (future supported fmts) { ... */ + } + + if (bayerFormat.bitDepth == 10 && bayerFormat.packing == BayerFormat::Packing::CSI2) { bpp_ = 10;