From patchwork Fri Feb 25 14:14:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nejc Galof X-Patchwork-Id: 15389 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 B3D90BF415 for ; Fri, 25 Feb 2022 14:14:21 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E2DA861168; Fri, 25 Feb 2022 15:14:20 +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="AG5Yn63X"; dkim-atps=neutral Received: from mail-wm1-x331.google.com (mail-wm1-x331.google.com [IPv6:2a00:1450:4864:20::331]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 64A54601FE for ; Fri, 25 Feb 2022 15:14:19 +0100 (CET) Received: by mail-wm1-x331.google.com with SMTP id p184-20020a1c29c1000000b0037f76d8b484so1754717wmp.5 for ; Fri, 25 Feb 2022 06:14:19 -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=30tOVa/50GYapJXLVrH4oY87I6nX4MrkPw2LcfN6OP0=; b=AG5Yn63X8bUnYvd6icNKe4QWU9tcZmXMaWak+DkdQtI1vaNmNmFC59zrE/XG/jO1Xt aaTqKpzD8QBHPt4yph966awA7LpUVFbm9uOlr21apYEYUz8xOr3atNDQLVFsWTjoR7Z9 7wyr+0FaNvoUcw3UkiyTQHR6tb+Dl/qe1mKOQzm/fPikSYjZzsx28f4JRRdX1g6HBnu/ DXtr/hThFGhIeKfDLR5yeR4/BuVb+AMofCdJBqfLY+j/Zt0Rb+vvd01/jQxOXRxpnJjj 5+IAn9t+ro+gbn0brpXUa7CGM73V3mwsK2XBc7MD8eU+g4RaQ5Hj2ymdhfGrR+a1x+8B exHg== 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=30tOVa/50GYapJXLVrH4oY87I6nX4MrkPw2LcfN6OP0=; b=QgjkUjiYPksk/BMh5lwy9tj1sFENPvV37YzlPx68M9q+3wt2aoL9C9+H8ncF4MGddV CdCsUz6mFKrS3Exe0Ube7HP6mLkFUbZTRE4wkYQd6oJxz9ZuNVLCDD7fqZ19f9gA1au0 gbBGIaJniyzT+873iMi64ZMIOeen+jJoCzuiYvY4OWCAlEEz6rhxz0eUhoHi13yddrxr RwSetOwrruywUu1zLjNoTv7dgjoJNVF4M+9TAOrER7VeFXZv1MvkGbv7Dt2/Y0i5zwPf OV0Zevk1ffrMibtkF6mjfZdr9In08qLZbiNPsG4FzWJLH/LJXFLivV1KnibPuLFHjRcY 1yng== X-Gm-Message-State: AOAM531V/L7JHLu5BKavu+HqHzDbU0qsUOiN74GNkJt3y1tRf/2LM6WU V6V/Vqpfd6+YkfWnFW9VIQqwOIByRbY5cg== X-Google-Smtp-Source: ABdhPJwtHEwpAgnSLqSxW8d8pBl9PxZkGmTPyiBmZ010X8oqxsBlLcb+6tV+k/WC9H8ZSFgDeMP4EQ== X-Received: by 2002:a05:600c:500a:b0:37b:ec27:1a2c with SMTP id n10-20020a05600c500a00b0037bec271a2cmr2871324wmr.179.1645798458799; Fri, 25 Feb 2022 06:14:18 -0800 (PST) Received: from e28887faee29.8.8.8.8 ([91.224.238.83]) by smtp.gmail.com with ESMTPSA id i22-20020a05600c355600b0037bee3a4e00sm5963810wmq.47.2022.02.25.06.14.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 25 Feb 2022 06:14:18 -0800 (PST) From: Nejc Galof To: libcamera-devel@lists.libcamera.org Date: Fri, 25 Feb 2022 15:14:02 +0100 Message-Id: <20220225141403.53678-1-galof.nejc@gmail.com> X-Mailer: git-send-email 2.17.1 Subject: [libcamera-devel] [PATCH 1/2] 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 --- 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 74bd54ce..8da42068 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);