summaryrefslogtreecommitdiff
path: root/src/libcamera/v4l2_videodevice.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcamera/v4l2_videodevice.cpp')
-rw-r--r--src/libcamera/v4l2_videodevice.cpp53
1 files changed, 53 insertions, 0 deletions
diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp
index 0830be80..c3a1b6c4 100644
--- a/src/libcamera/v4l2_videodevice.cpp
+++ b/src/libcamera/v4l2_videodevice.cpp
@@ -539,6 +539,7 @@ V4L2VideoDevice::V4L2VideoDevice(const std::string &deviceNode)
V4L2VideoDevice::V4L2VideoDevice(const MediaEntity *entity)
: V4L2VideoDevice(entity->deviceNode())
{
+ watchdog_.timeout.connect(this, &V4L2VideoDevice::watchdogExpired);
}
V4L2VideoDevice::~V4L2VideoDevice()
@@ -1726,6 +1727,9 @@ FrameBuffer *V4L2VideoDevice::dequeueBuffer()
return nullptr;
}
+ if (watchdogDuration_.count())
+ watchdog_.start(std::chrono::duration_cast<std::chrono::milliseconds>(watchdogDuration_));
+
cache_->put(buf.index);
FrameBuffer *buffer = it->second;
@@ -1828,6 +1832,8 @@ int V4L2VideoDevice::streamOn()
}
state_ = State::Streaming;
+ if (watchdogDuration_.count())
+ watchdog_.start(std::chrono::duration_cast<std::chrono::milliseconds>(watchdogDuration_));
return 0;
}
@@ -1852,6 +1858,9 @@ int V4L2VideoDevice::streamOff()
if (state_ != State::Streaming && queuedBuffers_.empty())
return 0;
+ if (watchdogDuration_.count())
+ watchdog_.stop();
+
ret = ioctl(VIDIOC_STREAMOFF, &bufferType_);
if (ret < 0) {
LOG(V4L2, Error)
@@ -1880,6 +1889,50 @@ int V4L2VideoDevice::streamOff()
}
/**
+ * \brief Set the dequeue timeout value
+ * \param[in] timeout The timeout value to be used
+ *
+ * Sets a timeout value, given by \a timeout, that will be used by a watchdog
+ * timer to ensure buffer dequeue events are periodically occurring when the
+ * device is streaming. The watchdog timer is only active when the device is
+ * streaming, so it is not necessary to disable it when the device stops
+ * streaming. The timeout value can be safely updated at any time.
+ *
+ * If the timer expires, the \ref V4L2VideoDevice::dequeueTimeout signal is
+ * emitted. This can typically be used by pipeline handlers to be notified of
+ * stalled devices.
+ *
+ * Set \a timeout to 0 to disable the watchdog timer.
+ */
+void V4L2VideoDevice::setDequeueTimeout(utils::Duration timeout)
+{
+ watchdogDuration_ = timeout;
+
+ watchdog_.stop();
+ if (watchdogDuration_.count() && state_ == State::Streaming)
+ watchdog_.start(std::chrono::duration_cast<std::chrono::milliseconds>(timeout));
+}
+
+/**
+ * \var V4L2VideoDevice::dequeueTimeout
+ * \brief A Signal emitted when the dequeue watchdog timer expires
+ */
+
+/**
+ * \brief Slot to handle an expired dequeue timer
+ *
+ * When this slot is called, the time between successive dequeue events is over
+ * the required timeout. Emit the \ref V4L2VideoDevice::dequeueTimeout signal.
+ */
+void V4L2VideoDevice::watchdogExpired()
+{
+ LOG(V4L2, Warning)
+ << "Dequeue timer of " << watchdogDuration_ << " has expired!";
+
+ dequeueTimeout.emit();
+}
+
+/**
* \brief Create a new video device instance from \a entity in media device
* \a media
* \param[in] media The media device where the entity is registered