[{"id":36261,"web_url":"https://patchwork.libcamera.org/comment/36261/","msgid":"<176055925768.162040.9228637979484542029@ping.linuxembedded.co.uk>","date":"2025-10-15T20:14:17","subject":"Re: [PATCH v3 08/39] libcamera: swstats_cpu: Add processFrame()\n\tmethod","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Bryan O'Donoghue (2025-10-15 02:22:20)\n> From: Hans de Goede <hdegoede@redhat.com>\n> \n> Add a method to the SwstatsCpu class to process a whole Framebuffer in\n> one go, rather then line by line. This is useful for gathering stats\n> when debayering is not necessary or is not done on the CPU.\n> \n> Reviewed-by: Milan Zamazal <mzamazal@redhat.com>\n> Signed-off-by: Hans de Goede <hdegoede@redhat.com>\n> [bod: various rebase spalts fixed]\n\ns/spalts/splats/\n\n> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>\n> ---\n>  .../internal/software_isp/swstats_cpu.h       | 15 ++++-\n>  src/libcamera/software_isp/software_isp.cpp   |  5 +-\n>  src/libcamera/software_isp/swstats_cpu.cpp    | 55 ++++++++++++++++++-\n>  3 files changed, 70 insertions(+), 5 deletions(-)\n> \n> diff --git a/include/libcamera/internal/software_isp/swstats_cpu.h b/include/libcamera/internal/software_isp/swstats_cpu.h\n> index fae575f8..64b3e23f 100644\n> --- a/include/libcamera/internal/software_isp/swstats_cpu.h\n> +++ b/include/libcamera/internal/software_isp/swstats_cpu.h\n> @@ -18,18 +18,23 @@\n>  #include <libcamera/geometry.h>\n>  \n>  #include \"libcamera/internal/bayer_format.h\"\n> +#include \"libcamera/internal/framebuffer.h\"\n> +#include \"libcamera/internal/global_configuration.h\"\n>  #include \"libcamera/internal/shared_mem_object.h\"\n>  #include \"libcamera/internal/software_isp/swisp_stats.h\"\n>  \n> +#include \"benchmark.h\"\n> +\n>  namespace libcamera {\n>  \n>  class PixelFormat;\n> +class MappedFrameBuffer;\n>  struct StreamConfiguration;\n>  \n>  class SwStatsCpu\n>  {\n>  public:\n> -       SwStatsCpu();\n> +       SwStatsCpu(const GlobalConfiguration &configuration);\n>         ~SwStatsCpu() = default;\n>  \n>         /*\n> @@ -50,6 +55,7 @@ public:\n>         void setWindow(const Rectangle &window);\n>         void startFrame(uint32_t frame);\n>         void finishFrame(uint32_t frame, uint32_t bufferId);\n> +       void processFrame(uint32_t frame, uint32_t bufferId, FrameBuffer *input);\n>  \n>         void processLine0(uint32_t frame, unsigned int y, const uint8_t *src[])\n>         {\n> @@ -79,6 +85,7 @@ public:\n>  \n>  private:\n>         using statsProcessFn = void (SwStatsCpu::*)(const uint8_t *src[]);\n> +       using processFrameFn = void (SwStatsCpu::*)(MappedFrameBuffer &in);\n>  \n>         int setupStandardBayerOrder(BayerFormat::Order order);\n>         /* Bayer 8 bpp unpacked */\n> @@ -91,6 +98,10 @@ private:\n>         void statsBGGR10PLine0(const uint8_t *src[]);\n>         void statsGBRG10PLine0(const uint8_t *src[]);\n>  \n> +       void processBayerFrame2(MappedFrameBuffer &in);\n> +\n> +       processFrameFn processFrame_;\n> +\n>         /* Variables set by configure(), used every line */\n>         statsProcessFn stats0_;\n>         statsProcessFn stats2_;\n> @@ -103,9 +114,11 @@ private:\n>         Size patternSize_;\n>  \n>         unsigned int xShift_;\n> +       unsigned int stride_;\n>  \n>         SharedMemObject<SwIspStats> sharedStats_;\n>         SwIspStats stats_;\n> +       Benchmark bench_;\n>  };\n>  \n>  } /* namespace libcamera */\n> diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp\n> index b7651b7d..6f1f88fe 100644\n> --- a/src/libcamera/software_isp/software_isp.cpp\n> +++ b/src/libcamera/software_isp/software_isp.cpp\n> @@ -107,14 +107,15 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor,\n>                 return;\n>         }\n>  \n> -       auto stats = std::make_unique<SwStatsCpu>();\n> +       const GlobalConfiguration &configuration = pipe->cameraManager()->_d()->configuration();\n> +\n> +       auto stats = std::make_unique<SwStatsCpu>(configuration);\n>         if (!stats->isValid()) {\n>                 LOG(SoftwareIsp, Error) << \"Failed to create SwStatsCpu object\";\n>                 return;\n>         }\n>         stats->statsReady.connect(this, &SoftwareIsp::statsReady);\n>  \n> -       const GlobalConfiguration &configuration = pipe->cameraManager()->_d()->configuration();\n>         debayer_ = std::make_unique<DebayerCpu>(std::move(stats), configuration);\n>         debayer_->inputBufferReady.connect(this, &SoftwareIsp::inputReady);\n>         debayer_->outputBufferReady.connect(this, &SoftwareIsp::outputReady);\n> diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp\n> index 55e764b0..48d12c51 100644\n> --- a/src/libcamera/software_isp/swstats_cpu.cpp\n> +++ b/src/libcamera/software_isp/swstats_cpu.cpp\n> @@ -16,6 +16,7 @@\n>  #include <libcamera/stream.h>\n>  \n>  #include \"libcamera/internal/bayer_format.h\"\n> +#include \"libcamera/internal/mapped_framebuffer.h\"\n>  \n>  namespace libcamera {\n>  \n> @@ -144,8 +145,8 @@ namespace libcamera {\n>  \n>  LOG_DEFINE_CATEGORY(SwStatsCpu)\n>  \n> -SwStatsCpu::SwStatsCpu()\n> -       : sharedStats_(\"softIsp_stats\")\n> +SwStatsCpu::SwStatsCpu(const GlobalConfiguration &configuration)\n> +       : sharedStats_(\"softIsp_stats\"), bench_(configuration)\n>  {\n>         if (!sharedStats_)\n>                 LOG(SwStatsCpu, Error)\n> @@ -386,11 +387,14 @@ int SwStatsCpu::setupStandardBayerOrder(BayerFormat::Order order)\n>   */\n>  int SwStatsCpu::configure(const StreamConfiguration &inputCfg)\n>  {\n> +       stride_ = inputCfg.stride;\n> +\n>         BayerFormat bayerFormat =\n>                 BayerFormat::fromPixelFormat(inputCfg.pixelFormat);\n>  \n>         if (bayerFormat.packing == BayerFormat::Packing::None &&\n>             setupStandardBayerOrder(bayerFormat.order) == 0) {\n> +               processFrame_ = &SwStatsCpu::processBayerFrame2;\n>                 switch (bayerFormat.bitDepth) {\n>                 case 8:\n>                         stats0_ = &SwStatsCpu::statsBGGR8Line0;\n> @@ -411,6 +415,7 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg)\n>                 /* Skip every 3th and 4th line, sample every other 2x2 block */\n>                 ySkipMask_ = 0x02;\n>                 xShift_ = 0;\n> +               processFrame_ = &SwStatsCpu::processBayerFrame2;\n\nI thought this was duplicated in the same scope - but looking up after\nit's applied looks correct here.\n\n\n>  \n>                 switch (bayerFormat.order) {\n>                 case BayerFormat::BGGR:\n> @@ -475,4 +480,50 @@ void SwStatsCpu::setWindow(const Rectangle &window)\n>         window_.height &= ~(patternSize_.height - 1);\n>  }\n>  \n> +void SwStatsCpu::processBayerFrame2(MappedFrameBuffer &in)\n> +{\n> +       const uint8_t *src = in.planes()[0].data();\n> +       const uint8_t *linePointers[3];\n> +\n> +       /* Adjust src for starting at window_.y */\n> +       src += window_.y * stride_;\n> +\n> +       for (unsigned int y = 0; y < window_.height; y += 2) {\n> +               if (y & ySkipMask_) {\n> +                       src += stride_ * 2;\n> +                       continue;\n> +               }\n> +\n> +               /* linePointers[0] is not used by any stats0_ functions */\n\nAha this looks bizarre, but I think that's because it's\n\n - previous line,\n - current line,\n - next line,\n\nSo I think this is all fine:\n\n\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\n> +               linePointers[1] = src;\n> +               linePointers[2] = src + stride_;\n> +               (this->*stats0_)(linePointers);\n> +               src += stride_ * 2;\n> +       }\n> +}\n> +\n> +/**\n> + * \\brief Calculate statistics for a frame in one go\n> + * \\param[in] frame The frame number\n> + * \\param[in] bufferId ID of the statistics buffer\n> + * \\param[in] input The frame to process\n> + *\n> + * This may only be called after a successful setWindow() call.\n> + */\n> +void SwStatsCpu::processFrame(uint32_t frame, uint32_t bufferId, FrameBuffer *input)\n> +{\n> +       bench_.startFrame();\n> +       startFrame(frame);\n> +\n> +       MappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read);\n> +       if (!in.isValid()) {\n> +               LOG(SwStatsCpu, Error) << \"mmap-ing buffer(s) failed\";\n> +               return;\n> +       }\n> +\n> +       (this->*processFrame_)(in);\n> +       finishFrame(frame, bufferId);\n> +       bench_.finishFrame();\n> +}\n> +\n>  } /* namespace libcamera */\n> -- \n> 2.51.0\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 79132BE080\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 15 Oct 2025 20:14:22 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id D1A5B60629;\n\tWed, 15 Oct 2025 22:14:21 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id BFB2A60615\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 15 Oct 2025 22:14:20 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 53467E7C;\n\tWed, 15 Oct 2025 22:12:41 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"sUOlhl9Z\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1760559161;\n\tbh=1zZmeGEoinaBIJGYzFkSAab19mIstyv2hYnPpkAoGxM=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=sUOlhl9Zg8yDDgUplooTmn8EzrPXNeWDMyJe4nCoX/8i1h69ocJ+ZRnpLy3Tjf+46\n\tN9sTDJhc1JSZonEZw4uY/wXNnZn3FvsmCgyzKYwM4bhlSmhU82AQgt4/iJoQr1mtEN\n\tA5QlPLuy22/W44gdK9DdrJ3HgvoAjFVJzPBAsfvs=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20251015012251.17508-9-bryan.odonoghue@linaro.org>","References":"<20251015012251.17508-1-bryan.odonoghue@linaro.org>\n\t<20251015012251.17508-9-bryan.odonoghue@linaro.org>","Subject":"Re: [PATCH v3 08/39] libcamera: swstats_cpu: Add processFrame()\n\tmethod","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"hdegoede@redhat.com, mzamazal@redhat.com, bryan.odonoghue@linaro.org,\n\tbod.linux@nxsw.ie","To":"Bryan O'Donoghue <bryan.odonoghue@linaro.org>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Wed, 15 Oct 2025 21:14:17 +0100","Message-ID":"<176055925768.162040.9228637979484542029@ping.linuxembedded.co.uk>","User-Agent":"alot/0.9.1","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":36262,"web_url":"https://patchwork.libcamera.org/comment/36262/","msgid":"<f2e462ca-6ed4-4fd7-8fc5-a78eb4984012@nxsw.ie>","date":"2025-10-15T20:55:19","subject":"Re: [PATCH v3 08/39] libcamera: swstats_cpu: Add processFrame()\n\tmethod","submitter":{"id":226,"url":"https://patchwork.libcamera.org/api/people/226/","name":"Bryan O'Donoghue","email":"bod.linux@nxsw.ie"},"content":"On 15/10/2025 21:14, Kieran Bingham wrote:\n>> [bod: various rebase spalts fixed]\n> s/spalts/splats/\n\nI done it on purpose your honour.\n\nSpalts is the apotheosis splats you know.\n\n---\nbod","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 02063C3259\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 15 Oct 2025 20:55:27 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 3CB0F6062A;\n\tWed, 15 Oct 2025 22:55:27 +0200 (CEST)","from tor.source.kernel.org (tor.source.kernel.org\n\t[IPv6:2600:3c04:e001:324:0:1991:8:25])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 0755160615\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 15 Oct 2025 22:55:24 +0200 (CEST)","from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58])\n\tby tor.source.kernel.org (Postfix) with ESMTP id 66C6762733;\n\tWed, 15 Oct 2025 20:55:23 +0000 (UTC)","by smtp.kernel.org (Postfix) with ESMTPSA id D0CE5C4CEF8;\n\tWed, 15 Oct 2025 20:55:21 +0000 (UTC)"],"Message-ID":"<f2e462ca-6ed4-4fd7-8fc5-a78eb4984012@nxsw.ie>","Date":"Wed, 15 Oct 2025 21:55:19 +0100","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH v3 08/39] libcamera: swstats_cpu: Add processFrame()\n\tmethod","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>,\n\tBryan O'Donoghue <bryan.odonoghue@linaro.org>,\n\tlibcamera-devel@lists.libcamera.org","Cc":"hdegoede@redhat.com, mzamazal@redhat.com","References":"<20251015012251.17508-1-bryan.odonoghue@linaro.org>\n\t<20251015012251.17508-9-bryan.odonoghue@linaro.org>\n\t<4gYVtKaoE3pQogBxTzpVbBfm9-3XQa8eXxeRAsPoaq41Oww6aoCNQTe63-ndjiu2T-mYIjsOiLwu8QEQ41o5yg==@protonmail.internalid>\n\t<176055925768.162040.9228637979484542029@ping.linuxembedded.co.uk>","From":"Bryan O'Donoghue <bod.linux@nxsw.ie>","Content-Language":"en-US","In-Reply-To":"<176055925768.162040.9228637979484542029@ping.linuxembedded.co.uk>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"7bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]