[libcamera-devel] [PATCH v1 2/3] libcamera: v4l2_videodevice: Add a dequeue timer

Naushir Patuck naush at raspberrypi.com
Tue Mar 22 14:16:34 CET 2022


Add a timer that gets reset on every buffer dequeue event. If the timeout
expires, optionally call a slot in the pipeline handler to handle this
condition. This may be useful in detecting and handling stalls in either the
hardware or device driver.

Signed-off-by: Naushir Patuck <naush at raspberrypi.com>
---
 include/libcamera/internal/v4l2_videodevice.h |  9 ++++
 src/libcamera/v4l2_videodevice.cpp            | 47 +++++++++++++++++++
 2 files changed, 56 insertions(+)

diff --git a/include/libcamera/internal/v4l2_videodevice.h b/include/libcamera/internal/v4l2_videodevice.h
index 2d2ccc477c91..dd6e96438637 100644
--- a/include/libcamera/internal/v4l2_videodevice.h
+++ b/include/libcamera/internal/v4l2_videodevice.h
@@ -20,6 +20,7 @@
 #include <libcamera/base/class.h>
 #include <libcamera/base/log.h>
 #include <libcamera/base/signal.h>
+#include <libcamera/base/timer.h>
 #include <libcamera/base/unique_fd.h>
 
 #include <libcamera/color_space.h>
@@ -216,6 +217,9 @@ public:
 	int streamOn();
 	int streamOff();
 
+	void setDequeueTimeout(utils::Duration duration);
+	Signal<V4L2VideoDevice *> dequeueTimeout;
+
 	static std::unique_ptr<V4L2VideoDevice>
 	fromEntityName(const MediaDevice *media, const std::string &entity);
 
@@ -246,6 +250,8 @@ private:
 	void bufferAvailable();
 	FrameBuffer *dequeueBuffer();
 
+	void timerExpired();
+
 	V4L2Capability caps_;
 	V4L2DeviceFormat format_;
 	const PixelFormatInfo *formatInfo_;
@@ -259,6 +265,9 @@ private:
 	EventNotifier *fdBufferNotifier_;
 
 	bool streaming_;
+
+	Timer timer_;
+	utils::Duration timerDuration_;
 };
 
 class V4L2M2MDevice
diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp
index 5f36ee20710d..25bce5475e07 100644
--- a/src/libcamera/v4l2_videodevice.cpp
+++ b/src/libcamera/v4l2_videodevice.cpp
@@ -600,6 +600,8 @@ int V4L2VideoDevice::open()
 	fdBufferNotifier_->activated.connect(this, &V4L2VideoDevice::bufferAvailable);
 	fdBufferNotifier_->setEnabled(false);
 
+	timer_.timeout.connect(this, &V4L2VideoDevice::timerExpired);
+
 	LOG(V4L2, Debug)
 		<< "Opened device " << caps_.bus_info() << ": "
 		<< caps_.driver() << ": " << caps_.card();
@@ -1695,6 +1697,9 @@ FrameBuffer *V4L2VideoDevice::dequeueBuffer()
 		return nullptr;
 	}
 
+	if (timerDuration_.count())
+		timer_.start(timerDuration_);
+
 	cache_->put(buf.index);
 
 	FrameBuffer *buffer = it->second;
@@ -1797,6 +1802,8 @@ int V4L2VideoDevice::streamOn()
 	}
 
 	streaming_ = true;
+	if (timerDuration_.count())
+		timer_.start(timerDuration_);
 
 	return 0;
 }
@@ -1821,6 +1828,9 @@ int V4L2VideoDevice::streamOff()
 	if (!streaming_ && queuedBuffers_.empty())
 		return 0;
 
+	if (timerDuration_.count())
+		timer_.stop();
+
 	ret = ioctl(VIDIOC_STREAMOFF, &bufferType_);
 	if (ret < 0) {
 		LOG(V4L2, Error)
@@ -1843,6 +1853,43 @@ int V4L2VideoDevice::streamOff()
 	return 0;
 }
 
+/**
+ * \brief Set the dequeue timeout value
+ * \param[in] duration The timeout value to be used
+ *
+ * Sets a timeout value, given by \a duration, that will be used by a timer to
+ * ensure buffer dequeue events are periodically occurring. If the timer
+ * expires, a slot in the pipeline handler may be optionally called to handle
+ * this condition through the \a dequeueTimeout signal.
+ *
+ * Set \a duration to 0 to disable the timeout.
+ *
+ */
+void V4L2VideoDevice::setDequeueTimeout(utils::Duration duration)
+{
+	timerDuration_ = duration;
+
+	timer_.stop();
+	if (duration.count() && streaming_)
+		timer_.start(duration);
+}
+
+/**
+ * \brief Slot to handle an expired dequeue timer.
+ *
+ * When this slot is called, the the time between successive dequeue events
+ * is over the required timeout. Optionally call a slot in the pipeline handler
+ * given by the \a dequeueTimeout signal.
+ */
+void V4L2VideoDevice::timerExpired()
+{
+	LOG(V4L2, Info)
+		<< "Dequeue timer of " << timerDuration_
+		<< " has expired!";
+
+	dequeueTimeout.emit(this);
+}
+
 /**
  * \brief Create a new video device instance from \a entity in media device
  * \a media
-- 
2.25.1



More information about the libcamera-devel mailing list