[libcamera-devel,v2,3/4] test: camera: Add capture test

Message ID 20190311022232.4759-4-niklas.soderlund@ragnatech.se
State Superseded
Headers show
Series
  • test: camera: Add basic tests for the camera
Related show

Commit Message

Niklas Söderlund March 11, 2019, 2:22 a.m. UTC
Correctly configure the camera using the default configuration and run a
capture session for 100 milliseconds, which is plenty of time, in tests
over 600 requests completed using the vimc pipeline.

The test passes if at least the number of buffers used in the capture
times two number of requests completes to prove we cycle through all
buffers.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
---
 test/camera/capture.cpp | 136 ++++++++++++++++++++++++++++++++++++++++
 test/camera/meson.build |   1 +
 2 files changed, 137 insertions(+)
 create mode 100644 test/camera/capture.cpp

Comments

Laurent Pinchart March 11, 2019, 8:45 a.m. UTC | #1
Hi Niklas,

Thank you for the patch.

On Mon, Mar 11, 2019 at 03:22:31AM +0100, Niklas Söderlund wrote:
> Correctly configure the camera using the default configuration and run a
> capture session for 100 milliseconds, which is plenty of time, in tests
> over 600 requests completed using the vimc pipeline.
> 
> The test passes if at least the number of buffers used in the capture
> times two number of requests completes to prove we cycle through all
> buffers.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
> ---
>  test/camera/capture.cpp | 136 ++++++++++++++++++++++++++++++++++++++++
>  test/camera/meson.build |   1 +
>  2 files changed, 137 insertions(+)
>  create mode 100644 test/camera/capture.cpp
> 
> diff --git a/test/camera/capture.cpp b/test/camera/capture.cpp
> new file mode 100644
> index 0000000000000000..44adcf3639393d3f
> --- /dev/null
> +++ b/test/camera/capture.cpp
> @@ -0,0 +1,136 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (C) 2019, Google Inc.
> + *
> + * libcamera Camera API tests
> + */
> +
> +#include <iostream>
> +
> +#include "camera_test.h"
> +
> +using namespace std;
> +
> +namespace {
> +
> +class Capture : public CameraTest
> +{
> +protected:
> +	unsigned int completeBuffersCount_;
> +	unsigned int completeRequestsCount_;
> +
> +	void bufferComplete(Request *request, Buffer *buffer)
> +	{
> +		if (buffer->status() != Buffer::BufferSuccess)
> +			return;
> +
> +		completeBuffersCount_++;
> +	}
> +
> +	void requestComplete(Request *request, const std::map<Stream *, Buffer *> &buffers)
> +	{
> +		if (request->status() != Request::RequestComplete)
> +			return;
> +
> +		completeRequestsCount_++;
> +
> +		/* Reuse the buffers for a new request. */
> +		request = camera_->createRequest();
> +		request->setBuffers(buffers);
> +		camera_->queueRequest(request);
> +	}
> +
> +	int run()
> +	{
> +		Stream *stream = *camera_->streams().begin();
> +		std::set<Stream *> streams = { stream };
> +		std::map<Stream *, StreamConfiguration> conf =
> +			camera_->streamConfiguration(streams);
> +		StreamConfiguration *sconf = &conf.begin()->second;
> +
> +		if (!configurationValid(streams, conf)) {
> +			cout << "Reading default configuration" << endl;

"Failed to read"

> +			return TestFail;
> +		}
> +
> +		if (camera_->acquire()) {
> +			cout << "Acquiring the camera" << endl;

Same here. And everywhere below.

> +			return TestFail;
> +		}
> +
> +		if (camera_->configureStreams(conf)) {
> +			cout << "Setting default configuration" << endl;
> +			return TestFail;
> +		}
> +
> +		if (camera_->allocateBuffers()) {
> +			cout << "Allocating buffers" << endl;
> +			return TestFail;
> +		}
> +
> +		BufferPool &pool = stream->bufferPool();
> +		std::vector<Request *> requests;
> +		for (Buffer &buffer : pool.buffers()) {
> +			Request *request = camera_->createRequest();
> +			if (!request) {
> +				cout << "Creating requests" << endl;
> +				return TestFail;
> +			}
> +
> +			std::map<Stream *, Buffer *> map = { { stream, &buffer } };
> +			if (request->setBuffers(map)) {
> +				cout << "Associating buffers with requests" << endl;
> +				return TestFail;
> +			}
> +
> +			requests.push_back(request);
> +		}
> +
> +		completeRequestsCount_ = 0;
> +		completeBuffersCount_ = 0;
> +
> +		camera_->bufferCompleted.connect(this, &Capture::bufferComplete);
> +		camera_->requestCompleted.connect(this, &Capture::requestComplete);
> +
> +		if (camera_->start()) {
> +			cout << "Starting camera" << endl;
> +			return TestFail;
> +		}
> +
> +		for (Request *request : requests) {
> +			if (camera_->queueRequest(request)) {
> +				cout << "Queueing requests" << endl;
> +				return TestFail;
> +			}
> +		}
> +
> +		EventDispatcher *dispatcher = CameraManager::instance()->eventDispatcher();
> +
> +		Timer timer;
> +		timer.start(100);
> +		while (timer.isRunning())
> +			dispatcher->processEvents();
> +
> +		if (completeRequestsCount_ <= sconf->bufferCount * 2 ||
> +		    completeRequestsCount_ != completeBuffersCount_) {
> +			cout << "Capture failed" << endl;
> +			return TestFail;
> +		}

I would split those two error cases and detail the failure messages.
Maybe "Failed to capture enough frames (got %u, expected at least %u)"
and "Number of completed buffers and requests differ" ?

With these small issues fixed,

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> +
> +		if (camera_->stop()) {
> +			cout << "Stopping camera" << endl;
> +			return TestFail;
> +		}
> +
> +		if (camera_->freeBuffers()) {
> +			cout << "Freeing buffers" << endl;
> +			return TestFail;
> +		}
> +
> +		return TestPass;
> +	}
> +};
> +
> +} /* namespace */
> +
> +TEST_REGISTER(Capture);
> diff --git a/test/camera/meson.build b/test/camera/meson.build
> index ed4837190ff6c52c..a1fd20326e97538b 100644
> --- a/test/camera/meson.build
> +++ b/test/camera/meson.build
> @@ -3,6 +3,7 @@
>  camera_tests = [
>    [ 'configuration_default',  'configuration_default.cpp' ],
>    [ 'configuration_set',      'configuration_set.cpp' ],
> +  [ 'capture',                'capture.cpp' ],
>  ]
>  
>  foreach t : camera_tests

