summaryrefslogtreecommitdiff
path: root/src/libcamera/v4l2_device.cpp
diff options
context:
space:
mode:
authorNiklas Söderlund <niklas.soderlund@ragnatech.se>2020-10-18 03:47:23 +0200
committerNiklas Söderlund <niklas.soderlund@ragnatech.se>2020-11-10 01:20:30 +0100
commit3d624b745b31383dbcd94d96246fab865820085f (patch)
tree60b0bdcec8479f1322e6cd914b019a757bf2f033 /src/libcamera/v4l2_device.cpp
parent68d2c41835a871ecd7b441cd650cab3fefa88cf5 (diff)
libcamera: v4l2_device: Move start of frame detection to V4L2Device
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 <niklas.soderlund@ragnatech.se> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
Diffstat (limited to 'src/libcamera/v4l2_device.cpp')
-rw-r--r--src/libcamera/v4l2_device.cpp76
1 files changed, 74 insertions, 2 deletions
diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp
index f747ba79..fd0b140f 100644
--- a/src/libcamera/v4l2_device.cpp
+++ b/src/libcamera/v4l2_device.cpp
@@ -16,6 +16,8 @@
#include <sys/syscall.h>
#include <unistd.h>
+#include <libcamera/event_notifier.h>
+
#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
}
/**
+ * \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
* \param[in] argp A pointer to the IOCTL argument
@@ -518,4 +561,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 */