From patchwork Sun Apr 26 00:43:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 3549 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 31D8562E55 for ; Sun, 26 Apr 2020 02:43:28 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="KjjczxPV"; dkim-atps=neutral Received: from pendragon.bb.dnainternet.fi (81-175-216-236.bb.dnainternet.fi [81.175.216.236]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id BA983583 for ; Sun, 26 Apr 2020 02:43:27 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1587861807; bh=+pQZvmeJ3RUdi7AP82toKPoXIDjIZVJgI2GuEkRuJ9I=; h=From:To:Subject:Date:In-Reply-To:References:From; b=KjjczxPVJjaZm+jy3iCv+Bf20yFrhXHss19NQxhXZxtQNvMIx80TUoKuN5kDMnBsI 13zjUJT3ncJVaVWlgPosEVi3io/9yGF8RBfvjs23zIy3BaLN2nS9J2SuqUIlkcOi3h yXqbMoamNOcYsVH0tHZWIce4Y5tapPn30qtKqjdQ= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sun, 26 Apr 2020 03:43:09 +0300 Message-Id: <20200426004309.2743-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.25.3 In-Reply-To: <20200426004309.2743-1-laurent.pinchart@ideasonboard.com> References: <20200426004309.2743-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 2/2] libcamera: v4l2_videodevice: Add support for frame start events 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-List-Received-Date: Sun, 26 Apr 2020 00:43:28 -0000 Extend the V4L2VideoDevice to support notifying of frame start events. The events are received from the device through the V4L2 event API, and passed to users of the class through a signal. Signed-off-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- src/libcamera/include/v4l2_videodevice.h | 8 +++ src/libcamera/v4l2_videodevice.cpp | 75 +++++++++++++++++++++++- 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/src/libcamera/include/v4l2_videodevice.h b/src/libcamera/include/v4l2_videodevice.h index ee63d28da734..a0409e59c08f 100644 --- a/src/libcamera/include/v4l2_videodevice.h +++ b/src/libcamera/include/v4l2_videodevice.h @@ -224,6 +224,9 @@ public: int queueBuffer(FrameBuffer *buffer); Signal bufferReady; + int setFrameStartEnabled(bool enable); + Signal frameStart; + int streamOn(); int streamOff(); @@ -262,6 +265,8 @@ private: void bufferAvailable(EventNotifier *notifier); FrameBuffer *dequeueBuffer(); + void eventAvailable(EventNotifier *notifier); + V4L2Capability caps_; enum v4l2_buf_type bufferType_; @@ -271,6 +276,9 @@ private: std::map queuedBuffers_; EventNotifier *fdBufferNotifier_; + EventNotifier *fdEventNotifier_; + + bool frameStartEnabled_; }; class V4L2M2MDevice diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp index 18a71e4f8a7f..45aedb1a9490 100644 --- a/src/libcamera/v4l2_videodevice.cpp +++ b/src/libcamera/v4l2_videodevice.cpp @@ -544,7 +544,8 @@ 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) + : V4L2Device(deviceNode), cache_(nullptr), fdBufferNotifier_(nullptr), + fdEventNotifier_(nullptr), frameStartEnabled_(false) { /* * We default to an MMAP based CAPTURE video device, however this will @@ -637,6 +638,10 @@ 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(); @@ -726,6 +731,10 @@ 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(); @@ -743,6 +752,7 @@ void V4L2VideoDevice::close() releaseBuffers(); delete fdBufferNotifier_; + delete fdEventNotifier_; V4L2Device::close(); } @@ -1570,11 +1580,74 @@ 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(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