From patchwork Wed Oct 28 01:00:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 10274 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 D8B5BC3B5C for ; Wed, 28 Oct 2020 01:01:12 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B76B362244; Wed, 28 Oct 2020 02:01:12 +0100 (CET) Received: from bin-mail-out-06.binero.net (bin-mail-out-06.binero.net [195.74.38.229]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D57B56220D for ; Wed, 28 Oct 2020 02:01:10 +0100 (CET) X-Halon-ID: 106f6308-18b9-11eb-954c-0050569116f7 Authorized-sender: niklas.soderlund@fsdn.se Received: from bismarck.berto.se (p4fca2458.dip0.t-ipconnect.de [79.202.36.88]) by bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA id 106f6308-18b9-11eb-954c-0050569116f7; Wed, 28 Oct 2020 02:01:09 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org, david.plowman@raspberrypi.com, naush@raspberrypi.com Date: Wed, 28 Oct 2020 02:00:43 +0100 Message-Id: <20201028010051.3830668-2-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.29.1 In-Reply-To: <20201028010051.3830668-1-niklas.soderlund@ragnatech.se> References: <20201028010051.3830668-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 1/9] libcamera: v4l2_device: Move start of frame detection to V4L2Device 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 V4L2_EVENT_FRAME_SYNC event may occur on both V4L2 video-devices (V4L2VideoDevice) and sub-devices (V4L2Subdevice). Move the start of frame detection to the common base class of the two, V4L2Device. There is no functional change. Signed-off-by: Niklas Söderlund Reviewed-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- * Changes since v1 - Mark eventAvailable() private instead of protected. - Remove a blank line. - Call setFd() instead of duplicating it. --- include/libcamera/internal/v4l2_device.h | 13 +++- include/libcamera/internal/v4l2_videodevice.h | 8 -- src/libcamera/v4l2_device.cpp | 76 ++++++++++++++++++- src/libcamera/v4l2_videodevice.cpp | 75 +----------------- 4 files changed, 87 insertions(+), 85 deletions(-) diff --git a/include/libcamera/internal/v4l2_device.h b/include/libcamera/internal/v4l2_device.h index 722fb72207d74111..295f08f0be6f1980 100644 --- a/include/libcamera/internal/v4l2_device.h +++ b/include/libcamera/internal/v4l2_device.h @@ -13,11 +13,15 @@ #include +#include + #include "libcamera/internal/log.h" #include "libcamera/internal/v4l2_controls.h" namespace libcamera { +class EventNotifier; + class V4L2Device : protected Loggable { public: @@ -34,6 +38,9 @@ public: const std::string &deviceNode() const { return deviceNode_; } std::string devicePath() const; + int setFrameStartEnabled(bool enable); + Signal frameStart; + protected: V4L2Device(const std::string &deviceNode); ~V4L2Device(); @@ -44,18 +51,22 @@ protected: int ioctl(unsigned long request, void *argp); int fd() { return fd_; } - private: void listControls(); void updateControls(ControlList *ctrls, const struct v4l2_ext_control *v4l2Ctrls, unsigned int count); + void eventAvailable(EventNotifier *notifier); + std::map controlInfo_; std::vector> controlIds_; ControlInfoMap controls_; std::string deviceNode_; int fd_; + + EventNotifier *fdEventNotifier_; + bool frameStartEnabled_; }; } /* namespace libcamera */ diff --git a/include/libcamera/internal/v4l2_videodevice.h b/include/libcamera/internal/v4l2_videodevice.h index 53f6a2d5515b9bb3..cf705ec9cd6ad118 100644 --- a/include/libcamera/internal/v4l2_videodevice.h +++ b/include/libcamera/internal/v4l2_videodevice.h @@ -204,9 +204,6 @@ public: int queueBuffer(FrameBuffer *buffer); Signal bufferReady; - int setFrameStartEnabled(bool enable); - Signal frameStart; - int streamOn(); int streamOff(); @@ -240,8 +237,6 @@ private: void bufferAvailable(EventNotifier *notifier); FrameBuffer *dequeueBuffer(); - void eventAvailable(EventNotifier *notifier); - V4L2Capability caps_; enum v4l2_buf_type bufferType_; @@ -251,9 +246,6 @@ private: std::map queuedBuffers_; EventNotifier *fdBufferNotifier_; - EventNotifier *fdEventNotifier_; - - bool frameStartEnabled_; }; class V4L2M2MDevice diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 31d4dad0ee47b734..36fe62b04003551e 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -16,6 +16,8 @@ #include #include +#include + #include "libcamera/internal/log.h" #include "libcamera/internal/sysfs.h" #include "libcamera/internal/utils.h" @@ -52,7 +54,8 @@ LOG_DEFINE_CATEGORY(V4L2) * at open() time, and the \a logTag to prefix log messages with. */ V4L2Device::V4L2Device(const std::string &deviceNode) - : deviceNode_(deviceNode), fd_(-1) + : deviceNode_(deviceNode), fd_(-1), fdEventNotifier_(nullptr), + frameStartEnabled_(false) { } @@ -87,7 +90,7 @@ int V4L2Device::open(unsigned int flags) return ret; } - fd_ = ret; + setFd(ret); listControls(); @@ -117,6 +120,10 @@ int V4L2Device::setFd(int fd) fd_ = fd; + fdEventNotifier_ = new EventNotifier(fd_, EventNotifier::Exception); + fdEventNotifier_->activated.connect(this, &V4L2Device::eventAvailable); + fdEventNotifier_->setEnabled(false); + return 0; } @@ -130,6 +137,8 @@ void V4L2Device::close() if (!isOpen()) return; + delete fdEventNotifier_; + if (::close(fd_) < 0) LOG(V4L2, Error) << "Failed to close V4L2 device: " << strerror(errno); @@ -396,6 +405,40 @@ std::string V4L2Device::devicePath() const return path; } +/** + * \brief Enable or disable frame start event notification + * \param[in] enable True to enable frame start events, false to disable them + * + * This function enables or disables generation of frame start events. Once + * enabled, the events are signalled through the frameStart signal. + * + * \return 0 on success, a negative error code otherwise + */ +int V4L2Device::setFrameStartEnabled(bool enable) +{ + if (frameStartEnabled_ == enable) + return 0; + + struct v4l2_event_subscription event{}; + event.type = V4L2_EVENT_FRAME_SYNC; + + unsigned long request = enable ? VIDIOC_SUBSCRIBE_EVENT + : VIDIOC_UNSUBSCRIBE_EVENT; + int ret = ioctl(request, &event); + if (enable && ret) + return ret; + + fdEventNotifier_->setEnabled(enable); + frameStartEnabled_ = enable; + + return ret; +} + +/** + * \var V4L2Device::frameStart + * \brief A Signal emitted when capture of a frame has started + */ + /** * \brief Perform an IOCTL system call on the device node * \param[in] request The IOCTL request code @@ -519,4 +562,33 @@ void V4L2Device::updateControls(ControlList *ctrls, } } +/** + * \brief Slot to handle V4L2 events from the V4L2 device + * \param[in] notifier The event notifier + * + * When this slot is called, a V4L2 event is available to be dequeued from the + * device. + */ +void V4L2Device::eventAvailable([[maybe_unused]] EventNotifier *notifier) +{ + struct v4l2_event event{}; + int ret = ioctl(VIDIOC_DQEVENT, &event); + if (ret < 0) { + LOG(V4L2, Error) + << "Failed to dequeue event, disabling event notifier"; + fdEventNotifier_->setEnabled(false); + return; + } + + if (event.type != V4L2_EVENT_FRAME_SYNC) { + LOG(V4L2, Error) + << "Spurious event (" << event.type + << "), disabling event notifier"; + fdEventNotifier_->setEnabled(false); + return; + } + + frameStart.emit(event.u.frame_sync.frame_sequence); +} + } /* namespace libcamera */ diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp index 36d7d9a0f27a103f..012d9bc73f30ad09 100644 --- a/src/libcamera/v4l2_videodevice.cpp +++ b/src/libcamera/v4l2_videodevice.cpp @@ -472,8 +472,7 @@ const std::string V4L2DeviceFormat::toString() const * \param[in] deviceNode The file-system path to the video device node */ V4L2VideoDevice::V4L2VideoDevice(const std::string &deviceNode) - : V4L2Device(deviceNode), cache_(nullptr), fdBufferNotifier_(nullptr), - fdEventNotifier_(nullptr), frameStartEnabled_(false) + : V4L2Device(deviceNode), cache_(nullptr), fdBufferNotifier_(nullptr) { /* * We default to an MMAP based CAPTURE video device, however this will @@ -566,10 +565,6 @@ int V4L2VideoDevice::open() fdBufferNotifier_->activated.connect(this, &V4L2VideoDevice::bufferAvailable); fdBufferNotifier_->setEnabled(false); - fdEventNotifier_ = new EventNotifier(fd(), EventNotifier::Exception); - fdEventNotifier_->activated.connect(this, &V4L2VideoDevice::eventAvailable); - fdEventNotifier_->setEnabled(false); - LOG(V4L2, Debug) << "Opened device " << caps_.bus_info() << ": " << caps_.driver() << ": " << caps_.card(); @@ -659,10 +654,6 @@ int V4L2VideoDevice::open(int handle, enum v4l2_buf_type type) fdBufferNotifier_->activated.connect(this, &V4L2VideoDevice::bufferAvailable); fdBufferNotifier_->setEnabled(false); - fdEventNotifier_ = new EventNotifier(fd(), EventNotifier::Exception); - fdEventNotifier_->activated.connect(this, &V4L2VideoDevice::eventAvailable); - fdEventNotifier_->setEnabled(false); - LOG(V4L2, Debug) << "Opened device " << caps_.bus_info() << ": " << caps_.driver() << ": " << caps_.card(); @@ -680,7 +671,6 @@ void V4L2VideoDevice::close() releaseBuffers(); delete fdBufferNotifier_; - delete fdEventNotifier_; V4L2Device::close(); } @@ -1533,74 +1523,11 @@ FrameBuffer *V4L2VideoDevice::dequeueBuffer() return buffer; } -/** - * \brief Slot to handle V4L2 events from the V4L2 video device - * \param[in] notifier The event notifier - * - * When this slot is called, a V4L2 event is available to be dequeued from the - * device. - */ -void V4L2VideoDevice::eventAvailable([[maybe_unused]] EventNotifier *notifier) -{ - struct v4l2_event event{}; - int ret = ioctl(VIDIOC_DQEVENT, &event); - if (ret < 0) { - LOG(V4L2, Error) - << "Failed to dequeue event, disabling event notifier"; - fdEventNotifier_->setEnabled(false); - return; - } - - if (event.type != V4L2_EVENT_FRAME_SYNC) { - LOG(V4L2, Error) - << "Spurious event (" << event.type - << "), disabling event notifier"; - fdEventNotifier_->setEnabled(false); - return; - } - - frameStart.emit(event.u.frame_sync.frame_sequence); -} - /** * \var V4L2VideoDevice::bufferReady * \brief A Signal emitted when a framebuffer completes */ -/** - * \brief Enable or disable frame start event notification - * \param[in] enable True to enable frame start events, false to disable them - * - * This function enables or disables generation of frame start events. Once - * enabled, the events are signalled through the frameStart signal. - * - * \return 0 on success, a negative error code otherwise - */ -int V4L2VideoDevice::setFrameStartEnabled(bool enable) -{ - if (frameStartEnabled_ == enable) - return 0; - - struct v4l2_event_subscription event{}; - event.type = V4L2_EVENT_FRAME_SYNC; - - unsigned long request = enable ? VIDIOC_SUBSCRIBE_EVENT - : VIDIOC_UNSUBSCRIBE_EVENT; - int ret = ioctl(request, &event); - if (enable && ret) - return ret; - - fdEventNotifier_->setEnabled(enable); - frameStartEnabled_ = enable; - - return ret; -} - -/** - * \var V4L2VideoDevice::frameStart - * \brief A Signal emitted when capture of a frame has started - */ - /** * \brief Start the video stream * \return 0 on success or a negative error code otherwise