From patchwork Fri Feb 25 14:45:07 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nejc Galof X-Patchwork-Id: 15392 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 20F63BF415 for ; Fri, 25 Feb 2022 14:45:18 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6C0BB6116E; Fri, 25 Feb 2022 15:45:17 +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="c0iY+hvq"; dkim-atps=neutral Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C745561166 for ; Fri, 25 Feb 2022 15:45:15 +0100 (CET) Received: by mail-wr1-x42c.google.com with SMTP id d3so4912698wrf.1 for ; Fri, 25 Feb 2022 06:45:15 -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=ZDjDID+wtBprRlhnvPY2FiUBNOe3Fb8fuuRlnpahR+8=; b=c0iY+hvqDUHPn97QFJ49SO7L8F9qkgHwOE5P7oIMvEfodfKUwsqkClsOpxz5NHYhgZ fpOgqrzQ4M6LH192Rq3RHFYhstF7da00rKqA2SCOrbchDLjvFBWyZS9LTrH7nq/JQ6IN jC4s7dzdhoBKWzrE2OYXEnDQT4CA2DGEZYrMC0w3wrYTgYtoT0w8Sixumv1HbW2lh59Y c09o0GHl0KGcbAz3f/SIduG9rnZJvXYJe/GhLZcE04JRUYwjCSmoGfSemj7xstdyWIuy l8MtU3m2D5yt3K+W2cF4cvGxbVRuB5KpT0c3j+rU0RSfJZpMIg7484H0M0nQ6HFtMTrV +iEA== 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=ZDjDID+wtBprRlhnvPY2FiUBNOe3Fb8fuuRlnpahR+8=; b=gNyoXQxjN5UHBqKxufG9mITSwUQ6mLKvQMAQJyt2eSG2rGdQzdOTYdgiqkmIEXuKat Aj29XKyRGZoyK99pp4lWmk61l2FBUDMOcuZGz1MvQW43SmeWIj4GOl0zsI6JlC3g8S22 VKaYw6XOwB+i1Yw2w59L5sE9al8BLNDpwNgiYPPyiZOm6/dmWZVsWkc5XDXWxwwBde71 BVcTB4hSm1xcoaYOHPYckm+sKz+3RmsPNJdtlHrdg7XzruySqVGrY72OCkvMDESFMs12 rH+QeklXf7lC0tajJVavABFyuQlHTj0O1wBvexbydBWQfBQmmPPVhVvUvZ9FJ4yrLK2y 4DDw== X-Gm-Message-State: AOAM532MB/QHL4UvrZW1d/5LksfW07ZJdDooSn6nU0i6RPcpcAL5am3z ZiWqjDpxLTcEe4r/smWUuT+SYmAT+x4HZw== X-Google-Smtp-Source: ABdhPJym4jjLMEt35D+Npci//f4NKS7hT+aPBl/bbgiqB0J6fCJ6x61hhqLCGu+WC9AEUieuKXuXAg== X-Received: by 2002:a05:6000:2c2:b0:1ea:9ab5:174f with SMTP id o2-20020a05600002c200b001ea9ab5174fmr6200325wry.274.1645800315438; Fri, 25 Feb 2022 06:45:15 -0800 (PST) Received: from e28887faee29.8.8.8.8 ([91.224.238.83]) by smtp.gmail.com with ESMTPSA id m10-20020adfe94a000000b001ef57f562ccsm2441597wrn.51.2022.02.25.06.45.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 25 Feb 2022 06:45:15 -0800 (PST) From: Nejc Galof To: libcamera-devel@lists.libcamera.org Date: Fri, 25 Feb 2022 15:45:07 +0100 Message-Id: <20220225144507.69550-1-galof.nejc@gmail.com> X-Mailer: git-send-email 2.17.1 Subject: [libcamera-devel] [PATCH v3] 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 | 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 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..4c203e31 100644 --- a/src/v4l2/v4l2_camera.h +++ b/src/v4l2/v4l2_camera.h @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -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 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..493c41c0 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,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(); + vcam_->controls().set(controls::FrameDurationLimits, { uDuration, uDuration }); + + return 0; +} + const std::set V4L2CameraProxy::supportedIoctls_ = { VIDIOC_QUERYCAP, VIDIOC_ENUM_FRAMESIZES, @@ -775,6 +795,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 +873,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_parm(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..c1aeaff9 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_parm(V4L2CameraFile *file, struct v4l2_streamparm *arg); bool hasOwnership(V4L2CameraFile *file); int acquire(V4L2CameraFile *file);