From patchwork Wed Apr 21 16:51:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4gUHJhZG8=?= X-Patchwork-Id: 12052 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 ABD5EBDB15 for ; Wed, 21 Apr 2021 16:52:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6A1DC68854; Wed, 21 Apr 2021 18:52:30 +0200 (CEST) Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [46.235.227.227]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id CD98468851 for ; Wed, 21 Apr 2021 18:52:27 +0200 (CEST) Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: nfraprado) with ESMTPSA id BD7BC1F423ED From: =?utf-8?b?TsOtY29sYXMgRi4gUi4gQS4gUHJhZG8=?= To: libcamera-devel@lists.libcamera.org Date: Wed, 21 Apr 2021 13:51:38 -0300 Message-Id: <20210421165139.318432-4-nfraprado@collabora.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210421165139.318432-1-nfraprado@collabora.com> References: <20210421165139.318432-1-nfraprado@collabora.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 3/4] lc-compliance: Add test to queue more requests than hardware depth 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: , Cc: =?utf-8?q?Andr=C3=A9_Almeida?= , kernel@collabora.com Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" A pipeline handler should be able to handle an arbitrary amount of simultaneous requests by submitting what it can to the video device and queuing the rest internally until resources are available. This isn't currently done by some pipeline handlers however [1]. Add a new test to lc-compliance that submits a lot of requests at once to check if the pipeline handler is behaving well in this situation. [1] https://bugs.libcamera.org/show_bug.cgi?id=24 Signed-off-by: NĂ­colas F. R. A. Prado --- src/lc-compliance/simple_capture.cpp | 70 ++++++++++++++++++++++++++++ src/lc-compliance/simple_capture.h | 15 ++++++ src/lc-compliance/single_stream.cpp | 31 +++++++++++- 3 files changed, 115 insertions(+), 1 deletion(-) diff --git a/src/lc-compliance/simple_capture.cpp b/src/lc-compliance/simple_capture.cpp index 875772a80c27..01d76380e998 100644 --- a/src/lc-compliance/simple_capture.cpp +++ b/src/lc-compliance/simple_capture.cpp @@ -223,3 +223,73 @@ void SimpleCaptureUnbalanced::requestComplete(Request *request) if (camera_->queueRequest(request)) loop_->exit(-EINVAL); } + +SimpleCaptureOverflow::SimpleCaptureOverflow(std::shared_ptr camera) + : SimpleCapture(camera) +{ +} + +Results::Result SimpleCaptureOverflow::capture() +{ + Results::Result ret = start(); + if (ret.first != Results::Pass) + return ret; + + Stream *stream = config_->at(0).stream(); + const std::vector> &buffers = allocator_->buffers(stream); + + captureCount_ = 0; + captureLimit_ = buffers.size(); + + std::vector> requests; + for (const std::unique_ptr &buffer : buffers) { + std::unique_ptr request = camera_->createRequest(); + if (!request) { + stop(); + return { Results::Fail, "Can't create request" }; + } + + if (request->addBuffer(stream, buffer.get())) { + stop(); + return { Results::Fail, "Can't set buffer for request" }; + } + + if (camera_->queueRequest(request.get()) < 0) { + stop(); + return { Results::Fail, "Failed to queue request" }; + } + + requests.push_back(std::move(request)); + } + + /* Run capture session. */ + loop_ = new EventLoop(); + loop_->exec(); + stop(); + delete loop_; + + if (captureCount_ != captureLimit_) + return { Results::Fail, "Got " + std::to_string(captureCount_) + + " request, wanted " + std::to_string(captureLimit_) }; + + return { Results::Pass, "Overflow capture of " + + std::to_string(captureLimit_) + " requests" }; +} + +void SimpleCaptureOverflow::requestComplete([[maybe_unused]]Request *request) +{ + captureCount_++; + if (captureCount_ >= captureLimit_) { + loop_->exit(0); + return; + } +} + +Results::Result SimpleCaptureOverflow::allocateBuffers(unsigned int count) +{ + Stream *stream = config_->at(0).stream(); + if (allocator_->allocate(stream, count) < 0) + return { Results::Fail, "Failed to allocate buffers" }; + + return { Results::Pass, "Allocated buffers" }; +} diff --git a/src/lc-compliance/simple_capture.h b/src/lc-compliance/simple_capture.h index 82e2c56a55f1..cafcdafe10c2 100644 --- a/src/lc-compliance/simple_capture.h +++ b/src/lc-compliance/simple_capture.h @@ -66,4 +66,19 @@ private: unsigned int captureLimit_; }; +class SimpleCaptureOverflow : public SimpleCapture +{ +public: + SimpleCaptureOverflow(std::shared_ptr camera); + + Results::Result allocateBuffers(unsigned int count); + Results::Result capture(); + +private: + void requestComplete(libcamera::Request *request) override; + + unsigned int captureCount_; + unsigned int captureLimit_; +}; + #endif /* __LC_COMPLIANCE_SIMPLE_CAPTURE_H__ */ diff --git a/src/lc-compliance/single_stream.cpp b/src/lc-compliance/single_stream.cpp index 649291c7bb73..61979f66d92d 100644 --- a/src/lc-compliance/single_stream.cpp +++ b/src/lc-compliance/single_stream.cpp @@ -12,6 +12,23 @@ using namespace libcamera; +static const unsigned int MAX_SIMULTANEOUS_REQUESTS = 8; + +Results::Result testRequestOverflow(std::shared_ptr camera, + StreamRole role, unsigned int numRequests) +{ + SimpleCaptureOverflow capture(camera); + + Results::Result ret = capture.configure(role); + if (ret.first != Results::Pass) + return ret; + capture.allocateBuffers(numRequests); + if (ret.first != Results::Pass) + return ret; + + return capture.capture(); +} + Results::Result testRequestBalance(std::shared_ptr camera, StreamRole role, unsigned int startCycles, unsigned int numRequests) @@ -61,7 +78,7 @@ Results testSingleStream(std::shared_ptr camera) }; static const std::vector numRequests = { 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 }; - Results results(numRequests.size() * roles.size() * 3); + Results results(numRequests.size() * roles.size() * 3 + roles.size() * 1); for (const auto &role : roles) { std::cout << "= Test role " << role.first << std::endl; @@ -97,6 +114,18 @@ Results testSingleStream(std::shared_ptr camera) std::cout << "* Test unbalanced stop" << std::endl; for (unsigned int num : numRequests) results.add(testRequestUnbalance(camera, role.second, num)); + + /* + * Test overflowing pipeline with requests + * + * Makes sure that the camera supports receiving a large amount + * of requests at once. Example failure is a camera that doesn't + * check if there are available resources (free internal + * buffers, free buffers in the video devices) before handling a + * request. + */ + std::cout << "* Test overflowing requests" << std::endl; + results.add(testRequestOverflow(camera, role.second, MAX_SIMULTANEOUS_REQUESTS)); } return results;