@@ -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);
}
@@ -203,10 +205,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_) {
@@ -266,6 +270,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";
@@ -15,6 +15,7 @@
#include <libcamera/base/shared_fd.h>
#include <libcamera/camera.h>
+#include <libcamera/controls.h>
#include <libcamera/framebuffer.h>
#include <libcamera/framebuffer_allocator.h>
@@ -49,6 +50,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);
@@ -69,6 +72,8 @@ private:
std::shared_ptr<libcamera::Camera> camera_;
std::unique_ptr<libcamera::CameraConfiguration> config_;
+ libcamera::ControlList controls_;
+
bool isRunning_;
libcamera::Mutex bufferLock_;
@@ -18,6 +18,8 @@
#include <unistd.h>
#include <libcamera/camera.h>
+#include <libcamera/controls.h>
+#include <libcamera/control_ids.h>
#include <libcamera/formats.h>
#include <libcamera/base/log.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 request, void *arg)
@@ -852,6 +873,9 @@ int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long request, void *ar
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;
@@ -65,6 +65,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);