From patchwork Fri Dec 4 06:54:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 10553 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 84A73BE177 for ; Fri, 4 Dec 2020 06:55:05 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4D45C635D2; Fri, 4 Dec 2020 07:55:05 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=uajain.com header.i=@uajain.com header.b="qqYLkn90"; dkim-atps=neutral Received: from mail.uajain.com (static.126.159.217.95.clients.your-server.de [95.217.159.126]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 74891635D1 for ; Fri, 4 Dec 2020 07:55:03 +0100 (CET) From: Umang Jain DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=uajain.com; s=mail; t=1607064903; bh=0KCGP4zxC3q9W8gTwNnQUVSqEd/MT8angyTCA5ukjzg=; h=From:To:Cc:Subject:In-Reply-To:References; b=qqYLkn90o9GmXkDLqGbfQ6qXP3nc4TQQp0038PfahHbnEEWkaNBapGhannhTD6V92 AHzA8mS9OL5bZJPP6jphLMDoQns1HRz5GiITfIfa1Bk5ZsMhVZa+ctEgQNjRWHyXH5 QIB6WZ6c5UR1aIc4YLcmcYc92ksO1/xyiGhx+dDvVU41BkT3srK8LYgcNfOJGStORQ CTXRlh02BGNMYFSxsB21DJnud0j1DStK/IjUIy0MCJVbwfkGsp4eJCBbqZwqb9h9rm Vhw+eCJAxJC0WaBZQH9IPOvsrMNwBsIp6xpwXJ2ETFLl0DRChxABK0swLBa5RYcWWA bsaxPqOMMBGzg== To: libcamera-devel@lists.libcamera.org Date: Fri, 4 Dec 2020 12:24:49 +0530 Message-Id: <20201204065452.2764628-2-email@uajain.com> In-Reply-To: <20201204065452.2764628-1-email@uajain.com> References: <20201204065452.2764628-1-email@uajain.com> Mime-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 1/4] simple-cam: Make return codes consistent for main() 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" Use EXIT_FAILURE or EXIT_SUCCESS to indicate program execution status. These are the return codes that should be used for main() as per the C++ standard. Signed-off-by: Umang Jain Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham --- simple-cam.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/simple-cam.cpp b/simple-cam.cpp index 727bb6d..e88fb85 100644 --- a/simple-cam.cpp +++ b/simple-cam.cpp @@ -184,7 +184,7 @@ int main() int ret = camera->configure(config.get()); if (ret) { std::cout << "CONFIGURATION FAILED!" << std::endl; - return -1; + return EXIT_FAILURE; } #endif @@ -217,7 +217,7 @@ int main() int ret = allocator->allocate(cfg.stream()); if (ret < 0) { std::cerr << "Can't allocate buffers" << std::endl; - return -ENOMEM; + return EXIT_FAILURE; } unsigned int allocated = allocator->buffers(cfg.stream()).size(); @@ -250,7 +250,7 @@ int main() if (!request) { std::cerr << "Can't create request" << std::endl; - return -ENOMEM; + return EXIT_FAILURE; } const std::unique_ptr &buffer = buffers[i]; @@ -259,7 +259,7 @@ int main() { std::cerr << "Can't set buffer for request" << std::endl; - return ret; + return EXIT_FAILURE; } /* @@ -341,5 +341,5 @@ int main() camera.reset(); cm->stop(); - return 0; + return EXIT_SUCCESS; } From patchwork Fri Dec 4 06:54:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 10554 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 D7863BE177 for ; Fri, 4 Dec 2020 06:55:07 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A4B79635D6; Fri, 4 Dec 2020 07:55:07 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=uajain.com header.i=@uajain.com header.b="IS0vGEWN"; dkim-atps=neutral Received: from mail.uajain.com (static.126.159.217.95.clients.your-server.de [95.217.159.126]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id ED816635C4 for ; Fri, 4 Dec 2020 07:55:05 +0100 (CET) From: Umang Jain DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=uajain.com; s=mail; t=1607064905; bh=OMmssAISbEHqoBoqkvh61nTusb+34VnOj2cq0UfiYt4=; h=From:To:Cc:Subject:In-Reply-To:References; b=IS0vGEWN8ciGOyVQ+d8kAoG6vm0PYUXNLbMJV6fLHjmu3fGIBVfV3Hdoc7CMqtZd7 OHrBrNzhmtNdqU9tEBsxSGZvJeUxKqIAcxbfK2b4QCmju0W5wNtbb30zEVn0CObyB9 k63k5mB9GuNG/WS3Nf1UoOhWBnqw5v3yKA7zYY1wZFc1XOQRfalheWT6+BOdwny0lR js/yYZKe2qzW2pK0WZshLUWDvEZFfEKM3R3aktfPc8hPWST2bA1V5++8nRFx+KrNAS VnjbpSra5/dXyAhNqQ610UidXf1lBHg6dwVh8otw7kmzBBvVpK9pBhwdY0amHxJFzh Q5d+pXr3rYgKw== To: libcamera-devel@lists.libcamera.org Date: Fri, 4 Dec 2020 12:24:50 +0530 Message-Id: <20201204065452.2764628-3-email@uajain.com> In-Reply-To: <20201204065452.2764628-1-email@uajain.com> References: <20201204065452.2764628-1-email@uajain.com> Mime-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 2/4] simple-cam: Early return if no cameras are found on the system. 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" Failing to do so, the codepath will segfault while trying to acquire a non-existent camera. Signed-off-by: Umang Jain Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- simple-cam.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/simple-cam.cpp b/simple-cam.cpp index e88fb85..aace5c8 100644 --- a/simple-cam.cpp +++ b/simple-cam.cpp @@ -307,6 +307,13 @@ int main() for (std::unique_ptr &request : requests) camera->queueRequest(request.get()); + if (!cm->cameras().size()) { + std::cout << "No cameras were identified on the system." + << std::endl; + cm->stop(); + return EXIT_FAILURE; + } + /* * -------------------------------------------------------------------- * Run an EventLoop From patchwork Fri Dec 4 06:54:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 10555 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 3687BBE177 for ; Fri, 4 Dec 2020 06:55:09 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 042FE635DC; Fri, 4 Dec 2020 07:55:09 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=uajain.com header.i=@uajain.com header.b="DIJqdn4Q"; dkim-atps=neutral Received: from mail.uajain.com (static.126.159.217.95.clients.your-server.de [95.217.159.126]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 539A9635C4 for ; Fri, 4 Dec 2020 07:55:08 +0100 (CET) From: Umang Jain DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=uajain.com; s=mail; t=1607064907; bh=iZUfMY9iUuBNpfAav9Jl9QuWu1l9Ak5OlVgGPaJ3CPA=; h=From:To:Cc:Subject:In-Reply-To:References; b=DIJqdn4Q6u1cz99rDlt1P8uCEi4n9H3H+j+F4l0mPhe+hLjNwIW4Xz+JFM6vbu/sr 0eRga9G8x2Zj8Cljp4ghV1FQ8XyzpbPDrFWbdEFJ+tSLdjBnOJO1y+vmoRQdvcFKPS gZYW4aaLCQHDCerSXjJl+FxXObh6FOmwxITZPh4SZLAGeKbc/umqqzvtBJUYadwiPd beclxz09zTJI8SjpsfcKlum+LCbz9Vex7y+PJ8i9L0WG8TUSgzI7hgPXBAXkW3gcJZ Bx2zqCvAxyhXpl9Jtrr98LEqNNCywzmflyOVXXCty7swpuCx/tYrYBWykA7MdaIOmF fTDfKT6xiMQWQ== To: libcamera-devel@lists.libcamera.org Date: Fri, 4 Dec 2020 12:24:51 +0530 Message-Id: <20201204065452.2764628-4-email@uajain.com> In-Reply-To: <20201204065452.2764628-1-email@uajain.com> References: <20201204065452.2764628-1-email@uajain.com> Mime-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 3/4] simple-cam: Fix documentation typo 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" Signed-off-by: Umang Jain Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham --- simple-cam.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simple-cam.cpp b/simple-cam.cpp index aace5c8..bfe30d7 100644 --- a/simple-cam.cpp +++ b/simple-cam.cpp @@ -319,7 +319,7 @@ int main() * Run an EventLoop * * In order to dispatch events received from the video devices, such - * as buffer completions, an even loop as to be run. + * as buffer completions, an event loop has to be run. * * Libcamera provides its own default event dispatcher realized by * polling a set of file descriptors, but applications can integrate From patchwork Fri Dec 4 06:54:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 10556 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 8EA4ABE177 for ; Fri, 4 Dec 2020 06:55:11 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5A40E635DB; Fri, 4 Dec 2020 07:55:11 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=uajain.com header.i=@uajain.com header.b="j8wXu8R8"; dkim-atps=neutral Received: from mail.uajain.com (static.126.159.217.95.clients.your-server.de [95.217.159.126]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5648C635D8 for ; Fri, 4 Dec 2020 07:55:10 +0100 (CET) From: Umang Jain DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=uajain.com; s=mail; t=1607064909; bh=egQOzgGw04MrvNbjfhHa++HkAr9Z8XG1Ak5+8GUWrPY=; h=From:To:Cc:Subject:In-Reply-To:References; b=j8wXu8R8jHhIy5xq8rRS+izoOZACslbSgwzgam6irW+a4ljqubV0WdfO+seJqRvzS dG2dZYyShRz/2V7m9Z3bJvKLuBY6l6o5ModBqGqFp5JhIwWtOeFJttzmToYBvkaPih WRwQgC6pLQNIgViF0xaBhnAhWPpZiWhwVSBSAGRiNSo2HfTYziO5HxgdxUoebH/fO9 uoVu1M8YKX1Cd0LG4uSSx5E2/iPaLTAwMF9HGS5kPk8xAJRl0eg+2OKBfzjGPS48hq otOJ0pyuo01DZl5i8PBsSHAuGXhPu22hV0WB+KOX1nIGRsizj0kql70PfYsjb9foTG YBrj4mGT5cvtA== To: libcamera-devel@lists.libcamera.org Date: Fri, 4 Dec 2020 12:24:52 +0530 Message-Id: <20201204065452.2764628-5-email@uajain.com> In-Reply-To: <20201204065452.2764628-1-email@uajain.com> References: <20201204065452.2764628-1-email@uajain.com> Mime-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 4/4] simple-cam: Provide event-loop backed by libevent 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" libcamera moved its EventDispatcher and Timer API to its internal API, since providing an event loop to applications should not be the job of libcamera. Application utility like cam, were ported to use libevent, hence inspired from that, un-break simple-cam by using the similar implementation to replace the EventDispatcher and Timer functionality by libevent. Signed-off-by: Umang Jain --- event_loop.cpp | 103 +++++++++++++++++++++++++++++++++++++++++++++++++ event_loop.h | 44 +++++++++++++++++++++ meson.build | 2 + simple-cam.cpp | 35 ++++++++++------- 4 files changed, 171 insertions(+), 13 deletions(-) create mode 100644 event_loop.cpp create mode 100644 event_loop.h diff --git a/event_loop.cpp b/event_loop.cpp new file mode 100644 index 0000000..f40a635 --- /dev/null +++ b/event_loop.cpp @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020, Google Inc. + * + * event_loop.cpp - Event loop based on cam + */ + +#include "event_loop.h" + +#include +#include +#include + +EventLoop *EventLoop::instance_ = nullptr; + +EventLoop::EventLoop() +{ + assert(!instance_); + + evthread_use_pthreads(); + event_ = event_base_new(); + instance_ = this; +} + +EventLoop::~EventLoop() +{ + instance_ = nullptr; + + event_base_free(event_); + libevent_global_shutdown(); +} + +int EventLoop::exec() +{ + exitCode_ = -1; + exit_.store(false, std::memory_order_release); + + while (!exit_.load(std::memory_order_acquire)) { + dispatchCalls(); + event_base_loop(event_, EVLOOP_NO_EXIT_ON_EMPTY); + } + + return exitCode_; +} + +void EventLoop::exit(int code) +{ + exitCode_ = code; + exit_.store(true, std::memory_order_release); + interrupt(); +} + +void EventLoop::interrupt() +{ + event_base_loopbreak(event_); +} + +void EventLoop::timeoutTriggered() +{ + exit(); +} + +void timeoutCb(int fd, short event, void *arg) +{ + EventLoop *ptr = static_cast(arg); + ptr->timeoutTriggered(); +} + +void EventLoop::timeout(unsigned int sec) +{ + struct event *ev; + struct timeval tv; + + tv.tv_sec = sec; + tv.tv_usec = 0; + ev = evtimer_new(event_, &timeoutCb, this); + evtimer_add(ev, &tv); +} + +void EventLoop::callLater(const std::function &func) +{ + { + std::unique_lock locker(lock_); + calls_.push_back(func); + } + + interrupt(); +} + +void EventLoop::dispatchCalls() +{ + std::unique_lock locker(lock_); + + for (auto iter = calls_.begin(); iter != calls_.end(); ) { + std::function call = std::move(*iter); + + iter = calls_.erase(iter); + + locker.unlock(); + call(); + locker.lock(); + } +} diff --git a/event_loop.h b/event_loop.h new file mode 100644 index 0000000..fcb964f --- /dev/null +++ b/event_loop.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020, Google Inc. + * + * event_loop.h - Event loop based on cam's + */ +#ifndef __SIMPLE_CAM_EVENT_LOOP_H__ +#define __SIMPLE_CAM_EVENT_LOOP_H__ + +#include +#include +#include +#include + +struct event_base; + +class EventLoop +{ +public: + EventLoop(); + ~EventLoop(); + + void exit(int code = 0); + int exec(); + + void timeout(unsigned int sec); + void timeoutTriggered(); + void callLater(const std::function &func); + +private: + static EventLoop *instance_; + + struct event_base *event_; + std::atomic exit_; + int exitCode_; + + std::list> calls_; + std::mutex lock_; + + void interrupt(); + void dispatchCalls(); +}; + +#endif /* __SIMPLE_CAM_EVENT_LOOP_H__ */ diff --git a/meson.build b/meson.build index c312f2c..4d580c2 100644 --- a/meson.build +++ b/meson.build @@ -8,12 +8,14 @@ project('simple-cam', 'c', 'cpp', # simple-cam.cpp is the fully commented application src_files = files([ 'simple-cam.cpp', + 'event_loop.cpp', ]) # Point your PKG_CONFIG_PATH environment variable to the # libcamera install path camera.pc file ($prefix/lib/pkgconfig/camera.pc) libcamera_deps = [ dependency('camera', required : true), + dependency('libevent_pthreads'), ] cpp_arguments = [ '-Wno-unused-parameter', ] diff --git a/simple-cam.cpp b/simple-cam.cpp index bfe30d7..6d1d84f 100644 --- a/simple-cam.cpp +++ b/simple-cam.cpp @@ -11,8 +11,13 @@ #include +#include "event_loop.h" + +#define TIMEOUT_SEC 3 + using namespace libcamera; std::shared_ptr camera; +EventLoop loop; /* * -------------------------------------------------------------------- @@ -21,13 +26,26 @@ std::shared_ptr camera; * For each Camera::requestCompleted Signal emitted from the Camera the * connected Slot is invoked. * + * The Slot is invoked in the CameraManager's thread, hence one should avoid + * any heavy processing here. The processing of the request shall be re-directed + * to the application's thread instead, so as not to block the CameraManager's + * thread for large amount of time. + * * The Slot receives the Request as a parameter. */ + +static void processRequest(Request *request); + static void requestComplete(Request *request) { if (request->status() == Request::RequestCancelled) return; + loop.callLater(std::bind(&processRequest, request)); +} + +static void processRequest(Request *request) +{ const Request::BufferMap &buffers = request->buffers(); for (auto bufferPair : buffers) { @@ -320,20 +338,11 @@ int main() * * In order to dispatch events received from the video devices, such * as buffer completions, an event loop has to be run. - * - * Libcamera provides its own default event dispatcher realized by - * polling a set of file descriptors, but applications can integrate - * their own even loop with the Libcamera EventDispatcher. - * - * Here, as an example, run the poll-based EventDispatcher for 3 - * seconds. */ - EventDispatcher *dispatcher = cm->eventDispatcher(); - Timer timer; - timer.start(3000); - while (timer.isRunning()) - dispatcher->processEvents(); - + loop.timeout(TIMEOUT_SEC); + int ret = loop.exec(); + std::cout << "Capture ran for " << TIMEOUT_SEC << " seconds and " + << "stopped with exit status: " << ret << std::endl; /* * -------------------------------------------------------------------- * Clean Up