From patchwork Thu Mar 9 14:26:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomi Valkeinen X-Patchwork-Id: 18376 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 CD191C32A6 for ; Thu, 9 Mar 2023 14:26:31 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6EDB062718; Thu, 9 Mar 2023 15:26:31 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1678371991; bh=H9Z7KLUXihKcr8UogM/YAwzpdvBQoIgZwip8xyxiUKE=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=Von8tyngRaZVFLcngtTJdmZ0M2Hbu17JNoatDm70T8uK2BQUtDdt/0l1OQX+GLPf9 Rjc9joTVONTAbx3NXxPvAmzMqAGEtyAb1+1F652cARWzPGJWzC3DTBh3QLQIqfp7k8 0kg8+HUA2AMFS/6UbgpA2R0T9oPIAlXrKV+K3u/OfxtmAdeVKYUoK30FzoWYPKECi6 V4PXmeSI0c5Ny2ZTJOYqTUDvnKaMdddUqzX9vUFpoIflBAULEqTVabCsKUl/VLrqrF lz2okTvComplWE5GA1lwaEnRcA/myHD981l3FNY1xI3RwZOg0P5NCRJ/uM7a/a2Ae0 Sky/+l3E+ihAw== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 590A6626D8 for ; Thu, 9 Mar 2023 15:26:22 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="AAx2kdGr"; dkim-atps=neutral Received: from desky.lan (91-154-32-225.elisa-laajakaista.fi [91.154.32.225]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id E537E886; Thu, 9 Mar 2023 15:26:21 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1678371982; bh=H9Z7KLUXihKcr8UogM/YAwzpdvBQoIgZwip8xyxiUKE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AAx2kdGru3mqqccaOtY9QEJFeJfp13kOxUYv5gX7lxTpw81IdqQfiFuOl6eWNeWJn F8m9sJFHLrYp+SDlJTKrD71FjzOyAPVH1QCj68vGk6yjHvJLkSR149VqEextn0xOU1 IxH6nm/75SkW3LQf10OsJ+Mq8CmdZwyj5PqpDGcA= To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Mar 2023 16:26:01 +0200 Message-Id: <20230309142601.70556-16-tomi.valkeinen@ideasonboard.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230309142601.70556-1-tomi.valkeinen@ideasonboard.com> References: <20230309142601.70556-1-tomi.valkeinen@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 15/15] py: Hack for different event enable mechanism 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: , X-Patchwork-Original-From: Tomi Valkeinen via libcamera-devel From: Tomi Valkeinen Reply-To: Tomi Valkeinen Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Instead of connecting all the event signals automatically (except bufferCompletedEvent), add properties to Camera object to enable/disable the events. E.g. cam.requestCompletedEnabled = True would enable the delivery of request completed events. Also, as (I think) almost everyone wants request completed events, subscribe to them automatically for all cameras when creating the PyCameraManager singleton. If someone doesn't want request completed events, they can set the cam.requestCompletedEnabled to False. This is just a quick hack, a proper implementation would need a bit more abstraction functionality to the PyCameraManager. Signed-off-by: Tomi Valkeinen --- src/py/libcamera/py_camera_manager.cpp | 3 - src/py/libcamera/py_camera_manager.h | 5 +- src/py/libcamera/py_main.cpp | 113 ++++++++++++++++++++----- 3 files changed, 96 insertions(+), 25 deletions(-) diff --git a/src/py/libcamera/py_camera_manager.cpp b/src/py/libcamera/py_camera_manager.cpp index c3b9646f..ca0f6f7a 100644 --- a/src/py/libcamera/py_camera_manager.cpp +++ b/src/py/libcamera/py_camera_manager.cpp @@ -182,9 +182,6 @@ std::vector PyCameraManager::getPyCameraEvents(std::shared_ptr cam, Request *req, FrameBuffer *fb) { - if (!bufferCompletedEventActive_) - return; - CameraEvent ev(CameraEventType::BufferCompleted, cam, req, fb); pushEvent(ev); diff --git a/src/py/libcamera/py_camera_manager.h b/src/py/libcamera/py_camera_manager.h index 648d78af..41105de7 100644 --- a/src/py/libcamera/py_camera_manager.h +++ b/src/py/libcamera/py_camera_manager.h @@ -77,10 +77,11 @@ public: void handleCameraAdded(std::shared_ptr cam); void handleCameraRemoved(std::shared_ptr cam); - bool bufferCompletedEventActive_ = false; + uint32_t event_mask_; + std::map, uint32_t> camera_event_masks_; + std::unique_ptr cameraManager_; private: - std::unique_ptr cameraManager_; UniqueFD eventFd_; libcamera::Mutex eventsMutex_; diff --git a/src/py/libcamera/py_main.cpp b/src/py/libcamera/py_main.cpp index cb7088b1..54b58366 100644 --- a/src/py/libcamera/py_main.cpp +++ b/src/py/libcamera/py_main.cpp @@ -48,6 +48,57 @@ void init_py_geometry(py::module &m); void init_py_properties_generated(py::module &m); void init_py_transform(py::module &m); +static bool py_camera_get_event_flag(std::shared_ptr camera, CameraEventType event_type) +{ + const uint32_t evbit = 1 << (uint32_t)event_type; + + auto cm = gCameraManager.lock(); + ASSERT(cm); + + auto it = cm->camera_event_masks_.find(camera); + + uint32_t mask = 0; + + if (it != cm->camera_event_masks_.end()) + mask = it->second; + + return !!(mask & evbit); +} + +static void py_camera_set_event_flag(std::shared_ptr camera, CameraEventType event_type, bool value) +{ + const uint32_t evbit = 1 << (uint32_t)event_type; + + auto cm = gCameraManager.lock(); + ASSERT(cm); + + uint32_t mask = 0; + + auto it = cm->camera_event_masks_.find(camera); + if (it != cm->camera_event_masks_.end()) + mask = it->second; + + bool old_val = !!(mask & evbit); + + if (old_val == value) + return; + + if (value) + mask |= evbit; + else + mask &= ~evbit; + + cm->camera_event_masks_[camera] = mask; + + if (value) { + camera->requestCompleted.connect(camera.get(), [cm, camera](Request *req) { + cm->handleRequestCompleted(camera, req); + }); + } else { + camera->requestCompleted.disconnect(); + } +} + PYBIND11_MODULE(_libcamera, m) { init_py_enums(m); @@ -121,6 +172,10 @@ PYBIND11_MODULE(_libcamera, m) if (!cm) { cm = std::make_shared(); gCameraManager = cm; + + /* Always enable RequestCompleted for all cameras */ + for (auto cam : cm->cameraManager_->cameras()) + py_camera_set_event_flag(cam, CameraEventType::RequestCompleted, true); } return cm; @@ -132,12 +187,47 @@ PYBIND11_MODULE(_libcamera, m) .def_property_readonly("event_fd", &PyCameraManager::eventFd) - .def("get_events", &PyCameraManager::getPyEvents) - - .def_readwrite("buffer_completed_active", &PyCameraManager::bufferCompletedEventActive_); + .def("get_events", &PyCameraManager::getPyEvents); pyCamera .def_property_readonly("id", &Camera::id) + + .def_property( + "requestCompletedEnabled", + [](Camera &self) { + return py_camera_get_event_flag(self.shared_from_this(), + CameraEventType::RequestCompleted); + }, + [](Camera &self, bool val) { + py_camera_set_event_flag(self.shared_from_this(), + CameraEventType::RequestCompleted, + val); + }) + + .def_property( + "bufferCompletedEnabled", + [](Camera &self) { + return py_camera_get_event_flag(self.shared_from_this(), + CameraEventType::BufferCompleted); + }, + [](Camera &self, bool val) { + py_camera_set_event_flag(self.shared_from_this(), + CameraEventType::BufferCompleted, + val); + }) + + .def_property( + "disconnectEnabled", + [](Camera &self) { + return py_camera_get_event_flag(self.shared_from_this(), + CameraEventType::Disconnect); + }, + [](Camera &self, bool val) { + py_camera_set_event_flag(self.shared_from_this(), + CameraEventType::Disconnect, + val); + }) + .def("acquire", [](Camera &self) { int ret = self.acquire(); if (ret) @@ -157,18 +247,6 @@ PYBIND11_MODULE(_libcamera, m) auto cm = gCameraManager.lock(); ASSERT(cm); - self.requestCompleted.connect(&self, [cm, camera=self.shared_from_this()](Request *req) { - cm->handleRequestCompleted(camera, req); - }); - - self.bufferCompleted.connect(&self, [cm, camera=self.shared_from_this()](Request *req, FrameBuffer *fb) { - cm->handleBufferCompleted(camera, req, fb); - }); - - self.disconnected.connect(&self, [cm, camera=self.shared_from_this()]() { - cm->handleDisconnected(camera); - }); - ControlList controlList(self.controls()); for (const auto& [id, obj]: controls) { @@ -178,7 +256,6 @@ PYBIND11_MODULE(_libcamera, m) int ret = self.start(&controlList); if (ret) { - self.requestCompleted.disconnect(); throw std::system_error(-ret, std::generic_category(), "Failed to start camera"); } @@ -187,10 +264,6 @@ PYBIND11_MODULE(_libcamera, m) .def("stop", [](Camera &self) { int ret = self.stop(); - self.requestCompleted.disconnect(); - self.bufferCompleted.disconnect(); - self.disconnected.disconnect(); - auto cm = gCameraManager.lock(); ASSERT(cm);