[PATCH v4] v4l2: Support setting frame rate in the V4L2 Adaptation layer
Paul Elder
paul.elder at ideasonboard.com
Tue Sep 10 22:00:59 CEST 2024
On Tue, Sep 10, 2024 at 07:33:27PM +0200, Kieran Bingham wrote:
> From: Nejc Galof <galof.nejc at gmail.com>
>
> The V4L2 adaptation layer can already support streaming with components
> such as OpenCV, however it is not accepting, or handling any requests to
> configure the frame rate.
>
> In V4L2 the frame rate is set by configuring the timeperframe component
> of the v4l2_streamparm structure through the VIDIOC_S_PARM ioctl.
>
> Extend the V4L2 compatibility layer to accept the VIDIOC_S_PARM ioctls
> and provide an interface for setting controls on the V4L2Camera class to
> set the requested rate when starting the camera.
>
> Signed-off-by: Nejc Galof <galof.nejc at gmail.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
> Signed-off-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder at ideasonboard.com>
> ---
>
> v4: Handle rebase conflicts only.
>
> src/v4l2/v4l2_camera.cpp | 12 +++++++++---
> src/v4l2/v4l2_camera.h | 5 +++++
> src/v4l2/v4l2_camera_proxy.cpp | 24 ++++++++++++++++++++++++
> src/v4l2/v4l2_camera_proxy.h | 1 +
> 4 files changed, 39 insertions(+), 3 deletions(-)
>
>
> diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp
> index 0f3b862f5bc3..94d138cd5710 100644
> --- a/src/v4l2/v4l2_camera.cpp
> +++ b/src/v4l2/v4l2_camera.cpp
> @@ -12,13 +12,15 @@
>
> #include <libcamera/base/log.h>
>
> +#include <libcamera/control_ids.h>
> +
> using namespace libcamera;
>
> LOG_DECLARE_CATEGORY(V4L2Compat)
>
> V4L2Camera::V4L2Camera(std::shared_ptr<Camera> camera)
> - : camera_(camera), isRunning_(false), bufferAllocator_(nullptr),
> - efd_(-1), bufferAvailableCount_(0)
> + : camera_(camera), controls_(controls::controls), isRunning_(false),
> + bufferAllocator_(nullptr), efd_(-1), bufferAvailableCount_(0)
> {
> camera_->requestCompleted.connect(this, &V4L2Camera::requestComplete);
> }
> @@ -202,10 +204,12 @@ int V4L2Camera::streamOn()
> if (isRunning_)
> return 0;
>
> - int ret = camera_->start();
> + int ret = camera_->start(&controls_);
> if (ret < 0)
> return ret == -EACCES ? -EBUSY : ret;
>
> + controls_.clear();
> +
> isRunning_ = true;
>
> for (Request *req : pendingRequests_) {
> @@ -265,6 +269,8 @@ int V4L2Camera::qbuf(unsigned int index)
> return 0;
> }
>
> + request->controls().merge(std::move(controls_));
> +
> ret = camera_->queueRequest(request);
> if (ret < 0) {
> LOG(V4L2Compat, Error) << "Can't queue request";
> diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h
> index 9a0b04551c9d..e54371fb4e00 100644
> --- a/src/v4l2/v4l2_camera.h
> +++ b/src/v4l2/v4l2_camera.h
> @@ -16,6 +16,7 @@
> #include <libcamera/base/shared_fd.h>
>
> #include <libcamera/camera.h>
> +#include <libcamera/controls.h>
> #include <libcamera/framebuffer.h>
> #include <libcamera/framebuffer_allocator.h>
>
> @@ -50,6 +51,8 @@ public:
> const libcamera::Size &size,
> libcamera::StreamConfiguration *streamConfigOut);
>
> + libcamera::ControlList &controls() { return controls_; }
> +
> int allocBuffers(unsigned int count);
> void freeBuffers();
> int getBufferFd(unsigned int index);
> @@ -71,6 +74,8 @@ private:
> std::shared_ptr<libcamera::Camera> camera_;
> std::unique_ptr<libcamera::CameraConfiguration> config_;
>
> + libcamera::ControlList controls_;
> +
> bool isRunning_;
>
> libcamera::Mutex bufferLock_;
> diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp
> index da1170536a8f..00ba9ed360eb 100644
> --- a/src/v4l2/v4l2_camera_proxy.cpp
> +++ b/src/v4l2/v4l2_camera_proxy.cpp
> @@ -22,6 +22,8 @@
> #include <libcamera/base/utils.h>
>
> #include <libcamera/camera.h>
> +#include <libcamera/controls.h>
> +#include <libcamera/control_ids.h>
> #include <libcamera/formats.h>
>
> #include "libcamera/internal/v4l2_pixelformat.h"
> @@ -33,6 +35,7 @@
> #define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
>
> using namespace libcamera;
> +using namespace std::literals::chrono_literals;
>
> LOG_DECLARE_CATEGORY(V4L2Compat)
>
> @@ -755,6 +758,23 @@ int V4L2CameraProxy::vidioc_streamoff(V4L2CameraFile *file, int *arg)
> return ret;
> }
>
> +int V4L2CameraProxy::vidioc_s_parm(V4L2CameraFile *file, struct v4l2_streamparm *arg)
> +{
> + LOG(V4L2Compat, Debug)
> + << "[" << file->description() << "] " << __func__ << "()";
> +
> + if (!validateBufferType(arg->type))
> + return -EINVAL;
> +
> + struct v4l2_fract *timeperframe = &arg->parm.capture.timeperframe;
> + utils::Duration frameDuration = 1.0s * timeperframe->numerator / timeperframe->denominator;
> +
> + int64_t uDuration = frameDuration.get<std::micro>();
> + vcam_->controls().set(controls::FrameDurationLimits, { uDuration, uDuration });
> +
> + return 0;
> +}
> +
> const std::set<unsigned long> V4L2CameraProxy::supportedIoctls_ = {
> VIDIOC_QUERYCAP,
> VIDIOC_ENUM_FRAMESIZES,
> @@ -775,6 +795,7 @@ const std::set<unsigned long> V4L2CameraProxy::supportedIoctls_ = {
> VIDIOC_EXPBUF,
> VIDIOC_STREAMON,
> VIDIOC_STREAMOFF,
> + VIDIOC_S_PARM,
> };
>
> int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long longRequest, void *arg)
> @@ -862,6 +883,9 @@ int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long longRequest, void
> case VIDIOC_STREAMOFF:
> ret = vidioc_streamoff(file, static_cast<int *>(arg));
> break;
> + case VIDIOC_S_PARM:
> + ret = vidioc_s_parm(file, static_cast<struct v4l2_streamparm *>(arg));
> + break;
> default:
> ret = -ENOTTY;
> break;
> diff --git a/src/v4l2/v4l2_camera_proxy.h b/src/v4l2/v4l2_camera_proxy.h
> index 3d8784dfdbf1..c957db5349cc 100644
> --- a/src/v4l2/v4l2_camera_proxy.h
> +++ b/src/v4l2/v4l2_camera_proxy.h
> @@ -67,6 +67,7 @@ private:
> int vidioc_expbuf(V4L2CameraFile *file, struct v4l2_exportbuffer *arg);
> int vidioc_streamon(V4L2CameraFile *file, int *arg);
> int vidioc_streamoff(V4L2CameraFile *file, int *arg);
> + int vidioc_s_parm(V4L2CameraFile *file, struct v4l2_streamparm *arg);
>
> bool hasOwnership(V4L2CameraFile *file);
> int acquire(V4L2CameraFile *file);
> --
> 2.46.0
>
More information about the libcamera-devel
mailing list