From patchwork Tue Feb 15 11:42:22 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nejc Galof X-Patchwork-Id: 15365 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 96F29BF415 for ; Tue, 15 Feb 2022 11:42:43 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id ED277610F8; Tue, 15 Feb 2022 12:42:42 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="GBFrWPJK"; dkim-atps=neutral Received: from mail-ej1-x62d.google.com (mail-ej1-x62d.google.com [IPv6:2a00:1450:4864:20::62d]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 61FA7601FF for ; Tue, 15 Feb 2022 12:42:41 +0100 (CET) Received: by mail-ej1-x62d.google.com with SMTP id qx21so3833319ejb.13 for ; Tue, 15 Feb 2022 03:42:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id; bh=Dr/TnI7lbtnce8QM/N35GI2psSFhqIJ0kZbJbHgOaTg=; b=GBFrWPJK1YaaUl5rSCA+4ONC6sFss7qXFUa90csBVlSGImMkSW2Orhde8g2JDud12S Oo5cyuUZ9nO8Mvk/7/d1wdcTkOX+xdNmHSUy+A3i4hIqySFdm2z+TYzyikE91G0ro9+V mDu0nAFkK2ErK+wg7X3IqjfWOD7eKrLuGlHsuqElI1CEMxiIyrhfx4MFpPF8z4o19LYV rVsozoDFXM7/dIWFGiEJqMTrYfALa/lxsKQm0gzvupbv2QSYbmYGynSpq18AwyXuWoov J4mOD5dgds4POzuj+nRNVFJ5z89mCrBmDgGdMeqh4Pwgfcd/oAzhkOouFTzr59VnUayV VFWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=Dr/TnI7lbtnce8QM/N35GI2psSFhqIJ0kZbJbHgOaTg=; b=vrEL27PuVczxSZL7YKiBpPtoIYOsr0tFm4uAAezeFmHcscg9v6VKPBODDSExp65A15 7w3DMsjjEYIF//w1XXQbKHgkU2dGCAUQ9MyqTXaE4Dau38gEvwjhm/FnKUPVbRS32RiH TJD3DfoOEE8TvLC16smn5TSqnVAoLvuMAbF3BNH0uWMLgdm0T/W2J83kYjMLEz441zF3 Yy1Gtik1/IziUkOYWtIW/QaV1gtSxKvWFT0QqpKW/eK9U/0t2JyHdAUop9Z6yFndenoH AJXXfkiRtFfW860LJYtdS9YAss3UrbK8xLKC12u7NLlhdYauMsrbVXBR8ygXakzDEiD5 zRIg== X-Gm-Message-State: AOAM530Iswp4h+2lH1VjDaIdf1qbrJPfSVGq2AzxsWDBjpYOY64tHAek df0zlQCFjj6l8Alwo4S5KQTjhOZlGM1hsA== X-Google-Smtp-Source: ABdhPJxufzPX3tZ5c37/Bar62DZqW1utzJAcbpq/5E9aQI+WVvnb4GIL9n0BiQuXpydozppNMwQMuA== X-Received: by 2002:a17:907:1c87:: with SMTP id nb7mr2633330ejc.279.1644925360917; Tue, 15 Feb 2022 03:42:40 -0800 (PST) Received: from e28887faee29.8.8.8.8 ([91.224.238.83]) by smtp.gmail.com with ESMTPSA id el5sm456373edb.71.2022.02.15.03.42.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 15 Feb 2022 03:42:40 -0800 (PST) From: Nejc Galof To: libcamera-devel@lists.libcamera.org Date: Tue, 15 Feb 2022 12:42:22 +0100 Message-Id: <20220215114222.115790-1-galof.nejc@gmail.com> X-Mailer: git-send-email 2.17.1 Subject: [libcamera-devel] [PATCH] v4l2: Support setting frame rate in the V4L2 Adaptation layer X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" 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 Signed-off-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/v4l2/v4l2_camera.cpp | 12 +++++++++--- src/v4l2/v4l2_camera.h | 7 +++++++ src/v4l2/v4l2_camera_proxy.cpp | 25 +++++++++++++++++++++++++ src/v4l2/v4l2_camera_proxy.h | 1 + 4 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp index e922b9e6..e4eb3a2b 100644 --- a/src/v4l2/v4l2_camera.cpp +++ b/src/v4l2/v4l2_camera.cpp @@ -12,13 +12,15 @@ #include +#include + using namespace libcamera; LOG_DECLARE_CATEGORY(V4L2Compat) V4L2Camera::V4L2Camera(std::shared_ptr 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"; diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h index 03e74118..9e6c895a 100644 --- a/src/v4l2/v4l2_camera.h +++ b/src/v4l2/v4l2_camera.h @@ -10,11 +10,14 @@ #include #include +#include + #include #include #include #include +#include #include #include @@ -49,6 +52,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 +74,8 @@ private: std::shared_ptr camera_; std::unique_ptr 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 e114d09f..f005b21c 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -18,6 +18,8 @@ #include #include +#include +#include #include #include @@ -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,24 @@ int V4L2CameraProxy::vidioc_streamoff(V4L2CameraFile *file, int *arg) return ret; } +int V4L2CameraProxy::vidioc_s_param(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 = 1s * (static_cast(timeperframe->numerator) / + static_cast(timeperframe->denominator)); + + int64_t uDuration = frameDuration.get(); + vcam_->controls().set(controls::FrameDurationLimits, { uDuration, uDuration }); + + return 0; +} + const std::set V4L2CameraProxy::supportedIoctls_ = { VIDIOC_QUERYCAP, VIDIOC_ENUM_FRAMESIZES, @@ -775,6 +796,7 @@ const std::set V4L2CameraProxy::supportedIoctls_ = { VIDIOC_EXPBUF, VIDIOC_STREAMON, VIDIOC_STREAMOFF, + VIDIOC_S_PARM, }; int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long request, void *arg) @@ -852,6 +874,9 @@ int V4L2CameraProxy::ioctl(V4L2CameraFile *file, unsigned long request, void *ar case VIDIOC_STREAMOFF: ret = vidioc_streamoff(file, static_cast(arg)); break; + case VIDIOC_S_PARM: + ret = vidioc_s_param(file, static_cast(arg)); + break; default: ret = -ENOTTY; break; diff --git a/src/v4l2/v4l2_camera_proxy.h b/src/v4l2/v4l2_camera_proxy.h index 76ca2d8a..30a3f492 100644 --- a/src/v4l2/v4l2_camera_proxy.h +++ b/src/v4l2/v4l2_camera_proxy.h @@ -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_param(V4L2CameraFile *file, struct v4l2_streamparm *arg); bool hasOwnership(V4L2CameraFile *file); int acquire(V4L2CameraFile *file);