[libcamera-devel] [PATCH v5 2/2] lc-compliance: Add test stopping single stream with requests queued

Niklas Söderlund niklas.soderlund at ragnatech.se
Fri Apr 9 17:00:37 CEST 2021


Add a test which stops a camera while requests are still queued. This
intends to test cleanup paths where requests are dequeued from video
devices in an uncompleted state.

Signed-off-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>
Acked-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
Tested-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
---
* Changes since v4
- Update commit message.
---
 src/lc-compliance/simple_capture.cpp | 63 ++++++++++++++++++++++++++++
 src/lc-compliance/simple_capture.h   | 14 +++++++
 src/lc-compliance/single_stream.cpp  | 25 ++++++++++-
 3 files changed, 101 insertions(+), 1 deletion(-)

diff --git a/src/lc-compliance/simple_capture.cpp b/src/lc-compliance/simple_capture.cpp
index 389dc11fc60225c5..0ff720bfd0052e45 100644
--- a/src/lc-compliance/simple_capture.cpp
+++ b/src/lc-compliance/simple_capture.cpp
@@ -149,3 +149,66 @@ void SimpleCaptureBalanced::requestComplete(Request *request)
 	if (queueRequest(request))
 		loop_->exit(-EINVAL);
 }
+
+/* SimpleCaptureUnbalanced */
+
+SimpleCaptureUnbalanced::SimpleCaptureUnbalanced(std::shared_ptr<Camera> camera)
+	: SimpleCapture(camera)
+{
+}
+
+Results::Result SimpleCaptureUnbalanced::capture(unsigned int numRequests)
+{
+	Results::Result ret = start();
+	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;
+
+	/* Queue the recommended number of reqeuests. */
+	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();
+	int status = loop_->exec();
+	stop();
+	delete loop_;
+
+	return { status ? Results::Fail : Results::Pass, "Unbalanced capture of " + std::to_string(numRequests) + " requests" };
+}
+
+void SimpleCaptureUnbalanced::requestComplete(Request *request)
+{
+	captureCount_++;
+	if (captureCount_ >= captureLimit_) {
+		loop_->exit(0);
+		return;
+	}
+
+	request->reuse(Request::ReuseBuffers);
+	if (camera_->queueRequest(request))
+		loop_->exit(-EINVAL);
+}
diff --git a/src/lc-compliance/simple_capture.h b/src/lc-compliance/simple_capture.h
index 3a6afc538c623050..4693c13404cee7d2 100644
--- a/src/lc-compliance/simple_capture.h
+++ b/src/lc-compliance/simple_capture.h
@@ -51,4 +51,18 @@ private:
 	unsigned int captureLimit_;
 };
 
+class SimpleCaptureUnbalanced : public SimpleCapture
+{
+public:
+	SimpleCaptureUnbalanced(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 e9ca1d58ecb959cd..8318b42f42d640aa 100644
--- a/src/lc-compliance/single_stream.cpp
+++ b/src/lc-compliance/single_stream.cpp
@@ -33,6 +33,18 @@ Results::Result testRequestBalance(std::shared_ptr<Camera> camera,
 		std::to_string(startCycles) + " start cycles" };
 }
 
+Results::Result testRequestUnbalance(std::shared_ptr<Camera> camera,
+				     StreamRole role, unsigned int numRequests)
+{
+	SimpleCaptureUnbalanced capture(camera);
+
+	Results::Result ret = capture.configure(role);
+	if (ret.first != Results::Pass)
+		return ret;
+
+	return capture.capture(numRequests);
+}
+
 Results testSingleStream(std::shared_ptr<Camera> camera)
 {
 	static const std::vector<std::pair<std::string, StreamRole>> roles = {
@@ -43,7 +55,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() * 2);
+	Results results(numRequests.size() * roles.size() * 3);
 
 	for (const auto &role : roles) {
 		std::cout << "= Test role " << role.first << std::endl;
@@ -68,6 +80,17 @@ Results testSingleStream(std::shared_ptr<Camera> camera)
 		std::cout << "* Test multiple start/stop cycles" << std::endl;
 		for (unsigned int num : numRequests)
 			results.add(testRequestBalance(camera, role.second, 3, num));
+
+		/*
+		 * Test unbalanced stop
+		 *
+		 * Makes sure the camera supports a stop with requests queued.
+		 * Example failure is a camera that does not handle cancelation
+		 * of buffers coming back from the video device while stopping.
+		 */
+		std::cout << "* Test unbalanced stop" << std::endl;
+		for (unsigned int num : numRequests)
+			results.add(testRequestUnbalance(camera, role.second, num));
 	}
 
 	return results;
-- 
2.31.1



More information about the libcamera-devel mailing list