From patchwork Wed Jun 29 07:04:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomi Valkeinen X-Patchwork-Id: 16419 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 64F0EBE173 for ; Wed, 29 Jun 2022 07:05:00 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 04BC665659; Wed, 29 Jun 2022 09:04:59 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656486300; bh=jMNfoKH54gCKMC1c4+vxSz2aDSApVNlcC2eDc42ZuDA=; 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=kt+osuUNlpo2pR6JjZzxtuECzAZHs5bnWNtAxu/BrRQItO10bMYPOVVZTojzI6E8f JXwioi0v5hyuXeJlovwfvry4g/hJPIGUypHuhS2Is0lYkEjABX+BdTQMncNEgKe9e8 zlRtMjHFLdWBSgmBUN0fA9fP9+U7u3fSKDI01aDWiiJqxHLtKq0NNDxEUNgI2VeejQ GBWEub+1GjPQnEIFd8NbQoUaiQoBC0HL9WKiaLecGkG2lMKZzSSKcV2KZUaZ9tNpA4 FKYZN4UaZF2czhqUWKxEFmN5d1C/JaA8M4LbMhwRVBqQUc1vVqZuwPtryPFdgNgzsp S13Qi9TIL7rVw== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C977D65647 for ; Wed, 29 Jun 2022 09:04:47 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="PslNNwxa"; dkim-atps=neutral Received: from deskari.lan (91-158-154-79.elisa-laajakaista.fi [91.158.154.79]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 395356D1; Wed, 29 Jun 2022 09:04:47 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1656486287; bh=jMNfoKH54gCKMC1c4+vxSz2aDSApVNlcC2eDc42ZuDA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PslNNwxad2l/DDnCOyggrk0sDAxwJ8RYZuYaLw90UtDFkqbxQmUyGET9gDRbr+dkN CvwMatdL28XoqDCwFkKlyAr7B14ypnLRVn0YvbChgOElHmUs9fWv0yLYFCfgoy3E4S NTorJ9od4IHlQCmZVPkpiVzgSyoHICR1LKCKlClo= To: libcamera-devel@lists.libcamera.org, David Plowman , Kieran Bingham , Laurent Pinchart , Jacopo Mondi Date: Wed, 29 Jun 2022 10:04:15 +0300 Message-Id: <20220629070416.17550-14-tomi.valkeinen@ideasonboard.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220629070416.17550-1-tomi.valkeinen@ideasonboard.com> References: <20220629070416.17550-1-tomi.valkeinen@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 13/14] py: Discard/Dispatch Request events on camera.stop() 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" To prevent old Request related events from being left in the event queue, messing up the next camera.start(), force the events to be either discarded or dispatched when camera.stop() is called. camera.stop() will discard all Request events (RequestCompleted and BufferCompleted) for that camera. camera.stop(dispatch_events=True) will instead dispatch all events, also for other cameras. The dispatch version dispatches all events instead of just the Request events for one camera so that the event ordering stays the same. Signed-off-by: Tomi Valkeinen --- src/py/libcamera/py_camera_manager.cpp | 30 ++++++++++++++++++++++++++ src/py/libcamera/py_camera_manager.h | 1 + src/py/libcamera/py_main.cpp | 12 +++++++++-- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/py/libcamera/py_camera_manager.cpp b/src/py/libcamera/py_camera_manager.cpp index 599a9f7e..dfd43a09 100644 --- a/src/py/libcamera/py_camera_manager.cpp +++ b/src/py/libcamera/py_camera_manager.cpp @@ -218,6 +218,36 @@ void PyCameraManager::discardEvents() } } +void PyCameraManager::discardRequests(std::shared_ptr camera) +{ + MutexLocker guard(cameraEventsMutex_); + + size_t oldSize = cameraEvents_.size(); + + for (const auto &ev : cameraEvents_) { + if (ev.type_ != CameraEvent::Type::RequestCompleted) + continue; + + if (ev.camera_ != camera) + continue; + + /* Decrease the ref increased in Camera.queue_request() */ + py::object o = py::cast(ev.request_); + o.dec_ref(); + } + + cameraEvents_.erase(std::remove_if(cameraEvents_.begin(), cameraEvents_.end(), + [&camera](const CameraEvent &ev) { + return ev.camera_ == camera && + (ev.type_ == CameraEvent::Type::RequestCompleted || + ev.type_ == CameraEvent::Type::BufferCompleted); + }), + cameraEvents_.end()); + + LOG(Python, Debug) << "Discarded " << oldSize - cameraEvents_.size() + << " request events"; +} + std::function)> PyCameraManager::getCameraAdded() const { return cameraAddedHandler_; diff --git a/src/py/libcamera/py_camera_manager.h b/src/py/libcamera/py_camera_manager.h index aa51a6bc..9c8d6ca8 100644 --- a/src/py/libcamera/py_camera_manager.h +++ b/src/py/libcamera/py_camera_manager.h @@ -38,6 +38,7 @@ public: void dispatchEvents(); void discardEvents(); + void discardRequests(std::shared_ptr camera); std::function)> getCameraAdded() const; void setCameraAdded(std::function)> func); diff --git a/src/py/libcamera/py_main.cpp b/src/py/libcamera/py_main.cpp index a07f06c4..c4755bea 100644 --- a/src/py/libcamera/py_main.cpp +++ b/src/py/libcamera/py_main.cpp @@ -168,16 +168,24 @@ PYBIND11_MODULE(_libcamera, m) } }, py::arg("controls") = std::unordered_map()) - .def("stop", [](Camera &self) { + .def("stop", [](Camera &self, bool dispatchEvents) { int ret = self.stop(); self.requestCompleted.disconnect(); + auto cm = gCameraManager.lock(); + ASSERT(cm); + + if (dispatchEvents) + cm->dispatchEvents(); + else + cm->discardRequests(self.shared_from_this()); + /* \todo Should we just ignore the error? */ if (ret) throw std::system_error(-ret, std::generic_category(), "Failed to start camera"); - }) + }, py::arg("dispatch_events") = false) .def_property("request_completed", [](Camera &self) {