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', ]) From patchwork Fri Oct 9 13:39:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 10040 X-Patchwork-Delegate: jacopo@jmondi.org 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 DAF57BEEE0 for ; Fri, 9 Oct 2020 13:36:31 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B83136073B; Fri, 9 Oct 2020 15:36:31 +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 C39FA6081E 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 47EEEFF817; Fri, 9 Oct 2020 13:36:29 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Fri, 9 Oct 2020 15:39:56 +0200 Message-Id: <20201009133956.77396-3-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 2/2] android: camera_device: Queue request to Worker 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" Add a CameraWorker class member to the CameraDevice class and queue capture requests to it to delegate fence handling and capture requests queueing to the camera. Signed-off-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- src/android/camera_device.cpp | 19 +++++++++---------- src/android/camera_device.h | 3 +++ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp index 0a94c1ae17ac..0e42e2e194d8 100644 --- a/src/android/camera_device.cpp +++ b/src/android/camera_device.cpp @@ -194,8 +194,8 @@ CameraDevice::Camera3RequestDescriptor::~Camera3RequestDescriptor() */ CameraDevice::CameraDevice(unsigned int id, const std::shared_ptr &camera) - : id_(id), running_(false), camera_(camera), staticMetadata_(nullptr), - facing_(CAMERA_FACING_FRONT), orientation_(0) + : id_(id), worker_(camera), running_(false), camera_(camera), + staticMetadata_(nullptr), facing_(CAMERA_FACING_FRONT), orientation_(0) { camera_->requestCompleted.connect(this, &CameraDevice::requestComplete); @@ -519,6 +519,7 @@ void CameraDevice::close() { streams_.clear(); + worker_.stop(); camera_->stop(); camera_->release(); @@ -1356,6 +1357,8 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques return ret; } + worker_.start(); + running_ = true; } @@ -1377,6 +1380,7 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques Request *request = camera_->createRequest(reinterpret_cast(descriptor)); + std::unique_ptr captureRequest = std::make_unique(request); LOG(HAL, Debug) << "Queueing Request to libcamera with " << descriptor->numBuffers << " HAL streams"; @@ -1445,16 +1449,11 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques return -ENOMEM; } - request->addBuffer(cameraStream->stream(), buffer); + captureRequest->addBuffer(cameraStream->stream(), buffer, + camera3Buffers[i].acquire_fence); } - int ret = camera_->queueRequest(request); - if (ret) { - LOG(HAL, Error) << "Failed to queue request"; - delete request; - delete descriptor; - return ret; - } + worker_.queueRequest(std::move(captureRequest)); return 0; } diff --git a/src/android/camera_device.h b/src/android/camera_device.h index 777d1a35e801..b4b32f77a29a 100644 --- a/src/android/camera_device.h +++ b/src/android/camera_device.h @@ -25,6 +25,7 @@ #include "libcamera/internal/message.h" #include "camera_stream.h" +#include "camera_worker.h" #include "jpeg/encoder.h" class CameraMetadata; @@ -108,6 +109,8 @@ private: unsigned int id_; camera3_device_t camera3Device_; + CameraWorker worker_; + bool running_; std::shared_ptr camera_; std::unique_ptr config_;