From patchwork Fri Feb 21 11:26:09 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stanislaw Gruszka X-Patchwork-Id: 22819 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 8D654BEFBE for ; Fri, 21 Feb 2025 11:26:24 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3FC17686AC; Fri, 21 Feb 2025 12:26:24 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="Pl8LNmVz"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.9]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4DE3661857 for ; Fri, 21 Feb 2025 12:26:21 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1740137182; x=1771673182; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=UW4k0FDkjeG9k7lQqLjmcgK/9CP9EV+BixgUzzq22kE=; b=Pl8LNmVzff8L6T3IXFTGRCLdAF1OVqvBLj+G6R89GuOZcBSQMh+j2Hb5 juaf9P6A0IGGwEwTrtpV+epK7R2T5ACwnn0o0zKCC2qpnGAToQWUz+HAh UDKHnf/YqnK3YDE6NRlAaJjrfupVPKXzsh+yy2NW9KYvHG27UVMxhS/CQ tz+qjsl2QS+hpLj5i5U8r+nZG2tDVLFt1Ldrvl4Ru9uBBkTPdcjeMDPXg ZhnACEkg8fILxRarZouo7LW4HQg625OXiU4qOGxS2si40O4lcey0DhDiK GSHiQeo0Srlh/gvJ37zJRLy4QOytgNX87ShNBL86VOq0avIj2ik5QZNr2 Q==; X-CSE-ConnectionGUID: YQJiRlP9QjiUPM4HtHemBg== X-CSE-MsgGUID: h6LCZ0xwQ4C6Ro0OWGmBQA== X-IronPort-AV: E=McAfee;i="6700,10204,11351"; a="51596199" X-IronPort-AV: E=Sophos;i="6.13,304,1732608000"; d="scan'208";a="51596199" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Feb 2025 03:26:19 -0800 X-CSE-ConnectionGUID: UyJi8bGUQUqOGrotsikGHA== X-CSE-MsgGUID: m2rOIAt7TBKjKzN+9soF1Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.13,304,1732608000"; d="scan'208";a="119970879" Received: from sgruszka-mobl.ger.corp.intel.com (HELO localhost) ([10.245.97.15]) by fmviesa005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Feb 2025 03:26:17 -0800 From: Stanislaw Gruszka To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Laurent Pinchart , Kieran Bingham , Naushir Patuck , Sakari Ailus , Hans de Goede Subject: [PATCH v4 1/2] libcamera: v4l2_device: add frame start event helpers Date: Fri, 21 Feb 2025 12:26:09 +0100 Message-Id: <20250221112610.42402-2-stanislaw.gruszka@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250221112610.42402-1-stanislaw.gruszka@linux.intel.com> References: <20250221112610.42402-1-stanislaw.gruszka@linux.intel.com> MIME-Version: 1.0 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" Add helper to check if frame start event are supported by subdevice. Since kernel does not have interface to query supported events use subscribe interface. Additionally add helper for checking if the event enabled. Will be needed later to proper code flow if enabling the event fail for some reason. Reviewed-by: Kieran Bingham # v3 Signed-off-by: Stanislaw Gruszka --- include/libcamera/internal/v4l2_device.h | 2 ++ src/libcamera/v4l2_device.cpp | 25 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/include/libcamera/internal/v4l2_device.h b/include/libcamera/internal/v4l2_device.h index affe52c2..edbd7c32 100644 --- a/include/libcamera/internal/v4l2_device.h +++ b/include/libcamera/internal/v4l2_device.h @@ -45,6 +45,8 @@ public: const std::string &deviceNode() const { return deviceNode_; } std::string devicePath() const; + bool supportsFrameStartEvent(); + bool frameStartEnabled() const { return frameStartEnabled_; } int setFrameStartEnabled(bool enable); Signal frameStart; diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 2f65a43a..ca718897 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -449,6 +449,31 @@ std::string V4L2Device::devicePath() const return path; } +/** + * \brief Check if frame start event is supported + * \return True if frame start event is supported, false otherwise + */ + +bool V4L2Device::supportsFrameStartEvent() +{ + struct v4l2_event_subscription event { + }; + event.type = V4L2_EVENT_FRAME_SYNC; + + int ret = ioctl(VIDIOC_SUBSCRIBE_EVENT, &event); + if (ret) + return false; + + ioctl(VIDIOC_UNSUBSCRIBE_EVENT, &event); + return true; +} + +/** + * \fn V4L2Device::frameStartEnabled() + * \brief Check if frame start event is enabled + * \return True if frame start event is enabled, false otherwise + */ + /** * \brief Enable or disable frame start event notification * \param[in] enable True to enable frame start events, false to disable them From patchwork Fri Feb 21 11:26:10 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stanislaw Gruszka X-Patchwork-Id: 22820 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 CA316BEFBE for ; Fri, 21 Feb 2025 11:26:27 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7EBD1686B0; Fri, 21 Feb 2025 12:26:27 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="gRLZZ7Se"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 40C0D68686 for ; Fri, 21 Feb 2025 12:26:25 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1740137185; x=1771673185; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=54fDOP/oX+p7uk9qUdPX4gcO8WT9ItyPgz8hgCSpXnk=; b=gRLZZ7SeAtsheTBvykQGUg0LHCXVvGk8A9bJbBcmbD07MVUutqMsvntf ZVsMH9vTIpzRkDdK6FTKN7rhIinTsZu6tPGaUbp6mt2yZr8OZhnBPS8k+ JuXnrP67QvUMcZp2p/g3qHMWAWbTvGrrXsY4IRTzIbKxbSJBRyIKlKuFH b3iHKx1Qa/yO5n/x/O4noX5rOTF4qk/UTb5K4kM6ZUg9wOnPb1SojcGZa SLqYe6p4VfsgLaG72oodTjJF/SaOGmUyoaiVBsFeDLmmzme5NNfUSV9P/ z58gTTNQkNqTXd+xqXEz/WDGIXkLVQgtG85h2D8H3IF3JN6tswccNCDdw w==; X-CSE-ConnectionGUID: YFK/fOXWTda+hK94WcyUKQ== X-CSE-MsgGUID: tLGkB/oeR+aLjr0Lw/vG5g== X-IronPort-AV: E=McAfee;i="6700,10204,11351"; a="44738605" X-IronPort-AV: E=Sophos;i="6.13,304,1732608000"; d="scan'208";a="44738605" Received: from fmviesa009.fm.intel.com ([10.60.135.149]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Feb 2025 03:26:24 -0800 X-CSE-ConnectionGUID: Zvjl0p+1ROCQY+uX4ykN8Q== X-CSE-MsgGUID: cOi0Kly2QqiFqTttwx4srQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.13,304,1732608000"; d="scan'208";a="115990715" Received: from sgruszka-mobl.ger.corp.intel.com (HELO localhost) ([10.245.97.15]) by fmviesa009-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Feb 2025 03:26:21 -0800 From: Stanislaw Gruszka To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Laurent Pinchart , Kieran Bingham , Naushir Patuck , Sakari Ailus , Hans de Goede Subject: [PATCH v4 2/2] pipeline: simple: Use proper device for frame start events Date: Fri, 21 Feb 2025 12:26:10 +0100 Message-Id: <20250221112610.42402-3-stanislaw.gruszka@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250221112610.42402-1-stanislaw.gruszka@linux.intel.com> References: <20250221112610.42402-1-stanislaw.gruszka@linux.intel.com> MIME-Version: 1.0 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" Currently we use frame start event from video capture device to apply controls. But the capture device might not generate the events. Usually CSI-2 receiver is proper device to subscribe for start frame events. To fix, loop over devices in the pipeline (starting from the last one), find one that emits start frame events and connect applyControls() to it. Additionally remove direct call to sensor_->setControls() if the emitter device was found. This also fixes the assertion like below: ../src/libcamera/delayed_controls.cpp:227: libcamera::ControlList libcamera::DelayedControls::get(uint32_t): Assertion `info.type() != ControlTypeNone' failed which can happen rarely at the beginning of streaming when ControlRingBuffer is not yet filled and there are errors on CSI-2. In such rare scenario we can have call to DelayedControls::get() with frame number that exceed number of saved entries. Handing frame start signal assures we do DelayedConntrols::applyControls() with (possibly out of sequence) frame number and later call to DelayedControls::get() will get proper not-empty control entry. Bug: https://bugs.libcamera.org/show_bug.cgi?id=241 Co-developed-by: Hans de Goede Signed-off-by: Hans de Goede Reviewed-by: Hans de Goede # v2 Tested-by: Hans de Goede # Lenovo X1 Yoga IPU6 + ov2740 # v2 Reviewed-by: Milan Zamazal # v2 Reviewed-by: Kieran Bingham # v3 Signed-off-by: Stanislaw Gruszka --- src/libcamera/pipeline/simple/simple.cpp | 40 +++++++++++++++++++++--- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 6e039bf3..088b9156 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -277,6 +277,7 @@ public: std::list entities_; std::unique_ptr sensor_; V4L2VideoDevice *video_; + V4L2Subdevice *frameStartEmitter_; std::vector configs_; std::map> formats_; @@ -579,6 +580,19 @@ int SimpleCameraData::init() properties_ = sensor_->properties(); + frameStartEmitter_ = nullptr; + for (auto it = entities_.rbegin(); it != entities_.rend(); ++it) { + V4L2Subdevice *sd = pipe->subdev(it->entity); + if (!sd || !sd->supportsFrameStartEvent()) + continue; + + LOG(SimplePipeline, Debug) + << "Using " << it->entity->name() << " frameStart signal"; + + frameStartEmitter_ = sd; + break; + } + return 0; } @@ -897,8 +911,11 @@ void SimpleCameraData::ispStatsReady(uint32_t frame, uint32_t bufferId) void SimpleCameraData::setSensorControls(const ControlList &sensorControls) { delayedCtrls_->push(sensorControls); - ControlList ctrls(sensorControls); - sensor_->setControls(&ctrls); + /* Directly apply controls now if there is no frameStart signal */ + if (!frameStartEmitter_ || !frameStartEmitter_->frameStartEnabled()) { + ControlList ctrls(sensorControls); + sensor_->setControls(&ctrls); + } } /* Retrieve all source pads connected to a sink pad through active routes. */ @@ -1285,8 +1302,6 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) data->delayedCtrls_ = std::make_unique(data->sensor_->device(), params); - data->video_->frameStart.connect(data->delayedCtrls_.get(), - &DelayedControls::applyControls); StreamConfiguration inputCfg; inputCfg.pixelFormat = pipeConfig->captureFormat; @@ -1325,6 +1340,7 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL { SimpleCameraData *data = cameraData(camera); V4L2VideoDevice *video = data->video_; + V4L2Subdevice *frameStartEmitter = data->frameStartEmitter_; int ret; const MediaPad *pad = acquirePipeline(data); @@ -1354,6 +1370,15 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL video->bufferReady.connect(data, &SimpleCameraData::imageBufferReady); + if (frameStartEmitter) { + ret = frameStartEmitter->setFrameStartEnabled(true); + if (ret == 0) + frameStartEmitter->frameStart.connect(data->delayedCtrls_.get(), + &DelayedControls::applyControls); + } + + data->delayedCtrls_->reset(); + ret = video->streamOn(); if (ret < 0) { stop(camera); @@ -1385,6 +1410,13 @@ void SimplePipelineHandler::stopDevice(Camera *camera) { SimpleCameraData *data = cameraData(camera); V4L2VideoDevice *video = data->video_; + V4L2Subdevice *frameStartEmitter = data->frameStartEmitter_; + + if (frameStartEmitter) { + frameStartEmitter->setFrameStartEnabled(false); + frameStartEmitter->frameStart.disconnect(data->delayedCtrls_.get(), + &DelayedControls::applyControls); + } if (data->useConversion_) { if (data->converter_)