[libcamera-devel] [RFC PATCH 1/3] lc-compliance: Test queuing more requests than hardware depth

Nícolas F. R. A. Prado nfraprado at collabora.com
Fri Apr 9 23:38:13 CEST 2021


Currently some pipeline handlers allocate a fixed number of buffers for
internal usage, and if no internal buffer is available when a request is
received, it fails [1].

Extend the current lc-compliance tests so they also test sending more
simultaneous requests in order to detect that issue.

[1] https://bugs.libcamera.org/show_bug.cgi?id=24

Signed-off-by: Nícolas F. R. A. Prado <nfraprado at collabora.com>
---
 src/lc-compliance/simple_capture.cpp | 25 +++++++++++++++-------
 src/lc-compliance/simple_capture.h   |  2 +-
 src/lc-compliance/single_stream.cpp  | 31 ++++++++++++++++------------
 3 files changed, 37 insertions(+), 21 deletions(-)

diff --git a/src/lc-compliance/simple_capture.cpp b/src/lc-compliance/simple_capture.cpp
index 0ff720bfd005..61a8c0f40eef 100644
--- a/src/lc-compliance/simple_capture.cpp
+++ b/src/lc-compliance/simple_capture.cpp
@@ -18,10 +18,13 @@ SimpleCapture::~SimpleCapture()
 {
 }
 
-Results::Result SimpleCapture::configure(StreamRole role)
+Results::Result SimpleCapture::configure(StreamRole role, unsigned int numBuffers)
 {
 	config_ = camera_->generateConfiguration({ role });
 
+	if (numBuffers > 0)
+		config_->at(0).bufferCount = numBuffers;
+
 	if (config_->validate() != CameraConfiguration::Valid) {
 		config_.reset();
 		return { Results::Fail, "Configuration not valid" };
@@ -32,6 +35,10 @@ Results::Result SimpleCapture::configure(StreamRole role)
 		return { Results::Fail, "Failed to configure camera" };
 	}
 
+	if (numBuffers > 0 && config_->at(0).bufferCount != numBuffers)
+		return { Results::Skip,
+			"Pipeline doesn't support overriding bufferCount" };
+
 	return { Results::Pass, "Configure camera" };
 }
 
@@ -77,14 +84,14 @@ Results::Result SimpleCaptureBalanced::capture(unsigned int numRequests)
 
 	Stream *stream = config_->at(0).stream();
 	const std::vector<std::unique_ptr<FrameBuffer>> &buffers = allocator_->buffers(stream);
+	/* Cache buffers.size() before we destroy it in stop() */
+	unsigned int bufSize = buffers.size();
 
 	/* No point in testing less requests then the camera depth. */
-	if (buffers.size() > numRequests) {
-		/* Cache buffers.size() before we destroy it in stop() */
-		int buffers_size = buffers.size();
+	if (bufSize > numRequests) {
 		stop();
 
-		return { Results::Skip, "Camera needs " + std::to_string(buffers_size)
+		return { Results::Skip, "Camera needs " + std::to_string(bufSize)
 			+ " requests, can't test only " + std::to_string(numRequests) };
 	}
 
@@ -125,7 +132,8 @@ Results::Result SimpleCaptureBalanced::capture(unsigned int numRequests)
 			" request, wanted " + std::to_string(captureLimit_) };
 
 	return { Results::Pass, "Balanced capture of " +
-		std::to_string(numRequests) + " requests" };
+		std::to_string(numRequests) + " requests, using " +
+		std::to_string(bufSize) + " buffers"};
 }
 
 int SimpleCaptureBalanced::queueRequest(Request *request)
@@ -197,7 +205,10 @@ Results::Result SimpleCaptureUnbalanced::capture(unsigned int numRequests)
 	stop();
 	delete loop_;
 
-	return { status ? Results::Fail : Results::Pass, "Unbalanced capture of " + std::to_string(numRequests) + " requests" };
+	return { status ? Results::Fail :
+		Results::Pass, "Unbalanced capture of " +
+		std::to_string(numRequests) + " requests, using " +
+		std::to_string(buffers.size()) + " buffers"};
 }
 
 void SimpleCaptureUnbalanced::requestComplete(Request *request)
