From patchwork Fri Feb 25 14:36: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: 15391 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 000A9BE08A for ; Fri, 25 Feb 2022 14:36:19 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 50AE261168; Fri, 25 Feb 2022 15:36:19 +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="eOaGpzzJ"; dkim-atps=neutral Received: from mail-wm1-x32c.google.com (mail-wm1-x32c.google.com [IPv6:2a00:1450:4864:20::32c]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4730C61166 for ; Fri, 25 Feb 2022 15:36:17 +0100 (CET) Received: by mail-wm1-x32c.google.com with SMTP id y5so1795976wmi.0 for ; Fri, 25 Feb 2022 06:36:17 -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=tdxXKvHQF1H/63TdVZZfYAPp1pBDU2Kwnr+01R/d1yU=; b=eOaGpzzJP65T+N3/XkxcBib2xmZ9yjkt/AhSCfhC3r46eZiQxDN3WhM/1zxzK8bvne RUxF1Mu68wWCx4BGrzqOfp4xI9sF1Ml5BMUSXKNnfrastGGlufPoud3El4UorI3hj3PM qAWqebO5IHlKqYqKIFtgxDJyK9iOVpBY16om579aEMHXQjLiru1QwSKffUDhoAcOzWex o1P3y0Ac9l/3gVVcg/5ltxQ6iDwFXLiaW+pLU3oaxbV/KtwlMi5OUjQW8PfQw9Lq/8Op Y4rE6DO1f1juQQNBB+lgVzqHg1m4vbnqsDVtbOLeR31bIjDqMED10uoqeUzhFhegg/GJ qQQg== 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=tdxXKvHQF1H/63TdVZZfYAPp1pBDU2Kwnr+01R/d1yU=; b=6h6F/9yauDkKYoVX/B7WqtvBCyiFMeCKw17MjXn3xEX3HgeQv9LQ+kuNmXUCMsz43E +dAm4XwfH50TMP2XHzejTMQIJuEg949usKDrWmQk09p2B4hRmOOCBLwbY4WPC9xCP+q6 LI0vJgqjSDslUkAKhAMXIFFMzVjzO2nKI6Hw8yBgTaDS4qBEc2YNMT+gV3MEQGszvO6X IF6+Fy5DKH3BdG4a/4wqzs9mZCz3wCYqpE6DdL82qFUGILbKLUHy8Ektj9JpSphx6Zy4 N26bHoNF0UZ2c/u74UZXVs8f6elJDrwECHF+ORWvqnSMzcLEAqUzi8PGNZefLaKhzkDt s78w== X-Gm-Message-State: AOAM533UM6wd1TI/Nl2yJNhl9qcOzNpOQ3YotkoECE1T27zGrUzyfJoW YD8uebtIPPpNc/sxGKYxPxlAw+O6GL4o4A== X-Google-Smtp-Source: ABdhPJwDOAPaKJkQqM9+bjrsThyH77bVC2FaHXMB60Iq42k8OR0m2TTz+bmdBOSE4cFSxfg4dNyv8A== X-Received: by 2002:a05:600c:154f:b0:37d:f2e5:d89b with SMTP id f15-20020a05600c154f00b0037df2e5d89bmr2929290wmg.92.1645799776511; Fri, 25 Feb 2022 06:36:16 -0800 (PST) Received: from e28887faee29.8.8.8.8 ([91.224.238.83]) by smtp.gmail.com with ESMTPSA id i15-20020a05600c354f00b0037c050d73ebsm2715891wmq.26.2022.02.25.06.36.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 25 Feb 2022 06:36:16 -0800 (PST) From: Nejc Galof To: libcamera-devel@lists.libcamera.org Date: Fri, 25 Feb 2022 15:36:07 +0100 Message-Id: <20220225143607.62892-1-galof.nejc@gmail.com> X-Mailer: git-send-email 2.17.1 Subject: [libcamera-devel] [PATCH v3] 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. 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" 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);