Skip to content

Commit 5456e02

Browse files
nejcgalofRahi374
authored andcommitted
v4l2: Support setting frame rate in the V4L2 Adaptation layer
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@gmail.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
1 parent 5c5bc85 commit 5456e02

File tree

4 files changed

+39
-3
lines changed

4 files changed

+39
-3
lines changed

src/v4l2/v4l2_camera.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@
1212

1313
#include <libcamera/base/log.h>
1414

15+
#include <libcamera/control_ids.h>
16+
1517
using namespace libcamera;
1618

1719
LOG_DECLARE_CATEGORY(V4L2Compat)
1820

1921
V4L2Camera::V4L2Camera(std::shared_ptr<Camera> camera)
20-
: camera_(camera), isRunning_(false), bufferAllocator_(nullptr),
21-
efd_(-1), bufferAvailableCount_(0)
22+
: camera_(camera), controls_(controls::controls), isRunning_(false),
23+
bufferAllocator_(nullptr), efd_(-1), bufferAvailableCount_(0)
2224
{
2325
camera_->requestCompleted.connect(this, &V4L2Camera::requestComplete);
2426
}
@@ -202,10 +204,12 @@ int V4L2Camera::streamOn()
202204
if (isRunning_)
203205
return 0;
204206

205-
int ret = camera_->start();
207+
int ret = camera_->start(&controls_);
206208
if (ret < 0)
207209
return ret == -EACCES ? -EBUSY : ret;
208210

211+
controls_.clear();
212+
209213
isRunning_ = true;
210214

211215
for (Request *req : pendingRequests_) {
@@ -265,6 +269,8 @@ int V4L2Camera::qbuf(unsigned int index)
265269
return 0;
266270
}
267271

272+
request->controls().merge(std::move(controls_));
273+
268274
ret = camera_->queueRequest(request);
269275
if (ret < 0) {
270276
LOG(V4L2Compat, Error) << "Can't queue request";

src/v4l2/v4l2_camera.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <libcamera/base/shared_fd.h>
1717

1818
#include <libcamera/camera.h>
19+
#include <libcamera/controls.h>
1920
#include <libcamera/framebuffer.h>
2021
#include <libcamera/framebuffer_allocator.h>
2122

@@ -50,6 +51,8 @@ class V4L2Camera
5051
const libcamera::Size &size,
5152
libcamera::StreamConfiguration *streamConfigOut);
5253

54+
libcamera::ControlList &controls() { return controls_; }
55+
5356
int allocBuffers(unsigned int count);
5457
void freeBuffers();
5558
int getBufferFd(unsigned int index);
@@ -71,6 +74,8 @@ class V4L2Camera
7174
std::shared_ptr<libcamera::Camera> camera_;
7275
std::unique_ptr<libcamera::CameraConfiguration> config_;
7376

77+
libcamera::ControlList controls_;
78+
7479
bool isRunning_;
7580

7681
libcamera::Mutex bufferLock_;

src/v4l2/v4l2_camera_proxy.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include <libcamera/base/utils.h>
2323

2424
#include <libcamera/camera.h>
25+
#include <libcamera/control_ids.h>
26+
#include <libcamera/controls.h>
2527
#include <libcamera/formats.h>
2628

2729
#include "libcamera/internal/v4l2_pixelformat.h"
@@ -33,6 +35,7 @@
3335
#define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
3436

3537
using namespace libcamera;
38+
using namespace std::literals::chrono_literals;
3639

3740
LOG_DECLARE_CATEGORY(V4L2Compat)
3841

@@ -755,6 +758,23 @@ int V4L2CameraProxy::vidioc_streamoff(V4L2CameraFile *file, int *arg)
755758
return ret;
756759
}
757760

761+
int V4L2CameraProxy::vidioc_s_parm(V4L2CameraFile *file, struct v4l2_streamparm *arg)
762+
{
763+
LOG(V4L2Compat, Debug)
764+
<< "[" << file->description() << "] " << __func__ << "()";
765+
766+
if (!validateBufferType(arg->type))
767+
return -EINVAL;
768+
769+
struct v4l2_fract *timeperframe = &arg->parm.capture.timeperframe;
770+
utils::Duration frameDuration = 1.0s * timeperframe->numerator / timeperframe->denominator;
771+
772+
int64_t uDuration = frameDuration.get<std::micro>();
773+
vcam_->controls().set(controls::FrameDurationLimits, { uDuration, uDuration });
774+
775+
return 0;
776+
}
777+
758778
const std::set<unsigned long> V4L2CameraProxy::supportedIoctls_ = {
759779
VIDIOC_QUERYCAP,
760780
VIDIOC_ENUM_FRAMESIZES,
@@ -775,6 +795,7 @@ const std::set<unsigned long> V4L2CameraProxy::supportedIoctls_ = {
775795
VIDIOC_EXPBUF,
776796
VIDIOC_STREAMON,
777797
VIDIOC_STREAMOFF,
798+
VIDIOC_S_PARM,
778799
};
779800

780801
int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long longRequest, void *arg)
@@ -862,6 +883,9 @@ int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long longRequest, void
862883
case VIDIOC_STREAMOFF:
863884
ret = vidioc_streamoff(file, static_cast<int *>(arg));
864885
break;
886+
case VIDIOC_S_PARM:
887+
ret = vidioc_s_parm(file, static_cast<struct v4l2_streamparm *>(arg));
888+
break;
865889
default:
866890
ret = -ENOTTY;
867891
break;

src/v4l2/v4l2_camera_proxy.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ class V4L2CameraProxy
6767
int vidioc_expbuf(V4L2CameraFile *file, struct v4l2_exportbuffer *arg);
6868
int vidioc_streamon(V4L2CameraFile *file, int *arg);
6969
int vidioc_streamoff(V4L2CameraFile *file, int *arg);
70+
int vidioc_s_parm(V4L2CameraFile *file, struct v4l2_streamparm *arg);
7071

7172
bool hasOwnership(V4L2CameraFile *file);
7273
int acquire(V4L2CameraFile *file);

0 commit comments

Comments
 (0)