[libcamera-devel,v2,2/2] lc-compliance: Add test stopping single stream with requests queued
diff mbox series

Message ID 20210208102137.2164282-3-niklas.soderlund@ragnatech.se
State Superseded
Delegated to: Niklas Söderlund
Headers show
Series
  • lc-compliance: Add a libcamera compliance tool
Related show

Commit Message

Niklas Söderlund Feb. 8, 2021, 10:21 a.m. UTC
Add a test which stops a camera while requests are still queued. This
intents to test cleanup paths where requests are dequeued from video
devices in an uncompleted state.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
---
 src/lc-compliance/simple_capture.cpp | 63 ++++++++++++++++++++++++++++
 src/lc-compliance/simple_capture.h   | 14 +++++++
 src/lc-compliance/single_stream.cpp  | 23 ++++++++++
 3 files changed, 100 insertions(+)

Patch
diff mbox series

diff --git a/src/lc-compliance/simple_capture.cpp b/src/lc-compliance/simple_capture.cpp
index e6699b689ace180d..cfcad79ad655fbfb 100644
--- a/src/lc-compliance/simple_capture.cpp
+++ b/src/lc-compliance/simple_capture.cpp
@@ -143,3 +143,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 0ed6f5dcfb5a516d..3d5ffdeadd7a0e1f 100644
--- a/src/lc-compliance/single_stream.cpp
+++ b/src/lc-compliance/single_stream.cpp
@@ -31,6 +31,18 @@  Results::Result testRequestBalance(std::shared_ptr<Camera> camera,
 	return { Results::Pass, "Balanced capture of " + std::to_string(numRequests) + " requests with " + 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)
 {
 	const std::vector<std::pair<std::string, StreamRole>> roles = {
@@ -69,6 +81,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;