From patchwork Fri Oct 9 13:39:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 10039 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id C364CBEEE0 for ; Fri, 9 Oct 2020 13:36:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9A9576081E; Fri, 9 Oct 2020 15:36:30 +0200 (CEST) Received: from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net [217.70.183.199]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 1456060358 for ; Fri, 9 Oct 2020 15:36:29 +0200 (CEST) X-Originating-IP: 93.34.118.233 Received: from uno.lan (93-34-118-233.ip49.fastwebnet.it [93.34.118.233]) (Authenticated sender: jacopo@jmondi.org) by relay9-d.mail.gandi.net (Postfix) with ESMTPSA id 95BB4FF804; Fri, 9 Oct 2020 13:36:28 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 9 Oct 2020 15:39:55 +0200 Message-Id: <20201009133956.77396-2-jacopo@jmondi.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201009133956.77396-1-jacopo@jmondi.org> References: <20201009133956.77396-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 1/2] android: camera_worker: Introduce CameraWorker X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The Android camera framework provides for each buffer part of a capture request an acquisition fence the camera HAL is supposed to wait on before using the buffer. As the libcamera HAL runs in the camera service thread, it is not possible to perform a synchronous wait there. Introduce a CameraWorker class that runs an internal thread to wait on a set of fences before queueing a capture request to the libcamera::Camera. Fences completion is handled through a simple poll, similar in implementation to the sync_wait() function provided by libdrm. Signed-off-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- src/android/camera_worker.cpp | 88 +++++++++++++++++++++++++++++++++++ src/android/camera_worker.h | 73 +++++++++++++++++++++++++++++ src/android/meson.build | 1 + 3 files changed, 162 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..775473da9f6e --- /dev/null +++ b/src/android/camera_worker.cpp @@ -0,0 +1,88 @@ +/* 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 +#include + +#include "camera_device.h" + +using namespace libcamera; + +void CaptureRequest::addBuffer(Stream *stream, FrameBuffer *buffer, int fence) +{ + request_->addBuffer(stream, buffer); + acquireFences_.push_back(fence); +} + +void CaptureRequest::queue(Camera *camera) +{ + camera->queueRequest(request_); +} + +CameraWorker::CameraWorker(const std::shared_ptr &camera) + : worker_(camera) +{ + worker_.moveToThread(&thread_); +} + +void CameraWorker::start() +{ + thread_.start(); +} + +void CameraWorker::stop() +{ + thread_.exit(); + thread_.wait(); +} + +void CameraWorker::queueRequest(std::unique_ptr 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->fences()) { + if (fence == -1) + continue; + + int ret = waitFence(fence); + if (ret < 0) + return; + + close(fence); + } + + request->queue(camera_.get()); + delete request; +} diff --git a/src/android/camera_worker.h b/src/android/camera_worker.h new file mode 100644 index 000000000000..7e193513d6f4 --- /dev/null +++ b/src/android/camera_worker.h @@ -0,0 +1,73 @@ +/* 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 + +#include +#include +#include +#include +#include + +#include "libcamera/internal/thread.h" + +class CameraDevice; + +struct CaptureRequest { + CaptureRequest(libcamera::Request *request) + : request_(request) + { + } + + const std::vector &fences() const { return acquireFences_; } + + void addBuffer(libcamera::Stream *stream, + libcamera::FrameBuffer *buffer, int fence); + void queue(libcamera::Camera *camera); + +private: + std::vector acquireFences_; + libcamera::Request *request_; +}; + +class CameraWorker +{ +public: + CameraWorker(const std::shared_ptr &camera); + + void start(); + void stop(); + + void queueRequest(std::unique_ptr request); + +private: + class Worker : public libcamera::Object + { + public: + Worker(const std::shared_ptr &camera) + : camera_(camera) + { + } + ~Worker() + { + } + + void processRequest(CaptureRequest *request); + + private: + int waitFence(int fence); + + const std::shared_ptr 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', ])