[libcamera-devel] [RFC 1/2] android: camera_worker: Introduce CameraWorker

Jacopo Mondi jacopo at jmondi.org
Tue Oct 6 18:06:36 CEST 2020


The CameraWork class creates a Worker instance and runs on an internal
thread. The worker waits on a set of fences before queueing a capture
requests to the the libcamera::Camera.

Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
---
 src/android/camera_worker.cpp | 67 +++++++++++++++++++++++++++++++
 src/android/camera_worker.h   | 75 +++++++++++++++++++++++++++++++++++
 src/android/meson.build       |  1 +
 3 files changed, 143 insertions(+)
 create mode 100644 src/android/camera_worker.cpp
 create mode 100644 src/android/camera_worker.h

diff --git a/src/android/camera_worker.cpp b/src/android/camera_worker.cpp
new file mode 100644
index 000000000000..2bb94775a195
--- /dev/null
+++ b/src/android/camera_worker.cpp
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2020, Google Inc.
+ *
+ * camera_worker.cpp - Process capture request on behalf of the Camera HAL
+ */
+
+#include "camera_worker.h"
+
+#include <errno.h>
+#include <sys/poll.h>
+
+#include "camera_device.h"
+
+using namespace libcamera;
+
+CameraWorker::CameraWorker(const std::shared_ptr<Camera> &camera)
+	: camera_(camera), worker_(camera_.get())
+{
+	worker_.moveToThread(&thread_);
+	thread_.start();
+}
+
+void CameraWorker::queueRequest(std::unique_ptr<CaptureRequest> request)
+{
+	CaptureRequest *req = request.release();
+	worker_.invokeMethod(&Worker::processRequest, ConnectionTypeQueued, req);
+}
+
+int CameraWorker::Worker::waitFence(int fence)
+{
+	struct pollfd fds = { fence, POLLIN, 0 };
+	constexpr unsigned int timeoutMs = 300;
+	int ret;
+
+	do {
+		ret = poll(&fds, 1, timeoutMs);
+		if (ret == 0)
+			return -ETIME;
+
+		if (ret > 0) {
+			if (fds.revents & (POLLERR | POLLNVAL))
+				return -EINVAL;
+
+			return 0;
+		}
+	} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
+
+	return ret;
+}
+
+void CameraWorker::Worker::processRequest(CaptureRequest *request)
+{
+	for (int fence : request->acquireFences_) {
+		if (fence == -1)
+			continue;
+
+		int ret = waitFence(fence);
+		if (ret < 0)
+			return;
+
+		close(fence);
+	}
+
+	camera_->queueRequest(request->request_);
+	delete request;
+}
diff --git a/src/android/camera_worker.h b/src/android/camera_worker.h
new file mode 100644
index 000000000000..24b176d6269c
--- /dev/null
+++ b/src/android/camera_worker.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2020, Google Inc.
+ *
+ * camera_worker.h - Process capture request on behalf of the Camera HAL
+ */
+#ifndef __ANDROID_CAMERA_WORKER_H__
+#define __ANDROID_CAMERA_WORKER_H__
+
+#include <memory>
+
+#include <libcamera/buffer.h>
+#include <libcamera/camera.h>
+#include <libcamera/object.h>
+#include <libcamera/request.h>
+#include <libcamera/stream.h>
+
+#include "libcamera/internal/thread.h"
+
+class CameraDevice;
+
+struct CaptureRequest {
+	CaptureRequest(libcamera::Request *request)
+		: request_(request)
+	{
+	}
+
+	void addBuffer(libcamera::Stream *stream,
+		       libcamera::FrameBuffer *buffer, int fence)
+	{
+		request_->addBuffer(stream, buffer);
+		acquireFences_.push_back(fence);
+	}
+
+private:
+	friend class CameraWorker;
+
+	std::vector<int> acquireFences_;
+	libcamera::Request *request_;
+};
+
+class CameraWorker
+{
+public:
+	CameraWorker(const std::shared_ptr<libcamera::Camera> &camera);
+
+	void queueRequest(std::unique_ptr<CaptureRequest> request);
+
+private:
+	class Worker : public libcamera::Object
+	{
+	public:
+		Worker(libcamera::Camera *camera)
+			: camera_(camera)
+		{
+		}
+		~Worker()
+		{
+		}
+
+		void processRequest(CaptureRequest *request);
+
+	private:
+		int waitFence(int fence);
+
+		libcamera::Camera *camera_;
+	};
+
+	std::shared_ptr<libcamera::Camera> camera_;
+
+	Worker worker_;
+	libcamera::Thread thread_;
+};
+
+#endif /* __ANDROID_CAMERA_WORKER_H__ */
diff --git a/src/android/meson.build b/src/android/meson.build
index 802bb89afe57..b2b2293cf62d 100644
--- a/src/android/meson.build
+++ b/src/android/meson.build
@@ -21,6 +21,7 @@ android_hal_sources = files([
     'camera_metadata.cpp',
     'camera_ops.cpp',
     'camera_stream.cpp',
+    'camera_worker.cpp',
     'jpeg/encoder_libjpeg.cpp',
     'jpeg/exif.cpp',
 ])
-- 
2.28.0



More information about the libcamera-devel mailing list