Patch Detail
Show a patch.
GET /api/patches/12248/?format=api
{ "id": 12248, "url": "https://patchwork.libcamera.org/api/patches/12248/?format=api", "web_url": "https://patchwork.libcamera.org/patch/12248/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/projects/1/?format=api", "name": "libcamera", "link_name": "libcamera", "list_id": "libcamera_core", "list_email": "libcamera-devel@lists.libcamera.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20210510105235.28319-9-jacopo@jmondi.org>", "date": "2021-05-10T10:52:35", "name": "[libcamera-devel,8/8] android: Implement flush() camera operation", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "3983d150d96bbb094e0efe388e0f35bf39b0fd51", "submitter": { "id": 3, "url": "https://patchwork.libcamera.org/api/people/3/?format=api", "name": "Jacopo Mondi", "email": "jacopo@jmondi.org" }, "delegate": { "id": 15, "url": "https://patchwork.libcamera.org/api/users/15/?format=api", "username": "jmondi", "first_name": "Jacopo", "last_name": "Mondi", "email": "jacopo@jmondi.org" }, "mbox": "https://patchwork.libcamera.org/patch/12248/mbox/", "series": [ { "id": 2016, "url": "https://patchwork.libcamera.org/api/series/2016/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=2016", "date": "2021-05-10T10:52:27", "name": "android: Implement flush() camera operation", "version": 1, "mbox": "https://patchwork.libcamera.org/series/2016/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/12248/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/12248/checks/", "tags": {}, "headers": { "Return-Path": "<libcamera-devel-bounces@lists.libcamera.org>", "X-Original-To": "parsemail@patchwork.libcamera.org", "Delivered-To": "parsemail@patchwork.libcamera.org", "Received": [ "from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id AF131BF839\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 10 May 2021 10:52:04 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 4AE236892D;\n\tMon, 10 May 2021 12:52:04 +0200 (CEST)", "from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net\n\t[217.70.183.196])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id C27A86891C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 10 May 2021 12:52:02 +0200 (CEST)", "from uno.homenet.telecomitalia.it\n\t(host-82-59-136-116.retail.telecomitalia.it [82.59.136.116])\n\t(Authenticated sender: jacopo@jmondi.org)\n\tby relay4-d.mail.gandi.net (Postfix) with ESMTPSA id 131FBE01CF;\n\tMon, 10 May 2021 10:52:01 +0000 (UTC)" ], "X-Originating-IP": "82.59.136.116", "From": "Jacopo Mondi <jacopo@jmondi.org>", "To": "libcamera-devel@lists.libcamera.org", "Date": "Mon, 10 May 2021 12:52:35 +0200", "Message-Id": "<20210510105235.28319-9-jacopo@jmondi.org>", "X-Mailer": "git-send-email 2.31.1", "In-Reply-To": "<20210510105235.28319-1-jacopo@jmondi.org>", "References": "<20210510105235.28319-1-jacopo@jmondi.org>", "MIME-Version": "1.0", "Subject": "[libcamera-devel] [PATCH 8/8] android: Implement flush() camera\n\toperation", "X-BeenThere": "libcamera-devel@lists.libcamera.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "<libcamera-devel.lists.libcamera.org>", "List-Unsubscribe": "<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>", "List-Archive": "<https://lists.libcamera.org/pipermail/libcamera-devel/>", "List-Post": "<mailto:libcamera-devel@lists.libcamera.org>", "List-Help": "<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>", "List-Subscribe": "<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Errors-To": "libcamera-devel-bounces@lists.libcamera.org", "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>" }, "content": "Implement the flush() camera operation in the CameraDevice class\nand make it available to the camera framework by implementing the\noperation wrapper in camera_ops.cpp.\n\nThe flush() implementation stops the Camera and the worker thread and\nwaits for all in-flight requests to be returned. Stopping the Camera\nforces all Requests already queued to be returned immediately in error\nstate. As flush() has to wait until all of them have been returned, make it\nwait on a newly introduced condition variable which is notified by the\nrequest completion handler when the queue of pending requests has been\nexhausted.\n\nAs flush() can race with processCaptureRequest() protect the requests\nqueueing by introducing a new CameraState::CameraFlushing state that\nprocessCaptureRequest() inspects before queuing the Request to the\nCamera. If flush() has been called while processCaptureRequest() was\nexecuting, return the current Request immediately in error state.\n\nSigned-off-by: Jacopo Mondi <jacopo@jmondi.org>\n---\n src/android/camera_device.cpp | 63 +++++++++++++++++++++++++++++++++++\n src/android/camera_device.h | 6 ++++\n src/android/camera_ops.cpp | 8 ++++-\n 3 files changed, 76 insertions(+), 1 deletion(-)", "diff": "diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp\nindex fa12ce5b0133..01b3acd93c4b 100644\n--- a/src/android/camera_device.cpp\n+++ b/src/android/camera_device.cpp\n@@ -756,6 +756,42 @@ void CameraDevice::close()\n \tcamera_->release();\n }\n \n+/*\n+ * Flush is similar to stop() but sets the camera state to 'flushing' and wait\n+ * until all the in-flight requests have been returned.\n+ */\n+void CameraDevice::flush()\n+{\n+\t{\n+\t\tMutexLocker cameraLock(cameraMutex_);\n+\n+\t\tif (state_ != CameraRunning)\n+\t\t\treturn;\n+\n+\t\tstate_ = CameraFlushing;\n+\n+\t\t/*\n+\t\t * Stop the camera and set the state to flushing to prevent any\n+\t\t * new request to be queued from this point on.\n+\t\t */\n+\t\tworker_.stop();\n+\t\tcamera_->stop();\n+\t}\n+\n+\t/*\n+\t * Now wait for all the in-flight requests to be completed before\n+\t * returning. Stopping the Camera guarantees that all in-flight requests\n+\t * are completed in error state.\n+\t */\n+\t{\n+\t\tMutexLocker flushLock(flushMutex_);\n+\t\tflushing_.wait(flushLock, [&] { return descriptors_.empty(); });\n+\t}\n+\n+\tMutexLocker cameraLock(cameraMutex_);\n+\tstate_ = CameraStopped;\n+}\n+\n void CameraDevice::stop()\n {\n \tMutexLocker cameraLock(cameraMutex_);\n@@ -2019,6 +2055,26 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques\n \tif (ret)\n \t\treturn ret;\n \n+\n+\t/*\n+\t * Just before queuing the request, make sure flush() has not\n+\t * been called after this function has been executed. In that\n+\t * case, immediately return the request with errors.\n+\t */\n+\tMutexLocker cameraLock(cameraMutex_);\n+\tif (state_ == CameraFlushing || state_ == CameraStopped) {\n+\t\tfor (camera3_stream_buffer_t &buffer : descriptor.buffers_) {\n+\t\t\tbuffer.status = CAMERA3_BUFFER_STATUS_ERROR;\n+\t\t\tbuffer.release_fence = buffer.acquire_fence;\n+\t\t}\n+\n+\t\tnotifyError(descriptor.frameNumber_,\n+\t\t\t descriptor.buffers_[0].stream,\n+\t\t\t CAMERA3_MSG_ERROR_REQUEST);\n+\n+\t\treturn 0;\n+\t}\n+\n \tworker_.queueRequest(descriptor.request_.get());\n \n \t{\n@@ -2052,6 +2108,13 @@ void CameraDevice::requestComplete(Request *request)\n \t}\n \tCamera3RequestDescriptor &descriptor = node.mapped();\n \n+\t/* Release flush if all the pending requests have been completed. */\n+\t{\n+\t\tMutexLocker flushLock(flushMutex_);\n+\t\tif (descriptors_.empty())\n+\t\t\tflushing_.notify_one();\n+\t}\n+\n \t/*\n \t * Prepare the capture result for the Android camera stack.\n \t *\ndiff --git a/src/android/camera_device.h b/src/android/camera_device.h\nindex ed992ae56d5d..4a9ef495b776 100644\n--- a/src/android/camera_device.h\n+++ b/src/android/camera_device.h\n@@ -7,6 +7,7 @@\n #ifndef __ANDROID_CAMERA_DEVICE_H__\n #define __ANDROID_CAMERA_DEVICE_H__\n \n+#include <condition_variable>\n #include <map>\n #include <memory>\n #include <mutex>\n@@ -42,6 +43,7 @@ public:\n \n \tint open(const hw_module_t *hardwareModule);\n \tvoid close();\n+\tvoid flush();\n \n \tunsigned int id() const { return id_; }\n \tcamera3_device_t *camera3Device() { return &camera3Device_; }\n@@ -92,6 +94,7 @@ private:\n \tenum State {\n \t\tCameraStopped,\n \t\tCameraRunning,\n+\t\tCameraFlushing,\n \t};\n \n \tvoid stop();\n@@ -124,6 +127,9 @@ private:\n \tlibcamera::Mutex cameraMutex_; /* Protects access to the camera state. */\n \tState state_;\n \n+\tlibcamera::Mutex flushMutex_; /* Protects the flushing condition variable. */\n+\tstd::condition_variable flushing_;\n+\n \tstd::shared_ptr<libcamera::Camera> camera_;\n \tstd::unique_ptr<libcamera::CameraConfiguration> config_;\n \ndiff --git a/src/android/camera_ops.cpp b/src/android/camera_ops.cpp\nindex 696e80436821..8a3cfa175ff5 100644\n--- a/src/android/camera_ops.cpp\n+++ b/src/android/camera_ops.cpp\n@@ -66,8 +66,14 @@ static void hal_dev_dump([[maybe_unused]] const struct camera3_device *dev,\n {\n }\n \n-static int hal_dev_flush([[maybe_unused]] const struct camera3_device *dev)\n+static int hal_dev_flush(const struct camera3_device *dev)\n {\n+\tif (!dev)\n+\t\treturn -EINVAL;\n+\n+\tCameraDevice *camera = reinterpret_cast<CameraDevice *>(dev->priv);\n+\tcamera->flush();\n+\n \treturn 0;\n }\n \n", "prefixes": [ "libcamera-devel", "8/8" ] }