From patchwork Fri Mar 14 17:42:18 2025 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: 22953 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 EAA3FC32F7 for ; Fri, 14 Mar 2025 17:42:26 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 68ABF6894D; Fri, 14 Mar 2025 18:42:26 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="LAj+IzxV"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A1F8E68946 for ; Fri, 14 Mar 2025 18:42:23 +0100 (CET) Received: from pb-laptop.local (185.221.143.221.nat.pool.zt.hu [185.221.143.221]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 4C487842 for ; Fri, 14 Mar 2025 18:40:44 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1741974044; bh=/QFfEbvgSHSuyA1vcYwIaRA3fGlJ7YCG3d/4tnsg5l4=; h=From:To:Subject:Date:In-Reply-To:References:From; b=LAj+IzxV0ZWlun7bbZb/ks62pOUykq5dwcJ3tewl3ZBIZIeET28hRHOI+0+0MJEpf zTEmv3+oGwF7VaQxkjan6eUnKu5N0q7Y7EganjIgyp6Sq/mQNnZHvO21rUXW/PYY+q Lkf4A1nOFllBLfIynFKh8Bc0DgW7WxtDGMRZVSXU= From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= To: libcamera-devel@lists.libcamera.org Subject: [PATCH v4 1/2] apps: lc-compliance: Support multiple streams in helpers Date: Fri, 14 Mar 2025 18:42:18 +0100 Message-ID: <20250314174220.1015597-2-barnabas.pocze@ideasonboard.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250314174220.1015597-1-barnabas.pocze@ideasonboard.com> References: <20250314174220.1015597-1-barnabas.pocze@ideasonboard.com> 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" Prepare to add a test suite for capture operations with multiple streams. Modify the Capture helper class to support multiple roles and streams in the configure() and capture() operations. The buffer count of each stream is asserted to be the same. Multi-stream support will be added in next patches. Signed-off-by: Barnabás Pőcze --- src/apps/lc-compliance/helpers/capture.cpp | 64 ++++++++++++++----- src/apps/lc-compliance/helpers/capture.h | 2 +- src/apps/lc-compliance/tests/capture_test.cpp | 6 +- 3 files changed, 51 insertions(+), 21 deletions(-) diff --git a/src/apps/lc-compliance/helpers/capture.cpp b/src/apps/lc-compliance/helpers/capture.cpp index f2c6d58ce..2a3fa3b68 100644 --- a/src/apps/lc-compliance/helpers/capture.cpp +++ b/src/apps/lc-compliance/helpers/capture.cpp @@ -23,12 +23,29 @@ Capture::~Capture() stop(); } -void Capture::configure(StreamRole role) +void Capture::configure(libcamera::Span roles) { - config_ = camera_->generateConfiguration({ role }); + assert(!roles.empty()); + config_ = camera_->generateConfiguration(roles); if (!config_) - GTEST_SKIP() << "Role not supported by camera"; + GTEST_SKIP() << "Roles not supported by camera"; + + ASSERT_EQ(config_->size(), roles.size()) << "Unexpected number of streams in configuration"; + + /* + * Set the buffers count to the largest value across all streams. + * \todo: Should all streams from a Camera have the same buffer count ? + */ + auto largest = + std::max_element(config_->begin(), config_->end(), + [](const StreamConfiguration &l, const StreamConfiguration &r) + { return l.bufferCount < r.bufferCount; }); + + assert(largest != config_->end()); + + for (auto &cfg : *config_) + cfg.bufferCount = largest->bufferCount; if (config_->validate() != CameraConfiguration::Valid) { config_.reset(); @@ -103,29 +120,37 @@ void Capture::start() assert(!allocator_.allocated()); assert(requests_.empty()); - Stream *stream = config_->at(0).stream(); - int count = allocator_.allocate(stream); - - ASSERT_GE(count, 0) << "Failed to allocate buffers"; - EXPECT_EQ(count, config_->at(0).bufferCount) << "Allocated less buffers than expected"; - - const std::vector> &buffers = allocator_.buffers(stream); + const auto bufferCount = config_->at(0).bufferCount; /* No point in testing less requests then the camera depth. */ - if (queueLimit_ && *queueLimit_ < buffers.size()) { - GTEST_SKIP() << "Camera needs " << buffers.size() + if (queueLimit_ && *queueLimit_ < bufferCount) { + GTEST_SKIP() << "Camera needs " << bufferCount << " requests, can't test only " << *queueLimit_; } - for (const std::unique_ptr &buffer : buffers) { + for (std::size_t i = 0; i < bufferCount; i++) { std::unique_ptr request = camera_->createRequest(); ASSERT_TRUE(request) << "Can't create request"; + requests_.push_back(std::move(request)); + } - ASSERT_EQ(request->addBuffer(stream, buffer.get()), 0) << "Can't set buffer for request"; + for (const auto &cfg : *config_) { + Stream *stream = cfg.stream(); - requests_.push_back(std::move(request)); + int count = allocator_.allocate(stream); + ASSERT_GE(count, 0) << "Failed to allocate buffers"; + + const auto &buffers = allocator_.buffers(stream); + ASSERT_EQ(buffers.size(), bufferCount) << "Mismatching buffer count"; + + for (std::size_t i = 0; i < bufferCount; i++) { + ASSERT_EQ(requests_[i]->addBuffer(stream, buffers[i].get()), 0) + << "Failed to add buffer to request"; + } } + ASSERT_TRUE(allocator_.allocated()); + camera_->requestCompleted.connect(this, &Capture::requestComplete); ASSERT_EQ(camera_->start(), 0) << "Failed to start camera"; @@ -140,7 +165,12 @@ void Capture::stop() camera_->requestCompleted.disconnect(this); - Stream *stream = config_->at(0).stream(); requests_.clear(); - allocator_.free(stream); + + for (const auto &cfg : *config_) { + EXPECT_EQ(allocator_.free(cfg.stream()), 0) + << "Failed to free buffers associated with stream"; + } + + EXPECT_FALSE(allocator_.allocated()); } diff --git a/src/apps/lc-compliance/helpers/capture.h b/src/apps/lc-compliance/helpers/capture.h index 0e7b848fb..ea01c11c1 100644 --- a/src/apps/lc-compliance/helpers/capture.h +++ b/src/apps/lc-compliance/helpers/capture.h @@ -20,7 +20,7 @@ public: Capture(std::shared_ptr camera); ~Capture(); - void configure(libcamera::StreamRole role); + void configure(libcamera::Span roles); void run(unsigned int captureLimit, std::optional queueLimit = {}); private: diff --git a/src/apps/lc-compliance/tests/capture_test.cpp b/src/apps/lc-compliance/tests/capture_test.cpp index 93bed48f0..06f15bdb4 100644 --- a/src/apps/lc-compliance/tests/capture_test.cpp +++ b/src/apps/lc-compliance/tests/capture_test.cpp @@ -89,7 +89,7 @@ TEST_P(SingleStream, Capture) Capture capture(camera_); - capture.configure(role); + capture.configure({ { role } }); capture.run(numRequests, numRequests); } @@ -108,7 +108,7 @@ TEST_P(SingleStream, CaptureStartStop) Capture capture(camera_); - capture.configure(role); + capture.configure({ { role } }); for (unsigned int starts = 0; starts < numRepeats; starts++) capture.run(numRequests, numRequests); @@ -127,7 +127,7 @@ TEST_P(SingleStream, UnbalancedStop) Capture capture(camera_); - capture.configure(role); + capture.configure({ { role } }); capture.run(numRequests); }