[{"id":38333,"web_url":"https://patchwork.libcamera.org/comment/38333/","msgid":"<af87b2b8-eac4-49d0-8f63-94af8ae9ca29@ideasonboard.com>","date":"2026-03-04T13:47:56","subject":"Re: [PATCH v5 2/5] software_isp: debayer_cpu: Add DebayerCpuThread\n\tclass","submitter":{"id":216,"url":"https://patchwork.libcamera.org/api/people/216/","name":"Barnabás Pőcze","email":"barnabas.pocze@ideasonboard.com"},"content":"Hi\n\n2026. 03. 04. 8:50 keltezéssel, Hans de Goede írta:\n> Add a DebayerCpuThreadclass and use this in the inner render loop.\n> This contains data which needs to be separate per thread.\n> \n> This is a preparation patch for making DebayerCpu support multi-threading.\n> \n> Benchmarking on the Arduino Uno-Q with a weak CPU which is good for\n> performance testing, shows 146-147ms per 3272x2464 frame both before and\n> after this change, with things maybe being 0.5 ms slower after this change.\n> \n> Reviewed-by: Milan Zamazal <mzamazal@redhat.com>\n> Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>\n> ---\n> Changes in v4:\n> - Move kMaxLineBuffers constant to DebayerCpuThread class\n> - Add Milan's Reviewed-by\n> \n> Changes in v3:\n> - Use std::unique_ptr for the DebayerCpuThread pointers\n> - Document new DebayerCpuThread class\n> - Make DebayerCpuThread inherit from both Thread and Object\n> \n> Changes in v2:\n> - Replace the DebayerCpuThreadData struct from v1 with a DebayerCpuThread\n>    class, derived from Object to allow calling invokeMethod for thread re-use\n>    in followup patches\n> - As part of this also move a bunch of methods which primarily deal with\n>    per thread data: setupInputMemcpy(), shiftLinePointers(), memcpyNextLine(),\n>    process*() to the new DebayerCpuThread class\n> ---\n>   src/libcamera/software_isp/debayer_cpu.cpp | 247 +++++++++++++++------\n>   src/libcamera/software_isp/debayer_cpu.h   |  23 +-\n>   2 files changed, 191 insertions(+), 79 deletions(-)\n> \n> diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp\n> index e7b012105..d57d640df 100644\n> --- a/src/libcamera/software_isp/debayer_cpu.cpp\n> +++ b/src/libcamera/software_isp/debayer_cpu.cpp\n> @@ -18,6 +18,8 @@\n>   \n>   #include <linux/dma-buf.h>\n>   \n> +#include <libcamera/base/thread.h>\n> +\n>   #include <libcamera/formats.h>\n>   \n>   #include \"libcamera/internal/bayer_format.h\"\n> @@ -27,6 +29,55 @@\n>   \n>   namespace libcamera {\n>   \n> +/**\n> + * \\brief Class representing one CPU debayering thread\n> + *\n> + * Implementation for CPU based debayering threads.\n> + */\n> +class DebayerCpuThread : public Thread, public Object\n> +{\n> +public:\n> +\tDebayerCpuThread(DebayerCpu *debayer, unsigned int threadIndex,\n> +\t\t\t bool enableInputMemcpy);\n> +\n> +\tvoid configure(unsigned int yStart, unsigned int yEnd);\n> +\tvoid process(uint32_t frame, const uint8_t *src, uint8_t *dst);\n> +\n> +private:\n> +\tvoid setupInputMemcpy(const uint8_t *linePointers[]);\n> +\tvoid shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src);\n> +\tvoid memcpyNextLine(const uint8_t *linePointers[]);\n> +\tvoid process2(uint32_t frame, const uint8_t *src, uint8_t *dst);\n> +\tvoid process4(uint32_t frame, const uint8_t *src, uint8_t *dst);\n> +\n> +\t/* Max. supported Bayer pattern height is 4, debayering this requires 5 lines */\n> +\tstatic constexpr unsigned int kMaxLineBuffers = 5;\n> +\n> +\tDebayerCpu *debayer_;\n> +\tunsigned int threadIndex_;\n> +\tunsigned int yStart_;\n> +\tunsigned int yEnd_;\n> +\tunsigned int lineBufferLength_;\n> +\tunsigned int lineBufferPadding_;\n> +\tunsigned int lineBufferIndex_;\n> +\tstd::vector<uint8_t> lineBuffers_[kMaxLineBuffers];\n> +\tbool enableInputMemcpy_;\n> +};\n> +\n> +/**\n> + * \\brief Construct a DebayerCpuThread object\n> + * \\param[in] debayer pointer back to the DebayerCpuObject this thread belongs to\n> + * \\param[in] threadIndex 0 .. n thread-index value for the thread\n> + * \\param[in] enableInputMemcpy when set copy input data to a heap buffer before use\n> + */\n> +DebayerCpuThread::DebayerCpuThread(DebayerCpu *debayer, unsigned int threadIndex,\n> +\t\t\t\t   bool enableInputMemcpy)\n> +\t: Thread(\"DebayerCpu:\" + std::to_string(threadIndex)),\n> +\t  debayer_(debayer), threadIndex_(threadIndex),\n> +\t  enableInputMemcpy_(enableInputMemcpy)\n> +{\n> +}\n> +\n>   /**\n>    * \\class DebayerCpu\n>    * \\brief Class for debayering on the CPU\n> @@ -53,8 +104,14 @@ DebayerCpu::DebayerCpu(std::unique_ptr<SwStatsCpu> stats, const GlobalConfigurat\n>   \t * \\todo Make memcpy automatic based on runtime detection of platform\n>   \t * capabilities.\n>   \t */\n> -\tenableInputMemcpy_ =\n> +\tbool enableInputMemcpy =\n>   \t\tconfiguration.option<bool>({ \"software_isp\", \"copy_input_buffer\" }).value_or(true);\n> +\n> +\t/* Just one thread object for now, which will be called inline rather than async */\n> +\tthreads_.resize(1);\n> +\n> +\tfor (unsigned int i = 0; i < threads_.size(); i++)\n> +\t\tthreads_[i] = std::make_unique<DebayerCpuThread>(this, i, enableInputMemcpy);\n>   }\n>   \n>   DebayerCpu::~DebayerCpu() = default;\n> @@ -484,7 +541,7 @@ int DebayerCpu::configure(const StreamConfiguration &inputCfg,\n>   \tif (getInputConfig(inputCfg.pixelFormat, inputConfig_) != 0)\n>   \t\treturn -EINVAL;\n>   \n> -\tif (stats_->configure(inputCfg) != 0)\n> +\tif (stats_->configure(inputCfg, threads_.size()) != 0)\n>   \t\treturn -EINVAL;\n>   \n>   \tconst Size &statsPatternSize = stats_->patternSize();\n> @@ -548,17 +605,43 @@ int DebayerCpu::configure(const StreamConfiguration &inputCfg,\n>   \t */\n>   \tstats_->setWindow(Rectangle(window_.size()));\n>   \n> +\tunsigned int yStart = 0;\n> +\tunsigned int linesPerThread = (window_.height / threads_.size()) &\n> +\t\t\t\t      ~(inputConfig_.patternSize.height - 1);\n> +\tunsigned int i;\n> +\n> +\tfor (i = 0; i < (threads_.size() - 1); i++) {\n> +\t\tthreads_[i]->configure(yStart, yStart + linesPerThread);\n> +\t\tyStart += linesPerThread;\n> +\t}\n> +\tthreads_[i]->configure(yStart, window_.height);\n\nOr possibly `threads_.back()->configure(...`\n\n\n> +\n> +\treturn 0;\n> +}\n> +\n> +/**\n> + * \\brief Configure thread to process a specific part of the image\n> + * \\param[in] yStart y coordinate of first line to process\n> + * \\param[in] yEnd y coordinate of the line at which to stop processing\n> + *\n> + * Configure the thread to process lines yStart - (yEnd - 1).\n\nThis is a bit confusing in my opinion because `-` means two different things\nin the same sentence. Maybe \"lines from yStart to yEnd - 1\", or maybe\n\"lines [yStart, yEnd)\".\n\n\n> + */\n> [...]\n> diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h\n> index 7a6517462..780576090 100644\n> --- a/src/libcamera/software_isp/debayer_cpu.h\n> +++ b/src/libcamera/software_isp/debayer_cpu.h\n> @@ -26,6 +26,7 @@\n>   \n>   namespace libcamera {\n>   \n> +class DebayerCpuThread;\n>   class DebayerCpu : public Debayer\n>   {\n>   public:\n> @@ -44,6 +45,8 @@ public:\n>   \tconst SharedFD &getStatsFD() { return stats_->getStatsFD(); }\n>   \n>   private:\n> +\tfriend class DebayerCpuThread;\n> +\n>   \t/**\n>   \t * \\brief Called to debayer 1 line of Bayer input data to output format\n>   \t * \\param[out] dst Pointer to the start of the output line to write\n> @@ -74,6 +77,11 @@ private:\n>   \t */\n>   \tusing debayerFn = void (DebayerCpu::*)(uint8_t *dst, const uint8_t *src[]);\n>   \n> +\tvoid debayer0(uint8_t *dst, const uint8_t *src[]) { (this->*debayer0_)(dst, src); }\n> +\tvoid debayer1(uint8_t *dst, const uint8_t *src[]) { (this->*debayer1_)(dst, src); }\n> +\tvoid debayer2(uint8_t *dst, const uint8_t *src[]) { (this->*debayer2_)(dst, src); }\n> +\tvoid debayer3(uint8_t *dst, const uint8_t *src[]) { (this->*debayer3_)(dst, src); }\n> +\n>   \t/* 8-bit raw bayer format */\n>   \ttemplate<bool addAlphaByte, bool ccmEnabled>\n>   \tvoid debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);\n> @@ -105,17 +113,9 @@ private:\n>   \tint setDebayerFunctions(PixelFormat inputFormat,\n>   \t\t\t\tPixelFormat outputFormat,\n>   \t\t\t\tbool ccmEnabled);\n> -\tvoid setupInputMemcpy(const uint8_t *linePointers[]);\n> -\tvoid shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src);\n> -\tvoid memcpyNextLine(const uint8_t *linePointers[]);\n> -\tvoid process2(uint32_t frame, const uint8_t *src, uint8_t *dst);\n> -\tvoid process4(uint32_t frame, const uint8_t *src, uint8_t *dst);\n>   \tvoid updateGammaTable(const DebayerParams &params);\n>   \tvoid updateLookupTables(const DebayerParams &params);\n>   \n> -\t/* Max. supported Bayer pattern height is 4, debayering this requires 5 lines */\n> -\tstatic constexpr unsigned int kMaxLineBuffers = 5;\n> -\n>   \tstatic constexpr unsigned int kRGBLookupSize = 256;\n>   \tstatic constexpr unsigned int kGammaLookupSize = 1024;\n>   \tstruct CcmColumn {\n> @@ -142,12 +142,9 @@ private:\n>   \tdebayerFn debayer3_;\n>   \tRectangle window_;\n>   \tstd::unique_ptr<SwStatsCpu> stats_;\n> -\tstd::vector<uint8_t> lineBuffers_[kMaxLineBuffers];\n> -\tunsigned int lineBufferLength_;\n> -\tunsigned int lineBufferPadding_;\n> -\tunsigned int lineBufferIndex_;\n>   \tunsigned int xShift_; /* Offset of 0/1 applied to window_.x */\n> -\tbool enableInputMemcpy_;\n> +\n> +\tstd::vector<std::unique_ptr<DebayerCpuThread>>threads_;\n\nMissing space before the name.\n\nTested-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> # ThinkPad X1 Yoga Gen 7 + ov2740\n\n\n>   };\n>   \n>   } /* namespace libcamera */","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 D684EBE086\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed,  4 Mar 2026 13:48:01 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 8CACD623A7;\n\tWed,  4 Mar 2026 14:48:01 +0100 (CET)","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 403746239D\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed,  4 Mar 2026 14:48:00 +0100 (CET)","from [192.168.33.100] (185.182.214.224.nat.pool.zt.hu\n\t[185.182.214.224])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id A70BE838;\n\tWed,  4 Mar 2026 14:46:57 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"C/WgQ2zC\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1772632017;\n\tbh=NHvY46uW3uD1XWcLZlaYHcAzpa5nV+BHOeEAE7ZogCA=;\n\th=Date:Subject:To:References:From:In-Reply-To:From;\n\tb=C/WgQ2zCLMdppeCqlll6+iKPYxxMG+aEZAcIBz1cXfGIcKnz1OJTQopaIFdocUGZt\n\tSyiCB1ocZyeScmg/9ldZKaWRQjfSV2jkrYCclUkKYavuj9iRmTG372sU4BVVE2kaHE\n\tTEXdrwxe4GXi0VnsF5XCkcb+S+CsR1PsWx5la0xo=","Message-ID":"<af87b2b8-eac4-49d0-8f63-94af8ae9ca29@ideasonboard.com>","Date":"Wed, 4 Mar 2026 14:47:56 +0100","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH v5 2/5] software_isp: debayer_cpu: Add DebayerCpuThread\n\tclass","To":"Hans de Goede <johannes.goede@oss.qualcomm.com>,\n\tlibcamera-devel@lists.libcamera.org, Milan Zamazal <mzamazal@redhat.com>","References":"<20260304075052.11599-1-johannes.goede@oss.qualcomm.com>\n\t<20260304075052.11599-3-johannes.goede@oss.qualcomm.com>","From":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","Content-Language":"en-US, hu-HU","In-Reply-To":"<20260304075052.11599-3-johannes.goede@oss.qualcomm.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"8bit","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":38335,"web_url":"https://patchwork.libcamera.org/comment/38335/","msgid":"<027ae3d0-4c6c-4af2-8594-202834c31a46@oss.qualcomm.com>","date":"2026-03-05T12:04:28","subject":"Re: [PATCH v5 2/5] software_isp: debayer_cpu: Add DebayerCpuThread\n\tclass","submitter":{"id":242,"url":"https://patchwork.libcamera.org/api/people/242/","name":"Hans de Goede","email":"johannes.goede@oss.qualcomm.com"},"content":"Hi,\n\nOn 4-Mar-26 14:47, Barnabás Pőcze wrote:\n> Hi\n> \n> 2026. 03. 04. 8:50 keltezéssel, Hans de Goede írta:\n>> Add a DebayerCpuThreadclass and use this in the inner render loop.\n>> This contains data which needs to be separate per thread.\n>>\n>> This is a preparation patch for making DebayerCpu support multi-threading.\n>>\n>> Benchmarking on the Arduino Uno-Q with a weak CPU which is good for\n>> performance testing, shows 146-147ms per 3272x2464 frame both before and\n>> after this change, with things maybe being 0.5 ms slower after this change.\n>>\n>> Reviewed-by: Milan Zamazal <mzamazal@redhat.com>\n>> Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>\n>> ---\n>> Changes in v4:\n>> - Move kMaxLineBuffers constant to DebayerCpuThread class\n>> - Add Milan's Reviewed-by\n>>\n>> Changes in v3:\n>> - Use std::unique_ptr for the DebayerCpuThread pointers\n>> - Document new DebayerCpuThread class\n>> - Make DebayerCpuThread inherit from both Thread and Object\n>>\n>> Changes in v2:\n>> - Replace the DebayerCpuThreadData struct from v1 with a DebayerCpuThread\n>>    class, derived from Object to allow calling invokeMethod for thread re-use\n>>    in followup patches\n>> - As part of this also move a bunch of methods which primarily deal with\n>>    per thread data: setupInputMemcpy(), shiftLinePointers(), memcpyNextLine(),\n>>    process*() to the new DebayerCpuThread class\n>> ---\n>>   src/libcamera/software_isp/debayer_cpu.cpp | 247 +++++++++++++++------\n>>   src/libcamera/software_isp/debayer_cpu.h   |  23 +-\n>>   2 files changed, 191 insertions(+), 79 deletions(-)\n>>\n>> diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp\n>> index e7b012105..d57d640df 100644\n>> --- a/src/libcamera/software_isp/debayer_cpu.cpp\n>> +++ b/src/libcamera/software_isp/debayer_cpu.cpp\n>> @@ -18,6 +18,8 @@\n>>     #include <linux/dma-buf.h>\n>>   +#include <libcamera/base/thread.h>\n>> +\n>>   #include <libcamera/formats.h>\n>>     #include \"libcamera/internal/bayer_format.h\"\n>> @@ -27,6 +29,55 @@\n>>     namespace libcamera {\n>>   +/**\n>> + * \\brief Class representing one CPU debayering thread\n>> + *\n>> + * Implementation for CPU based debayering threads.\n>> + */\n>> +class DebayerCpuThread : public Thread, public Object\n>> +{\n>> +public:\n>> +    DebayerCpuThread(DebayerCpu *debayer, unsigned int threadIndex,\n>> +             bool enableInputMemcpy);\n>> +\n>> +    void configure(unsigned int yStart, unsigned int yEnd);\n>> +    void process(uint32_t frame, const uint8_t *src, uint8_t *dst);\n>> +\n>> +private:\n>> +    void setupInputMemcpy(const uint8_t *linePointers[]);\n>> +    void shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src);\n>> +    void memcpyNextLine(const uint8_t *linePointers[]);\n>> +    void process2(uint32_t frame, const uint8_t *src, uint8_t *dst);\n>> +    void process4(uint32_t frame, const uint8_t *src, uint8_t *dst);\n>> +\n>> +    /* Max. supported Bayer pattern height is 4, debayering this requires 5 lines */\n>> +    static constexpr unsigned int kMaxLineBuffers = 5;\n>> +\n>> +    DebayerCpu *debayer_;\n>> +    unsigned int threadIndex_;\n>> +    unsigned int yStart_;\n>> +    unsigned int yEnd_;\n>> +    unsigned int lineBufferLength_;\n>> +    unsigned int lineBufferPadding_;\n>> +    unsigned int lineBufferIndex_;\n>> +    std::vector<uint8_t> lineBuffers_[kMaxLineBuffers];\n>> +    bool enableInputMemcpy_;\n>> +};\n>> +\n>> +/**\n>> + * \\brief Construct a DebayerCpuThread object\n>> + * \\param[in] debayer pointer back to the DebayerCpuObject this thread belongs to\n>> + * \\param[in] threadIndex 0 .. n thread-index value for the thread\n>> + * \\param[in] enableInputMemcpy when set copy input data to a heap buffer before use\n>> + */\n>> +DebayerCpuThread::DebayerCpuThread(DebayerCpu *debayer, unsigned int threadIndex,\n>> +                   bool enableInputMemcpy)\n>> +    : Thread(\"DebayerCpu:\" + std::to_string(threadIndex)),\n>> +      debayer_(debayer), threadIndex_(threadIndex),\n>> +      enableInputMemcpy_(enableInputMemcpy)\n>> +{\n>> +}\n>> +\n>>   /**\n>>    * \\class DebayerCpu\n>>    * \\brief Class for debayering on the CPU\n>> @@ -53,8 +104,14 @@ DebayerCpu::DebayerCpu(std::unique_ptr<SwStatsCpu> stats, const GlobalConfigurat\n>>        * \\todo Make memcpy automatic based on runtime detection of platform\n>>        * capabilities.\n>>        */\n>> -    enableInputMemcpy_ =\n>> +    bool enableInputMemcpy =\n>>           configuration.option<bool>({ \"software_isp\", \"copy_input_buffer\" }).value_or(true);\n>> +\n>> +    /* Just one thread object for now, which will be called inline rather than async */\n>> +    threads_.resize(1);\n>> +\n>> +    for (unsigned int i = 0; i < threads_.size(); i++)\n>> +        threads_[i] = std::make_unique<DebayerCpuThread>(this, i, enableInputMemcpy);\n>>   }\n>>     DebayerCpu::~DebayerCpu() = default;\n>> @@ -484,7 +541,7 @@ int DebayerCpu::configure(const StreamConfiguration &inputCfg,\n>>       if (getInputConfig(inputCfg.pixelFormat, inputConfig_) != 0)\n>>           return -EINVAL;\n>>   -    if (stats_->configure(inputCfg) != 0)\n>> +    if (stats_->configure(inputCfg, threads_.size()) != 0)\n>>           return -EINVAL;\n>>         const Size &statsPatternSize = stats_->patternSize();\n>> @@ -548,17 +605,43 @@ int DebayerCpu::configure(const StreamConfiguration &inputCfg,\n>>        */\n>>       stats_->setWindow(Rectangle(window_.size()));\n>>   +    unsigned int yStart = 0;\n>> +    unsigned int linesPerThread = (window_.height / threads_.size()) &\n>> +                      ~(inputConfig_.patternSize.height - 1);\n>> +    unsigned int i;\n>> +\n>> +    for (i = 0; i < (threads_.size() - 1); i++) {\n>> +        threads_[i]->configure(yStart, yStart + linesPerThread);\n>> +        yStart += linesPerThread;\n>> +    }\n>> +    threads_[i]->configure(yStart, window_.height);\n> \n> Or possibly `threads_.back()->configure(...`\n\nI think that sticking with [i] to match the configure() calls inside\nthe for loop is more consistent so I'm going to keep this as is.\n\n>> +\n>> +    return 0;\n>> +}\n>> +\n>> +/**\n>> + * \\brief Configure thread to process a specific part of the image\n>> + * \\param[in] yStart y coordinate of first line to process\n>> + * \\param[in] yEnd y coordinate of the line at which to stop processing\n>> + *\n>> + * Configure the thread to process lines yStart - (yEnd - 1).\n> \n> This is a bit confusing in my opinion because `-` means two different things\n> in the same sentence. Maybe \"lines from yStart to yEnd - 1\", or maybe\n> \"lines [yStart, yEnd)\".\n\nAck, will fix for the next version.\n\n>> + */\n>> [...]\n>> diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h\n>> index 7a6517462..780576090 100644\n>> --- a/src/libcamera/software_isp/debayer_cpu.h\n>> +++ b/src/libcamera/software_isp/debayer_cpu.h\n>> @@ -26,6 +26,7 @@\n>>     namespace libcamera {\n>>   +class DebayerCpuThread;\n>>   class DebayerCpu : public Debayer\n>>   {\n>>   public:\n>> @@ -44,6 +45,8 @@ public:\n>>       const SharedFD &getStatsFD() { return stats_->getStatsFD(); }\n>>     private:\n>> +    friend class DebayerCpuThread;\n>> +\n>>       /**\n>>        * \\brief Called to debayer 1 line of Bayer input data to output format\n>>        * \\param[out] dst Pointer to the start of the output line to write\n>> @@ -74,6 +77,11 @@ private:\n>>        */\n>>       using debayerFn = void (DebayerCpu::*)(uint8_t *dst, const uint8_t *src[]);\n>>   +    void debayer0(uint8_t *dst, const uint8_t *src[]) { (this->*debayer0_)(dst, src); }\n>> +    void debayer1(uint8_t *dst, const uint8_t *src[]) { (this->*debayer1_)(dst, src); }\n>> +    void debayer2(uint8_t *dst, const uint8_t *src[]) { (this->*debayer2_)(dst, src); }\n>> +    void debayer3(uint8_t *dst, const uint8_t *src[]) { (this->*debayer3_)(dst, src); }\n>> +\n>>       /* 8-bit raw bayer format */\n>>       template<bool addAlphaByte, bool ccmEnabled>\n>>       void debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);\n>> @@ -105,17 +113,9 @@ private:\n>>       int setDebayerFunctions(PixelFormat inputFormat,\n>>                   PixelFormat outputFormat,\n>>                   bool ccmEnabled);\n>> -    void setupInputMemcpy(const uint8_t *linePointers[]);\n>> -    void shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src);\n>> -    void memcpyNextLine(const uint8_t *linePointers[]);\n>> -    void process2(uint32_t frame, const uint8_t *src, uint8_t *dst);\n>> -    void process4(uint32_t frame, const uint8_t *src, uint8_t *dst);\n>>       void updateGammaTable(const DebayerParams &params);\n>>       void updateLookupTables(const DebayerParams &params);\n>>   -    /* Max. supported Bayer pattern height is 4, debayering this requires 5 lines */\n>> -    static constexpr unsigned int kMaxLineBuffers = 5;\n>> -\n>>       static constexpr unsigned int kRGBLookupSize = 256;\n>>       static constexpr unsigned int kGammaLookupSize = 1024;\n>>       struct CcmColumn {\n>> @@ -142,12 +142,9 @@ private:\n>>       debayerFn debayer3_;\n>>       Rectangle window_;\n>>       std::unique_ptr<SwStatsCpu> stats_;\n>> -    std::vector<uint8_t> lineBuffers_[kMaxLineBuffers];\n>> -    unsigned int lineBufferLength_;\n>> -    unsigned int lineBufferPadding_;\n>> -    unsigned int lineBufferIndex_;\n>>       unsigned int xShift_; /* Offset of 0/1 applied to window_.x */\n>> -    bool enableInputMemcpy_;\n>> +\n>> +    std::vector<std::unique_ptr<DebayerCpuThread>>threads_;\n> \n> Missing space before the name.\n\nAck. \n> Tested-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> # ThinkPad X1 Yoga Gen 7 + ov2740\n\nThanks.\n\nRegards,\n\nHans","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 5DFDEC0DA4\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu,  5 Mar 2026 12:04:35 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 53617623A8;\n\tThu,  5 Mar 2026 13:04:34 +0100 (CET)","from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com\n\t[205.220.180.131])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A11BE622AE\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  5 Mar 2026 13:04:32 +0100 (CET)","from pps.filterd (m0279869.ppops.net [127.0.0.1])\n\tby mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id\n\t625AVNFY2399395 for <libcamera-devel@lists.libcamera.org>;\n\tThu, 5 Mar 2026 12:04:31 GMT","from mail-qk1-f197.google.com (mail-qk1-f197.google.com\n\t[209.85.222.197])\n\tby mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4cq85dg7j2-1\n\t(version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT)\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 05 Mar 2026 12:04:30 +0000 (GMT)","by mail-qk1-f197.google.com with SMTP id\n\taf79cd13be357-8cb4b8e9112so683161085a.2\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 05 Mar 2026 04:04:30 -0800 (PST)","from ?IPV6:2001:1c00:c32:7800:5bfa:a036:83f0:f9ec?\n\t(2001-1c00-0c32-7800-5bfa-a036-83f0-f9ec.cable.dynamic.v6.ziggo.nl.\n\t[2001:1c00:c32:7800:5bfa:a036:83f0:f9ec])\n\tby smtp.gmail.com with ESMTPSA id\n\ta640c23a62f3a-b935ae93348sm899464566b.46.2026.03.05.04.04.28\n\t(version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128);\n\tThu, 05 Mar 2026 04:04:28 -0800 (PST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key;\n\tunprotected) header.d=qualcomm.com header.i=@qualcomm.com\n\theader.b=\"WVAion9X\"; dkim=pass (2048-bit key;\n\tunprotected) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com\n\theader.b=\"Lx0Tn+gV\"; dkim-atps=neutral","DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h=\n\tcontent-transfer-encoding:content-type:date:from:in-reply-to\n\t:message-id:mime-version:references:subject:to; s=qcppdkim1; bh=\n\tJBdyGBRwXdE6BAhUb25qtM8aumyvNatzvgq9I/9tvFs=; b=WVAion9XHzwbEu/M\n\t+s3raNEWXCo1ptzo9ACFV49UY8g8KPGVKKB/o5yLlOY+xwqMtJYWsD4W+Qu1l5Oa\n\tVIfl9CeBRUyXI+h7fnVSwZyyVyEr89Kn9+8Td090VhSce0NuesOIJqJ4a/0cq8Ss\n\tQL4BYYr63XPtifwq6+ZGZIlyuqh9sjPG5PnBNfuhN6PmUqkBa/cVTj1JRSVQ+QG9\n\tQR3AK+l0C7cSgtaR4lVfVOIRAlyC8JGnMJy7KsgHxRqHU5u2Lzbjxwp0n1zZwInT\n\txuFqUhO04ba6szaGnltd2BZexQ07ulB6dCGJ/k4NEYCEp7asd/5QdDcXELg7WUGv\n\tcbPj2A==","v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=oss.qualcomm.com; s=google; t=1772712270; x=1773317070;\n\tdarn=lists.libcamera.org; \n\th=content-transfer-encoding:in-reply-to:content-language:references\n\t:to:subject:from:user-agent:mime-version:date:message-id:from:to:cc\n\t:subject:date:message-id:reply-to;\n\tbh=JBdyGBRwXdE6BAhUb25qtM8aumyvNatzvgq9I/9tvFs=;\n\tb=Lx0Tn+gVGL6XT0VkwNsKAdFX7r+prYld4IcLUy9YTR67zRs74Ur+VpA6qwvjYcPJtC\n\tZfuHkW5tDmZccPKVSA62TebCH+E3UTLdt3WOCcWKVtcMJg5lJzi5TIf0I1itp96pZOhs\n\tZzVDgjHZYht48HYeAFthSElV5Pb3OrnADJeEQ3UrBxBTc4KXD0OxkOMK6W0Z3BfbtLTU\n\tGaOdMHcGJ4ZCfSeV8hXA1fOqO6TsTP5YrjOEJagOFnSrpzUzXsMzSK36hlFF15WC3ARK\n\tAY306PGYHKjwZCtnNaNUf/GK4TcB0Qb5NCBDzEueUZUczuB+KdWaQ6JMxhPVCT4LdcUb\n\tYGzg=="],"X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20230601; t=1772712270; x=1773317070;\n\th=content-transfer-encoding:in-reply-to:content-language:references\n\t:to:subject:from:user-agent:mime-version:date:message-id:x-gm-gg\n\t:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to;\n\tbh=JBdyGBRwXdE6BAhUb25qtM8aumyvNatzvgq9I/9tvFs=;\n\tb=t8/ZQbrz0HJfGYIOxYXtlZk8UTWE78kCAC11yz2dTBwli8c/wBr8r04abAcYFadYcx\n\tK9VM6LRvo6hiosYHNoro6/OwH9229Z2hBWEyC8Kn9HPY/uSqfOU5LeQRJqyU4XJyds2w\n\tFlxqBzHWo6B4gBepXjMollm7EsiYoZHwOUEqWjOhcL9tr+bnamqeefhzcuuil8WmKEDW\n\t0bqJ6743u9VetySzKNAxcRCT3Ug2u/0fjKSNBscmv5BlplUX99cR4TdoRiYJCkv1aptK\n\tqzL7BGzdqYGqsulpogpGNNzZ7Xo8d2EAhGEo6MeHtUy9wWj73jLxIZwmJlJ9Xk9Ifaw1\n\trT6w==","X-Forwarded-Encrypted":"i=1;\n\tAJvYcCWYLU25ulejQTBDgbs3Xs9xMOJYJHCsCS3cx9nTtwVHAKRmJ9WWay+Zan/ryQhVowMQaygO7JlGQDxR0oFZ914=@lists.libcamera.org","X-Gm-Message-State":"AOJu0YwjT5aq6T7Evwk1hs/xnfkJbycfdsl2fphKl38w8rrs1VRm170i\n\tHKcOnwzfjYrbTcaYLMILzeJYZebKUUcqmT1QyJsHC3ai9NjNPhD+rLLpcvQJyan+BatdwFUDQsG\n\tEfjsOlrDizIcFFVatgV6ZfAcxsFsCjYh9OeRg/Z6mQDTYZutuTfyC+PCIOvJCejCGXVxTos5JTM\n\tYk","X-Gm-Gg":"ATEYQzwbDI+Ep2fWOBenSH8r+ZwVSqCv4a5y+kLOW7b0YMOoKbSv38F09Y1VPgbaVaK\n\tS8iRpI80unT9FQoXN42V3IGZPWxgpi8oc+/ZAUr8dKn4S8ZwstNMq0mTKBKwK2jvT+X6g3//R5g\n\tcMJSiTGNBcl6sNYyMpbJT+pYrQAXWksjsAXTS3CJtkLPB8vLHKg9kNj/daF+y9/P7R0bMBZJ+ES\n\tPEhfuYcfQNO3j88hTuB+HFmZSjnVuC8ZYdHJR15JG4mZ3zSQ3VL8e1c9Df15Rapelje4Mp1tDHx\n\t6KY0nXBcjiI7hAiwyYIl9Vld2pZJ6azd+9qhO2gL6oHG9UBDC9ZSyPJOAAPTpBVE8CaxW7uOQKu\n\tzUGlev4J08cgUWumBoizK2qdBNi53FFxaFSgNYbyDOCKJZAaakIpR69TMZlAWzKC749po9aKvY9\n\tZU6ZSXGTlk/V9Ew2DLMsthHicL/RuhYBeVk/cn/e4jmoqyZc6shs5JVXR6LRWXhnkDC7goEaaCg\n\tuzKBrKnhhnNMFyV","X-Received":["by 2002:a05:620a:4727:b0:80e:3af7:7a0c with SMTP id\n\taf79cd13be357-8cd5af8484emr652563185a.43.1772712270001; \n\tThu, 05 Mar 2026 04:04:30 -0800 (PST)","by 2002:a05:620a:4727:b0:80e:3af7:7a0c with SMTP id\n\taf79cd13be357-8cd5af8484emr652558085a.43.1772712269452; \n\tThu, 05 Mar 2026 04:04:29 -0800 (PST)"],"Message-ID":"<027ae3d0-4c6c-4af2-8594-202834c31a46@oss.qualcomm.com>","Date":"Thu, 5 Mar 2026 13:04:28 +0100","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","From":"Hans de Goede <johannes.goede@oss.qualcomm.com>","Subject":"Re: [PATCH v5 2/5] software_isp: debayer_cpu: Add DebayerCpuThread\n\tclass","To":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org, Milan Zamazal <mzamazal@redhat.com>","References":"<20260304075052.11599-1-johannes.goede@oss.qualcomm.com>\n\t<20260304075052.11599-3-johannes.goede@oss.qualcomm.com>\n\t<af87b2b8-eac4-49d0-8f63-94af8ae9ca29@ideasonboard.com>","Content-Language":"en-US, nl","In-Reply-To":"<af87b2b8-eac4-49d0-8f63-94af8ae9ca29@ideasonboard.com>","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","X-Proofpoint-ORIG-GUID":"w_C2oeKntH3-NOjhWOnp1NzuEgO9nEDY","X-Proofpoint-Spam-Details-Enc":"AW1haW4tMjYwMzA1MDA5OCBTYWx0ZWRfX4iqXVtPAIAy9\n\tVY2zobdX+yYpn7p28qXA3Le93ckVfpG5YL7lYA9SLCiYnR5tAsGo1MXc9PJe7Os6SqpEAGzXSYG\n\tIxGJXGFWhZf8GNmFGY9pi0+LSw7MYMZ3y7nUTMFxXeLnOvCVn0nKfW99uePD/H9YlnUbJoBR157\n\tlpitBt5eId993FF6MvEgko8kGx29YgY2BYWjYWKSWo1pA7dtcrb6yjgj2qpbnCr2mS+eVCMsN0n\n\tzQ3ejwQJu5YnDpNfgmS4fZtWSXFN2vDG4jltff6nGZcLXUfxbuNpuM9Vp6m/zVQqrsm7QX2F1M+\n\tN/oHqe+XiGDxpcaug20KJkUw6Cyy43Ca0eUFq00NcENl3JhgMUAn9mXthhueQsUuvG6j4SE/elr\n\tUyfkJ3bdReq9CoJH1bsZbRCgAGJnTHGe60fflvvkuGddUO6KXZbeg7VfaThZKlOlhyDCmheKI6J\n\taW9yilbNHoQST3wQhMg==","X-Authority-Analysis":"v=2.4 cv=aOb9aL9m c=1 sm=1 tr=0 ts=69a9714e cx=c_pps\n\ta=50t2pK5VMbmlHzFWWp8p/g==:117 a=xqWC_Br6kY4A:10 a=IkcTkHD0fZMA:10\n\ta=Yq5XynenixoA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22\n\ta=u7WPNUs3qKkmUXheDGA7:22 a=_glEPmIy2e8OvE2BGh3C:22 a=20KFwNOVAAAA:8\n\ta=EUspDBNiAAAA:8 a=P1BnusSwAAAA:8 a=ipnQbZBAk82DIQQAo2wA:9\n\ta=3ZKOabzyN94A:10\n\ta=QEXdDO2ut3YA:10 a=IoWCM6iH3mJn3m4BftBB:22 a=D0XLA9XvdZm18NrgonBM:22","X-Proofpoint-GUID":"w_C2oeKntH3-NOjhWOnp1NzuEgO9nEDY","X-Proofpoint-Virus-Version":"vendor=baseguard\n\tengine=ICAP:2.0.293, Aquarius:18.0.1143, Hydra:6.1.51,\n\tFMLib:17.12.100.49\n\tdefinitions=2026-03-05_04,2026-03-04_01,2025-10-01_01","X-Proofpoint-Spam-Details":"rule=outbound_notspam policy=outbound score=0\n\tphishscore=0 bulkscore=0 clxscore=1015 adultscore=0 suspectscore=0\n\tpriorityscore=1501 lowpriorityscore=0 spamscore=0 malwarescore=0\n\timpostorscore=0 classifier=typeunknown authscore=0 authtc= authcc=\n\troute=outbound adjust=0 reason=mlx scancount=1\n\tengine=8.22.0-2602130000\n\tdefinitions=main-2603050098","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>"}}]