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

Message ID 20210409150037.1440033-3-niklas.soderlund@ragnatech.se
State Accepted
Headers show
Series
  • lc-compliance: Add a libcamera compliance tool
Related show

Commit Message

Niklas Söderlund April 9, 2021, 3 p.m. UTC
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@ragnatech.se>
Acked-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@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(-)

Comments

Jean-Michel Hautbois April 11, 2021, 12:05 p.m. UTC | #1
Hi Niklas,

Thanks for that patch !

On 09/04/2021 17:00, Niklas Söderlund wrote:
> 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@ragnatech.se>
> Acked-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Tested-by: Jean-Michel Hautbois <jeanmichel.hautbois@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;
>

Patch
diff mbox series

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;