Patch

diff --git a/test/camera/capture.cpp b/test/camera/capture.cpp
new file mode 100644
index 0000000000000000..44adcf3639393d3f
--- /dev/null
+++ b/test/camera/capture.cpp
@@ -0,0 +1,136 @@ 
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * libcamera Camera API tests
+ */
+
+#include <iostream>
+
+#include "camera_test.h"
+
+using namespace std;
+
+namespace {
+
+class Capture : public CameraTest
+{
+protected:
+	unsigned int completeBuffersCount_;
+	unsigned int completeRequestsCount_;
+
+	void bufferComplete(Request *request, Buffer *buffer)
+	{
+		if (buffer->status() != Buffer::BufferSuccess)
+			return;
+
+		completeBuffersCount_++;
+	}
+
+	void requestComplete(Request *request, const std::map<Stream *, Buffer *> &buffers)
+	{
+		if (request->status() != Request::RequestComplete)
+			return;
+
+		completeRequestsCount_++;
+
+		/* Reuse the buffers for a new request. */
+		request = camera_->createRequest();
+		request->setBuffers(buffers);
+		camera_->queueRequest(request);
+	}
+
+	int run()
+	{
+		Stream *stream = *camera_->streams().begin();
+		std::set<Stream *> streams = { stream };
+		std::map<Stream *, StreamConfiguration> conf =
+			camera_->streamConfiguration(streams);
+		StreamConfiguration *sconf = &conf.begin()->second;
+
+		if (!configurationValid(streams, conf)) {
+			cout << "Reading default configuration" << endl;
+			return TestFail;
+		}
+
+		if (camera_->acquire()) {
+			cout << "Acquiring the camera" << endl;
+			return TestFail;
+		}
+
+		if (camera_->configureStreams(conf)) {
+			cout << "Setting default configuration" << endl;
+			return TestFail;
+		}
+
+		if (camera_->allocateBuffers()) {
+			cout << "Allocating buffers" << endl;
+			return TestFail;
+		}
+
+		BufferPool &pool = stream->bufferPool();
+		std::vector<Request *> requests;
+		for (Buffer &buffer : pool.buffers()) {
+			Request *request = camera_->createRequest();
+			if (!request) {
+				cout << "Creating requests" << endl;
+				return TestFail;
+			}
+
+			std::map<Stream *, Buffer *> map = { { stream, &buffer } };
+			if (request->setBuffers(map)) {
+				cout << "Associating buffers with requests" << endl;
+				return TestFail;
+			}
+
+			requests.push_back(request);
+		}
+
+		completeRequestsCount_ = 0;
+		completeBuffersCount_ = 0;
+
+		camera_->bufferCompleted.connect(this, &Capture::bufferComplete);
+		camera_->requestCompleted.connect(this, &Capture::requestComplete);
+
+		if (camera_->start()) {
+			cout << "Starting camera" << endl;
+			return TestFail;
+		}
+
+		for (Request *request : requests) {
+			if (camera_->queueRequest(request)) {
+				cout << "Queueing requests" << endl;
+				return TestFail;
+			}
+		}
+
+		EventDispatcher *dispatcher = CameraManager::instance()->eventDispatcher();
+
+		Timer timer;
+		timer.start(100);
+		while (timer.isRunning())
+			dispatcher->processEvents();
+
+		if (completeRequestsCount_ <= sconf->bufferCount * 2 ||
+		    completeRequestsCount_ != completeBuffersCount_) {
+			cout << "Capture failed" << endl;
+			return TestFail;
+		}
+
+		if (camera_->stop()) {
+			cout << "Stopping camera" << endl;
+			return TestFail;
+		}
+
+		if (camera_->freeBuffers()) {
+			cout << "Freeing buffers" << endl;
+			return TestFail;
+		}
+
+		return TestPass;
+	}
+};
+
+} /* namespace */
+
+TEST_REGISTER(Capture);
diff --git a/test/camera/meson.build b/test/camera/meson.build
index ed4837190ff6c52c..a1fd20326e97538b 100644
--- a/test/camera/meson.build
+++ b/test/camera/meson.build
@@ -3,6 +3,7 @@ 
 camera_tests = [
   [ 'configuration_default',  'configuration_default.cpp' ],
   [ 'configuration_set',      'configuration_set.cpp' ],
+  [ 'capture',                'capture.cpp' ],
 ]
 
 foreach t : camera_tests