diff --git a/src/lc-compliance/simple_capture.h b/src/lc-compliance/simple_capture.h
index 4693c13404ce..f96fb3224290 100644
--- a/src/lc-compliance/simple_capture.h
+++ b/src/lc-compliance/simple_capture.h
@@ -17,7 +17,7 @@
 class SimpleCapture
 {
 public:
-	Results::Result configure(libcamera::StreamRole role);
+	Results::Result configure(libcamera::StreamRole role, unsigned int numBuffers);
 
 protected:
 	SimpleCapture(std::shared_ptr<libcamera::Camera> camera);
diff --git a/src/lc-compliance/single_stream.cpp b/src/lc-compliance/single_stream.cpp
index 60dacd63bf2b..9e33e231f4a9 100644
--- a/src/lc-compliance/single_stream.cpp
+++ b/src/lc-compliance/single_stream.cpp
@@ -14,11 +14,11 @@ using namespace libcamera;
 
 Results::Result testRequestBalance(std::shared_ptr<Camera> camera,
 				   StreamRole role, unsigned int startCycles,
-				   unsigned int numRequests)
+				   unsigned int numRequests, unsigned int numBuffers)
 {
 	SimpleCaptureBalanced capture(camera);
 
-	Results::Result ret = capture.configure(role);
+	Results::Result ret = capture.configure(role, numBuffers);
 	if (ret.first != Results::Pass)
 		return ret;
 
@@ -28,17 +28,17 @@ Results::Result testRequestBalance(std::shared_ptr<Camera> camera,
 			return ret;
 	}
 
-	return { Results::Pass, "Balanced capture of " +
-		std::to_string(numRequests) + " requests with " +
+	return { Results::Pass, ret.second + " and " +
 		std::to_string(startCycles) + " start cycles" };
 }
 
 Results::Result testRequestUnbalance(std::shared_ptr<Camera> camera,
-				     StreamRole role, unsigned int numRequests)
+				     StreamRole role, unsigned int numRequests,
+				     unsigned int numBuffers)
 {
 	SimpleCaptureUnbalanced capture(camera);
 
-	Results::Result ret = capture.configure(role);
+	Results::Result ret = capture.configure(role, numBuffers);
 	if (ret.first != Results::Pass)
 		return ret;
 
@@ -54,8 +54,10 @@ Results testSingleStream(std::shared_ptr<Camera> camera)
 		{ "viewfinder", Viewfinder },
 	};
 	static const std::vector<unsigned int> numRequests = { 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 };
+	/* 0 means default */
+	static const std::vector<unsigned int> numBuffers = { 0, 5, 8 };
 
-	Results results(numRequests.size() * roles.size() * 3);
+	Results results(numRequests.size() * roles.size() * numBuffers.size() * 3);
 
 	for (const auto &role : roles) {
 		std::cout << "= Test role " << role.first << std::endl;
@@ -67,8 +69,9 @@ Results testSingleStream(std::shared_ptr<Camera> camera)
 		 * complete N requests to the application.
 		 */
 		std::cout << "* Test single capture cycles" << std::endl;
-		for (unsigned int num : numRequests)
-			results.add(testRequestBalance(camera, role.second, 1, num));
+		for (unsigned int buf : numBuffers)
+			for (unsigned int num : numRequests)
+				results.add(testRequestBalance(camera, role.second, 1, num, buf));
 
 		/*
 		 * Test multiple start/stop cycles
@@ -78,8 +81,9 @@ Results testSingleStream(std::shared_ptr<Camera> camera)
 		 * error path but is only tested by single-capture applications.
 		 */
 		std::cout << "* Test multiple start/stop cycles" << std::endl;
-		for (unsigned int num : numRequests)
-			results.add(testRequestBalance(camera, role.second, 3, num));
+		for (unsigned int buf : numBuffers)
+			for (unsigned int num : numRequests)
+				results.add(testRequestBalance(camera, role.second, 3, num, buf));
 
 		/*
 		 * Test unbalanced stop
@@ -89,8 +93,9 @@ Results testSingleStream(std::shared_ptr<Camera> camera)
 		 * 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));
+		for (unsigned int buf : numBuffers)
+			for (unsigned int num : numRequests)
+				results.add(testRequestUnbalance(camera, role.second, num, buf));
 	}
 
 	return results;
-- 
2.31.1



More information about the libcamera-devel mailing list