From patchwork Wed Dec 11 15:25:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 22288 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 D96BCBD80A for ; Wed, 11 Dec 2024 15:25:53 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id BE93B618AE; Wed, 11 Dec 2024 16:25:52 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=protonmail.com header.i=@protonmail.com header.b="BcIHm8Qu"; dkim-atps=neutral Received: from mail-4316.protonmail.ch (mail-4316.protonmail.ch [185.70.43.16]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DF953618AE for ; Wed, 11 Dec 2024 16:25:50 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=protonmail3; t=1733930750; x=1734189950; bh=TGWjDxXM60xccBAJlriHxnD/+p3vnWahO7X0XBWXAWc=; h=Date:To:From:Subject:Message-ID:Feedback-ID:From:To:Cc:Date: Subject:Reply-To:Feedback-ID:Message-ID:BIMI-Selector: List-Unsubscribe:List-Unsubscribe-Post; b=BcIHm8Qutz+iB3OXPnV1+gzw8YdfxorzxrLx4tzQSZNeLisH78xUXMij0uaSw5GY3 gjr7pBoBL0i8mRt/vDYL3Gap7PxQ6xNmNQ36IufrHAlhQV6TyS9sqZiAyZV7U6x86f gOPXaeHVib3tgCu6/NzO89/Ks3FKvPLIhODTX1aWB1rCHkY51UDygIMPRsC8mLY6yD +JfK9LR/Jf/BUqcAola9Topwah0/W+WZjHG6JbQ0G3twKEcfXSvBX3ulVidR2l1GHU yo2jnad0wk5WJZy3H42xiCthnYGY4M1OiQO/UkeuRXdTUoIXcX8upruDcR95PoMCaS 4Tz8R17kZctvA== Date: Wed, 11 Dec 2024 15:25:45 +0000 To: libcamera-devel@lists.libcamera.org From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= Subject: [PATCH v1 1/3] libcamera: virtual: Avoid some copies Message-ID: <20241211152542.1095857-1-pobrn@protonmail.com> Feedback-ID: 20568564:user:proton X-Pm-Message-ID: 74cf5cd1adcf4322cd9da40c46e28a2097628f84 MIME-Version: 1.0 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" There is no reason make copies, these functions return const lvalue references, access the data through those. Signed-off-by: Barnabás Pőcze Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham --- src/libcamera/pipeline/virtual/image_frame_generator.cpp | 2 +- src/libcamera/pipeline/virtual/test_pattern_generator.cpp | 2 +- src/libcamera/pipeline/virtual/virtual.cpp | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/libcamera/pipeline/virtual/image_frame_generator.cpp b/src/libcamera/pipeline/virtual/image_frame_generator.cpp index 277efbb09..d1545b5d9 100644 --- a/src/libcamera/pipeline/virtual/image_frame_generator.cpp +++ b/src/libcamera/pipeline/virtual/image_frame_generator.cpp @@ -129,7 +129,7 @@ int ImageFrameGenerator::generateFrame(const Size &size, const FrameBuffer *buff MappedFrameBuffer mappedFrameBuffer(buffer, MappedFrameBuffer::MapFlag::Write); - auto planes = mappedFrameBuffer.planes(); + const auto &planes = mappedFrameBuffer.planes(); /* Loop only around the number of images available */ frameIndex_ %= imageFrameDatas_.size(); diff --git a/src/libcamera/pipeline/virtual/test_pattern_generator.cpp b/src/libcamera/pipeline/virtual/test_pattern_generator.cpp index 7bc2b338c..47d341919 100644 --- a/src/libcamera/pipeline/virtual/test_pattern_generator.cpp +++ b/src/libcamera/pipeline/virtual/test_pattern_generator.cpp @@ -25,7 +25,7 @@ int TestPatternGenerator::generateFrame(const Size &size, MappedFrameBuffer mappedFrameBuffer(buffer, MappedFrameBuffer::MapFlag::Write); - auto planes = mappedFrameBuffer.planes(); + const auto &planes = mappedFrameBuffer.planes(); shiftLeft(size); diff --git a/src/libcamera/pipeline/virtual/virtual.cpp b/src/libcamera/pipeline/virtual/virtual.cpp index 1b7cd5cb3..3126bdd7d 100644 --- a/src/libcamera/pipeline/virtual/virtual.cpp +++ b/src/libcamera/pipeline/virtual/virtual.cpp @@ -275,8 +275,7 @@ int PipelineHandlerVirtual::exportFrameBuffers([[maybe_unused]] Camera *camera, return -ENOBUFS; const StreamConfiguration &config = stream->configuration(); - - auto info = PixelFormatInfo::info(config.pixelFormat); + const PixelFormatInfo &info = PixelFormatInfo::info(config.pixelFormat); std::vector planeSizes; for (size_t i = 0; i < info.planes.size(); ++i) From patchwork Wed Dec 11 15:25:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 22289 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 DCA1ABD80A for ; Wed, 11 Dec 2024 15:25:57 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8A35F67EB1; Wed, 11 Dec 2024 16:25:57 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=protonmail.com header.i=@protonmail.com header.b="YJDDzDaW"; dkim-atps=neutral Received: from mail-4322.protonmail.ch (mail-4322.protonmail.ch [185.70.43.22]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7480267EAF for ; Wed, 11 Dec 2024 16:25:55 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=protonmail3; t=1733930754; x=1734189954; bh=9dLZiyxCFSsxmWXHT9J+DD9fEQsZ2odtHDZ9KO8IyxM=; h=Date:To:From:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector:List-Unsubscribe:List-Unsubscribe-Post; b=YJDDzDaWhsgFlBP5DETfRzwF1/OYaWna0dUuFWAermoQiFuu53IlV4KMbmN3VA8+N DwAg2R9fzUwo9gUM84jnFJ3W2st0uENzotEHzCoOnqGPpHIy5r5RZXuS2H/G+ueqcv ZO17xjga3aaOVvNZC+L3/YNUUgSNuJBpwnIzU4GvzFoeZANAqMxOZqNs4BDQNPkQCf 0X0WFMQcPNQrolGPMjcHU6oVw9JNdOp8zvitBoKTvEYK8rLcEhkfM3sGNrpMIxL/+b a0ZZj0l0iutvSzhI9HRNyrHJGbBdwrzhrYdyoyqqGzRpYJm8Qn2dAQTA8zinbp1UsR 2kDAsmrIrniZQ== Date: Wed, 11 Dec 2024 15:25:50 +0000 To: libcamera-devel@lists.libcamera.org From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= Subject: [PATCH v1 2/3] libcamera: virtual: Query number of planes correctly Message-ID: <20241211152542.1095857-2-pobrn@protonmail.com> In-Reply-To: <20241211152542.1095857-1-pobrn@protonmail.com> References: <20241211152542.1095857-1-pobrn@protonmail.com> Feedback-ID: 20568564:user:proton X-Pm-Message-ID: f5f2a4c838910251c779db82801f401fe0bca8fd MIME-Version: 1.0 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" `PixelFormatInfo::planes.size()` always returns 3 since `planes` is an array, but that is not the number of planes of the pixel format. Use the `numPlanes()` getter instead. Signed-off-by: Barnabás Pőcze Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham --- src/libcamera/pipeline/virtual/virtual.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcamera/pipeline/virtual/virtual.cpp b/src/libcamera/pipeline/virtual/virtual.cpp index 3126bdd7d..aae94efee 100644 --- a/src/libcamera/pipeline/virtual/virtual.cpp +++ b/src/libcamera/pipeline/virtual/virtual.cpp @@ -278,7 +278,7 @@ int PipelineHandlerVirtual::exportFrameBuffers([[maybe_unused]] Camera *camera, const PixelFormatInfo &info = PixelFormatInfo::info(config.pixelFormat); std::vector planeSizes; - for (size_t i = 0; i < info.planes.size(); ++i) + for (size_t i = 0; i < info.numPlanes(); ++i) planeSizes.push_back(info.planeSize(config.size, i)); return dmaBufAllocator_.exportBuffers(config.bufferCount, planeSizes, buffers); From patchwork Wed Dec 11 15:25:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 22290 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 11232BD80A for ; Wed, 11 Dec 2024 15:26:06 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id BAA5E67EBA; Wed, 11 Dec 2024 16:26:05 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=protonmail.com header.i=@protonmail.com header.b="WgfVUf/j"; dkim-atps=neutral Received: from mail-40133.protonmail.ch (mail-40133.protonmail.ch [185.70.40.133]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C0E9B67EB1 for ; Wed, 11 Dec 2024 16:26:03 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=protonmail3; t=1733930763; x=1734189963; bh=uLrSfwP4FXc2HR+sNpRAijAkImv9mgf1ETXXrtpNPdk=; h=Date:To:From:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector:List-Unsubscribe:List-Unsubscribe-Post; b=WgfVUf/jqoqOfowK9oVJ/jd9m7uJ3LJUaXxfsJ02a7ASdPFpNz/lYzG2sI9x3VJdb QbQWzgf/kQ+uYUwoe4YVo+Zs9QlCnqaLZGDBu5eiAbXQttnRtfG2kSAxuT2TE3UEm+ hYhZAdV9JcN5hVf5QZU1BvjVckcMPvsh28lJYIsBh2rfi0tVKtXE3N1c0ghoEmenXL tX4es1F7CaS/VIBk6j/0fuO25d6/wnpJ2FIi7CJNgdfjdLvTBxH/pepgntz/OdtEHP Ogfyoj9Wk/xHh0mmbL6OC4LsJVa4DNNIMy4KMXWXIAJHcDDJ1wk6n+j1x+3PCvuXB4 C4segC6kk/38A== Date: Wed, 11 Dec 2024 15:25:56 +0000 To: libcamera-devel@lists.libcamera.org From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= Subject: [PATCH v1 3/3] libcamera: virtual: Speed up test pattern animation Message-ID: <20241211152542.1095857-3-pobrn@protonmail.com> In-Reply-To: <20241211152542.1095857-1-pobrn@protonmail.com> References: <20241211152542.1095857-1-pobrn@protonmail.com> Feedback-ID: 20568564:user:proton X-Pm-Message-ID: 869d255ffcfb0670811601ba1af026beb2cf5323 MIME-Version: 1.0 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" After the initial generation, when a frame is requested, the test pattern generator rotates the image left by 1 column. The current approach has two shortcomings: (1) it allocates a temporary buffer to hold one column; (2) it swaps two columns at a time. The test patterns are simple ARGB images, in row-major order, so doing (2) works against memory prefetching. This can be addressed by doing the rotation one row at a time as that way the image is addressed in a purely linear fashion. Doing so also eliminates the need for a dynamically allocated temporary buffer, as the required buffer now only needs to hold one sample, which is 4 bytes in this case. In an optimized build, this results in about a 2x increase in the number of frames per second as reported by `cam`. In an unoptimized, ASAN and UBSAN intrumented build, the difference is even bigger, which is useful for running lc-compliance in CI in a reasonable time. Signed-off-by: Barnabás Pőcze Tested-by: Kieran Bingham Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- .../virtual/test_pattern_generator.cpp | 68 +++++++++---------- .../pipeline/virtual/test_pattern_generator.h | 4 -- 2 files changed, 34 insertions(+), 38 deletions(-) diff --git a/src/libcamera/pipeline/virtual/test_pattern_generator.cpp b/src/libcamera/pipeline/virtual/test_pattern_generator.cpp index 47d341919..eeadc1646 100644 --- a/src/libcamera/pipeline/virtual/test_pattern_generator.cpp +++ b/src/libcamera/pipeline/virtual/test_pattern_generator.cpp @@ -5,6 +5,8 @@ * Derived class of FrameGenerator for generating test patterns */ +#include + #include "test_pattern_generator.h" #include @@ -13,6 +15,37 @@ #include +namespace { + +template +void rotateLeft1Sample(uint8_t *samples, size_t width) +{ + if (width <= 0) + return; + + const size_t stride = width * SampleSize; + uint8_t first[SampleSize]; + + memcpy(first, &samples[0], SampleSize); + for (size_t i = 0; i < stride - SampleSize; i += SampleSize) + memcpy(&samples[i], &samples[i + SampleSize], SampleSize); + memcpy(&samples[stride - SampleSize], first, SampleSize); +} + +template +void rotateLeft1Column(const libcamera::Size &size, uint8_t *image) +{ + if (size.width < 2) + return; + + const size_t stride = size.width * SampleSize; + + for (size_t i = 0; i < size.height; i++, image += stride) + rotateLeft1Sample(image, size.width); +} + +} + namespace libcamera { LOG_DECLARE_CATEGORY(Virtual) @@ -27,7 +60,7 @@ int TestPatternGenerator::generateFrame(const Size &size, const auto &planes = mappedFrameBuffer.planes(); - shiftLeft(size); + rotateLeft1Column(size, template_.get()); /* Convert the template_ to the frame buffer */ int ret = libyuv::ARGBToNV12(template_.get(), size.width * kARGBSize, @@ -40,39 +73,6 @@ int TestPatternGenerator::generateFrame(const Size &size, return ret; } -void TestPatternGenerator::shiftLeft(const Size &size) -{ - /* Store the first column temporarily */ - auto firstColumn = std::make_unique(size.height * kARGBSize); - for (size_t h = 0; h < size.height; h++) { - unsigned int index = h * size.width * kARGBSize; - unsigned int index1 = h * kARGBSize; - firstColumn[index1] = template_[index]; - firstColumn[index1 + 1] = template_[index + 1]; - firstColumn[index1 + 2] = template_[index + 2]; - firstColumn[index1 + 3] = 0x00; - } - - /* Overwrite template_ */ - uint8_t *buf = template_.get(); - for (size_t h = 0; h < size.height; h++) { - for (size_t w = 0; w < size.width - 1; w++) { - /* Overwrite with the pixel on the right */ - unsigned int index = (h * size.width + w + 1) * kARGBSize; - *buf++ = template_[index]; /* B */ - *buf++ = template_[index + 1]; /* G */ - *buf++ = template_[index + 2]; /* R */ - *buf++ = 0x00; /* A */ - } - /* Overwrite the new last column with the original first column */ - unsigned int index1 = h * kARGBSize; - *buf++ = firstColumn[index1]; /* B */ - *buf++ = firstColumn[index1 + 1]; /* G */ - *buf++ = firstColumn[index1 + 2]; /* R */ - *buf++ = 0x00; /* A */ - } -} - void ColorBarsGenerator::configure(const Size &size) { constexpr uint8_t kColorBar[8][3] = { diff --git a/src/libcamera/pipeline/virtual/test_pattern_generator.h b/src/libcamera/pipeline/virtual/test_pattern_generator.h index 05f4ab7a7..2a51bd31a 100644 --- a/src/libcamera/pipeline/virtual/test_pattern_generator.h +++ b/src/libcamera/pipeline/virtual/test_pattern_generator.h @@ -29,10 +29,6 @@ public: protected: /* Buffer of test pattern template */ std::unique_ptr template_; - -private: - /* Shift the buffer by 1 pixel left each frame */ - void shiftLeft(const Size &size); }; class ColorBarsGenerator : public TestPatternGenerator