[libcamera-devel,v2,2/2] lc-compliance: Add test to queue more requests than hardware depth
diff mbox series

Message ID 20210416222830.335755-3-nfraprado@collabora.com
State Superseded
Headers show
Series
  • lc-compliance: Add test to queue more requests than hardware depth
Related show

Commit Message

NĂ­colas F. R. A. Prado April 16, 2021, 10:28 p.m. UTC
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 <nfraprado@collabora.com>
---
 src/lc-compliance/simple_capture.cpp | 61 ++++++++++++++++++++++++++++
 src/lc-compliance/simple_capture.h   | 14 +++++++
 src/lc-compliance/single_stream.cpp  | 28 ++++++++++++-
 3 files changed, 102 insertions(+), 1 deletion(-)

Patch
diff mbox series

diff --git a/src/lc-compliance/simple_capture.cpp b/src/lc-compliance/simple_capture.cpp
index 42e4c9b1302d..26d91e036656 100644
--- a/src/lc-compliance/simple_capture.cpp
+++ b/src/lc-compliance/simple_capture.cpp
@@ -214,3 +214,64 @@  void SimpleCaptureUnbalanced::requestComplete(Request *request)
 	if (camera_->queueRequest(request))
 		loop_->exit(-EINVAL);
 }
+
+SimpleCaptureOverflow::SimpleCaptureOverflow(std::shared_ptr<Camera> camera)
+	: SimpleCapture(camera)
+{
+}
+
+Results::Result SimpleCaptureOverflow::capture(unsigned int numRequests)
+{
+	Results::Result ret = start(numRequests);
+	if (ret.first != Results::Pass)
+		return ret;
+
+	Stream *stream = config_->at(0).stream();
+	const std::vector<std::unique_ptr<FrameBuffer>> &buffers = allocator_->buffers(stream);
+
+	captureCount_ = 0;
+	captureLimit_ = numRequests;
+
+	std::vector<std::unique_ptr<libcamera::Request>> requests;
+	for (const std::unique_ptr<FrameBuffer> &buffer : buffers) {
+		std::unique_ptr<Request> 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(numRequests) + " requests" };
+}
+
+void SimpleCaptureOverflow::requestComplete([[maybe_unused]]Request *request)
+{
+	captureCount_++;
+	if (captureCount_ >= captureLimit_) {
+		loop_->exit(0);
+		return;
+	}
+}
diff --git a/src/lc-compliance/simple_capture.h b/src/lc-compliance/simple_capture.h
index 2b1493ecaf96..d25c3b20d059 100644
--- a/src/lc-compliance/simple_capture.h
+++ b/src/lc-compliance/simple_capture.h
@@ -65,4 +65,18 @@  private:
 	unsigned int captureLimit_;
 };
 
+class SimpleCaptureOverflow : public SimpleCapture
+{
+public:
+	SimpleCaptureOverflow(std::shared_ptr<libcamera::Camera> camera);
+
+	Results::Result capture(unsigned int numRequests);
+
+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 8318b42f42d6..276a588f58e2 100644
--- a/src/lc-compliance/single_stream.cpp
+++ b/src/lc-compliance/single_stream.cpp
@@ -12,6 +12,20 @@ 
 
 using namespace libcamera;
 
+static const unsigned int MAX_SIMULTANEOUS_REQUESTS = 8;
+
+Results::Result testRequestOverflow(std::shared_ptr<Camera> camera,
+				   StreamRole role, unsigned int numRequests)
+{
+	SimpleCaptureOverflow capture(camera);
+
+	Results::Result ret = capture.configure(role);
+	if (ret.first != Results::Pass)
+		return ret;
+
+	return capture.capture(numRequests);
+}
+
 Results::Result testRequestBalance(std::shared_ptr<Camera> camera,
 				   StreamRole role, unsigned int startCycles,
 				   unsigned int numRequests)
@@ -55,7 +69,7 @@  Results testSingleStream(std::shared_ptr<Camera> camera)
 	};
 	static const std::vector<unsigned int> 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;
@@ -91,6 +105,18 @@  Results testSingleStream(std::shared_ptr<Camera> 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;