[libcamera-devel] [PATCH v3 1/3] libcamera: v4l2_videodevice: Add a dequeue timer

Umang Jain umang.jain at ideasonboard.com
Tue Apr 5 16:24:51 CEST 2022


Hi,

On 4/5/22 19:49, Naushir Patuck wrote:
> Hi Umang,
>
> On Tue, 5 Apr 2022 at 14:56, Umang Jain <umang.jain at ideasonboard.com> wrote:
>
>> Hi Naushir,
>>
>> Just a drive-by comment,
>>
>> On 3/29/22 16:59, Naushir Patuck via libcamera-devel wrote:
>>> 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 | 10 ++++
>>>    src/libcamera/v4l2_videodevice.cpp            | 54 +++++++++++++++++++
>>>    2 files changed, 64 insertions(+)
>>>
>>> diff --git a/include/libcamera/internal/v4l2_videodevice.h
>> b/include/libcamera/internal/v4l2_videodevice.h
>>> index cfeae7bd6c52..2a9ba1fe5c71 100644
>>> --- a/include/libcamera/internal/v4l2_videodevice.h
>>> +++ b/include/libcamera/internal/v4l2_videodevice.h
>>> @@ -9,6 +9,7 @@
>>>
>>>    #include <array>
>>>    #include <atomic>
>>> +#include <chrono>
>>>    #include <memory>
>>>    #include <optional>
>>>    #include <stdint.h>
>>> @@ -20,6 +21,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>
>>> @@ -217,6 +219,9 @@ public:
>>>        int streamOn();
>>>        int streamOff();
>>>
>>> +     void setDequeueTimeout(std::chrono::milliseconds msec);
>>> +     Signal<> dequeueTimeout;
>>> +
>>>        static std::unique_ptr<V4L2VideoDevice>
>>>        fromEntityName(const MediaDevice *media, const std::string
>> &entity);
>>> @@ -253,6 +258,8 @@ private:
>>>        void bufferAvailable();
>>>        FrameBuffer *dequeueBuffer();
>>>
>>> +     void watchdogExpired();
>>> +
>>>        V4L2Capability caps_;
>>>        V4L2DeviceFormat format_;
>>>        const PixelFormatInfo *formatInfo_;
>>> @@ -266,6 +273,9 @@ private:
>>>        EventNotifier *fdBufferNotifier_;
>>>
>>>        State state_;
>>> +
>>> +     Timer watchdog_;
>>> +     std::chrono::milliseconds watchdogDuration_;
>>
>> Any particular reason this is std::chrono::miiliseconds instead of using
>> utils::Duration ?
>>
> In the previous revision, I did use the utils::Duration type for this
> variable.
> However, Laurent suggested that we might want to avoid that as he intends to
> move utils::Duration to the "public" API, and would not be available to use
> in this case.  So I switched to std::chrono::milliseconds.


err, didn't read the previous iterations, sorry for the noise then :S

>
> Regards,
> Naush
>
>
>>>    };
>>>
>>>    class V4L2M2MDevice
>>> diff --git a/src/libcamera/v4l2_videodevice.cpp
>> b/src/libcamera/v4l2_videodevice.cpp
>>> index 009f6d55610f..22191cb9de4d 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()
>>> @@ -1723,6 +1724,9 @@ FrameBuffer *V4L2VideoDevice::dequeueBuffer()
>>>                return nullptr;
>>>        }
>>>
>>> +     if (watchdogDuration_.count())
>>> +             watchdog_.start(watchdogDuration_);
>>> +
>>>        cache_->put(buf.index);
>>>
>>>        FrameBuffer *buffer = it->second;
>>> @@ -1825,6 +1829,8 @@ int V4L2VideoDevice::streamOn()
>>>        }
>>>
>>>        state_ = State::Streaming;
>>> +     if (watchdogDuration_.count())
>>> +             watchdog_.start(watchdogDuration_);
>>>
>>>        return 0;
>>>    }
>>> @@ -1849,6 +1855,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)
>>> @@ -1876,6 +1885,51 @@ int V4L2VideoDevice::streamOff()
>>>        return 0;
>>>    }
>>>
>>> +/**
>>> + * \brief Set the dequeue timeout value
>>> + * \param[in] msec The timeout value to be used
>>> + *
>>> + * Sets a timeout value, given by \a msec, 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 msec to 0 to disable the watchdog timer.
>>> + */
>>> +void V4L2VideoDevice::setDequeueTimeout(std::chrono::milliseconds msec)
>>
>> Same here as well. I guess you take in a `utils::Duration msec` and
>> assign to watchdogDuration_ below (given you have utils::Duration
>> watchdogDuration_ too).
>>
>>> +{
>>> +     watchdogDuration_ = msec;
>>> +
>>> +     watchdog_.stop();
>>> +     if (watchdogDuration_.count() && state_ == State::Streaming)
>>> +             watchdog_.start(msec);
>>> +}
>>> +
>>> +/**
>>> + * \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_.count()
>>> +             << " ms has expired!";
>>> +
>>> +     dequeueTimeout.emit();
>>> +}
>>> +
>>>    /**
>>>     * \brief Create a new video device instance from \a entity in media
>> device
>>>     * \a media


More information about the libcamera-devel mailing list